3 * Copyright (c) 2010-2011 Peter Ross <pross@xvid.org>
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 * Phantom Cine demuxer
25 * @author Peter Ross <pross@xvid.org>
28 #include "libavutil/intreadwrite.h"
29 #include "libavcodec/bmp.h"
30 #include "libavutil/intfloat.h"
40 CC_RGB
= 0, /**< Gray */
41 CC_LEAD
= 1, /**< LEAD (M)JPEG */
42 CC_UNINT
= 2 /**< Uninterpolated color image (CFA field indicates color ordering) */
45 /** Color Filter Array */
47 CFA_NONE
= 0, /**< GRAY */
48 CFA_VRI
= 1, /**< GBRG/RGGB */
49 CFA_VRIV6
= 2, /**< BGGR/GRBG */
50 CFA_BAYER
= 3, /**< GB/RG */
51 CFA_BAYERFLIP
= 4, /**< RG/GB */
53 CFA_TLGRAY
= 0x80000000,
54 CFA_TRGRAY
= 0x40000000,
55 CFA_BLGRAY
= 0x20000000,
56 CFA_BRGRAY
= 0x10000000
59 static int cine_read_probe(AVProbeData
*p
)
62 if (p
->buf
[0] == 'C' && p
->buf
[1] == 'I' && // Type
63 (HeaderSize
= AV_RL16(p
->buf
+ 2)) >= 0x2C && // HeaderSize
64 AV_RL16(p
->buf
+ 4) <= CC_UNINT
&& // Compression
65 AV_RL16(p
->buf
+ 6) <= 1 && // Version
66 AV_RL32(p
->buf
+ 20) && // ImageCount
67 AV_RL32(p
->buf
+ 24) >= HeaderSize
&& // OffImageHeader
68 AV_RL32(p
->buf
+ 28) >= HeaderSize
&& // OffSetup
69 AV_RL32(p
->buf
+ 32) >= HeaderSize
) // OffImageOffsets
70 return AVPROBE_SCORE_MAX
;
74 static int set_metadata_int(AVDictionary
**dict
, const char *key
, int value
, int allow_zero
)
76 if (value
|| allow_zero
) {
77 return av_dict_set_int(dict
, key
, value
, 0);
82 static int set_metadata_float(AVDictionary
**dict
, const char *key
, float value
, int allow_zero
)
84 if (value
!= 0 || allow_zero
) {
86 snprintf(tmp
, sizeof(tmp
), "%f", value
);
87 return av_dict_set(dict
, key
, tmp
, 0);
92 static int cine_read_header(AVFormatContext
*avctx
)
94 AVIOContext
*pb
= avctx
->pb
;
96 unsigned int version
, compression
, offImageHeader
, offSetup
, offImageOffsets
, biBitCount
, length
, CFA
;
101 st
= avformat_new_stream(avctx
, NULL
);
103 return AVERROR(ENOMEM
);
104 st
->codec
->codec_type
= AVMEDIA_TYPE_VIDEO
;
105 st
->codec
->codec_id
= AV_CODEC_ID_RAWVIDEO
;
106 st
->codec
->codec_tag
= 0;
108 /* CINEFILEHEADER structure */
109 avio_skip(pb
, 4); // Type, Headersize
111 compression
= avio_rl16(pb
);
112 version
= avio_rl16(pb
);
114 avpriv_request_sample(avctx
, "uknown version %i", version
);
115 return AVERROR_INVALIDDATA
;
118 avio_skip(pb
, 12); // FirstMovieImage, TotalImageCount, FirstImageNumber
120 st
->duration
= avio_rl32(pb
);
121 offImageHeader
= avio_rl32(pb
);
122 offSetup
= avio_rl32(pb
);
123 offImageOffsets
= avio_rl32(pb
);
125 avio_skip(pb
, 8); // TriggerTime
127 /* BITMAPINFOHEADER structure */
128 avio_seek(pb
, offImageHeader
, SEEK_SET
);
129 avio_skip(pb
, 4); //biSize
130 st
->codec
->width
= avio_rl32(pb
);
131 st
->codec
->height
= avio_rl32(pb
);
133 if (avio_rl16(pb
) != 1) // biPlanes
134 return AVERROR_INVALIDDATA
;
136 biBitCount
= avio_rl16(pb
);
137 if (biBitCount
!= 8 && biBitCount
!= 16 && biBitCount
!= 24 && biBitCount
!= 48) {
138 avpriv_request_sample(avctx
, "unsupported biBitCount %i", biBitCount
);
139 return AVERROR_INVALIDDATA
;
142 switch (avio_rl32(pb
)) {
146 case 0x100: /* BI_PACKED */
147 st
->codec
->codec_tag
= MKTAG('B', 'I', 'T', 0);
151 avpriv_request_sample(avctx
, "unknown bitmap compression");
152 return AVERROR_INVALIDDATA
;
155 avio_skip(pb
, 4); // biSizeImage
157 /* parse SETUP structure */
158 avio_seek(pb
, offSetup
, SEEK_SET
);
159 avio_skip(pb
, 140); // FrameRatae16 .. descriptionOld
160 if (avio_rl16(pb
) != 0x5453)
161 return AVERROR_INVALIDDATA
;
162 length
= avio_rl16(pb
);
163 if (length
< 0x163C) {
164 avpriv_request_sample(avctx
, "short SETUP header");
165 return AVERROR_INVALIDDATA
;
168 avio_skip(pb
, 616); // Binning .. bFlipH
169 if (!avio_rl32(pb
) ^ vflip
) {
170 st
->codec
->extradata
= av_strdup("BottomUp");
171 st
->codec
->extradata_size
= 9;
174 avio_skip(pb
, 4); // Grid
176 avpriv_set_pts_info(st
, 64, 1, avio_rl32(pb
));
178 avio_skip(pb
, 20); // Shutter .. bEnableColor
180 set_metadata_int(&st
->metadata
, "camera_version", avio_rl32(pb
), 0);
181 set_metadata_int(&st
->metadata
, "firmware_version", avio_rl32(pb
), 0);
182 set_metadata_int(&st
->metadata
, "software_version", avio_rl32(pb
), 0);
183 set_metadata_int(&st
->metadata
, "recording_timezone", avio_rl32(pb
), 0);
187 set_metadata_int(&st
->metadata
, "brightness", avio_rl32(pb
), 1);
188 set_metadata_int(&st
->metadata
, "contrast", avio_rl32(pb
), 1);
189 set_metadata_int(&st
->metadata
, "gamma", avio_rl32(pb
), 1);
191 avio_skip(pb
, 12 + 16); // Reserved1 .. AutoExpRect
192 set_metadata_float(&st
->metadata
, "wbgain[0].r", av_int2float(avio_rl32(pb
)), 1);
193 set_metadata_float(&st
->metadata
, "wbgain[0].b", av_int2float(avio_rl32(pb
)), 1);
194 avio_skip(pb
, 36); // WBGain[1].. WBView
196 st
->codec
->bits_per_coded_sample
= avio_rl32(pb
);
198 if (compression
== CC_RGB
) {
199 if (biBitCount
== 8) {
200 st
->codec
->pix_fmt
= AV_PIX_FMT_GRAY8
;
201 } else if (biBitCount
== 16) {
202 st
->codec
->pix_fmt
= AV_PIX_FMT_GRAY16LE
;
203 } else if (biBitCount
== 24) {
204 st
->codec
->pix_fmt
= AV_PIX_FMT_BGR24
;
205 } else if (biBitCount
== 48) {
206 st
->codec
->pix_fmt
= AV_PIX_FMT_BGR48LE
;
208 avpriv_request_sample(avctx
, "unsupported biBitCount %i", biBitCount
);
209 return AVERROR_INVALIDDATA
;
211 } else if (compression
== CC_UNINT
) {
212 switch (CFA
& 0xFFFFFF) {
214 if (biBitCount
== 8) {
215 st
->codec
->pix_fmt
= AV_PIX_FMT_BAYER_GBRG8
;
216 } else if (biBitCount
== 16) {
217 st
->codec
->pix_fmt
= AV_PIX_FMT_BAYER_GBRG16LE
;
219 avpriv_request_sample(avctx
, "unsupported biBitCount %i", biBitCount
);
220 return AVERROR_INVALIDDATA
;
224 if (biBitCount
== 8) {
225 st
->codec
->pix_fmt
= AV_PIX_FMT_BAYER_RGGB8
;
226 } else if (biBitCount
== 16) {
227 st
->codec
->pix_fmt
= AV_PIX_FMT_BAYER_RGGB16LE
;
229 avpriv_request_sample(avctx
, "unsupported biBitCount %i", biBitCount
);
230 return AVERROR_INVALIDDATA
;
234 avpriv_request_sample(avctx
, "unsupported Color Field Array (CFA) %i", CFA
& 0xFFFFFF);
235 return AVERROR_INVALIDDATA
;
238 avpriv_request_sample(avctx
, "unsupported compression %i", compression
);
239 return AVERROR_INVALIDDATA
;
242 avio_skip(pb
, 668); // Conv8Min ... Sensor
244 set_metadata_int(&st
->metadata
, "shutter_ns", avio_rl32(pb
), 0);
246 avio_skip(pb
, 24); // EDRShutterNs ... ImHeightAcq
248 #define DESCRIPTION_SIZE 4096
249 description
= av_malloc(DESCRIPTION_SIZE
+ 1);
251 return AVERROR(ENOMEM
);
252 i
= avio_get_str(pb
, DESCRIPTION_SIZE
, description
, DESCRIPTION_SIZE
+ 1);
253 if (i
< DESCRIPTION_SIZE
)
254 avio_skip(pb
, DESCRIPTION_SIZE
- i
);
256 av_dict_set(&st
->metadata
, "description", description
, AV_DICT_DONT_STRDUP_VAL
);
258 av_free(description
);
260 avio_skip(pb
, 1176); // RisingEdge ... cmUser
262 set_metadata_int(&st
->metadata
, "enable_crop", avio_rl32(pb
), 1);
263 set_metadata_int(&st
->metadata
, "crop_left", avio_rl32(pb
), 1);
264 set_metadata_int(&st
->metadata
, "crop_top", avio_rl32(pb
), 1);
265 set_metadata_int(&st
->metadata
, "crop_right", avio_rl32(pb
), 1);
266 set_metadata_int(&st
->metadata
, "crop_bottom", avio_rl32(pb
), 1);
268 /* parse image offsets */
269 avio_seek(pb
, offImageOffsets
, SEEK_SET
);
270 for (i
= 0; i
< st
->duration
; i
++)
271 av_add_index_entry(st
, avio_rl64(pb
), i
, 0, 0, AVINDEX_KEYFRAME
);
276 static int cine_read_packet(AVFormatContext
*avctx
, AVPacket
*pkt
)
278 CineDemuxContext
*cine
= avctx
->priv_data
;
279 AVStream
*st
= avctx
->streams
[0];
280 AVIOContext
*pb
= avctx
->pb
;
283 if (cine
->pts
>= st
->duration
)
286 avio_seek(pb
, st
->index_entries
[cine
->pts
].pos
, SEEK_SET
);
289 return AVERROR_INVALIDDATA
;
290 avio_skip(pb
, n
- 8);
291 size
= avio_rl32(pb
);
293 ret
= av_get_packet(pb
, pkt
, size
);
297 pkt
->pts
= cine
->pts
++;
298 pkt
->stream_index
= 0;
299 pkt
->flags
|= AV_PKT_FLAG_KEY
;
303 static int cine_read_seek(AVFormatContext
*avctx
, int stream_index
, int64_t timestamp
, int flags
)
305 CineDemuxContext
*cine
= avctx
->priv_data
;
307 if ((flags
& AVSEEK_FLAG_FRAME
) || (flags
& AVSEEK_FLAG_BYTE
))
308 return AVERROR(ENOSYS
);
310 if (!avctx
->pb
->seekable
)
313 cine
->pts
= timestamp
;
317 AVInputFormat ff_cine_demuxer
= {
319 .long_name
= NULL_IF_CONFIG_SMALL("Phantom Cine"),
320 .priv_data_size
= sizeof(CineDemuxContext
),
321 .read_probe
= cine_read_probe
,
322 .read_header
= cine_read_header
,
323 .read_packet
= cine_read_packet
,
324 .read_seek
= cine_read_seek
,