LCOV - code coverage report
Current view: top level - libavformat - gxf.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 271 365 74.2 %
Date: 2017-12-16 01:21:47 Functions: 14 14 100.0 %

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

Generated by: LCOV version 1.13