3 * Copyright (c) 2006 Reimar Doeffinger.
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
28 AVRational frames_per_second
;
29 int32_t fields_per_frame
;
33 * \brief parses a packet header, extracting type and length
34 * \param pb ByteIOContext to read header from
35 * \param type detected packet type is stored here
36 * \param length detected packet length, excluding header is stored here
37 * \return 0 if header not found or contains invalid data, 1 otherwise
39 static int parse_packet_header(ByteIOContext
*pb
, pkt_type_t
*type
, int *length
) {
42 if (get_byte(pb
) != 1)
45 *length
= get_be32(pb
);
46 if ((*length
>> 24) || *length
< 16)
51 if (get_byte(pb
) != 0xe1)
53 if (get_byte(pb
) != 0xe2)
59 * \brief check if file starts with a PKT_MAP header
61 static int gxf_probe(AVProbeData
*p
) {
62 static const uint8_t startcode
[] = {0, 0, 0, 0, 1, 0xbc}; // start with map packet
63 static const uint8_t endcode
[] = {0, 0, 0, 0, 0xe1, 0xe2};
64 if (!memcmp(p
->buf
, startcode
, sizeof(startcode
)) &&
65 !memcmp(&p
->buf
[16 - sizeof(endcode
)], endcode
, sizeof(endcode
)))
66 return AVPROBE_SCORE_MAX
;
71 * \brief gets the stream index for the track with the specified id, creates new
73 * \param stream id of stream to find / add
74 * \param format stream format identifier
76 static int get_sindex(AVFormatContext
*s
, int id
, int format
) {
79 for (i
= 0; i
< s
->nb_streams
; i
++) {
80 if (s
->streams
[i
]->id
== id
)
83 st
= av_new_stream(s
, id
);
87 st
->codec
->codec_type
= CODEC_TYPE_VIDEO
;
88 st
->codec
->codec_id
= CODEC_ID_MJPEG
;
92 st
->codec
->codec_type
= CODEC_TYPE_VIDEO
;
93 st
->codec
->codec_id
= CODEC_ID_DVVIDEO
;
97 st
->codec
->codec_type
= CODEC_TYPE_VIDEO
;
98 st
->codec
->codec_id
= CODEC_ID_DVVIDEO
;
103 st
->codec
->codec_type
= CODEC_TYPE_VIDEO
;
104 st
->codec
->codec_id
= CODEC_ID_MPEG2VIDEO
;
105 st
->need_parsing
= AVSTREAM_PARSE_HEADERS
; //get keyframe flag etc.
109 st
->codec
->codec_type
= CODEC_TYPE_VIDEO
;
110 st
->codec
->codec_id
= CODEC_ID_MPEG1VIDEO
;
111 st
->need_parsing
= AVSTREAM_PARSE_HEADERS
; //get keyframe flag etc.
114 st
->codec
->codec_type
= CODEC_TYPE_AUDIO
;
115 st
->codec
->codec_id
= CODEC_ID_PCM_S24LE
;
116 st
->codec
->channels
= 1;
117 st
->codec
->sample_rate
= 48000;
118 st
->codec
->bit_rate
= 3 * 1 * 48000 * 8;
119 st
->codec
->block_align
= 3 * 1;
120 st
->codec
->bits_per_sample
= 24;
123 st
->codec
->codec_type
= CODEC_TYPE_AUDIO
;
124 st
->codec
->codec_id
= CODEC_ID_PCM_S16LE
;
125 st
->codec
->channels
= 1;
126 st
->codec
->sample_rate
= 48000;
127 st
->codec
->bit_rate
= 2 * 1 * 48000 * 8;
128 st
->codec
->block_align
= 2 * 1;
129 st
->codec
->bits_per_sample
= 16;
132 st
->codec
->codec_type
= CODEC_TYPE_AUDIO
;
133 st
->codec
->codec_id
= CODEC_ID_AC3
;
134 st
->codec
->channels
= 2;
135 st
->codec
->sample_rate
= 48000;
141 st
->codec
->codec_type
= CODEC_TYPE_DATA
;
142 st
->codec
->codec_id
= CODEC_ID_NONE
;
145 st
->codec
->codec_type
= CODEC_TYPE_UNKNOWN
;
146 st
->codec
->codec_id
= CODEC_ID_NONE
;
149 return s
->nb_streams
- 1;
153 * \brief filters out interesting tags from material information.
154 * \param len length of tag section, will be adjusted to contain remaining bytes
155 * \param si struct to store collected information into
157 static void gxf_material_tags(ByteIOContext
*pb
, int *len
, st_info_t
*si
) {
158 si
->first_field
= AV_NOPTS_VALUE
;
159 si
->last_field
= AV_NOPTS_VALUE
;
161 mat_tag_t tag
= get_byte(pb
);
162 int tlen
= get_byte(pb
);
168 uint32_t value
= get_be32(pb
);
169 if (tag
== MAT_FIRST_FIELD
)
170 si
->first_field
= value
;
171 else if (tag
== MAT_LAST_FIELD
)
172 si
->last_field
= value
;
179 * \brief convert fps tag value to AVRational fps
180 * \param fps fps value from tag
181 * \return fps as AVRational, or 0 / 0 if unknown
183 static AVRational
fps_tag2avr(int32_t fps
) {
184 extern const AVRational ff_frame_rate_tab
[];
185 if (fps
< 1 || fps
> 9) fps
= 9;
186 return ff_frame_rate_tab
[9 - fps
]; // values have opposite order
190 * \brief convert UMF attributes flags to AVRational fps
191 * \param fps fps value from flags
192 * \return fps as AVRational, or 0 / 0 if unknown
194 static AVRational
fps_umf2avr(uint32_t flags
) {
195 static const AVRational map
[] = {{50, 1}, {60000, 1001}, {24, 1},
196 {25, 1}, {30000, 1001}};
197 int idx
= av_log2((flags
& 0x7c0) >> 6);
202 * \brief filters out interesting tags from track information.
203 * \param len length of tag section, will be adjusted to contain remaining bytes
204 * \param si struct to store collected information into
206 static void gxf_track_tags(ByteIOContext
*pb
, int *len
, st_info_t
*si
) {
207 si
->frames_per_second
= (AVRational
){0, 0};
208 si
->fields_per_frame
= 0;
210 track_tag_t tag
= get_byte(pb
);
211 int tlen
= get_byte(pb
);
217 uint32_t value
= get_be32(pb
);
218 if (tag
== TRACK_FPS
)
219 si
->frames_per_second
= fps_tag2avr(value
);
220 else if (tag
== TRACK_FPF
&& (value
== 1 || value
== 2))
221 si
->fields_per_frame
= value
;
228 * \brief read index from FLT packet into stream 0 av_index
230 static void gxf_read_index(AVFormatContext
*s
, int pkt_len
) {
231 ByteIOContext
*pb
= s
->pb
;
232 AVStream
*st
= s
->streams
[0];
233 uint32_t fields_per_map
= get_le32(pb
);
234 uint32_t map_cnt
= get_le32(pb
);
237 if (map_cnt
> 1000) {
238 av_log(s
, AV_LOG_ERROR
, "GXF: too many index entries %u (%x)\n", map_cnt
, map_cnt
);
241 if (pkt_len
< 4 * map_cnt
) {
242 av_log(s
, AV_LOG_ERROR
, "GXF: invalid index length\n");
243 url_fskip(pb
, pkt_len
);
246 pkt_len
-= 4 * map_cnt
;
247 av_add_index_entry(st
, 0, 0, 0, 0, 0);
248 for (i
= 0; i
< map_cnt
; i
++)
249 av_add_index_entry(st
, (uint64_t)get_le32(pb
) * 1024,
250 i
* (uint64_t)fields_per_map
+ 1, 0, 0, 0);
251 url_fskip(pb
, pkt_len
);
254 static int gxf_header(AVFormatContext
*s
, AVFormatParameters
*ap
) {
255 ByteIOContext
*pb
= s
->pb
;
259 AVRational main_timebase
= {0, 0};
262 if (!parse_packet_header(pb
, &pkt_type
, &map_len
) || pkt_type
!= PKT_MAP
) {
263 av_log(s
, AV_LOG_ERROR
, "GXF: map packet not found\n");
267 if (get_byte(pb
) != 0x0e0 || get_byte(pb
) != 0xff) {
268 av_log(s
, AV_LOG_ERROR
, "GXF: unknown version or invalid map preamble\n");
272 len
= get_be16(pb
); // length of material data section
274 av_log(s
, AV_LOG_ERROR
, "GXF: material data longer than map data\n");
278 gxf_material_tags(pb
, &len
, &si
);
281 len
= get_be16(pb
); // length of track description
283 av_log(s
, AV_LOG_ERROR
, "GXF: track description longer than map data\n");
288 int track_type
, track_id
, track_len
;
292 track_type
= get_byte(pb
);
293 track_id
= get_byte(pb
);
294 track_len
= get_be16(pb
);
296 gxf_track_tags(pb
, &track_len
, &si
);
297 url_fskip(pb
, track_len
);
298 if (!(track_type
& 0x80)) {
299 av_log(s
, AV_LOG_ERROR
, "GXF: invalid track type %x\n", track_type
);
303 if ((track_id
& 0xc0) != 0xc0) {
304 av_log(s
, AV_LOG_ERROR
, "GXF: invalid track id %x\n", track_id
);
308 idx
= get_sindex(s
, track_id
, track_type
);
309 if (idx
< 0) continue;
310 st
= s
->streams
[idx
];
311 if (!main_timebase
.num
|| !main_timebase
.den
) {
312 main_timebase
.num
= si
.frames_per_second
.den
;
313 main_timebase
.den
= si
.frames_per_second
.num
* si
.fields_per_frame
;
315 st
->start_time
= si
.first_field
;
316 if (si
.first_field
!= AV_NOPTS_VALUE
&& si
.last_field
!= AV_NOPTS_VALUE
)
317 st
->duration
= si
.last_field
- si
.first_field
;
320 av_log(s
, AV_LOG_ERROR
, "GXF: invalid track description length specified\n");
322 url_fskip(pb
, map_len
);
323 if (!parse_packet_header(pb
, &pkt_type
, &len
)) {
324 av_log(s
, AV_LOG_ERROR
, "GXF: sync lost in header\n");
327 if (pkt_type
== PKT_FLT
) {
328 gxf_read_index(s
, len
);
329 if (!parse_packet_header(pb
, &pkt_type
, &len
)) {
330 av_log(s
, AV_LOG_ERROR
, "GXF: sync lost in header\n");
334 if (pkt_type
== PKT_UMF
) {
338 url_fskip(pb
, 5); // preamble
339 url_fskip(pb
, 0x30); // payload description
340 fps
= fps_umf2avr(get_le32(pb
));
341 if (!main_timebase
.num
|| !main_timebase
.den
) {
342 // this may not always be correct, but simply the best we can get
343 main_timebase
.num
= fps
.den
;
344 main_timebase
.den
= fps
.num
;
347 av_log(s
, AV_LOG_INFO
, "GXF: UMF packet too short\n");
349 av_log(s
, AV_LOG_INFO
, "GXF: UMF packet missing\n");
351 if (!main_timebase
.num
|| !main_timebase
.den
)
352 main_timebase
= (AVRational
){1, 50}; // set some arbitrary fallback
353 for (i
= 0; i
< s
->nb_streams
; i
++) {
354 AVStream
*st
= s
->streams
[i
];
355 av_set_pts_info(st
, 32, main_timebase
.num
, main_timebase
.den
);
362 if (!max_interval-- || url_feof(pb)) \
364 tmp = tmp << 8 | get_byte(pb); \
368 * \brief resync the stream on the next media packet with specified properties
369 * \param max_interval how many bytes to search for matching packet at most
370 * \param track track id the media packet must belong to, -1 for any
371 * \param timestamp minimum timestamp (== field number) the packet must have, -1 for any
372 * \return timestamp of packet found
374 static int64_t gxf_resync_media(AVFormatContext
*s
, uint64_t max_interval
, int track
, int timestamp
) {
377 uint64_t last_found_pos
= 0;
379 int64_t cur_timestamp
= AV_NOPTS_VALUE
;
381 ByteIOContext
*pb
= s
->pb
;
390 last_pos
= url_ftell(pb
);
391 url_fseek(pb
, -5, SEEK_CUR
);
392 if (!parse_packet_header(pb
, &type
, &len
) || type
!= PKT_MEDIA
) {
393 url_fseek(pb
, last_pos
, SEEK_SET
);
397 cur_track
= get_byte(pb
);
398 cur_timestamp
= get_be32(pb
);
399 last_found_pos
= url_ftell(pb
) - 16 - 6;
400 if ((track
>= 0 && track
!= cur_track
) || (timestamp
>= 0 && timestamp
> cur_timestamp
)) {
401 url_fseek(pb
, last_pos
, SEEK_SET
);
406 url_fseek(pb
, last_found_pos
, SEEK_SET
);
407 return cur_timestamp
;
410 static int gxf_packet(AVFormatContext
*s
, AVPacket
*pkt
) {
411 ByteIOContext
*pb
= s
->pb
;
414 while (!url_feof(pb
)) {
415 int track_type
, track_id
, ret
;
417 if (!parse_packet_header(pb
, &pkt_type
, &pkt_len
)) {
419 av_log(s
, AV_LOG_ERROR
, "GXF: sync lost\n");
422 if (pkt_type
== PKT_FLT
) {
423 gxf_read_index(s
, pkt_len
);
426 if (pkt_type
!= PKT_MEDIA
) {
427 url_fskip(pb
, pkt_len
);
431 av_log(s
, AV_LOG_ERROR
, "GXF: invalid media packet length\n");
435 track_type
= get_byte(pb
);
436 track_id
= get_byte(pb
);
437 field_nr
= get_be32(pb
);
438 get_be32(pb
); // field information
439 get_be32(pb
); // "timeline" field number
440 get_byte(pb
); // flags
441 get_byte(pb
); // reserved
442 // NOTE: there is also data length information in the
443 // field information, it might be better to take this into account
445 ret
= av_get_packet(pb
, pkt
, pkt_len
);
446 pkt
->stream_index
= get_sindex(s
, track_id
, track_type
);
453 static int gxf_seek(AVFormatContext
*s
, int stream_index
, int64_t timestamp
, int flags
) {
455 uint64_t maxlen
= 100 * 1024 * 1024;
456 AVStream
*st
= s
->streams
[0];
457 int64_t start_time
= s
->streams
[stream_index
]->start_time
;
460 if (timestamp
< start_time
) timestamp
= start_time
;
461 idx
= av_index_search_timestamp(st
, timestamp
- start_time
,
462 AVSEEK_FLAG_ANY
| AVSEEK_FLAG_BACKWARD
);
465 pos
= st
->index_entries
[idx
].pos
;
466 if (idx
< st
->nb_index_entries
- 2)
467 maxlen
= st
->index_entries
[idx
+ 2].pos
- pos
;
468 maxlen
= FFMAX(maxlen
, 200 * 1024);
469 url_fseek(s
->pb
, pos
, SEEK_SET
);
470 found
= gxf_resync_media(s
, maxlen
, -1, timestamp
);
471 if (FFABS(found
- timestamp
) > 4)
476 static int64_t gxf_read_timestamp(AVFormatContext
*s
, int stream_index
,
477 int64_t *pos
, int64_t pos_limit
) {
478 ByteIOContext
*pb
= s
->pb
;
480 url_fseek(pb
, *pos
, SEEK_SET
);
481 res
= gxf_resync_media(s
, pos_limit
- *pos
, -1, -1);
482 *pos
= url_ftell(pb
);
486 AVInputFormat gxf_demuxer
= {