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
22 #include "libavutil/common.h"
26 struct gxf_stream_info
{
29 AVRational frames_per_second
;
30 int32_t fields_per_frame
;
34 * \brief parses a packet header, extracting type and length
35 * \param pb ByteIOContext to read header from
36 * \param type detected packet type is stored here
37 * \param length detected packet length, excluding header is stored here
38 * \return 0 if header not found or contains invalid data, 1 otherwise
40 static int parse_packet_header(ByteIOContext
*pb
, GXFPktType
*type
, int *length
) {
43 if (get_byte(pb
) != 1)
46 *length
= get_be32(pb
);
47 if ((*length
>> 24) || *length
< 16)
52 if (get_byte(pb
) != 0xe1)
54 if (get_byte(pb
) != 0xe2)
60 * \brief check if file starts with a PKT_MAP header
62 static int gxf_probe(AVProbeData
*p
) {
63 static const uint8_t startcode
[] = {0, 0, 0, 0, 1, 0xbc}; // start with map packet
64 static const uint8_t endcode
[] = {0, 0, 0, 0, 0xe1, 0xe2};
65 if (!memcmp(p
->buf
, startcode
, sizeof(startcode
)) &&
66 !memcmp(&p
->buf
[16 - sizeof(endcode
)], endcode
, sizeof(endcode
)))
67 return AVPROBE_SCORE_MAX
;
72 * \brief gets the stream index for the track with the specified id, creates new
74 * \param stream id of stream to find / add
75 * \param format stream format identifier
77 static int get_sindex(AVFormatContext
*s
, int id
, int format
) {
80 for (i
= 0; i
< s
->nb_streams
; i
++) {
81 if (s
->streams
[i
]->id
== id
)
84 st
= av_new_stream(s
, id
);
86 return AVERROR(ENOMEM
);
90 st
->codec
->codec_type
= CODEC_TYPE_VIDEO
;
91 st
->codec
->codec_id
= CODEC_ID_MJPEG
;
95 st
->codec
->codec_type
= CODEC_TYPE_VIDEO
;
96 st
->codec
->codec_id
= CODEC_ID_DVVIDEO
;
100 st
->codec
->codec_type
= CODEC_TYPE_VIDEO
;
101 st
->codec
->codec_id
= CODEC_ID_DVVIDEO
;
106 st
->codec
->codec_type
= CODEC_TYPE_VIDEO
;
107 st
->codec
->codec_id
= CODEC_ID_MPEG2VIDEO
;
108 st
->need_parsing
= AVSTREAM_PARSE_HEADERS
; //get keyframe flag etc.
112 st
->codec
->codec_type
= CODEC_TYPE_VIDEO
;
113 st
->codec
->codec_id
= CODEC_ID_MPEG1VIDEO
;
114 st
->need_parsing
= AVSTREAM_PARSE_HEADERS
; //get keyframe flag etc.
117 st
->codec
->codec_type
= CODEC_TYPE_AUDIO
;
118 st
->codec
->codec_id
= CODEC_ID_PCM_S24LE
;
119 st
->codec
->channels
= 1;
120 st
->codec
->sample_rate
= 48000;
121 st
->codec
->bit_rate
= 3 * 1 * 48000 * 8;
122 st
->codec
->block_align
= 3 * 1;
123 st
->codec
->bits_per_coded_sample
= 24;
126 st
->codec
->codec_type
= CODEC_TYPE_AUDIO
;
127 st
->codec
->codec_id
= CODEC_ID_PCM_S16LE
;
128 st
->codec
->channels
= 1;
129 st
->codec
->sample_rate
= 48000;
130 st
->codec
->bit_rate
= 2 * 1 * 48000 * 8;
131 st
->codec
->block_align
= 2 * 1;
132 st
->codec
->bits_per_coded_sample
= 16;
135 st
->codec
->codec_type
= CODEC_TYPE_AUDIO
;
136 st
->codec
->codec_id
= CODEC_ID_AC3
;
137 st
->codec
->channels
= 2;
138 st
->codec
->sample_rate
= 48000;
144 st
->codec
->codec_type
= CODEC_TYPE_DATA
;
145 st
->codec
->codec_id
= CODEC_ID_NONE
;
148 st
->codec
->codec_type
= CODEC_TYPE_UNKNOWN
;
149 st
->codec
->codec_id
= CODEC_ID_NONE
;
152 return s
->nb_streams
- 1;
156 * \brief filters out interesting tags from material information.
157 * \param len length of tag section, will be adjusted to contain remaining bytes
158 * \param si struct to store collected information into
160 static void gxf_material_tags(ByteIOContext
*pb
, int *len
, struct gxf_stream_info
*si
) {
161 si
->first_field
= AV_NOPTS_VALUE
;
162 si
->last_field
= AV_NOPTS_VALUE
;
164 GXFMatTag tag
= get_byte(pb
);
165 int tlen
= get_byte(pb
);
171 uint32_t value
= get_be32(pb
);
172 if (tag
== MAT_FIRST_FIELD
)
173 si
->first_field
= value
;
174 else if (tag
== MAT_LAST_FIELD
)
175 si
->last_field
= value
;
182 * \brief convert fps tag value to AVRational fps
183 * \param fps fps value from tag
184 * \return fps as AVRational, or 0 / 0 if unknown
186 static AVRational
fps_tag2avr(int32_t fps
) {
187 extern const AVRational ff_frame_rate_tab
[];
188 if (fps
< 1 || fps
> 9) fps
= 9;
189 return ff_frame_rate_tab
[9 - fps
]; // values have opposite order
193 * \brief convert UMF attributes flags to AVRational fps
194 * \param fps fps value from flags
195 * \return fps as AVRational, or 0 / 0 if unknown
197 static AVRational
fps_umf2avr(uint32_t flags
) {
198 static const AVRational map
[] = {{50, 1}, {60000, 1001}, {24, 1},
199 {25, 1}, {30000, 1001}};
200 int idx
= av_log2((flags
& 0x7c0) >> 6);
205 * \brief filters out interesting tags from track information.
206 * \param len length of tag section, will be adjusted to contain remaining bytes
207 * \param si struct to store collected information into
209 static void gxf_track_tags(ByteIOContext
*pb
, int *len
, struct gxf_stream_info
*si
) {
210 si
->frames_per_second
= (AVRational
){0, 0};
211 si
->fields_per_frame
= 0;
213 GXFTrackTag tag
= get_byte(pb
);
214 int tlen
= get_byte(pb
);
220 uint32_t value
= get_be32(pb
);
221 if (tag
== TRACK_FPS
)
222 si
->frames_per_second
= fps_tag2avr(value
);
223 else if (tag
== TRACK_FPF
&& (value
== 1 || value
== 2))
224 si
->fields_per_frame
= value
;
231 * \brief read index from FLT packet into stream 0 av_index
233 static void gxf_read_index(AVFormatContext
*s
, int pkt_len
) {
234 ByteIOContext
*pb
= s
->pb
;
235 AVStream
*st
= s
->streams
[0];
236 uint32_t fields_per_map
= get_le32(pb
);
237 uint32_t map_cnt
= get_le32(pb
);
240 if (map_cnt
> 1000) {
241 av_log(s
, AV_LOG_ERROR
, "too many index entries %u (%x)\n", map_cnt
, map_cnt
);
244 if (pkt_len
< 4 * map_cnt
) {
245 av_log(s
, AV_LOG_ERROR
, "invalid index length\n");
246 url_fskip(pb
, pkt_len
);
249 pkt_len
-= 4 * map_cnt
;
250 av_add_index_entry(st
, 0, 0, 0, 0, 0);
251 for (i
= 0; i
< map_cnt
; i
++)
252 av_add_index_entry(st
, (uint64_t)get_le32(pb
) * 1024,
253 i
* (uint64_t)fields_per_map
+ 1, 0, 0, 0);
254 url_fskip(pb
, pkt_len
);
257 static int gxf_header(AVFormatContext
*s
, AVFormatParameters
*ap
) {
258 ByteIOContext
*pb
= s
->pb
;
262 AVRational main_timebase
= {0, 0};
263 struct gxf_stream_info si
;
265 if (!parse_packet_header(pb
, &pkt_type
, &map_len
) || pkt_type
!= PKT_MAP
) {
266 av_log(s
, AV_LOG_ERROR
, "map packet not found\n");
270 if (get_byte(pb
) != 0x0e0 || get_byte(pb
) != 0xff) {
271 av_log(s
, AV_LOG_ERROR
, "unknown version or invalid map preamble\n");
275 len
= get_be16(pb
); // length of material data section
277 av_log(s
, AV_LOG_ERROR
, "material data longer than map data\n");
281 gxf_material_tags(pb
, &len
, &si
);
284 len
= get_be16(pb
); // length of track description
286 av_log(s
, AV_LOG_ERROR
, "track description longer than map data\n");
291 int track_type
, track_id
, track_len
;
295 track_type
= get_byte(pb
);
296 track_id
= get_byte(pb
);
297 track_len
= get_be16(pb
);
299 gxf_track_tags(pb
, &track_len
, &si
);
300 url_fskip(pb
, track_len
);
301 if (!(track_type
& 0x80)) {
302 av_log(s
, AV_LOG_ERROR
, "invalid track type %x\n", track_type
);
306 if ((track_id
& 0xc0) != 0xc0) {
307 av_log(s
, AV_LOG_ERROR
, "invalid track id %x\n", track_id
);
311 idx
= get_sindex(s
, track_id
, track_type
);
312 if (idx
< 0) continue;
313 st
= s
->streams
[idx
];
314 if (!main_timebase
.num
|| !main_timebase
.den
) {
315 main_timebase
.num
= si
.frames_per_second
.den
;
316 main_timebase
.den
= si
.frames_per_second
.num
* si
.fields_per_frame
;
318 st
->start_time
= si
.first_field
;
319 if (si
.first_field
!= AV_NOPTS_VALUE
&& si
.last_field
!= AV_NOPTS_VALUE
)
320 st
->duration
= si
.last_field
- si
.first_field
;
323 av_log(s
, AV_LOG_ERROR
, "invalid track description length specified\n");
325 url_fskip(pb
, map_len
);
326 if (!parse_packet_header(pb
, &pkt_type
, &len
)) {
327 av_log(s
, AV_LOG_ERROR
, "sync lost in header\n");
330 if (pkt_type
== PKT_FLT
) {
331 gxf_read_index(s
, len
);
332 if (!parse_packet_header(pb
, &pkt_type
, &len
)) {
333 av_log(s
, AV_LOG_ERROR
, "sync lost in header\n");
337 if (pkt_type
== PKT_UMF
) {
341 url_fskip(pb
, 5); // preamble
342 url_fskip(pb
, 0x30); // payload description
343 fps
= fps_umf2avr(get_le32(pb
));
344 if (!main_timebase
.num
|| !main_timebase
.den
) {
345 // this may not always be correct, but simply the best we can get
346 main_timebase
.num
= fps
.den
;
347 main_timebase
.den
= fps
.num
;
350 av_log(s
, AV_LOG_INFO
, "UMF packet too short\n");
352 av_log(s
, AV_LOG_INFO
, "UMF packet missing\n");
354 if (!main_timebase
.num
|| !main_timebase
.den
)
355 main_timebase
= (AVRational
){1, 50}; // set some arbitrary fallback
356 for (i
= 0; i
< s
->nb_streams
; i
++) {
357 AVStream
*st
= s
->streams
[i
];
358 av_set_pts_info(st
, 32, main_timebase
.num
, main_timebase
.den
);
365 if (!max_interval-- || url_feof(pb)) \
367 tmp = tmp << 8 | get_byte(pb); \
371 * \brief resync the stream on the next media packet with specified properties
372 * \param max_interval how many bytes to search for matching packet at most
373 * \param track track id the media packet must belong to, -1 for any
374 * \param timestamp minimum timestamp (== field number) the packet must have, -1 for any
375 * \return timestamp of packet found
377 static int64_t gxf_resync_media(AVFormatContext
*s
, uint64_t max_interval
, int track
, int timestamp
) {
380 uint64_t last_found_pos
= 0;
382 int64_t cur_timestamp
= AV_NOPTS_VALUE
;
384 ByteIOContext
*pb
= s
->pb
;
393 last_pos
= url_ftell(pb
);
394 url_fseek(pb
, -5, SEEK_CUR
);
395 if (!parse_packet_header(pb
, &type
, &len
) || type
!= PKT_MEDIA
) {
396 url_fseek(pb
, last_pos
, SEEK_SET
);
400 cur_track
= get_byte(pb
);
401 cur_timestamp
= get_be32(pb
);
402 last_found_pos
= url_ftell(pb
) - 16 - 6;
403 if ((track
>= 0 && track
!= cur_track
) || (timestamp
>= 0 && timestamp
> cur_timestamp
)) {
404 url_fseek(pb
, last_pos
, SEEK_SET
);
409 url_fseek(pb
, last_found_pos
, SEEK_SET
);
410 return cur_timestamp
;
413 static int gxf_packet(AVFormatContext
*s
, AVPacket
*pkt
) {
414 ByteIOContext
*pb
= s
->pb
;
417 while (!url_feof(pb
)) {
419 int track_type
, track_id
, ret
;
420 int field_nr
, field_info
, skip
= 0;
422 if (!parse_packet_header(pb
, &pkt_type
, &pkt_len
)) {
424 av_log(s
, AV_LOG_ERROR
, "sync lost\n");
427 if (pkt_type
== PKT_FLT
) {
428 gxf_read_index(s
, pkt_len
);
431 if (pkt_type
!= PKT_MEDIA
) {
432 url_fskip(pb
, pkt_len
);
436 av_log(s
, AV_LOG_ERROR
, "invalid media packet length\n");
440 track_type
= get_byte(pb
);
441 track_id
= get_byte(pb
);
442 stream_index
= get_sindex(s
, track_id
, track_type
);
443 if (stream_index
< 0)
445 st
= s
->streams
[stream_index
];
446 field_nr
= get_be32(pb
);
447 field_info
= get_be32(pb
);
448 get_be32(pb
); // "timeline" field number
449 get_byte(pb
); // flags
450 get_byte(pb
); // reserved
451 if (st
->codec
->codec_id
== CODEC_ID_PCM_S24LE
||
452 st
->codec
->codec_id
== CODEC_ID_PCM_S16LE
) {
453 int first
= field_info
>> 16;
454 int last
= field_info
& 0xffff; // last is exclusive
455 int bps
= av_get_bits_per_sample(st
->codec
->codec_id
)>>3;
456 if (first
<= last
&& last
*bps
<= pkt_len
) {
457 url_fskip(pb
, first
*bps
);
458 skip
= pkt_len
- last
*bps
;
459 pkt_len
= (last
-first
)*bps
;
461 av_log(s
, AV_LOG_ERROR
, "invalid first and last sample values\n");
463 ret
= av_get_packet(pb
, pkt
, pkt_len
);
466 pkt
->stream_index
= stream_index
;
473 static int gxf_seek(AVFormatContext
*s
, int stream_index
, int64_t timestamp
, int flags
) {
475 uint64_t maxlen
= 100 * 1024 * 1024;
476 AVStream
*st
= s
->streams
[0];
477 int64_t start_time
= s
->streams
[stream_index
]->start_time
;
480 if (timestamp
< start_time
) timestamp
= start_time
;
481 idx
= av_index_search_timestamp(st
, timestamp
- start_time
,
482 AVSEEK_FLAG_ANY
| AVSEEK_FLAG_BACKWARD
);
485 pos
= st
->index_entries
[idx
].pos
;
486 if (idx
< st
->nb_index_entries
- 2)
487 maxlen
= st
->index_entries
[idx
+ 2].pos
- pos
;
488 maxlen
= FFMAX(maxlen
, 200 * 1024);
489 url_fseek(s
->pb
, pos
, SEEK_SET
);
490 found
= gxf_resync_media(s
, maxlen
, -1, timestamp
);
491 if (FFABS(found
- timestamp
) > 4)
496 static int64_t gxf_read_timestamp(AVFormatContext
*s
, int stream_index
,
497 int64_t *pos
, int64_t pos_limit
) {
498 ByteIOContext
*pb
= s
->pb
;
500 url_fseek(pb
, *pos
, SEEK_SET
);
501 res
= gxf_resync_media(s
, pos_limit
- *pos
, -1, -1);
502 *pos
= url_ftell(pb
);
506 AVInputFormat gxf_demuxer
= {
508 NULL_IF_CONFIG_SMALL("GXF format"),