• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavformat/gxf.c

Go to the documentation of this file.
00001 /*
00002  * GXF demuxer.
00003  * Copyright (c) 2006 Reimar Doeffinger
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00022 #include "libavutil/common.h"
00023 #include "avformat.h"
00024 #include "internal.h"
00025 #include "gxf.h"
00026 
00027 struct gxf_stream_info {
00028     int64_t first_field;
00029     int64_t last_field;
00030     AVRational frames_per_second;
00031     int32_t fields_per_frame;
00032     int64_t track_aux_data;
00033 };
00034 
00038 static int add_timecode_metadata(AVDictionary **pm, const char *key, uint32_t timecode, int fields_per_frame)
00039 {
00040    char tmp[128];
00041    int field  = timecode & 0xff;
00042    int frame  = fields_per_frame ? field / fields_per_frame : field;
00043    int second = (timecode >>  8) & 0xff;
00044    int minute = (timecode >> 16) & 0xff;
00045    int hour   = (timecode >> 24) & 0x1f;
00046    int drop   = (timecode >> 29) & 1;
00047    // bit 30: color_frame, unused
00048    // ignore invalid time code
00049    if (timecode >> 31)
00050        return 0;
00051    snprintf(tmp, sizeof(tmp), "%02d:%02d:%02d%c%02d",
00052        hour, minute, second, drop ? ';' : ':', frame);
00053    return av_dict_set(pm, key, tmp, 0);
00054 }
00055 
00063 static int parse_packet_header(AVIOContext *pb, GXFPktType *type, int *length) {
00064     if (avio_rb32(pb))
00065         return 0;
00066     if (avio_r8(pb) != 1)
00067         return 0;
00068     *type = avio_r8(pb);
00069     *length = avio_rb32(pb);
00070     if ((*length >> 24) || *length < 16)
00071         return 0;
00072     *length -= 16;
00073     if (avio_rb32(pb))
00074         return 0;
00075     if (avio_r8(pb) != 0xe1)
00076         return 0;
00077     if (avio_r8(pb) != 0xe2)
00078         return 0;
00079     return 1;
00080 }
00081 
00085 static int gxf_probe(AVProbeData *p) {
00086     static const uint8_t startcode[] = {0, 0, 0, 0, 1, 0xbc}; // start with map packet
00087     static const uint8_t endcode[] = {0, 0, 0, 0, 0xe1, 0xe2};
00088     if (!memcmp(p->buf, startcode, sizeof(startcode)) &&
00089         !memcmp(&p->buf[16 - sizeof(endcode)], endcode, sizeof(endcode)))
00090         return AVPROBE_SCORE_MAX;
00091     return 0;
00092 }
00093 
00100 static int get_sindex(AVFormatContext *s, int id, int format) {
00101     int i;
00102     AVStream *st = NULL;
00103     i = ff_find_stream_index(s, id);
00104     if (i >= 0)
00105         return i;
00106     st = avformat_new_stream(s, NULL);
00107     if (!st)
00108         return AVERROR(ENOMEM);
00109     st->id = id;
00110     switch (format) {
00111         case 3:
00112         case 4:
00113             st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00114             st->codec->codec_id = CODEC_ID_MJPEG;
00115             break;
00116         case 13:
00117         case 15:
00118             st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00119             st->codec->codec_id = CODEC_ID_DVVIDEO;
00120             break;
00121         case 14:
00122         case 16:
00123             st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00124             st->codec->codec_id = CODEC_ID_DVVIDEO;
00125             break;
00126         case 11:
00127         case 12:
00128         case 20:
00129             st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00130             st->codec->codec_id = CODEC_ID_MPEG2VIDEO;
00131             st->need_parsing = AVSTREAM_PARSE_HEADERS; //get keyframe flag etc.
00132             break;
00133         case 22:
00134         case 23:
00135             st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00136             st->codec->codec_id = CODEC_ID_MPEG1VIDEO;
00137             st->need_parsing = AVSTREAM_PARSE_HEADERS; //get keyframe flag etc.
00138             break;
00139         case 9:
00140             st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00141             st->codec->codec_id = CODEC_ID_PCM_S24LE;
00142             st->codec->channels = 1;
00143             st->codec->sample_rate = 48000;
00144             st->codec->bit_rate = 3 * 1 * 48000 * 8;
00145             st->codec->block_align = 3 * 1;
00146             st->codec->bits_per_coded_sample = 24;
00147             break;
00148         case 10:
00149             st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00150             st->codec->codec_id = CODEC_ID_PCM_S16LE;
00151             st->codec->channels = 1;
00152             st->codec->sample_rate = 48000;
00153             st->codec->bit_rate = 2 * 1 * 48000 * 8;
00154             st->codec->block_align = 2 * 1;
00155             st->codec->bits_per_coded_sample = 16;
00156             break;
00157         case 17:
00158             st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00159             st->codec->codec_id = CODEC_ID_AC3;
00160             st->codec->channels = 2;
00161             st->codec->sample_rate = 48000;
00162             break;
00163         // timecode tracks:
00164         case 7:
00165         case 8:
00166         case 24:
00167             st->codec->codec_type = AVMEDIA_TYPE_DATA;
00168             st->codec->codec_id = CODEC_ID_NONE;
00169             break;
00170         default:
00171             st->codec->codec_type = AVMEDIA_TYPE_UNKNOWN;
00172             st->codec->codec_id = CODEC_ID_NONE;
00173             break;
00174     }
00175     return s->nb_streams - 1;
00176 }
00177 
00183 static void gxf_material_tags(AVIOContext *pb, int *len, struct gxf_stream_info *si) {
00184     si->first_field = AV_NOPTS_VALUE;
00185     si->last_field = AV_NOPTS_VALUE;
00186     while (*len >= 2) {
00187         GXFMatTag tag = avio_r8(pb);
00188         int tlen = avio_r8(pb);
00189         *len -= 2;
00190         if (tlen > *len)
00191             return;
00192         *len -= tlen;
00193         if (tlen == 4) {
00194             uint32_t value = avio_rb32(pb);
00195             if (tag == MAT_FIRST_FIELD)
00196                 si->first_field = value;
00197             else if (tag == MAT_LAST_FIELD)
00198                 si->last_field = value;
00199         } else
00200             avio_skip(pb, tlen);
00201     }
00202 }
00203 
00209 static AVRational fps_tag2avr(int32_t fps) {
00210     extern const AVRational avpriv_frame_rate_tab[];
00211     if (fps < 1 || fps > 9) fps = 9;
00212     return avpriv_frame_rate_tab[9 - fps]; // values have opposite order
00213 }
00214 
00220 static AVRational fps_umf2avr(uint32_t flags) {
00221     static const AVRational map[] = {{50, 1}, {60000, 1001}, {24, 1},
00222         {25, 1}, {30000, 1001}};
00223     int idx =  av_log2((flags & 0x7c0) >> 6);
00224     return map[idx];
00225 }
00226 
00232 static void gxf_track_tags(AVIOContext *pb, int *len, struct gxf_stream_info *si) {
00233     si->frames_per_second = (AVRational){0, 0};
00234     si->fields_per_frame = 0;
00235     si->track_aux_data = 0x80000000;
00236     while (*len >= 2) {
00237         GXFTrackTag tag = avio_r8(pb);
00238         int tlen = avio_r8(pb);
00239         *len -= 2;
00240         if (tlen > *len)
00241             return;
00242         *len -= tlen;
00243         if (tlen == 4) {
00244             uint32_t value = avio_rb32(pb);
00245             if (tag == TRACK_FPS)
00246                 si->frames_per_second = fps_tag2avr(value);
00247             else if (tag == TRACK_FPF && (value == 1 || value == 2))
00248                 si->fields_per_frame = value;
00249         } else if (tlen == 8 && tag == TRACK_AUX)
00250             si->track_aux_data = avio_rl64(pb);
00251         else
00252             avio_skip(pb, tlen);
00253     }
00254 }
00255 
00259 static void gxf_read_index(AVFormatContext *s, int pkt_len) {
00260     AVIOContext *pb = s->pb;
00261     AVStream *st = s->streams[0];
00262     uint32_t fields_per_map = avio_rl32(pb);
00263     uint32_t map_cnt = avio_rl32(pb);
00264     int i;
00265     pkt_len -= 8;
00266     if (s->flags & AVFMT_FLAG_IGNIDX) {
00267         avio_skip(pb, pkt_len);
00268         return;
00269     }
00270     if (map_cnt > 1000) {
00271         av_log(s, AV_LOG_ERROR, "too many index entries %u (%x)\n", map_cnt, map_cnt);
00272         map_cnt = 1000;
00273     }
00274     if (pkt_len < 4 * map_cnt) {
00275         av_log(s, AV_LOG_ERROR, "invalid index length\n");
00276         avio_skip(pb, pkt_len);
00277         return;
00278     }
00279     pkt_len -= 4 * map_cnt;
00280     av_add_index_entry(st, 0, 0, 0, 0, 0);
00281     for (i = 0; i < map_cnt; i++)
00282         av_add_index_entry(st, (uint64_t)avio_rl32(pb) * 1024,
00283                            i * (uint64_t)fields_per_map + 1, 0, 0, 0);
00284     avio_skip(pb, pkt_len);
00285 }
00286 
00287 static int gxf_header(AVFormatContext *s, AVFormatParameters *ap) {
00288     AVIOContext *pb = s->pb;
00289     GXFPktType pkt_type;
00290     int map_len;
00291     int len;
00292     AVRational main_timebase = {0, 0};
00293     struct gxf_stream_info *si = s->priv_data;
00294     int i;
00295     if (!parse_packet_header(pb, &pkt_type, &map_len) || pkt_type != PKT_MAP) {
00296         av_log(s, AV_LOG_ERROR, "map packet not found\n");
00297         return 0;
00298     }
00299     map_len -= 2;
00300     if (avio_r8(pb) != 0x0e0 || avio_r8(pb) != 0xff) {
00301         av_log(s, AV_LOG_ERROR, "unknown version or invalid map preamble\n");
00302         return 0;
00303     }
00304     map_len -= 2;
00305     len = avio_rb16(pb); // length of material data section
00306     if (len > map_len) {
00307         av_log(s, AV_LOG_ERROR, "material data longer than map data\n");
00308         return 0;
00309     }
00310     map_len -= len;
00311     gxf_material_tags(pb, &len, si);
00312     avio_skip(pb, len);
00313     map_len -= 2;
00314     len = avio_rb16(pb); // length of track description
00315     if (len > map_len) {
00316         av_log(s, AV_LOG_ERROR, "track description longer than map data\n");
00317         return 0;
00318     }
00319     map_len -= len;
00320     while (len > 0) {
00321         int track_type, track_id, track_len;
00322         AVStream *st;
00323         int idx;
00324         len -= 4;
00325         track_type = avio_r8(pb);
00326         track_id = avio_r8(pb);
00327         track_len = avio_rb16(pb);
00328         len -= track_len;
00329         if (!(track_type & 0x80)) {
00330            av_log(s, AV_LOG_ERROR, "invalid track type %x\n", track_type);
00331            continue;
00332         }
00333         track_type &= 0x7f;
00334         if ((track_id & 0xc0) != 0xc0) {
00335            av_log(s, AV_LOG_ERROR, "invalid track id %x\n", track_id);
00336            continue;
00337         }
00338         track_id &= 0x3f;
00339         gxf_track_tags(pb, &track_len, si);
00340         // check for timecode tracks
00341         if (track_type == 7 || track_type == 8 || track_type == 24) {
00342             add_timecode_metadata(&s->metadata, "timecode",
00343                                   si->track_aux_data & 0xffffffff,
00344                                   si->fields_per_frame);
00345 
00346         }
00347         avio_skip(pb, track_len);
00348 
00349         idx = get_sindex(s, track_id, track_type);
00350         if (idx < 0) continue;
00351         st = s->streams[idx];
00352         if (!main_timebase.num || !main_timebase.den) {
00353             main_timebase.num = si->frames_per_second.den;
00354             main_timebase.den = si->frames_per_second.num * 2;
00355         }
00356         st->start_time = si->first_field;
00357         if (si->first_field != AV_NOPTS_VALUE && si->last_field != AV_NOPTS_VALUE)
00358             st->duration = si->last_field - si->first_field;
00359     }
00360     if (len < 0)
00361         av_log(s, AV_LOG_ERROR, "invalid track description length specified\n");
00362     if (map_len)
00363         avio_skip(pb, map_len);
00364     if (!parse_packet_header(pb, &pkt_type, &len)) {
00365         av_log(s, AV_LOG_ERROR, "sync lost in header\n");
00366         return -1;
00367     }
00368     if (pkt_type == PKT_FLT) {
00369         gxf_read_index(s, len);
00370         if (!parse_packet_header(pb, &pkt_type, &len)) {
00371             av_log(s, AV_LOG_ERROR, "sync lost in header\n");
00372             return -1;
00373         }
00374     }
00375     if (pkt_type == PKT_UMF) {
00376         if (len >= 0x39) {
00377             AVRational fps;
00378             len -= 0x39;
00379             avio_skip(pb, 5); // preamble
00380             avio_skip(pb, 0x30); // payload description
00381             fps = fps_umf2avr(avio_rl32(pb));
00382             if (!main_timebase.num || !main_timebase.den) {
00383                 av_log(s, AV_LOG_WARNING, "No FPS track tag, using UMF fps tag."
00384                                           " This might give wrong results.\n");
00385                 // this may not always be correct, but simply the best we can get
00386                 main_timebase.num = fps.den;
00387                 main_timebase.den = fps.num * 2;
00388             }
00389 
00390             if (len >= 0x18) {
00391                 len -= 0x18;
00392                 avio_skip(pb, 0x10);
00393                 add_timecode_metadata(&s->metadata, "timecode_at_mark_in",
00394                                       avio_rl32(pb), si->fields_per_frame);
00395                 add_timecode_metadata(&s->metadata, "timecode_at_mark_out",
00396                                       avio_rl32(pb), si->fields_per_frame);
00397             }
00398         } else
00399             av_log(s, AV_LOG_INFO, "UMF packet too short\n");
00400     } else
00401         av_log(s, AV_LOG_INFO, "UMF packet missing\n");
00402     avio_skip(pb, len);
00403     // set a fallback value, 60000/1001 is specified for audio-only files
00404     // so use that regardless of why we do not know the video frame rate.
00405     if (!main_timebase.num || !main_timebase.den)
00406         main_timebase = (AVRational){1001, 60000};
00407     for (i = 0; i < s->nb_streams; i++) {
00408         AVStream *st = s->streams[i];
00409         avpriv_set_pts_info(st, 32, main_timebase.num, main_timebase.den);
00410     }
00411     return 0;
00412 }
00413 
00414 #define READ_ONE() \
00415     { \
00416         if (!max_interval-- || url_feof(pb)) \
00417             goto out; \
00418         tmp = tmp << 8 | avio_r8(pb); \
00419     }
00420 
00428 static int64_t gxf_resync_media(AVFormatContext *s, uint64_t max_interval, int track, int timestamp) {
00429     uint32_t tmp;
00430     uint64_t last_pos;
00431     uint64_t last_found_pos = 0;
00432     int cur_track;
00433     int64_t cur_timestamp = AV_NOPTS_VALUE;
00434     int len;
00435     AVIOContext *pb = s->pb;
00436     GXFPktType type;
00437     tmp = avio_rb32(pb);
00438 start:
00439     while (tmp)
00440         READ_ONE();
00441     READ_ONE();
00442     if (tmp != 1)
00443         goto start;
00444     last_pos = avio_tell(pb);
00445     if (avio_seek(pb, -5, SEEK_CUR) < 0)
00446         goto out;
00447     if (!parse_packet_header(pb, &type, &len) || type != PKT_MEDIA) {
00448         if (avio_seek(pb, last_pos, SEEK_SET) < 0)
00449             goto out;
00450         goto start;
00451     }
00452     avio_r8(pb);
00453     cur_track = avio_r8(pb);
00454     cur_timestamp = avio_rb32(pb);
00455     last_found_pos = avio_tell(pb) - 16 - 6;
00456     if ((track >= 0 && track != cur_track) || (timestamp >= 0 && timestamp > cur_timestamp)) {
00457         if (avio_seek(pb, last_pos, SEEK_SET) >= 0)
00458             goto start;
00459     }
00460 out:
00461     if (last_found_pos)
00462         avio_seek(pb, last_found_pos, SEEK_SET);
00463     return cur_timestamp;
00464 }
00465 
00466 static int gxf_packet(AVFormatContext *s, AVPacket *pkt) {
00467     AVIOContext *pb = s->pb;
00468     GXFPktType pkt_type;
00469     int pkt_len;
00470     struct gxf_stream_info *si = s->priv_data;
00471 
00472     while (!pb->eof_reached) {
00473         AVStream *st;
00474         int track_type, track_id, ret;
00475         int field_nr, field_info, skip = 0;
00476         int stream_index;
00477         if (!parse_packet_header(pb, &pkt_type, &pkt_len)) {
00478             if (!url_feof(pb))
00479                 av_log(s, AV_LOG_ERROR, "sync lost\n");
00480             return -1;
00481         }
00482         if (pkt_type == PKT_FLT) {
00483             gxf_read_index(s, pkt_len);
00484             continue;
00485         }
00486         if (pkt_type != PKT_MEDIA) {
00487             avio_skip(pb, pkt_len);
00488             continue;
00489         }
00490         if (pkt_len < 16) {
00491             av_log(s, AV_LOG_ERROR, "invalid media packet length\n");
00492             continue;
00493         }
00494         pkt_len -= 16;
00495         track_type = avio_r8(pb);
00496         track_id = avio_r8(pb);
00497         stream_index = get_sindex(s, track_id, track_type);
00498         if (stream_index < 0)
00499             return stream_index;
00500         st = s->streams[stream_index];
00501         field_nr = avio_rb32(pb);
00502         field_info = avio_rb32(pb);
00503         avio_rb32(pb); // "timeline" field number
00504         avio_r8(pb); // flags
00505         avio_r8(pb); // reserved
00506         if (st->codec->codec_id == CODEC_ID_PCM_S24LE ||
00507             st->codec->codec_id == CODEC_ID_PCM_S16LE) {
00508             int first = field_info >> 16;
00509             int last  = field_info & 0xffff; // last is exclusive
00510             int bps = av_get_bits_per_sample(st->codec->codec_id)>>3;
00511             if (first <= last && last*bps <= pkt_len) {
00512                 avio_skip(pb, first*bps);
00513                 skip = pkt_len - last*bps;
00514                 pkt_len = (last-first)*bps;
00515             } else
00516                 av_log(s, AV_LOG_ERROR, "invalid first and last sample values\n");
00517         }
00518         ret = av_get_packet(pb, pkt, pkt_len);
00519         if (skip)
00520             avio_skip(pb, skip);
00521         pkt->stream_index = stream_index;
00522         pkt->dts = field_nr;
00523 
00524         //set duration manually for DV or else lavf misdetects the frame rate
00525         if (st->codec->codec_id == CODEC_ID_DVVIDEO)
00526             pkt->duration = si->fields_per_frame;
00527 
00528         return ret;
00529     }
00530     return AVERROR(EIO);
00531 }
00532 
00533 static int gxf_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) {
00534     int res = 0;
00535     uint64_t pos;
00536     uint64_t maxlen = 100 * 1024 * 1024;
00537     AVStream *st = s->streams[0];
00538     int64_t start_time = s->streams[stream_index]->start_time;
00539     int64_t found;
00540     int idx;
00541     if (timestamp < start_time) timestamp = start_time;
00542     idx = av_index_search_timestamp(st, timestamp - start_time,
00543                                     AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD);
00544     if (idx < 0)
00545         return -1;
00546     pos = st->index_entries[idx].pos;
00547     if (idx < st->nb_index_entries - 2)
00548         maxlen = st->index_entries[idx + 2].pos - pos;
00549     maxlen = FFMAX(maxlen, 200 * 1024);
00550     res = avio_seek(s->pb, pos, SEEK_SET);
00551     if (res < 0)
00552         return res;
00553     found = gxf_resync_media(s, maxlen, -1, timestamp);
00554     if (FFABS(found - timestamp) > 4)
00555         return -1;
00556     return 0;
00557 }
00558 
00559 static int64_t gxf_read_timestamp(AVFormatContext *s, int stream_index,
00560                                   int64_t *pos, int64_t pos_limit) {
00561     AVIOContext *pb = s->pb;
00562     int64_t res;
00563     if (avio_seek(pb, *pos, SEEK_SET) < 0)
00564         return AV_NOPTS_VALUE;
00565     res = gxf_resync_media(s, pos_limit - *pos, -1, -1);
00566     *pos = avio_tell(pb);
00567     return res;
00568 }
00569 
00570 AVInputFormat ff_gxf_demuxer = {
00571     .name           = "gxf",
00572     .long_name      = NULL_IF_CONFIG_SMALL("GXF format"),
00573     .priv_data_size = sizeof(struct gxf_stream_info),
00574     .read_probe     = gxf_probe,
00575     .read_header    = gxf_header,
00576     .read_packet    = gxf_packet,
00577     .read_seek      = gxf_seek,
00578     .read_timestamp = gxf_read_timestamp,
00579 };
Generated on Fri Feb 1 2013 14:34:51 for FFmpeg by doxygen 1.7.1