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 "libavutil/mem.h"
30 #include "libavcodec/bmp.h"
31 #include "libavutil/intfloat.h"
43 CC_RGB
= 0, /**< Gray */
44 CC_LEAD
= 1, /**< LEAD (M)JPEG */
45 CC_UNINT
= 2 /**< Uninterpolated color image (CFA field indicates color ordering) */
48 /** Color Filter Array */
50 CFA_NONE
= 0, /**< GRAY */
51 CFA_VRI
= 1, /**< GBRG/RGGB */
52 CFA_VRIV6
= 2, /**< BGGR/GRBG */
53 CFA_BAYER
= 3, /**< GB/RG */
54 CFA_BAYERFLIP
= 4, /**< RG/GB */
57 #define CFA_TLGRAY 0x80000000U
58 #define CFA_TRGRAY 0x40000000U
59 #define CFA_BLGRAY 0x20000000U
60 #define CFA_BRGRAY 0x10000000U
62 static int cine_read_probe(const AVProbeData
*p
)
65 if (p
->buf
[0] == 'C' && p
->buf
[1] == 'I' && // Type
66 (HeaderSize
= AV_RL16(p
->buf
+ 2)) >= 0x2C && // HeaderSize
67 AV_RL16(p
->buf
+ 4) <= CC_UNINT
&& // Compression
68 AV_RL16(p
->buf
+ 6) <= 1 && // Version
69 AV_RL32(p
->buf
+ 20) && // ImageCount
70 AV_RL32(p
->buf
+ 24) >= HeaderSize
&& // OffImageHeader
71 AV_RL32(p
->buf
+ 28) >= HeaderSize
&& // OffSetup
72 AV_RL32(p
->buf
+ 32) >= HeaderSize
) // OffImageOffsets
73 return AVPROBE_SCORE_MAX
;
77 static int set_metadata_int(AVDictionary
**dict
, const char *key
, int value
, int allow_zero
)
79 if (value
|| allow_zero
) {
80 return av_dict_set_int(dict
, key
, value
, 0);
85 static int set_metadata_float(AVDictionary
**dict
, const char *key
, float value
, int allow_zero
)
87 if (value
!= 0 || allow_zero
) {
89 snprintf(tmp
, sizeof(tmp
), "%f", value
);
90 return av_dict_set(dict
, key
, tmp
, 0);
95 static int cine_read_header(AVFormatContext
*avctx
)
97 AVIOContext
*pb
= avctx
->pb
;
99 unsigned int version
, compression
, offImageHeader
, offSetup
, offImageOffsets
, biBitCount
, length
, CFA
;
104 st
= avformat_new_stream(avctx
, NULL
);
106 return AVERROR(ENOMEM
);
107 st
->codecpar
->codec_type
= AVMEDIA_TYPE_VIDEO
;
108 st
->codecpar
->codec_id
= AV_CODEC_ID_RAWVIDEO
;
109 st
->codecpar
->codec_tag
= 0;
111 /* CINEFILEHEADER structure */
112 avio_skip(pb
, 4); // Type, Headersize
114 compression
= avio_rl16(pb
);
115 version
= avio_rl16(pb
);
117 avpriv_request_sample(avctx
, "unknown version %i", version
);
118 return AVERROR_INVALIDDATA
;
121 avio_skip(pb
, 12); // FirstMovieImage, TotalImageCount, FirstImageNumber
123 st
->duration
= avio_rl32(pb
);
124 offImageHeader
= avio_rl32(pb
);
125 offSetup
= avio_rl32(pb
);
126 offImageOffsets
= avio_rl32(pb
);
128 avio_skip(pb
, 8); // TriggerTime
130 /* BITMAPINFOHEADER structure */
131 avio_seek(pb
, offImageHeader
, SEEK_SET
);
132 avio_skip(pb
, 4); //biSize
133 st
->codecpar
->width
= avio_rl32(pb
);
134 st
->codecpar
->height
= avio_rl32(pb
);
136 if (avio_rl16(pb
) != 1) // biPlanes
137 return AVERROR_INVALIDDATA
;
139 biBitCount
= avio_rl16(pb
);
140 if (biBitCount
!= 8 && biBitCount
!= 16 && biBitCount
!= 24 && biBitCount
!= 48) {
141 avpriv_request_sample(avctx
, "unsupported biBitCount %i", biBitCount
);
142 return AVERROR_INVALIDDATA
;
145 switch (avio_rl32(pb
)) {
149 case 0x100: /* BI_PACKED */
150 st
->codecpar
->codec_tag
= MKTAG('B', 'I', 'T', 0);
154 avpriv_request_sample(avctx
, "unknown bitmap compression");
155 return AVERROR_INVALIDDATA
;
158 avio_skip(pb
, 4); // biSizeImage
160 /* parse SETUP structure */
161 avio_seek(pb
, offSetup
, SEEK_SET
);
162 avio_skip(pb
, 140); // FrameRatae16 .. descriptionOld
163 if (avio_rl16(pb
) != 0x5453)
164 return AVERROR_INVALIDDATA
;
165 length
= avio_rl16(pb
);
166 if (length
< 0x163C) {
167 avpriv_request_sample(avctx
, "short SETUP header");
168 return AVERROR_INVALIDDATA
;
171 avio_skip(pb
, 616); // Binning .. bFlipH
172 if (!avio_rl32(pb
) ^ vflip
) {
173 st
->codecpar
->extradata
= av_strdup("BottomUp");
174 if (!st
->codecpar
->extradata
) {
175 st
->codecpar
->extradata_size
= 0;
176 return AVERROR(ENOMEM
);
178 st
->codecpar
->extradata_size
= 9;
181 avio_skip(pb
, 4); // Grid
183 avpriv_set_pts_info(st
, 64, 1, avio_rl32(pb
));
185 avio_skip(pb
, 20); // Shutter .. bEnableColor
187 set_metadata_int(&st
->metadata
, "camera_version", avio_rl32(pb
), 0);
188 set_metadata_int(&st
->metadata
, "firmware_version", avio_rl32(pb
), 0);
189 set_metadata_int(&st
->metadata
, "software_version", avio_rl32(pb
), 0);
190 set_metadata_int(&st
->metadata
, "recording_timezone", avio_rl32(pb
), 0);
194 set_metadata_int(&st
->metadata
, "brightness", avio_rl32(pb
), 1);
195 set_metadata_int(&st
->metadata
, "contrast", avio_rl32(pb
), 1);
196 set_metadata_int(&st
->metadata
, "gamma", avio_rl32(pb
), 1);
198 avio_skip(pb
, 12 + 16); // Reserved1 .. AutoExpRect
199 set_metadata_float(&st
->metadata
, "wbgain[0].r", av_int2float(avio_rl32(pb
)), 1);
200 set_metadata_float(&st
->metadata
, "wbgain[0].b", av_int2float(avio_rl32(pb
)), 1);
201 avio_skip(pb
, 36); // WBGain[1].. WBView
203 st
->codecpar
->bits_per_coded_sample
= avio_rl32(pb
);
205 if (compression
== CC_RGB
) {
206 if (biBitCount
== 8) {
207 st
->codecpar
->format
= AV_PIX_FMT_GRAY8
;
208 } else if (biBitCount
== 16) {
209 st
->codecpar
->format
= AV_PIX_FMT_GRAY16LE
;
210 } else if (biBitCount
== 24) {
211 st
->codecpar
->format
= AV_PIX_FMT_BGR24
;
212 } else if (biBitCount
== 48) {
213 st
->codecpar
->format
= AV_PIX_FMT_BGR48LE
;
215 avpriv_request_sample(avctx
, "unsupported biBitCount %i", biBitCount
);
216 return AVERROR_INVALIDDATA
;
218 } else if (compression
== CC_UNINT
) {
219 switch (CFA
& 0xFFFFFF) {
221 if (biBitCount
== 8) {
222 st
->codecpar
->format
= AV_PIX_FMT_BAYER_GBRG8
;
223 } else if (biBitCount
== 16) {
224 st
->codecpar
->format
= AV_PIX_FMT_BAYER_GBRG16LE
;
226 avpriv_request_sample(avctx
, "unsupported biBitCount %i", biBitCount
);
227 return AVERROR_INVALIDDATA
;
231 if (biBitCount
== 8) {
232 st
->codecpar
->format
= AV_PIX_FMT_BAYER_RGGB8
;
233 } else if (biBitCount
== 16) {
234 st
->codecpar
->format
= AV_PIX_FMT_BAYER_RGGB16LE
;
236 avpriv_request_sample(avctx
, "unsupported biBitCount %i", biBitCount
);
237 return AVERROR_INVALIDDATA
;
241 avpriv_request_sample(avctx
, "unsupported Color Field Array (CFA) %i", CFA
& 0xFFFFFF);
242 return AVERROR_INVALIDDATA
;
245 avpriv_request_sample(avctx
, "unsupported compression %i", compression
);
246 return AVERROR_INVALIDDATA
;
249 avio_skip(pb
, 668); // Conv8Min ... Sensor
251 set_metadata_int(&st
->metadata
, "shutter_ns", avio_rl32(pb
), 0);
253 avio_skip(pb
, 24); // EDRShutterNs ... ImHeightAcq
255 #define DESCRIPTION_SIZE 4096
256 description
= av_malloc(DESCRIPTION_SIZE
+ 1);
258 return AVERROR(ENOMEM
);
259 i
= avio_get_str(pb
, DESCRIPTION_SIZE
, description
, DESCRIPTION_SIZE
+ 1);
260 if (i
< DESCRIPTION_SIZE
)
261 avio_skip(pb
, DESCRIPTION_SIZE
- i
);
263 av_dict_set(&st
->metadata
, "description", description
, AV_DICT_DONT_STRDUP_VAL
);
265 av_free(description
);
267 avio_skip(pb
, 1176); // RisingEdge ... cmUser
269 set_metadata_int(&st
->metadata
, "enable_crop", avio_rl32(pb
), 1);
270 set_metadata_int(&st
->metadata
, "crop_left", avio_rl32(pb
), 1);
271 set_metadata_int(&st
->metadata
, "crop_top", avio_rl32(pb
), 1);
272 set_metadata_int(&st
->metadata
, "crop_right", avio_rl32(pb
), 1);
273 set_metadata_int(&st
->metadata
, "crop_bottom", avio_rl32(pb
), 1);
275 /* parse image offsets */
276 avio_seek(pb
, offImageOffsets
, SEEK_SET
);
277 for (i
= 0; i
< st
->duration
; i
++) {
278 int64_t pos
= avio_rl64(pb
);
279 if (avio_feof(pb
) || pos
< 0)
280 return AVERROR_INVALIDDATA
;
282 av_add_index_entry(st
, pos
, i
, 0, 0, AVINDEX_KEYFRAME
);
288 static int cine_read_packet(AVFormatContext
*avctx
, AVPacket
*pkt
)
290 CineDemuxContext
*cine
= avctx
->priv_data
;
291 AVStream
*st
= avctx
->streams
[0];
292 FFStream
*const sti
= ffstream(st
);
293 AVIOContext
*pb
= avctx
->pb
;
297 if (cine
->pts
>= sti
->nb_index_entries
)
300 ret64
= avio_seek(pb
, sti
->index_entries
[cine
->pts
].pos
, SEEK_SET
);
305 return AVERROR_INVALIDDATA
;
306 avio_skip(pb
, n
- 8);
307 size
= avio_rl32(pb
);
308 if (avio_feof(pb
) || size
< 0)
309 return AVERROR_INVALIDDATA
;
311 if (cine
->maxsize
&& (uint64_t)sti
->index_entries
[cine
->pts
].pos
+ size
+ n
> cine
->maxsize
)
312 size
= cine
->maxsize
- sti
->index_entries
[cine
->pts
].pos
- n
;
314 ret
= av_get_packet(pb
, pkt
, size
);
319 cine
->maxsize
= (uint64_t)sti
->index_entries
[cine
->pts
].pos
+ n
+ ret
;
321 pkt
->pts
= cine
->pts
++;
322 pkt
->stream_index
= 0;
323 pkt
->flags
|= AV_PKT_FLAG_KEY
;
327 static int cine_read_seek(AVFormatContext
*avctx
, int stream_index
, int64_t timestamp
, int flags
)
329 CineDemuxContext
*cine
= avctx
->priv_data
;
331 if ((flags
& AVSEEK_FLAG_FRAME
) || (flags
& AVSEEK_FLAG_BYTE
))
332 return AVERROR(ENOSYS
);
334 if (!(avctx
->pb
->seekable
& AVIO_SEEKABLE_NORMAL
))
337 cine
->pts
= timestamp
;
341 const FFInputFormat ff_cine_demuxer
= {
343 .p
.long_name
= NULL_IF_CONFIG_SMALL("Phantom Cine"),
344 .priv_data_size
= sizeof(CineDemuxContext
),
345 .read_probe
= cine_read_probe
,
346 .read_header
= cine_read_header
,
347 .read_packet
= cine_read_packet
,
348 .read_seek
= cine_read_seek
,