LCOV - code coverage report
Current view: top level - libavformat - gxfenc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 499 601 83.0 %
Date: 2017-12-18 20:14:19 Functions: 30 32 93.8 %

          Line data    Source code
       1             : /*
       2             :  * GXF muxer.
       3             :  * Copyright (c) 2006 SmartJog S.A., Baptiste Coudurier <baptiste dot coudurier at smartjog dot com>
       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 "libavutil/avassert.h"
      23             : #include "libavutil/intfloat.h"
      24             : #include "libavutil/opt.h"
      25             : #include "libavutil/mathematics.h"
      26             : #include "libavutil/timecode.h"
      27             : #include "avformat.h"
      28             : #include "internal.h"
      29             : #include "gxf.h"
      30             : #include "audiointerleave.h"
      31             : 
      32             : #define GXF_AUDIO_PACKET_SIZE 65536
      33             : 
      34             : #define GXF_TIMECODE(c, d, h, m, s, f) \
      35             :     ((c) << 30 | (d) << 29 | (h) << 24 | (m) << 16 | (s) << 8 | (f))
      36             : 
      37             : typedef struct GXFTimecode{
      38             :     int hh;
      39             :     int mm;
      40             :     int ss;
      41             :     int ff;
      42             :     int color;
      43             :     int drop;
      44             : } GXFTimecode;
      45             : 
      46             : typedef struct GXFStreamContext {
      47             :     AudioInterleaveContext aic;
      48             :     uint32_t track_type;
      49             :     uint32_t sample_size;
      50             :     uint32_t sample_rate;
      51             :     uint16_t media_type;
      52             :     uint16_t media_info;
      53             :     int frame_rate_index;
      54             :     int lines_index;
      55             :     int fields;
      56             :     int iframes;
      57             :     int pframes;
      58             :     int bframes;
      59             :     int p_per_gop;
      60             :     int b_per_i_or_p; ///< number of B-frames per I-frame or P-frame
      61             :     int first_gop_closed;
      62             :     unsigned order;   ///< interleaving order
      63             : } GXFStreamContext;
      64             : 
      65             : typedef struct GXFContext {
      66             :     AVClass *av_class;
      67             :     uint32_t nb_fields;
      68             :     uint16_t audio_tracks;
      69             :     uint16_t mpeg_tracks;
      70             :     int64_t creation_time;
      71             :     uint32_t umf_start_offset;
      72             :     uint32_t umf_track_offset;
      73             :     uint32_t umf_media_offset;
      74             :     uint32_t umf_length;
      75             :     uint16_t umf_track_size;
      76             :     uint16_t umf_media_size;
      77             :     AVRational time_base;
      78             :     int flags;
      79             :     GXFStreamContext timecode_track;
      80             :     unsigned *flt_entries;    ///< offsets of packets /1024, starts after 2nd video field
      81             :     unsigned flt_entries_nb;
      82             :     uint64_t *map_offsets;    ///< offset of map packets
      83             :     unsigned map_offsets_nb;
      84             :     unsigned packet_count;
      85             :     GXFTimecode tc;
      86             : } GXFContext;
      87             : 
      88             : static const struct {
      89             :     int height, index;
      90             : } gxf_lines_tab[] = {
      91             :     { 480,  1 }, /* NTSC */
      92             :     { 512,  1 }, /* NTSC + VBI */
      93             :     { 576,  2 }, /* PAL */
      94             :     { 608,  2 }, /* PAL + VBI */
      95             :     { 1080, 4 },
      96             :     { 720,  6 },
      97             : };
      98             : 
      99             : static const AVCodecTag gxf_media_types[] = {
     100             :     { AV_CODEC_ID_MJPEG     ,   3 }, /* NTSC */
     101             :     { AV_CODEC_ID_MJPEG     ,   4 }, /* PAL */
     102             :     { AV_CODEC_ID_PCM_S24LE ,   9 },
     103             :     { AV_CODEC_ID_PCM_S16LE ,  10 },
     104             :     { AV_CODEC_ID_MPEG2VIDEO,  11 }, /* NTSC */
     105             :     { AV_CODEC_ID_MPEG2VIDEO,  12 }, /* PAL */
     106             :     { AV_CODEC_ID_DVVIDEO   ,  13 }, /* NTSC */
     107             :     { AV_CODEC_ID_DVVIDEO   ,  14 }, /* PAL */
     108             :     { AV_CODEC_ID_DVVIDEO   ,  15 }, /* 50M NTSC */
     109             :     { AV_CODEC_ID_DVVIDEO   ,  16 }, /* 50M PAL */
     110             :     { AV_CODEC_ID_AC3       ,  17 },
     111             :     //{ AV_CODEC_ID_NONE,  ,   18 }, /* Non compressed 24 bit audio */
     112             :     { AV_CODEC_ID_MPEG2VIDEO,  20 }, /* MPEG HD */
     113             :     { AV_CODEC_ID_MPEG1VIDEO,  22 }, /* NTSC */
     114             :     { AV_CODEC_ID_MPEG1VIDEO,  23 }, /* PAL */
     115             :     { AV_CODEC_ID_NONE,         0 },
     116             : };
     117             : 
     118             : #define SERVER_PATH "EXT:/PDR/default/"
     119             : #define ES_NAME_PATTERN "EXT:/PDR/default/ES."
     120             : 
     121           3 : static int gxf_find_lines_index(AVStream *st)
     122             : {
     123           3 :     GXFStreamContext *sc = st->priv_data;
     124             :     int i;
     125             : 
     126           7 :     for (i = 0; i < 6; ++i) {
     127           7 :         if (st->codecpar->height == gxf_lines_tab[i].height) {
     128           3 :             sc->lines_index = gxf_lines_tab[i].index;
     129           3 :             return 0;
     130             :         }
     131             :     }
     132           0 :     return -1;
     133             : }
     134             : 
     135          98 : static void gxf_write_padding(AVIOContext *pb, int64_t to_pad)
     136             : {
     137      105475 :     for (; to_pad > 0; to_pad--) {
     138      105377 :         avio_w8(pb, 0);
     139             :     }
     140          98 : }
     141             : 
     142         107 : static int64_t updatePacketSize(AVIOContext *pb, int64_t pos)
     143             : {
     144             :     int64_t curpos;
     145             :     int size;
     146             : 
     147         107 :     size = avio_tell(pb) - pos;
     148         107 :     if (size % 4) {
     149          12 :         gxf_write_padding(pb, 4 - size % 4);
     150          12 :         size = avio_tell(pb) - pos;
     151             :     }
     152         107 :     curpos = avio_tell(pb);
     153         107 :     avio_seek(pb, pos + 6, SEEK_SET);
     154         107 :     avio_wb32(pb, size);
     155         107 :     avio_seek(pb, curpos, SEEK_SET);
     156         107 :     return curpos - pos;
     157             : }
     158             : 
     159          30 : static int64_t updateSize(AVIOContext *pb, int64_t pos)
     160             : {
     161             :     int64_t curpos;
     162             : 
     163          30 :     curpos = avio_tell(pb);
     164          30 :     avio_seek(pb, pos, SEEK_SET);
     165          30 :     avio_wb16(pb, curpos - pos - 2);
     166          30 :     avio_seek(pb, curpos, SEEK_SET);
     167          30 :     return curpos - pos;
     168             : }
     169             : 
     170         107 : static void gxf_write_packet_header(AVIOContext *pb, GXFPktType type)
     171             : {
     172         107 :     avio_wb32(pb, 0);  /* packet leader for synchro */
     173         107 :     avio_w8(pb, 1);
     174         107 :     avio_w8(pb, type); /* map packet */
     175         107 :     avio_wb32(pb, 0);  /* size */
     176         107 :     avio_wb32(pb, 0);  /* reserved */
     177         107 :     avio_w8(pb, 0xE1); /* trailer 1 */
     178         107 :     avio_w8(pb, 0xE2); /* trailer 2 */
     179         107 : }
     180             : 
     181           6 : static int gxf_write_mpeg_auxiliary(AVIOContext *pb, AVStream *st)
     182             : {
     183           6 :     GXFStreamContext *sc = st->priv_data;
     184             :     char buffer[1024];
     185             :     int size, starting_line;
     186             : 
     187           6 :     if (sc->iframes) {
     188           3 :         sc->p_per_gop = sc->pframes / sc->iframes;
     189           3 :         if (sc->pframes % sc->iframes)
     190           2 :             sc->p_per_gop++;
     191           3 :         if (sc->pframes) {
     192           3 :             sc->b_per_i_or_p = sc->bframes / sc->pframes;
     193           3 :             if (sc->bframes % sc->pframes)
     194           0 :                 sc->b_per_i_or_p++;
     195             :         }
     196           3 :         if (sc->p_per_gop > 9)
     197           0 :             sc->p_per_gop = 9; /* ensure value won't take more than one char */
     198           3 :         if (sc->b_per_i_or_p > 9)
     199           0 :             sc->b_per_i_or_p = 9; /* ensure value won't take more than one char */
     200             :     }
     201           6 :     if (st->codecpar->height == 512 || st->codecpar->height == 608)
     202           0 :         starting_line = 7; // VBI
     203           6 :     else if (st->codecpar->height == 480)
     204           2 :         starting_line = 20;
     205             :     else
     206           4 :         starting_line = 23; // default PAL
     207             : 
     208          24 :     size = snprintf(buffer, sizeof(buffer), "Ver 1\nBr %.6f\nIpg 1\nPpi %d\nBpiop %d\n"
     209             :                     "Pix 0\nCf %d\nCg %d\nSl %d\nnl16 %d\nVi 1\nf1 1\n",
     210           6 :                     (float)st->codecpar->bit_rate, sc->p_per_gop, sc->b_per_i_or_p,
     211          12 :                     st->codecpar->format == AV_PIX_FMT_YUV422P ? 2 : 1, sc->first_gop_closed == 1,
     212           6 :                     starting_line, (st->codecpar->height + 15) / 16);
     213           6 :     av_assert0(size < sizeof(buffer));
     214           6 :     avio_w8(pb, TRACK_MPG_AUX);
     215           6 :     avio_w8(pb, size + 1);
     216           6 :     avio_write(pb, (uint8_t *)buffer, size + 1);
     217           6 :     return size + 3;
     218             : }
     219             : 
     220           0 : static int gxf_write_dv_auxiliary(AVIOContext *pb, AVStream *st)
     221             : {
     222           0 :     int64_t track_aux_data = 0;
     223             : 
     224           0 :     avio_w8(pb, TRACK_AUX);
     225           0 :     avio_w8(pb, 8);
     226           0 :     if (st->codecpar->format == AV_PIX_FMT_YUV420P)
     227           0 :         track_aux_data |= 0x01;     /* marks stream as DVCAM instead of DVPRO */
     228           0 :     track_aux_data |= 0x40000000;   /* aux data is valid */
     229           0 :     avio_wl64(pb, track_aux_data);
     230           0 :     return 8;
     231             : }
     232             : 
     233           6 : static int gxf_write_timecode_auxiliary(AVIOContext *pb, GXFContext *gxf)
     234             : {
     235           6 :     uint32_t timecode = GXF_TIMECODE(gxf->tc.color, gxf->tc.drop,
     236             :                                      gxf->tc.hh, gxf->tc.mm,
     237             :                                      gxf->tc.ss, gxf->tc.ff);
     238             : 
     239           6 :     avio_w8(pb, TRACK_AUX);
     240           6 :     avio_w8(pb, 8);
     241           6 :     avio_wl32(pb, timecode);
     242             :     /* reserved */
     243           6 :     avio_wl32(pb, 0);
     244           6 :     return 8;
     245             : }
     246             : 
     247          18 : static int gxf_write_track_description(AVFormatContext *s, GXFStreamContext *sc, int index)
     248             : {
     249          18 :     GXFContext *gxf = s->priv_data;
     250          18 :     AVIOContext *pb = s->pb;
     251             :     int64_t pos;
     252             : 
     253             :     /* track description section */
     254          18 :     avio_w8(pb, sc->media_type + 0x80);
     255          18 :     avio_w8(pb, index + 0xC0);
     256             : 
     257          18 :     pos = avio_tell(pb);
     258          18 :     avio_wb16(pb, 0); /* size */
     259             : 
     260             :     /* media file name */
     261          18 :     avio_w8(pb, TRACK_NAME);
     262          18 :     avio_w8(pb, strlen(ES_NAME_PATTERN) + 3);
     263          18 :     avio_write(pb, ES_NAME_PATTERN, sizeof(ES_NAME_PATTERN) - 1);
     264          18 :     avio_wb16(pb, sc->media_info);
     265          18 :     avio_w8(pb, 0);
     266             : 
     267          18 :     switch (sc->track_type) {
     268           6 :         case 3:     /* timecode */
     269           6 :             gxf_write_timecode_auxiliary(pb, gxf);
     270           6 :             break;
     271           6 :         case 4:     /* MPEG2 */
     272             :         case 9:     /* MPEG1 */
     273           6 :             gxf_write_mpeg_auxiliary(pb, s->streams[index]);
     274           6 :             break;
     275           0 :         case 5:     /* DV25 */
     276             :         case 6:     /* DV50 */
     277           0 :             gxf_write_dv_auxiliary(pb, s->streams[index]);
     278           0 :             break;
     279           6 :         default:
     280           6 :             avio_w8(pb, TRACK_AUX);
     281           6 :             avio_w8(pb, 8);
     282           6 :             avio_wl64(pb, 0);
     283             :     }
     284             : 
     285             :     /* file system version */
     286          18 :     avio_w8(pb, TRACK_VER);
     287          18 :     avio_w8(pb, 4);
     288          18 :     avio_wb32(pb, 0);
     289             : 
     290             :     /* frame rate */
     291          18 :     avio_w8(pb, TRACK_FPS);
     292          18 :     avio_w8(pb, 4);
     293          18 :     avio_wb32(pb, sc->frame_rate_index);
     294             : 
     295             :     /* lines per frame */
     296          18 :     avio_w8(pb, TRACK_LINES);
     297          18 :     avio_w8(pb, 4);
     298          18 :     avio_wb32(pb, sc->lines_index);
     299             : 
     300             :     /* fields per frame */
     301          18 :     avio_w8(pb, TRACK_FPF);
     302          18 :     avio_w8(pb, 4);
     303          18 :     avio_wb32(pb, sc->fields);
     304             : 
     305          18 :     return updateSize(pb, pos);
     306             : }
     307             : 
     308           6 : static int gxf_write_material_data_section(AVFormatContext *s)
     309             : {
     310           6 :     GXFContext *gxf = s->priv_data;
     311           6 :     AVIOContext *pb = s->pb;
     312             :     int64_t pos;
     313             :     int len;
     314           6 :     const char *filename = strrchr(s->filename, '/');
     315             : 
     316           6 :     pos = avio_tell(pb);
     317           6 :     avio_wb16(pb, 0); /* size */
     318             : 
     319             :     /* name */
     320           6 :     if (filename)
     321           6 :         filename++;
     322             :     else
     323           0 :         filename = s->filename;
     324           6 :     len = strlen(filename);
     325             : 
     326           6 :     avio_w8(pb, MAT_NAME);
     327           6 :     avio_w8(pb, strlen(SERVER_PATH) + len + 1);
     328           6 :     avio_write(pb, SERVER_PATH, sizeof(SERVER_PATH) - 1);
     329           6 :     avio_write(pb, filename, len);
     330           6 :     avio_w8(pb, 0);
     331             : 
     332             :     /* first field */
     333           6 :     avio_w8(pb, MAT_FIRST_FIELD);
     334           6 :     avio_w8(pb, 4);
     335           6 :     avio_wb32(pb, 0);
     336             : 
     337             :     /* last field */
     338           6 :     avio_w8(pb, MAT_LAST_FIELD);
     339           6 :     avio_w8(pb, 4);
     340           6 :     avio_wb32(pb, gxf->nb_fields);
     341             : 
     342             :     /* reserved */
     343           6 :     avio_w8(pb, MAT_MARK_IN);
     344           6 :     avio_w8(pb, 4);
     345           6 :     avio_wb32(pb, 0);
     346             : 
     347           6 :     avio_w8(pb, MAT_MARK_OUT);
     348           6 :     avio_w8(pb, 4);
     349           6 :     avio_wb32(pb, gxf->nb_fields);
     350             : 
     351             :     /* estimated size */
     352           6 :     avio_w8(pb, MAT_SIZE);
     353           6 :     avio_w8(pb, 4);
     354           6 :     avio_wb32(pb, avio_size(pb) / 1024);
     355             : 
     356           6 :     return updateSize(pb, pos);
     357             : }
     358             : 
     359           6 : static int gxf_write_track_description_section(AVFormatContext *s)
     360             : {
     361           6 :     GXFContext *gxf = s->priv_data;
     362           6 :     AVIOContext *pb = s->pb;
     363             :     int64_t pos;
     364             :     int i;
     365             : 
     366           6 :     pos = avio_tell(pb);
     367           6 :     avio_wb16(pb, 0); /* size */
     368          18 :     for (i = 0; i < s->nb_streams; ++i)
     369          12 :         gxf_write_track_description(s, s->streams[i]->priv_data, i);
     370             : 
     371           6 :     gxf_write_track_description(s, &gxf->timecode_track, s->nb_streams);
     372             : 
     373           6 :     return updateSize(pb, pos);
     374             : }
     375             : 
     376           6 : static int gxf_write_map_packet(AVFormatContext *s, int rewrite)
     377             : {
     378           6 :     GXFContext *gxf = s->priv_data;
     379           6 :     AVIOContext *pb = s->pb;
     380           6 :     int64_t pos = avio_tell(pb);
     381             : 
     382           6 :     if (!rewrite) {
     383           3 :         if (!(gxf->map_offsets_nb % 30)) {
     384             :             int err;
     385           3 :             if ((err = av_reallocp_array(&gxf->map_offsets,
     386           3 :                                          gxf->map_offsets_nb + 30,
     387             :                                          sizeof(*gxf->map_offsets))) < 0) {
     388           0 :                 gxf->map_offsets_nb = 0;
     389           0 :                 av_log(s, AV_LOG_ERROR, "could not realloc map offsets\n");
     390           0 :                 return err;
     391             :             }
     392             :         }
     393           3 :         gxf->map_offsets[gxf->map_offsets_nb++] = pos; // do not increment here
     394             :     }
     395             : 
     396           6 :     gxf_write_packet_header(pb, PKT_MAP);
     397             : 
     398             :     /* preamble */
     399           6 :     avio_w8(pb, 0xE0); /* version */
     400           6 :     avio_w8(pb, 0xFF); /* reserved */
     401             : 
     402           6 :     gxf_write_material_data_section(s);
     403           6 :     gxf_write_track_description_section(s);
     404             : 
     405           6 :     return updatePacketSize(pb, pos);
     406             : }
     407             : 
     408           6 : static int gxf_write_flt_packet(AVFormatContext *s)
     409             : {
     410           6 :     GXFContext *gxf = s->priv_data;
     411           6 :     AVIOContext *pb = s->pb;
     412           6 :     int64_t pos = avio_tell(pb);
     413           6 :     int fields_per_flt = (gxf->nb_fields+1) / 1000 + 1;
     414           6 :     int flt_entries = gxf->nb_fields / fields_per_flt;
     415           6 :     int i = 0;
     416             : 
     417           6 :     gxf_write_packet_header(pb, PKT_FLT);
     418             : 
     419           6 :     avio_wl32(pb, fields_per_flt); /* number of fields */
     420           6 :     avio_wl32(pb, flt_entries); /* number of active flt entries */
     421             : 
     422           6 :     if (gxf->flt_entries) {
     423         163 :         for (i = 0; i < flt_entries; i++)
     424         160 :             avio_wl32(pb, gxf->flt_entries[(i*fields_per_flt)>>1]);
     425             :     }
     426             : 
     427        5846 :     for (; i < 1000; i++)
     428        5840 :         avio_wl32(pb, 0);
     429             : 
     430           6 :     return updatePacketSize(pb, pos);
     431             : }
     432             : 
     433           6 : static int gxf_write_umf_material_description(AVFormatContext *s)
     434             : {
     435           6 :     GXFContext *gxf = s->priv_data;
     436           6 :     AVIOContext *pb = s->pb;
     437           6 :     int timecode_base = gxf->time_base.den == 60000 ? 60 : 50;
     438           6 :     int64_t timestamp = 0;
     439             :     uint64_t nb_fields;
     440             :     uint32_t timecode_in; // timecode at mark in
     441             :     uint32_t timecode_out; // timecode at mark out
     442             : 
     443           6 :     ff_parse_creation_time_metadata(s, &timestamp, 1);
     444             : 
     445           6 :     timecode_in = GXF_TIMECODE(gxf->tc.color, gxf->tc.drop,
     446             :                                gxf->tc.hh, gxf->tc.mm,
     447             :                                gxf->tc.ss, gxf->tc.ff);
     448             : 
     449          12 :     nb_fields = gxf->nb_fields +
     450           6 :                 gxf->tc.hh * (timecode_base * 3600) +
     451          12 :                 gxf->tc.mm * (timecode_base * 60)   +
     452          12 :                 gxf->tc.ss * timecode_base          +
     453           6 :                 gxf->tc.ff;
     454             : 
     455           6 :     timecode_out = GXF_TIMECODE(gxf->tc.color, gxf->tc.drop,
     456             :                                 nb_fields / (timecode_base * 3600) % 24,
     457             :                                 nb_fields / (timecode_base * 60)   % 60,
     458             :                                 nb_fields /  timecode_base % 60,
     459             :                                 nb_fields %  timecode_base);
     460             : 
     461           6 :     avio_wl32(pb, gxf->flags);
     462           6 :     avio_wl32(pb, gxf->nb_fields); /* length of the longest track */
     463           6 :     avio_wl32(pb, gxf->nb_fields); /* length of the shortest track */
     464           6 :     avio_wl32(pb, 0); /* mark in */
     465           6 :     avio_wl32(pb, gxf->nb_fields); /* mark out */
     466           6 :     avio_wl32(pb, timecode_in); /* timecode mark in */
     467           6 :     avio_wl32(pb, timecode_out); /* timecode mark out */
     468           6 :     avio_wl64(pb, timestamp); /* modification time */
     469           6 :     avio_wl64(pb, timestamp); /* creation time */
     470           6 :     avio_wl16(pb, 0); /* reserved */
     471           6 :     avio_wl16(pb, 0); /* reserved */
     472           6 :     avio_wl16(pb, gxf->audio_tracks);
     473           6 :     avio_wl16(pb, 1); /* timecode track count */
     474           6 :     avio_wl16(pb, 0); /* reserved */
     475           6 :     avio_wl16(pb, gxf->mpeg_tracks);
     476           6 :     return 48;
     477             : }
     478             : 
     479           6 : static int gxf_write_umf_payload(AVFormatContext *s)
     480             : {
     481           6 :     GXFContext *gxf = s->priv_data;
     482           6 :     AVIOContext *pb = s->pb;
     483             : 
     484           6 :     avio_wl32(pb, gxf->umf_length); /* total length of the umf data */
     485           6 :     avio_wl32(pb, 3); /* version */
     486           6 :     avio_wl32(pb, s->nb_streams+1);
     487           6 :     avio_wl32(pb, gxf->umf_track_offset); /* umf track section offset */
     488           6 :     avio_wl32(pb, gxf->umf_track_size);
     489           6 :     avio_wl32(pb, s->nb_streams+1);
     490           6 :     avio_wl32(pb, gxf->umf_media_offset);
     491           6 :     avio_wl32(pb, gxf->umf_media_size);
     492           6 :     avio_wl32(pb, gxf->umf_length); /* user data offset */
     493           6 :     avio_wl32(pb, 0); /* user data size */
     494           6 :     avio_wl32(pb, 0); /* reserved */
     495           6 :     avio_wl32(pb, 0); /* reserved */
     496           6 :     return 48;
     497             : }
     498             : 
     499           6 : static int gxf_write_umf_track_description(AVFormatContext *s)
     500             : {
     501           6 :     AVIOContext *pb = s->pb;
     502           6 :     GXFContext *gxf = s->priv_data;
     503           6 :     int64_t pos = avio_tell(pb);
     504             :     int i;
     505             : 
     506           6 :     gxf->umf_track_offset = pos - gxf->umf_start_offset;
     507          18 :     for (i = 0; i < s->nb_streams; ++i) {
     508          12 :         GXFStreamContext *sc = s->streams[i]->priv_data;
     509          12 :         avio_wl16(pb, sc->media_info);
     510          12 :         avio_wl16(pb, 1);
     511             :     }
     512             : 
     513           6 :     avio_wl16(pb, gxf->timecode_track.media_info);
     514           6 :     avio_wl16(pb, 1);
     515             : 
     516           6 :     return avio_tell(pb) - pos;
     517             : }
     518             : 
     519           6 : static int gxf_write_umf_media_mpeg(AVIOContext *pb, AVStream *st)
     520             : {
     521           6 :     GXFStreamContext *sc = st->priv_data;
     522             : 
     523           6 :     if (st->codecpar->format == AV_PIX_FMT_YUV422P)
     524           0 :         avio_wl32(pb, 2);
     525             :     else
     526           6 :         avio_wl32(pb, 1); /* default to 420 */
     527           6 :     avio_wl32(pb, sc->first_gop_closed == 1); /* closed = 1, open = 0, unknown = 255 */
     528           6 :     avio_wl32(pb, 3); /* top = 1, bottom = 2, frame = 3, unknown = 0 */
     529           6 :     avio_wl32(pb, 1); /* I picture per GOP */
     530           6 :     avio_wl32(pb, sc->p_per_gop);
     531           6 :     avio_wl32(pb, sc->b_per_i_or_p);
     532           6 :     if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO)
     533           6 :         avio_wl32(pb, 2);
     534           0 :     else if (st->codecpar->codec_id == AV_CODEC_ID_MPEG1VIDEO)
     535           0 :         avio_wl32(pb, 1);
     536             :     else
     537           0 :         avio_wl32(pb, 0);
     538           6 :     avio_wl32(pb, 0); /* reserved */
     539           6 :     return 32;
     540             : }
     541             : 
     542           6 : static int gxf_write_umf_media_timecode(AVIOContext *pb, int drop)
     543             : {
     544           6 :     avio_wl32(pb, drop); /* drop frame */
     545           6 :     avio_wl32(pb, 0); /* reserved */
     546           6 :     avio_wl32(pb, 0); /* reserved */
     547           6 :     avio_wl32(pb, 0); /* reserved */
     548           6 :     avio_wl32(pb, 0); /* reserved */
     549           6 :     avio_wl32(pb, 0); /* reserved */
     550           6 :     avio_wl32(pb, 0); /* reserved */
     551           6 :     avio_wl32(pb, 0); /* reserved */
     552           6 :     return 32;
     553             : }
     554             : 
     555           0 : static int gxf_write_umf_media_dv(AVIOContext *pb, GXFStreamContext *sc, AVStream *st)
     556             : {
     557           0 :     int dv_umf_data = 0;
     558             : 
     559           0 :     if (st->codecpar->format == AV_PIX_FMT_YUV420P)
     560           0 :         dv_umf_data |= 0x20; /* marks as DVCAM instead of DVPRO */
     561           0 :     avio_wl32(pb, dv_umf_data);
     562           0 :     avio_wl32(pb, 0);
     563           0 :     avio_wl32(pb, 0);
     564           0 :     avio_wl32(pb, 0);
     565           0 :     avio_wl32(pb, 0);
     566           0 :     avio_wl32(pb, 0);
     567           0 :     avio_wl32(pb, 0);
     568           0 :     avio_wl32(pb, 0);
     569           0 :     return 32;
     570             : }
     571             : 
     572           6 : static int gxf_write_umf_media_audio(AVIOContext *pb, GXFStreamContext *sc)
     573             : {
     574           6 :     avio_wl64(pb, av_double2int(1)); /* sound level to begin to */
     575           6 :     avio_wl64(pb, av_double2int(1)); /* sound level to begin to */
     576           6 :     avio_wl32(pb, 0); /* number of fields over which to ramp up sound level */
     577           6 :     avio_wl32(pb, 0); /* number of fields over which to ramp down sound level */
     578           6 :     avio_wl32(pb, 0); /* reserved */
     579           6 :     avio_wl32(pb, 0); /* reserved */
     580           6 :     return 32;
     581             : }
     582             : 
     583           6 : static int gxf_write_umf_media_description(AVFormatContext *s)
     584             : {
     585           6 :     GXFContext *gxf = s->priv_data;
     586           6 :     AVIOContext *pb = s->pb;
     587             :     int64_t pos;
     588             :     int i, j;
     589             : 
     590           6 :     pos = avio_tell(pb);
     591           6 :     gxf->umf_media_offset = pos - gxf->umf_start_offset;
     592          24 :     for (i = 0; i <= s->nb_streams; ++i) {
     593             :         GXFStreamContext *sc;
     594             :         int64_t startpos, curpos;
     595             : 
     596          18 :         if (i == s->nb_streams)
     597           6 :             sc = &gxf->timecode_track;
     598             :         else
     599          12 :             sc = s->streams[i]->priv_data;
     600             : 
     601          18 :         startpos = avio_tell(pb);
     602          18 :         avio_wl16(pb, 0); /* length */
     603          18 :         avio_wl16(pb, sc->media_info);
     604          18 :         avio_wl16(pb, 0); /* reserved */
     605          18 :         avio_wl16(pb, 0); /* reserved */
     606          18 :         avio_wl32(pb, gxf->nb_fields);
     607          18 :         avio_wl32(pb, 0); /* attributes rw, ro */
     608          18 :         avio_wl32(pb, 0); /* mark in */
     609          18 :         avio_wl32(pb, gxf->nb_fields); /* mark out */
     610          18 :         avio_write(pb, ES_NAME_PATTERN, strlen(ES_NAME_PATTERN));
     611          18 :         avio_wb16(pb, sc->media_info);
     612        1206 :         for (j = strlen(ES_NAME_PATTERN)+2; j < 88; j++)
     613        1188 :             avio_w8(pb, 0);
     614          18 :         avio_wl32(pb, sc->track_type);
     615          18 :         avio_wl32(pb, sc->sample_rate);
     616          18 :         avio_wl32(pb, sc->sample_size);
     617          18 :         avio_wl32(pb, 0); /* reserved */
     618             : 
     619          18 :         if (sc == &gxf->timecode_track)
     620           6 :             gxf_write_umf_media_timecode(pb, gxf->tc.drop);
     621             :         else {
     622          12 :             AVStream *st = s->streams[i];
     623          12 :             switch (st->codecpar->codec_id) {
     624           6 :             case AV_CODEC_ID_MPEG1VIDEO:
     625             :             case AV_CODEC_ID_MPEG2VIDEO:
     626           6 :                 gxf_write_umf_media_mpeg(pb, st);
     627           6 :                 break;
     628           6 :             case AV_CODEC_ID_PCM_S16LE:
     629           6 :                 gxf_write_umf_media_audio(pb, sc);
     630           6 :                 break;
     631           0 :             case AV_CODEC_ID_DVVIDEO:
     632           0 :                 gxf_write_umf_media_dv(pb, sc, st);
     633           0 :                 break;
     634             :             }
     635             :         }
     636             : 
     637          18 :         curpos = avio_tell(pb);
     638          18 :         avio_seek(pb, startpos, SEEK_SET);
     639          18 :         avio_wl16(pb, curpos - startpos);
     640          18 :         avio_seek(pb, curpos, SEEK_SET);
     641             :     }
     642           6 :     return avio_tell(pb) - pos;
     643             : }
     644             : 
     645           6 : static int gxf_write_umf_packet(AVFormatContext *s)
     646             : {
     647           6 :     GXFContext *gxf = s->priv_data;
     648           6 :     AVIOContext *pb = s->pb;
     649           6 :     int64_t pos = avio_tell(pb);
     650             : 
     651           6 :     gxf_write_packet_header(pb, PKT_UMF);
     652             : 
     653             :     /* preamble */
     654           6 :     avio_w8(pb, 3); /* first and last (only) packet */
     655           6 :     avio_wb32(pb, gxf->umf_length); /* data length */
     656             : 
     657           6 :     gxf->umf_start_offset = avio_tell(pb);
     658           6 :     gxf_write_umf_payload(s);
     659           6 :     gxf_write_umf_material_description(s);
     660           6 :     gxf->umf_track_size = gxf_write_umf_track_description(s);
     661           6 :     gxf->umf_media_size = gxf_write_umf_media_description(s);
     662           6 :     gxf->umf_length = avio_tell(pb) - gxf->umf_start_offset;
     663           6 :     return updatePacketSize(pb, pos);
     664             : }
     665             : 
     666             : static const int GXF_samples_per_frame[] = { 32768, 0 };
     667             : 
     668           3 : static void gxf_init_timecode_track(GXFStreamContext *sc, GXFStreamContext *vsc)
     669             : {
     670           3 :     if (!vsc)
     671           0 :         return;
     672             : 
     673           3 :     sc->media_type = vsc->sample_rate == 60 ? 7 : 8;
     674           3 :     sc->sample_rate = vsc->sample_rate;
     675           3 :     sc->media_info = ('T'<<8) | '0';
     676           3 :     sc->track_type = 3;
     677           3 :     sc->frame_rate_index = vsc->frame_rate_index;
     678           3 :     sc->lines_index = vsc->lines_index;
     679           3 :     sc->sample_size = 16;
     680           3 :     sc->fields = vsc->fields;
     681             : }
     682             : 
     683           2 : static int gxf_init_timecode(AVFormatContext *s, GXFTimecode *tc, const char *tcstr, int fields)
     684             : {
     685             :     char c;
     686             : 
     687           2 :     if (sscanf(tcstr, "%d:%d:%d%c%d", &tc->hh, &tc->mm, &tc->ss, &c, &tc->ff) != 5) {
     688           0 :         av_log(s, AV_LOG_ERROR, "unable to parse timecode, "
     689             :                                 "syntax: hh:mm:ss[:;.]ff\n");
     690           0 :         return -1;
     691             :     }
     692             : 
     693           2 :     tc->color = 0;
     694           2 :     tc->drop = c != ':';
     695             : 
     696           2 :     if (fields == 2)
     697           2 :         tc->ff = tc->ff * 2;
     698             : 
     699           2 :     return 0;
     700             : }
     701             : 
     702           3 : static int gxf_write_header(AVFormatContext *s)
     703             : {
     704           3 :     AVIOContext *pb = s->pb;
     705           3 :     GXFContext *gxf = s->priv_data;
     706           3 :     GXFStreamContext *vsc = NULL;
     707           3 :     uint8_t tracks[255] = {0};
     708           3 :     int i, media_info = 0;
     709             :     int ret;
     710           3 :     AVDictionaryEntry *tcr = av_dict_get(s->metadata, "timecode", NULL, 0);
     711             : 
     712           3 :     if (!(pb->seekable & AVIO_SEEKABLE_NORMAL)) {
     713           0 :         av_log(s, AV_LOG_ERROR, "gxf muxer does not support streamed output, patch welcome\n");
     714           0 :         return -1;
     715             :     }
     716             : 
     717           3 :     gxf->flags |= 0x00080000; /* material is simple clip */
     718           9 :     for (i = 0; i < s->nb_streams; ++i) {
     719           6 :         AVStream *st = s->streams[i];
     720           6 :         GXFStreamContext *sc = av_mallocz(sizeof(*sc));
     721           6 :         if (!sc)
     722           0 :             return AVERROR(ENOMEM);
     723           6 :         st->priv_data = sc;
     724             : 
     725           6 :         sc->media_type = ff_codec_get_tag(gxf_media_types, st->codecpar->codec_id);
     726           6 :         if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
     727           3 :             if (st->codecpar->codec_id != AV_CODEC_ID_PCM_S16LE) {
     728           0 :                 av_log(s, AV_LOG_ERROR, "only 16 BIT PCM LE allowed for now\n");
     729           0 :                 return -1;
     730             :             }
     731           3 :             if (st->codecpar->sample_rate != 48000) {
     732           0 :                 av_log(s, AV_LOG_ERROR, "only 48000hz sampling rate is allowed\n");
     733           0 :                 return -1;
     734             :             }
     735           3 :             if (st->codecpar->channels != 1) {
     736           0 :                 av_log(s, AV_LOG_ERROR, "only mono tracks are allowed\n");
     737           0 :                 return -1;
     738             :             }
     739           3 :             sc->track_type = 2;
     740           3 :             sc->sample_rate = st->codecpar->sample_rate;
     741           3 :             avpriv_set_pts_info(st, 64, 1, sc->sample_rate);
     742           3 :             sc->sample_size = 16;
     743           3 :             sc->frame_rate_index = -2;
     744           3 :             sc->lines_index = -2;
     745           3 :             sc->fields = -2;
     746           3 :             gxf->audio_tracks++;
     747           3 :             gxf->flags |= 0x04000000; /* audio is 16 bit pcm */
     748           3 :             media_info = 'A';
     749           3 :         } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
     750           3 :             if (i != 0) {
     751           0 :                 av_log(s, AV_LOG_ERROR, "video stream must be the first track\n");
     752           0 :                 return -1;
     753             :             }
     754             :             /* FIXME check from time_base ? */
     755           3 :             if (st->codecpar->height == 480 || st->codecpar->height == 512) { /* NTSC or NTSC+VBI */
     756           1 :                 sc->frame_rate_index = 5;
     757           1 :                 sc->sample_rate = 60;
     758           1 :                 gxf->flags |= 0x00000080;
     759           1 :                 gxf->time_base = (AVRational){ 1001, 60000 };
     760           2 :             } else if (st->codecpar->height == 576 || st->codecpar->height == 608) { /* PAL or PAL+VBI */
     761           2 :                 sc->frame_rate_index = 6;
     762           2 :                 sc->media_type++;
     763           2 :                 sc->sample_rate = 50;
     764           2 :                 gxf->flags |= 0x00000040;
     765           2 :                 gxf->time_base = (AVRational){ 1, 50 };
     766             :             } else {
     767           0 :                 av_log(s, AV_LOG_ERROR, "unsupported video resolution, "
     768             :                        "gxf muxer only accepts PAL or NTSC resolutions currently\n");
     769           0 :                 return -1;
     770             :             }
     771           3 :             if (!tcr)
     772           1 :                 tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
     773           3 :             avpriv_set_pts_info(st, 64, gxf->time_base.num, gxf->time_base.den);
     774           3 :             if (gxf_find_lines_index(st) < 0)
     775           0 :                 sc->lines_index = -1;
     776           3 :             sc->sample_size = st->codecpar->bit_rate;
     777           3 :             sc->fields = 2; /* interlaced */
     778             : 
     779           3 :             vsc = sc;
     780             : 
     781           3 :             switch (st->codecpar->codec_id) {
     782           0 :             case AV_CODEC_ID_MJPEG:
     783           0 :                 sc->track_type = 1;
     784           0 :                 gxf->flags |= 0x00004000;
     785           0 :                 media_info = 'J';
     786           0 :                 break;
     787           0 :             case AV_CODEC_ID_MPEG1VIDEO:
     788           0 :                 sc->track_type = 9;
     789           0 :                 gxf->mpeg_tracks++;
     790           0 :                 media_info = 'L';
     791           0 :                 break;
     792           3 :             case AV_CODEC_ID_MPEG2VIDEO:
     793           3 :                 sc->first_gop_closed = -1;
     794           3 :                 sc->track_type = 4;
     795           3 :                 gxf->mpeg_tracks++;
     796           3 :                 gxf->flags |= 0x00008000;
     797           3 :                 media_info = 'M';
     798           3 :                 break;
     799           0 :             case AV_CODEC_ID_DVVIDEO:
     800           0 :                 if (st->codecpar->format == AV_PIX_FMT_YUV422P) {
     801           0 :                     sc->media_type += 2;
     802           0 :                     sc->track_type = 6;
     803           0 :                     gxf->flags |= 0x00002000;
     804           0 :                     media_info = 'E';
     805             :                 } else {
     806           0 :                     sc->track_type = 5;
     807           0 :                     gxf->flags |= 0x00001000;
     808           0 :                     media_info = 'D';
     809             :                 }
     810           0 :                 break;
     811           0 :             default:
     812           0 :                 av_log(s, AV_LOG_ERROR, "video codec not supported\n");
     813           0 :                 return -1;
     814             :             }
     815           0 :         }
     816             :         /* FIXME first 10 audio tracks are 0 to 9 next 22 are A to V */
     817           6 :         sc->media_info = media_info<<8 | ('0'+tracks[media_info]++);
     818           6 :         sc->order = s->nb_streams - st->index;
     819             :     }
     820             : 
     821           3 :     if (ff_audio_interleave_init(s, GXF_samples_per_frame, (AVRational){ 1, 48000 }) < 0)
     822           0 :         return -1;
     823             : 
     824           3 :     if (tcr && vsc)
     825           2 :         gxf_init_timecode(s, &gxf->tc, tcr->value, vsc->fields);
     826             : 
     827           3 :     gxf_init_timecode_track(&gxf->timecode_track, vsc);
     828           3 :     gxf->flags |= 0x200000; // time code track is non-drop frame
     829             : 
     830           3 :     if ((ret = gxf_write_map_packet(s, 0)) < 0)
     831           0 :         return ret;
     832           3 :     gxf_write_flt_packet(s);
     833           3 :     gxf_write_umf_packet(s);
     834             : 
     835           3 :     gxf->packet_count = 3;
     836             : 
     837           3 :     avio_flush(pb);
     838           3 :     return 0;
     839             : }
     840             : 
     841           3 : static int gxf_write_eos_packet(AVIOContext *pb)
     842             : {
     843           3 :     int64_t pos = avio_tell(pb);
     844             : 
     845           3 :     gxf_write_packet_header(pb, PKT_EOS);
     846           3 :     return updatePacketSize(pb, pos);
     847             : }
     848             : 
     849           3 : static int gxf_write_trailer(AVFormatContext *s)
     850             : {
     851           3 :     GXFContext *gxf = s->priv_data;
     852           3 :     AVIOContext *pb = s->pb;
     853             :     int64_t end;
     854             :     int i;
     855             :     int ret;
     856             : 
     857           3 :     ff_audio_interleave_close(s);
     858             : 
     859           3 :     gxf_write_eos_packet(pb);
     860           3 :     end = avio_tell(pb);
     861           3 :     avio_seek(pb, 0, SEEK_SET);
     862             :     /* overwrite map, flt and umf packets with new values */
     863           3 :     if ((ret = gxf_write_map_packet(s, 1)) < 0)
     864           0 :         return ret;
     865           3 :     gxf_write_flt_packet(s);
     866           3 :     gxf_write_umf_packet(s);
     867           3 :     avio_flush(pb);
     868             :     /* update duration in all map packets */
     869           3 :     for (i = 1; i < gxf->map_offsets_nb; i++) {
     870           0 :         avio_seek(pb, gxf->map_offsets[i], SEEK_SET);
     871           0 :         if ((ret = gxf_write_map_packet(s, 1)) < 0)
     872           0 :             return ret;
     873           0 :         avio_flush(pb);
     874             :     }
     875             : 
     876           3 :     avio_seek(pb, end, SEEK_SET);
     877             : 
     878           3 :     av_freep(&gxf->flt_entries);
     879           3 :     av_freep(&gxf->map_offsets);
     880             : 
     881           3 :     return 0;
     882             : }
     883             : 
     884          80 : static int gxf_parse_mpeg_frame(GXFStreamContext *sc, const uint8_t *buf, int size)
     885             : {
     886          80 :     uint32_t c=-1;
     887             :     int i;
     888         670 :     for(i=0; i<size-4 && c!=0x100; i++){
     889         590 :         c = (c<<8) + buf[i];
     890         590 :         if(c == 0x1B8 && sc->first_gop_closed == -1) /* GOP start code */
     891           3 :             sc->first_gop_closed= (buf[i+4]>>6)&1;
     892             :     }
     893          80 :     return (buf[i+1]>>3)&7;
     894             : }
     895             : 
     896          86 : static int gxf_write_media_preamble(AVFormatContext *s, AVPacket *pkt, int size)
     897             : {
     898          86 :     GXFContext *gxf = s->priv_data;
     899          86 :     AVIOContext *pb = s->pb;
     900          86 :     AVStream *st = s->streams[pkt->stream_index];
     901          86 :     GXFStreamContext *sc = st->priv_data;
     902             :     unsigned field_nb;
     903             :     /* If the video is frame-encoded, the frame numbers shall be represented by
     904             :      * even field numbers.
     905             :      * see SMPTE360M-2004  6.4.2.1.3 Media field number */
     906          86 :     if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
     907          80 :         field_nb = gxf->nb_fields;
     908             :     } else {
     909           6 :         field_nb = av_rescale_rnd(pkt->dts, gxf->time_base.den,
     910           6 :                                   (int64_t)48000*gxf->time_base.num, AV_ROUND_UP);
     911             :     }
     912             : 
     913          86 :     avio_w8(pb, sc->media_type);
     914          86 :     avio_w8(pb, st->index);
     915          86 :     avio_wb32(pb, field_nb);
     916          86 :     if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
     917           6 :         avio_wb16(pb, 0);
     918           6 :         avio_wb16(pb, size / 2);
     919          80 :     } else if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
     920          80 :         int frame_type = gxf_parse_mpeg_frame(sc, pkt->data, pkt->size);
     921          80 :         if (frame_type == AV_PICTURE_TYPE_I) {
     922           9 :             avio_w8(pb, 0x0d);
     923           9 :             sc->iframes++;
     924          71 :         } else if (frame_type == AV_PICTURE_TYPE_B) {
     925           0 :             avio_w8(pb, 0x0f);
     926           0 :             sc->bframes++;
     927             :         } else {
     928          71 :             avio_w8(pb, 0x0e);
     929          71 :             sc->pframes++;
     930             :         }
     931          80 :         avio_wb24(pb, size);
     932           0 :     } else if (st->codecpar->codec_id == AV_CODEC_ID_DVVIDEO) {
     933           0 :         avio_w8(pb, size / 4096);
     934           0 :         avio_wb24(pb, 0);
     935             :     } else
     936           0 :         avio_wb32(pb, size);
     937          86 :     avio_wb32(pb, field_nb);
     938          86 :     avio_w8(pb, 1); /* flags */
     939          86 :     avio_w8(pb, 0); /* reserved */
     940          86 :     return 16;
     941             : }
     942             : 
     943          86 : static int gxf_write_packet(AVFormatContext *s, AVPacket *pkt)
     944             : {
     945          86 :     GXFContext *gxf = s->priv_data;
     946          86 :     AVIOContext *pb = s->pb;
     947          86 :     AVStream *st = s->streams[pkt->stream_index];
     948          86 :     int64_t pos = avio_tell(pb);
     949          86 :     int padding = 0;
     950          86 :     unsigned packet_start_offset = avio_tell(pb) / 1024;
     951             :     int ret;
     952             : 
     953          86 :     gxf_write_packet_header(pb, PKT_MEDIA);
     954          86 :     if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO && pkt->size % 4) /* MPEG-2 frames must be padded */
     955          57 :         padding = 4 - pkt->size % 4;
     956          29 :     else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
     957           6 :         padding = GXF_AUDIO_PACKET_SIZE - pkt->size;
     958          86 :     gxf_write_media_preamble(s, pkt, pkt->size + padding);
     959          86 :     avio_write(pb, pkt->data, pkt->size);
     960          86 :     gxf_write_padding(pb, padding);
     961             : 
     962          86 :     if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
     963          80 :         if (!(gxf->flt_entries_nb % 500)) {
     964             :             int err;
     965           3 :             if ((err = av_reallocp_array(&gxf->flt_entries,
     966           3 :                                          gxf->flt_entries_nb + 500,
     967             :                                          sizeof(*gxf->flt_entries))) < 0) {
     968           0 :                 gxf->flt_entries_nb = 0;
     969           0 :                 gxf->nb_fields = 0;
     970           0 :                 av_log(s, AV_LOG_ERROR, "could not reallocate flt entries\n");
     971           0 :                 return err;
     972             :             }
     973             :         }
     974          80 :         gxf->flt_entries[gxf->flt_entries_nb++] = packet_start_offset;
     975          80 :         gxf->nb_fields += 2; // count fields
     976             :     }
     977             : 
     978          86 :     updatePacketSize(pb, pos);
     979             : 
     980          86 :     gxf->packet_count++;
     981          86 :     if (gxf->packet_count == 100) {
     982           0 :         if ((ret = gxf_write_map_packet(s, 0)) < 0)
     983           0 :             return ret;
     984           0 :         gxf->packet_count = 0;
     985             :     }
     986             : 
     987          86 :     return 0;
     988             : }
     989             : 
     990          66 : static int gxf_compare_field_nb(AVFormatContext *s, AVPacket *next, AVPacket *cur)
     991             : {
     992          66 :     GXFContext *gxf = s->priv_data;
     993          66 :     AVPacket *pkt[2] = { cur, next };
     994             :     int i, field_nb[2];
     995             :     GXFStreamContext *sc[2];
     996             : 
     997         198 :     for (i = 0; i < 2; i++) {
     998         132 :         AVStream *st = s->streams[pkt[i]->stream_index];
     999         132 :         sc[i] = st->priv_data;
    1000         132 :         if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
    1001          66 :             field_nb[i] = av_rescale_rnd(pkt[i]->dts, gxf->time_base.den,
    1002          66 :                                          (int64_t)48000*gxf->time_base.num, AV_ROUND_UP);
    1003          66 :             field_nb[i] &= ~1; // compare against even field number because audio must be before video
    1004             :         } else
    1005          66 :             field_nb[i] = pkt[i]->dts; // dts are field based
    1006             :     }
    1007             : 
    1008         138 :     return field_nb[1] > field_nb[0] ||
    1009          66 :         (field_nb[1] == field_nb[0] && sc[1]->order > sc[0]->order);
    1010             : }
    1011             : 
    1012         304 : static int gxf_interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush)
    1013             : {
    1014         304 :     if (pkt && s->streams[pkt->stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
    1015          80 :         pkt->duration = 2; // enforce 2 fields
    1016         304 :     return ff_audio_rechunk_interleave(s, out, pkt, flush,
    1017             :                                ff_interleave_packet_per_dts, gxf_compare_field_nb);
    1018             : }
    1019             : 
    1020             : AVOutputFormat ff_gxf_muxer = {
    1021             :     .name              = "gxf",
    1022             :     .long_name         = NULL_IF_CONFIG_SMALL("GXF (General eXchange Format)"),
    1023             :     .extensions        = "gxf",
    1024             :     .priv_data_size    = sizeof(GXFContext),
    1025             :     .audio_codec       = AV_CODEC_ID_PCM_S16LE,
    1026             :     .video_codec       = AV_CODEC_ID_MPEG2VIDEO,
    1027             :     .write_header      = gxf_write_header,
    1028             :     .write_packet      = gxf_write_packet,
    1029             :     .write_trailer     = gxf_write_trailer,
    1030             :     .interleave_packet = gxf_interleave_packet,
    1031             : };

Generated by: LCOV version 1.13