Minor resync optimization
[ffmpeg.git] / libavformat / gxf.c
1 /*
2  * GXF demuxer.
3  * Copyright (c) 2006 Reimar Doeffinger.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 #include "avformat.h"
20 #include "common.h"
21
22 typedef enum {
23     PKT_MAP = 0xbc,
24     PKT_MEDIA = 0xbf,
25     PKT_EOS = 0xfb,
26     PKT_FLT = 0xfc,
27     PKT_UMF = 0xfd
28 } pkt_type_t;
29
30 typedef enum {
31     MAT_NAME = 0x40,
32     MAT_FIRST_FIELD = 0x41,
33     MAT_LAST_FIELD = 0x42,
34     MAT_MARK_IN = 0x43,
35     MAT_MARK_OUT = 0x44,
36     MAT_SIZE = 0x45
37 } mat_tag_t;
38
39 typedef enum {
40     TRACK_NAME = 0x4c,
41     TRACK_AUX = 0x4d,
42     TRACK_VER = 0x4e,
43     TRACK_MPG_AUX = 0x4f,
44     TRACK_FPS = 0x50,
45     TRACK_LINES = 0x51,
46     TRACK_FPF = 0x52
47 } track_tag_t;
48
49 typedef struct {
50     int64_t first_field;
51     int64_t last_field;
52     AVRational frames_per_second;
53     int32_t fields_per_frame;
54 } st_info_t;
55
56 /**
57  * \brief parses a packet header, extracting type and length
58  * \param pb ByteIOContext to read header from
59  * \param type detected packet type is stored here
60  * \param length detected packet length, excluding header is stored here
61  * \return 0 if header not found or contains invalid data, 1 otherwise
62  */
63 static int parse_packet_header(ByteIOContext *pb, pkt_type_t *type, int *length) {
64     if (get_be32(pb))
65         return 0;
66     if (get_byte(pb) != 1)
67         return 0;
68     *type = get_byte(pb);
69     *length = get_be32(pb);
70     if ((*length >> 24) || *length < 16)
71         return 0;
72     *length -= 16;
73     if (get_be32(pb))
74         return 0;
75     if (get_byte(pb) != 0xe1)
76         return 0;
77     if (get_byte(pb) != 0xe2)
78         return 0;
79     return 1;
80 }
81
82 /**
83  * \brief check if file starts with a PKT_MAP header
84  */
85 static int gxf_probe(AVProbeData *p) {
86     static const uint8_t startcode[] = {0, 0, 0, 0, 1, 0xbc}; // start with map packet
87     static const uint8_t endcode[] = {0, 0, 0, 0, 0xe1, 0xe2};
88     if (p->buf_size < 16)
89         return 0;
90     if (!memcmp(p->buf, startcode, sizeof(startcode)) &&
91         !memcmp(&p->buf[16 - sizeof(endcode)], endcode, sizeof(endcode)))
92         return AVPROBE_SCORE_MAX;
93     return 0;
94 }
95
96 /**
97  * \brief gets the stream index for the track with the specified id, creates new
98  *        stream if not found
99  * \param stream id of stream to find / add
100  * \param format stream format identifier
101  */
102 static int get_sindex(AVFormatContext *s, int id, int format) {
103     int i;
104     AVStream *st = NULL;
105     for (i = 0; i < s->nb_streams; i++) {
106         if (s->streams[i]->id == id)
107             return i;
108     }
109     st = av_new_stream(s, id);
110     switch (format) {
111         case 3:
112         case 4:
113             st->codec->codec_type = CODEC_TYPE_VIDEO;
114             st->codec->codec_id = CODEC_ID_MJPEG;
115             break;
116         case 13:
117         case 15:
118             st->codec->codec_type = CODEC_TYPE_VIDEO;
119             st->codec->codec_id = CODEC_ID_DVVIDEO;
120             break;
121         case 14:
122         case 16:
123             st->codec->codec_type = CODEC_TYPE_VIDEO;
124             st->codec->codec_id = CODEC_ID_DVVIDEO;
125             break;
126         case 11:
127         case 12:
128         case 20:
129             st->codec->codec_type = CODEC_TYPE_VIDEO;
130             st->codec->codec_id = CODEC_ID_MPEG2VIDEO;
131             break;
132         case 22:
133         case 23:
134             st->codec->codec_type = CODEC_TYPE_VIDEO;
135             st->codec->codec_id = CODEC_ID_MPEG1VIDEO;
136             break;
137         case 9:
138             st->codec->codec_type = CODEC_TYPE_AUDIO;
139             st->codec->codec_id = CODEC_ID_PCM_S24LE;
140             st->codec->codec_tag = 0x1;
141             st->codec->channels = 1;
142             st->codec->sample_rate = 48000;
143             st->codec->bit_rate = 3 * 1 * 48000 * 8;
144             st->codec->block_align = 3 * 1;
145             st->codec->bits_per_sample = 24;
146             break;
147         case 10:
148             st->codec->codec_type = CODEC_TYPE_AUDIO;
149             st->codec->codec_id = CODEC_ID_PCM_S16LE;
150             st->codec->codec_tag = 0x1;
151             st->codec->channels = 1;
152             st->codec->sample_rate = 48000;
153             st->codec->bit_rate = 2 * 1 * 48000 * 8;
154             st->codec->block_align = 2 * 1;
155             st->codec->bits_per_sample = 16;
156             break;
157         case 17:
158             st->codec->codec_type = CODEC_TYPE_AUDIO;
159             st->codec->codec_id = CODEC_ID_AC3;
160             st->codec->codec_tag = 0x2000;
161             st->codec->channels = 2;
162             st->codec->sample_rate = 48000;
163             break;
164         default:
165             st->codec->codec_type = CODEC_TYPE_UNKNOWN;
166             st->codec->codec_id = CODEC_ID_NONE;
167             break;
168     }
169     return s->nb_streams - 1;
170 }
171
172 /**
173  * \brief filters out interesting tags from material information.
174  * \param len lenght of tag section, will be adjusted to contain remaining bytes
175  * \param si struct to store collected information into
176  */
177 static void gxf_material_tags(ByteIOContext *pb, int *len, st_info_t *si) {
178     si->first_field = AV_NOPTS_VALUE;
179     si->last_field = AV_NOPTS_VALUE;
180     while (*len >= 2) {
181         mat_tag_t tag = get_byte(pb);
182         int tlen = get_byte(pb);
183         *len -= 2;
184         if (tlen > *len)
185             return;
186         *len -= tlen;
187         if (tlen == 4) {
188             uint32_t value = get_be32(pb);
189             if (tag == MAT_FIRST_FIELD)
190                 si->first_field = value;
191             else if (tag == MAT_LAST_FIELD)
192                 si->last_field = value;
193         } else
194             url_fskip(pb, tlen);
195     }
196 }
197
198 /**
199  * \brief convert fps tag value to AVRational fps
200  * \param fps fps value from tag
201  * \return fps as AVRational, or 0 / 0 if unknown
202  */
203 static AVRational fps_tag2avr(int32_t fps) {
204     extern const AVRational ff_frame_rate_tab[];
205     if (fps < 1 || fps > 9) fps = 9;
206     return ff_frame_rate_tab[9 - fps]; // values have opposite order
207 }
208
209 /**
210  * \brief convert UMF attributes flags to AVRational fps
211  * \param fps fps value from flags
212  * \return fps as AVRational, or 0 / 0 if unknown
213  */
214 static AVRational fps_umf2avr(uint32_t flags) {
215     static const AVRational map[] = {{50, 1}, {60000, 1001}, {24, 1},
216         {25, 1}, {30000, 1001}};
217     int idx =  av_log2((flags & 0x7c0) >> 6);
218     return map[idx];
219 }
220
221 /**
222  * \brief filters out interesting tags from track information.
223  * \param len length of tag section, will be adjusted to contain remaining bytes
224  * \param si struct to store collected information into
225  */
226 static void gxf_track_tags(ByteIOContext *pb, int *len, st_info_t *si) {
227     si->frames_per_second = (AVRational){0, 0};
228     si->fields_per_frame = 0;
229     while (*len >= 2) {
230         track_tag_t tag = get_byte(pb);
231         int tlen = get_byte(pb);
232         *len -= 2;
233         if (tlen > *len)
234             return;
235         *len -= tlen;
236         if (tlen == 4) {
237             uint32_t value = get_be32(pb);
238             if (tag == TRACK_FPS)
239                 si->frames_per_second = fps_tag2avr(value);
240             else if (tag == TRACK_FPF && (value == 1 || value == 2))
241                 si->fields_per_frame = value;
242         } else
243             url_fskip(pb, tlen);
244     }
245 }
246
247 /**
248  * \brief read index from FLT packet into stream 0 av_index
249  */
250 static void gxf_read_index(AVFormatContext *s, int pkt_len) {
251     ByteIOContext *pb = &s->pb;
252     AVStream *st = s->streams[0];
253     uint32_t fields_per_map = get_le32(pb);
254     uint32_t map_cnt = get_le32(pb);
255     int i;
256     pkt_len -= 8;
257     if (map_cnt > 1000) {
258         av_log(s, AV_LOG_ERROR, "GXF: too many index entries %u (%x)\n", map_cnt, map_cnt);
259         map_cnt = 1000;
260     }
261     if (pkt_len < 4 * map_cnt) {
262         av_log(s, AV_LOG_ERROR, "GXF: invalid index length\n");
263         url_fskip(pb, pkt_len);
264         return;
265     }
266     pkt_len -= 4 * map_cnt;
267     av_add_index_entry(st, 0, 0, 0, 0, 0);
268     for (i = 0; i < map_cnt; i++)
269         av_add_index_entry(st, (uint64_t)get_le32(pb) * 1024,
270                            i * (uint64_t)fields_per_map + 1, 0, 0, 0);
271     url_fskip(pb, pkt_len);
272 }
273
274 static int gxf_header(AVFormatContext *s, AVFormatParameters *ap) {
275     ByteIOContext *pb = &s->pb;
276     pkt_type_t pkt_type;
277     int map_len;
278     int len;
279     AVRational main_timebase = {0, 0};
280     st_info_t si;
281     int i;
282     if (!parse_packet_header(pb, &pkt_type, &map_len) || pkt_type != PKT_MAP) {
283         av_log(s, AV_LOG_ERROR, "GXF: map packet not found\n");
284         return 0;
285     }
286     map_len -= 2;
287     if (get_byte(pb) != 0x0e0 || get_byte(pb) != 0xff) {
288         av_log(s, AV_LOG_ERROR, "GXF: unknown version or invalid map preamble\n");
289         return 0;
290     }
291     map_len -= 2;
292     len = get_be16(pb); // length of material data section
293     if (len > map_len) {
294         av_log(s, AV_LOG_ERROR, "GXF: material data longer than map data\n");
295         return 0;
296     }
297     map_len -= len;
298     gxf_material_tags(pb, &len, &si);
299     url_fskip(pb, len);
300     map_len -= 2;
301     len = get_be16(pb); // length of track description
302     if (len > map_len) {
303         av_log(s, AV_LOG_ERROR, "GXF: track description longer than map data\n");
304         return 0;
305     }
306     map_len -= len;
307     while (len > 0) {
308         int track_type, track_id, track_len;
309         AVStream *st;
310         int idx;
311         len -= 4;
312         track_type = get_byte(pb);
313         track_id = get_byte(pb);
314         track_len = get_be16(pb);
315         len -= track_len;
316         gxf_track_tags(pb, &track_len, &si);
317         url_fskip(pb, track_len);
318         if (!(track_type & 0x80)) {
319            av_log(s, AV_LOG_ERROR, "GXF: invalid track type %x\n", track_type);
320            continue;
321         }
322         track_type &= 0x7f;
323         if ((track_id & 0xc0) != 0xc0) {
324            av_log(s, AV_LOG_ERROR, "GXF: invalid track id %x\n", track_id);
325            continue;
326         }
327         track_id &= 0x3f;
328         idx = get_sindex(s, track_id, track_type);
329         if (idx < 0) continue;
330         st = s->streams[idx];
331         if (!main_timebase.num || !main_timebase.den) {
332             main_timebase.num = si.frames_per_second.den;
333             main_timebase.den = si.frames_per_second.num * si.fields_per_frame;
334         }
335         st->start_time = si.first_field;
336         if (si.first_field != AV_NOPTS_VALUE && si.last_field != AV_NOPTS_VALUE)
337             st->duration = si.last_field - si.first_field;
338     }
339     if (len < 0)
340         av_log(s, AV_LOG_ERROR, "GXF: invalid track description length specified\n");
341     if (map_len)
342         url_fskip(pb, map_len);
343     if (!parse_packet_header(pb, &pkt_type, &len)) {
344         av_log(s, AV_LOG_ERROR, "GXF: sync lost in header\n");
345         return -1;
346     }
347     if (pkt_type == PKT_FLT) {
348         gxf_read_index(s, len);
349         if (!parse_packet_header(pb, &pkt_type, &len)) {
350             av_log(s, AV_LOG_ERROR, "GXF: sync lost in header\n");
351             return -1;
352         }
353     }
354     if (pkt_type == PKT_UMF) {
355         if (len >= 9) {
356             AVRational fps;
357             len -= 9;
358             url_fskip(pb, 5);
359             fps = fps_umf2avr(get_le32(pb));
360             if (!main_timebase.num || !main_timebase.den) {
361                 // this may not always be correct, but simply the best we can get
362                 main_timebase.num = fps.den;
363                 main_timebase.den = fps.num;
364             }
365         } else
366             av_log(s, AV_LOG_INFO, "GXF: UMF packet too short\n");
367     } else
368         av_log(s, AV_LOG_INFO, "GXF: UMF packet missing\n");
369     url_fskip(pb, len);
370     for (i = 0; i < s->nb_streams; i++) {
371         AVStream *st = s->streams[i];
372         if (main_timebase.num && main_timebase.den)
373             st->time_base = main_timebase;
374         else {
375             st->start_time = st->duration = AV_NOPTS_VALUE;
376         }
377     }
378     return 0;
379 }
380
381 #define READ_ONE() \
382     { \
383         if (!max_interval-- || url_feof(pb)) \
384             goto out; \
385         tmp = tmp << 8 | get_byte(pb); \
386     }
387
388 /**
389  * \brief resync the stream on the next media packet with specified properties
390  * \param max_interval how many bytes to search for matching packet at most
391  * \param track track id the media packet must belong to, -1 for any
392  * \param timestamp minimum timestamp (== field number) the packet must have, -1 for any
393  * \return timestamp of packet found
394  */
395 static int64_t gxf_resync_media(AVFormatContext *s, uint64_t max_interval, int track, int timestamp) {
396     uint32_t tmp;
397     uint64_t last_pos;
398     uint64_t last_found_pos = 0;
399     int cur_track;
400     int64_t cur_timestamp = AV_NOPTS_VALUE;
401     int len;
402     ByteIOContext *pb = &s->pb;
403     pkt_type_t type;
404     tmp = get_be32(pb);
405 start:
406     while (tmp)
407         READ_ONE();
408     READ_ONE();
409     if (tmp != 1)
410         goto start;
411     last_pos = url_ftell(pb);
412     url_fseek(pb, -5, SEEK_CUR);
413     if (!parse_packet_header(pb, &type, &len) || type != PKT_MEDIA) {
414         url_fseek(pb, last_pos, SEEK_SET);
415         goto start;
416     }
417     get_byte(pb);
418     cur_track = get_byte(pb);
419     cur_timestamp = get_be32(pb);
420     last_found_pos = url_ftell(pb) - 16 - 6;
421     if ((track >= 0 && track != cur_track) || (timestamp >= 0 && timestamp > cur_timestamp)) {
422         url_fseek(pb, last_pos, SEEK_SET);
423         goto start;
424     }
425 out:
426     if (last_found_pos)
427         url_fseek(pb, last_found_pos, SEEK_SET);
428     return cur_timestamp;
429 }
430
431 static int gxf_packet(AVFormatContext *s, AVPacket *pkt) {
432     ByteIOContext *pb = &s->pb;
433     pkt_type_t pkt_type;
434     int pkt_len;
435     while (!url_feof(pb)) {
436         int track_type, track_id, ret;
437         int field_nr;
438         if (!parse_packet_header(pb, &pkt_type, &pkt_len)) {
439             if (!url_feof(pb))
440                 av_log(s, AV_LOG_ERROR, "GXF: sync lost\n");
441             return -1;
442         }
443         if (pkt_type == PKT_FLT) {
444             gxf_read_index(s, pkt_len);
445             continue;
446         }
447         if (pkt_type != PKT_MEDIA) {
448             url_fskip(pb, pkt_len);
449             continue;
450         }
451         if (pkt_len < 16) {
452             av_log(s, AV_LOG_ERROR, "GXF: invalid media packet length\n");
453             continue;
454         }
455         pkt_len -= 16;
456         track_type = get_byte(pb);
457         track_id = get_byte(pb);
458         field_nr = get_be32(pb);
459         get_be32(pb); // field information
460         get_be32(pb); // "timeline" field number
461         get_byte(pb); // flags
462         get_byte(pb); // reserved
463         // NOTE: there is also data length information in the
464         // field information, it might be better to take this into account
465         // as well.
466         ret = av_get_packet(pb, pkt, pkt_len);
467         pkt->stream_index = get_sindex(s, track_id, track_type);
468         pkt->pts = field_nr;
469         return ret;
470     }
471     return AVERROR_IO;
472 }
473
474 static int gxf_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) {
475     uint64_t pos;
476     uint64_t maxlen = 100 * 1024 * 1024;
477     AVStream *st = s->streams[0];
478     int64_t start_time = s->streams[stream_index]->start_time;
479     int64_t found;
480     int idx;
481     if (timestamp < start_time) timestamp = start_time;
482     idx = av_index_search_timestamp(st, timestamp - start_time,
483                                     AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD);
484     if (idx < 0)
485         return -1;
486     pos = st->index_entries[idx].pos;
487     if (idx < st->nb_index_entries - 2)
488         maxlen = st->index_entries[idx + 2].pos - pos;
489     maxlen = FFMAX(maxlen, 200 * 1024);
490     url_fseek(&s->pb, pos, SEEK_SET);
491     found = gxf_resync_media(s, maxlen, -1, timestamp);
492     if (ABS(found - timestamp) > 4)
493         return -1;
494     return 0;
495 }
496
497 static int64_t gxf_read_timestamp(AVFormatContext *s, int stream_index,
498                                   int64_t *pos, int64_t pos_limit) {
499     ByteIOContext *pb = &s->pb;
500     int64_t res;
501     url_fseek(pb, *pos, SEEK_SET);
502     res = gxf_resync_media(s, pos_limit - *pos, -1, -1);
503     *pos = url_ftell(pb);
504     return res;
505 }
506
507 AVInputFormat gxf_demuxer = {
508     "gxf",
509     "GXF format",
510     0,
511     gxf_probe,
512     gxf_header,
513     gxf_packet,
514     NULL,
515     gxf_seek,
516     gxf_read_timestamp,
517 };