FFmpeg
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gxf.c
Go to the documentation of this file.
1 /*
2  * GXF demuxer.
3  * Copyright (c) 2006 Reimar Doeffinger
4  *
5  * This file is part of FFmpeg.
6  *
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.
11  *
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.
16  *
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
20  */
21 
23 #include "libavutil/common.h"
24 #include "avformat.h"
25 #include "internal.h"
26 #include "gxf.h"
27 #include "libavcodec/mpeg12data.h"
28 
30  int64_t first_field;
31  int64_t last_field;
34  int64_t track_aux_data;
35 };
36 
37 /**
38  * @brief parse gxf timecode and add it to metadata
39  */
40 static int add_timecode_metadata(AVDictionary **pm, const char *key, uint32_t timecode, int fields_per_frame)
41 {
42  char tmp[128];
43  int field = timecode & 0xff;
44  int frame = fields_per_frame ? field / fields_per_frame : field;
45  int second = (timecode >> 8) & 0xff;
46  int minute = (timecode >> 16) & 0xff;
47  int hour = (timecode >> 24) & 0x1f;
48  int drop = (timecode >> 29) & 1;
49  // bit 30: color_frame, unused
50  // ignore invalid time code
51  if (timecode >> 31)
52  return 0;
53  snprintf(tmp, sizeof(tmp), "%02d:%02d:%02d%c%02d",
54  hour, minute, second, drop ? ';' : ':', frame);
55  return av_dict_set(pm, key, tmp, 0);
56 }
57 
58 /**
59  * @brief parses a packet header, extracting type and length
60  * @param pb AVIOContext to read header from
61  * @param type detected packet type is stored here
62  * @param length detected packet length, excluding header is stored here
63  * @return 0 if header not found or contains invalid data, 1 otherwise
64  */
65 static int parse_packet_header(AVIOContext *pb, GXFPktType *type, int *length) {
66  if (avio_rb32(pb))
67  return 0;
68  if (avio_r8(pb) != 1)
69  return 0;
70  *type = avio_r8(pb);
71  *length = avio_rb32(pb);
72  if ((*length >> 24) || *length < 16)
73  return 0;
74  *length -= 16;
75  if (avio_rb32(pb))
76  return 0;
77  if (avio_r8(pb) != 0xe1)
78  return 0;
79  if (avio_r8(pb) != 0xe2)
80  return 0;
81  return 1;
82 }
83 
84 /**
85  * @brief check if file starts with a PKT_MAP header
86  */
87 static int gxf_probe(AVProbeData *p) {
88  static const uint8_t startcode[] = {0, 0, 0, 0, 1, 0xbc}; // start with map packet
89  static const uint8_t endcode[] = {0, 0, 0, 0, 0xe1, 0xe2};
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 id 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  i = ff_find_stream_index(s, id);
106  if (i >= 0)
107  return i;
108  st = avformat_new_stream(s, NULL);
109  if (!st)
110  return AVERROR(ENOMEM);
111  st->id = id;
112  switch (format) {
113  case 3:
114  case 4:
117  break;
118  case 13:
119  case 15:
122  break;
123  case 14:
124  case 16:
127  break;
128  case 11:
129  case 12:
130  case 20:
133  st->need_parsing = AVSTREAM_PARSE_HEADERS; //get keyframe flag etc.
134  break;
135  case 22:
136  case 23:
139  st->need_parsing = AVSTREAM_PARSE_HEADERS; //get keyframe flag etc.
140  break;
141  case 9:
144  st->codec->channels = 1;
146  st->codec->sample_rate = 48000;
147  st->codec->bit_rate = 3 * 1 * 48000 * 8;
148  st->codec->block_align = 3 * 1;
149  st->codec->bits_per_coded_sample = 24;
150  break;
151  case 10:
154  st->codec->channels = 1;
156  st->codec->sample_rate = 48000;
157  st->codec->bit_rate = 2 * 1 * 48000 * 8;
158  st->codec->block_align = 2 * 1;
159  st->codec->bits_per_coded_sample = 16;
160  break;
161  case 17:
164  st->codec->channels = 2;
166  st->codec->sample_rate = 48000;
167  break;
168  // timecode tracks:
169  case 7:
170  case 8:
171  case 24:
174  break;
175  default:
178  break;
179  }
180  return s->nb_streams - 1;
181 }
182 
183 /**
184  * @brief filters out interesting tags from material information.
185  * @param len length of tag section, will be adjusted to contain remaining bytes
186  * @param si struct to store collected information into
187  */
188 static void gxf_material_tags(AVIOContext *pb, int *len, struct gxf_stream_info *si) {
191  while (*len >= 2) {
192  GXFMatTag tag = avio_r8(pb);
193  int tlen = avio_r8(pb);
194  *len -= 2;
195  if (tlen > *len)
196  return;
197  *len -= tlen;
198  if (tlen == 4) {
199  uint32_t value = avio_rb32(pb);
200  if (tag == MAT_FIRST_FIELD)
201  si->first_field = value;
202  else if (tag == MAT_LAST_FIELD)
203  si->last_field = value;
204  } else
205  avio_skip(pb, tlen);
206  }
207 }
208 
209 static const AVRational frame_rate_tab[] = {
210  { 60, 1},
211  {60000, 1001},
212  { 50, 1},
213  { 30, 1},
214  {30000, 1001},
215  { 25, 1},
216  { 24, 1},
217  {24000, 1001},
218  { 0, 0},
219 };
220 
221 /**
222  * @brief convert fps tag value to AVRational fps
223  * @param fps fps value from tag
224  * @return fps as AVRational, or 0 / 0 if unknown
225  */
227  if (fps < 1 || fps > 9) fps = 9;
228  return frame_rate_tab[fps - 1];
229 }
230 
231 /**
232  * @brief convert UMF attributes flags to AVRational fps
233  * @param flags UMF flags to convert
234  * @return fps as AVRational, or 0 / 0 if unknown
235  */
236 static AVRational fps_umf2avr(uint32_t flags) {
237  static const AVRational map[] = {{50, 1}, {60000, 1001}, {24, 1},
238  {25, 1}, {30000, 1001}};
239  int idx = av_log2((flags & 0x7c0) >> 6);
240  return map[idx];
241 }
242 
243 /**
244  * @brief filters out interesting tags from track information.
245  * @param len length of tag section, will be adjusted to contain remaining bytes
246  * @param si struct to store collected information into
247  */
248 static void gxf_track_tags(AVIOContext *pb, int *len, struct gxf_stream_info *si) {
249  si->frames_per_second = (AVRational){0, 0};
250  si->fields_per_frame = 0;
251  si->track_aux_data = 0x80000000;
252  while (*len >= 2) {
253  GXFTrackTag tag = avio_r8(pb);
254  int tlen = avio_r8(pb);
255  *len -= 2;
256  if (tlen > *len)
257  return;
258  *len -= tlen;
259  if (tlen == 4) {
260  uint32_t value = avio_rb32(pb);
261  if (tag == TRACK_FPS)
262  si->frames_per_second = fps_tag2avr(value);
263  else if (tag == TRACK_FPF && (value == 1 || value == 2))
264  si->fields_per_frame = value;
265  } else if (tlen == 8 && tag == TRACK_AUX)
266  si->track_aux_data = avio_rl64(pb);
267  else
268  avio_skip(pb, tlen);
269  }
270 }
271 
272 /**
273  * @brief read index from FLT packet into stream 0 av_index
274  */
275 static void gxf_read_index(AVFormatContext *s, int pkt_len) {
276  AVIOContext *pb = s->pb;
277  AVStream *st;
278  uint32_t fields_per_map = avio_rl32(pb);
279  uint32_t map_cnt = avio_rl32(pb);
280  int i;
281  pkt_len -= 8;
282  if ((s->flags & AVFMT_FLAG_IGNIDX) || !s->streams) {
283  avio_skip(pb, pkt_len);
284  return;
285  }
286  st = s->streams[0];
287  if (map_cnt > 1000) {
288  av_log(s, AV_LOG_ERROR, "too many index entries %u (%x)\n", map_cnt, map_cnt);
289  map_cnt = 1000;
290  }
291  if (pkt_len < 4 * map_cnt) {
292  av_log(s, AV_LOG_ERROR, "invalid index length\n");
293  avio_skip(pb, pkt_len);
294  return;
295  }
296  pkt_len -= 4 * map_cnt;
297  av_add_index_entry(st, 0, 0, 0, 0, 0);
298  for (i = 0; i < map_cnt; i++)
299  av_add_index_entry(st, (uint64_t)avio_rl32(pb) * 1024,
300  i * (uint64_t)fields_per_map + 1, 0, 0, 0);
301  avio_skip(pb, pkt_len);
302 }
303 
304 static int gxf_header(AVFormatContext *s) {
305  AVIOContext *pb = s->pb;
306  GXFPktType pkt_type;
307  int map_len;
308  int len;
309  AVRational main_timebase = {0, 0};
310  struct gxf_stream_info *si = s->priv_data;
311  int i;
312  if (!parse_packet_header(pb, &pkt_type, &map_len) || pkt_type != PKT_MAP) {
313  av_log(s, AV_LOG_ERROR, "map packet not found\n");
314  return 0;
315  }
316  map_len -= 2;
317  if (avio_r8(pb) != 0x0e0 || avio_r8(pb) != 0xff) {
318  av_log(s, AV_LOG_ERROR, "unknown version or invalid map preamble\n");
319  return 0;
320  }
321  map_len -= 2;
322  len = avio_rb16(pb); // length of material data section
323  if (len > map_len) {
324  av_log(s, AV_LOG_ERROR, "material data longer than map data\n");
325  return 0;
326  }
327  map_len -= len;
328  gxf_material_tags(pb, &len, si);
329  avio_skip(pb, len);
330  map_len -= 2;
331  len = avio_rb16(pb); // length of track description
332  if (len > map_len) {
333  av_log(s, AV_LOG_ERROR, "track description longer than map data\n");
334  return 0;
335  }
336  map_len -= len;
337  while (len > 0) {
338  int track_type, track_id, track_len;
339  AVStream *st;
340  int idx;
341  len -= 4;
342  track_type = avio_r8(pb);
343  track_id = avio_r8(pb);
344  track_len = avio_rb16(pb);
345  len -= track_len;
346  if (!(track_type & 0x80)) {
347  av_log(s, AV_LOG_ERROR, "invalid track type %x\n", track_type);
348  continue;
349  }
350  track_type &= 0x7f;
351  if ((track_id & 0xc0) != 0xc0) {
352  av_log(s, AV_LOG_ERROR, "invalid track id %x\n", track_id);
353  continue;
354  }
355  track_id &= 0x3f;
356  gxf_track_tags(pb, &track_len, si);
357  // check for timecode tracks
358  if (track_type == 7 || track_type == 8 || track_type == 24) {
359  add_timecode_metadata(&s->metadata, "timecode",
360  si->track_aux_data & 0xffffffff,
361  si->fields_per_frame);
362 
363  }
364  avio_skip(pb, track_len);
365 
366  idx = get_sindex(s, track_id, track_type);
367  if (idx < 0) continue;
368  st = s->streams[idx];
369  if (!main_timebase.num || !main_timebase.den) {
370  main_timebase.num = si->frames_per_second.den;
371  main_timebase.den = si->frames_per_second.num * 2;
372  }
373  st->start_time = si->first_field;
375  st->duration = si->last_field - si->first_field;
376  }
377  if (len < 0)
378  av_log(s, AV_LOG_ERROR, "invalid track description length specified\n");
379  if (map_len)
380  avio_skip(pb, map_len);
381  if (!parse_packet_header(pb, &pkt_type, &len)) {
382  av_log(s, AV_LOG_ERROR, "sync lost in header\n");
383  return -1;
384  }
385  if (pkt_type == PKT_FLT) {
386  gxf_read_index(s, len);
387  if (!parse_packet_header(pb, &pkt_type, &len)) {
388  av_log(s, AV_LOG_ERROR, "sync lost in header\n");
389  return -1;
390  }
391  }
392  if (pkt_type == PKT_UMF) {
393  if (len >= 0x39) {
394  AVRational fps;
395  len -= 0x39;
396  avio_skip(pb, 5); // preamble
397  avio_skip(pb, 0x30); // payload description
398  fps = fps_umf2avr(avio_rl32(pb));
399  if (!main_timebase.num || !main_timebase.den) {
400  av_log(s, AV_LOG_WARNING, "No FPS track tag, using UMF fps tag."
401  " This might give wrong results.\n");
402  // this may not always be correct, but simply the best we can get
403  main_timebase.num = fps.den;
404  main_timebase.den = fps.num * 2;
405  }
406 
407  if (len >= 0x18) {
408  len -= 0x18;
409  avio_skip(pb, 0x10);
410  add_timecode_metadata(&s->metadata, "timecode_at_mark_in",
411  avio_rl32(pb), si->fields_per_frame);
412  add_timecode_metadata(&s->metadata, "timecode_at_mark_out",
413  avio_rl32(pb), si->fields_per_frame);
414  }
415  } else
416  av_log(s, AV_LOG_INFO, "UMF packet too short\n");
417  } else
418  av_log(s, AV_LOG_INFO, "UMF packet missing\n");
419  avio_skip(pb, len);
420  // set a fallback value, 60000/1001 is specified for audio-only files
421  // so use that regardless of why we do not know the video frame rate.
422  if (!main_timebase.num || !main_timebase.den)
423  main_timebase = (AVRational){1001, 60000};
424  for (i = 0; i < s->nb_streams; i++) {
425  AVStream *st = s->streams[i];
426  avpriv_set_pts_info(st, 32, main_timebase.num, main_timebase.den);
427  }
428  return 0;
429 }
430 
431 #define READ_ONE() \
432  { \
433  if (!max_interval-- || url_feof(pb)) \
434  goto out; \
435  tmp = tmp << 8 | avio_r8(pb); \
436  }
437 
438 /**
439  * @brief resync the stream on the next media packet with specified properties
440  * @param max_interval how many bytes to search for matching packet at most
441  * @param track track id the media packet must belong to, -1 for any
442  * @param timestamp minimum timestamp (== field number) the packet must have, -1 for any
443  * @return timestamp of packet found
444  */
445 static int64_t gxf_resync_media(AVFormatContext *s, uint64_t max_interval, int track, int timestamp) {
446  uint32_t tmp;
447  uint64_t last_pos;
448  uint64_t last_found_pos = 0;
449  int cur_track;
450  int64_t cur_timestamp = AV_NOPTS_VALUE;
451  int len;
452  AVIOContext *pb = s->pb;
453  GXFPktType type;
454  tmp = avio_rb32(pb);
455 start:
456  while (tmp)
457  READ_ONE();
458  READ_ONE();
459  if (tmp != 1)
460  goto start;
461  last_pos = avio_tell(pb);
462  if (avio_seek(pb, -5, SEEK_CUR) < 0)
463  goto out;
464  if (!parse_packet_header(pb, &type, &len) || type != PKT_MEDIA) {
465  if (avio_seek(pb, last_pos, SEEK_SET) < 0)
466  goto out;
467  goto start;
468  }
469  avio_r8(pb);
470  cur_track = avio_r8(pb);
471  cur_timestamp = avio_rb32(pb);
472  last_found_pos = avio_tell(pb) - 16 - 6;
473  if ((track >= 0 && track != cur_track) || (timestamp >= 0 && timestamp > cur_timestamp)) {
474  if (avio_seek(pb, last_pos, SEEK_SET) >= 0)
475  goto start;
476  }
477 out:
478  if (last_found_pos)
479  avio_seek(pb, last_found_pos, SEEK_SET);
480  return cur_timestamp;
481 }
482 
484  AVIOContext *pb = s->pb;
485  GXFPktType pkt_type;
486  int pkt_len;
487  struct gxf_stream_info *si = s->priv_data;
488 
489  while (!pb->eof_reached) {
490  AVStream *st;
491  int track_type, track_id, ret;
492  int field_nr, field_info, skip = 0;
493  int stream_index;
494  if (!parse_packet_header(pb, &pkt_type, &pkt_len)) {
495  if (!url_feof(pb))
496  av_log(s, AV_LOG_ERROR, "sync lost\n");
497  return -1;
498  }
499  if (pkt_type == PKT_FLT) {
500  gxf_read_index(s, pkt_len);
501  continue;
502  }
503  if (pkt_type != PKT_MEDIA) {
504  avio_skip(pb, pkt_len);
505  continue;
506  }
507  if (pkt_len < 16) {
508  av_log(s, AV_LOG_ERROR, "invalid media packet length\n");
509  continue;
510  }
511  pkt_len -= 16;
512  track_type = avio_r8(pb);
513  track_id = avio_r8(pb);
514  stream_index = get_sindex(s, track_id, track_type);
515  if (stream_index < 0)
516  return stream_index;
517  st = s->streams[stream_index];
518  field_nr = avio_rb32(pb);
519  field_info = avio_rb32(pb);
520  avio_rb32(pb); // "timeline" field number
521  avio_r8(pb); // flags
522  avio_r8(pb); // reserved
523  if (st->codec->codec_id == AV_CODEC_ID_PCM_S24LE ||
525  int first = field_info >> 16;
526  int last = field_info & 0xffff; // last is exclusive
527  int bps = av_get_bits_per_sample(st->codec->codec_id)>>3;
528  if (first <= last && last*bps <= pkt_len) {
529  avio_skip(pb, first*bps);
530  skip = pkt_len - last*bps;
531  pkt_len = (last-first)*bps;
532  } else
533  av_log(s, AV_LOG_ERROR, "invalid first and last sample values\n");
534  }
535  ret = av_get_packet(pb, pkt, pkt_len);
536  if (skip)
537  avio_skip(pb, skip);
538  pkt->stream_index = stream_index;
539  pkt->dts = field_nr;
540 
541  //set duration manually for DV or else lavf misdetects the frame rate
542  if (st->codec->codec_id == AV_CODEC_ID_DVVIDEO)
543  pkt->duration = si->fields_per_frame;
544 
545  return ret;
546  }
547  return AVERROR_EOF;
548 }
549 
550 static int gxf_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) {
551  int res = 0;
552  uint64_t pos;
553  uint64_t maxlen = 100 * 1024 * 1024;
554  AVStream *st = s->streams[0];
555  int64_t start_time = s->streams[stream_index]->start_time;
556  int64_t found;
557  int idx;
558  if (timestamp < start_time) timestamp = start_time;
559  idx = av_index_search_timestamp(st, timestamp - start_time,
561  if (idx < 0)
562  return -1;
563  pos = st->index_entries[idx].pos;
564  if (idx < st->nb_index_entries - 2)
565  maxlen = st->index_entries[idx + 2].pos - pos;
566  maxlen = FFMAX(maxlen, 200 * 1024);
567  res = avio_seek(s->pb, pos, SEEK_SET);
568  if (res < 0)
569  return res;
570  found = gxf_resync_media(s, maxlen, -1, timestamp);
571  if (FFABS(found - timestamp) > 4)
572  return -1;
573  return 0;
574 }
575 
576 static int64_t gxf_read_timestamp(AVFormatContext *s, int stream_index,
577  int64_t *pos, int64_t pos_limit) {
578  AVIOContext *pb = s->pb;
579  int64_t res;
580  if (avio_seek(pb, *pos, SEEK_SET) < 0)
581  return AV_NOPTS_VALUE;
582  res = gxf_resync_media(s, pos_limit - *pos, -1, -1);
583  *pos = avio_tell(pb);
584  return res;
585 }
586 
588  .name = "gxf",
589  .long_name = NULL_IF_CONFIG_SMALL("GXF (General eXchange Format)"),
590  .priv_data_size = sizeof(struct gxf_stream_info),
591  .read_probe = gxf_probe,
592  .read_header = gxf_header,
593  .read_packet = gxf_packet,
594  .read_seek = gxf_seek,
595  .read_timestamp = gxf_read_timestamp,
596 };