libavformat/gxfenc.c
Go to the documentation of this file.
00001 /*
00002  * GXF muxer.
00003  * Copyright (c) 2006 SmartJog S.A., Baptiste Coudurier <baptiste dot coudurier at smartjog dot com>
00004  *
00005  * This file is part of Libav.
00006  *
00007  * Libav 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  * Libav 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 Libav; 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/intfloat.h"
00023 #include "libavutil/mathematics.h"
00024 #include "avformat.h"
00025 #include "internal.h"
00026 #include "gxf.h"
00027 #include "riff.h"
00028 #include "audiointerleave.h"
00029 
00030 #define GXF_AUDIO_PACKET_SIZE 65536
00031 
00032 typedef struct GXFStreamContext {
00033     AudioInterleaveContext aic;
00034     uint32_t track_type;
00035     uint32_t sample_size;
00036     uint32_t sample_rate;
00037     uint16_t media_type;
00038     uint16_t media_info;
00039     int frame_rate_index;
00040     int lines_index;
00041     int fields;
00042     int iframes;
00043     int pframes;
00044     int bframes;
00045     int p_per_gop;
00046     int b_per_i_or_p; 
00047     int first_gop_closed;
00048     unsigned order;   
00049 } GXFStreamContext;
00050 
00051 typedef struct GXFContext {
00052     uint32_t nb_fields;
00053     uint16_t audio_tracks;
00054     uint16_t mpeg_tracks;
00055     int64_t creation_time;
00056     uint32_t umf_start_offset;
00057     uint32_t umf_track_offset;
00058     uint32_t umf_media_offset;
00059     uint32_t umf_length;
00060     uint16_t umf_track_size;
00061     uint16_t umf_media_size;
00062     AVRational time_base;
00063     int flags;
00064     GXFStreamContext timecode_track;
00065     unsigned *flt_entries;    
00066     unsigned flt_entries_nb;
00067     uint64_t *map_offsets;    
00068     unsigned map_offsets_nb;
00069     unsigned packet_count;
00070 } GXFContext;
00071 
00072 static const struct {
00073     int height, index;
00074 } gxf_lines_tab[] = {
00075     { 480,  1 }, /* NTSC */
00076     { 512,  1 }, /* NTSC + VBI */
00077     { 576,  2 }, /* PAL */
00078     { 608,  2 }, /* PAL + VBI */
00079     { 1080, 4 },
00080     { 720,  6 },
00081 };
00082 
00083 static const AVCodecTag gxf_media_types[] = {
00084     { CODEC_ID_MJPEG     ,   3 }, /* NTSC */
00085     { CODEC_ID_MJPEG     ,   4 }, /* PAL */
00086     { CODEC_ID_PCM_S24LE ,   9 },
00087     { CODEC_ID_PCM_S16LE ,  10 },
00088     { CODEC_ID_MPEG2VIDEO,  11 }, /* NTSC */
00089     { CODEC_ID_MPEG2VIDEO,  12 }, /* PAL */
00090     { CODEC_ID_DVVIDEO   ,  13 }, /* NTSC */
00091     { CODEC_ID_DVVIDEO   ,  14 }, /* PAL */
00092     { CODEC_ID_DVVIDEO   ,  15 }, /* 50M NTSC */
00093     { CODEC_ID_DVVIDEO   ,  16 }, /* 50M PAL */
00094     { CODEC_ID_AC3       ,  17 },
00095     //{ CODEC_ID_NONE,  ,   18 }, /* Non compressed 24 bit audio */
00096     { CODEC_ID_MPEG2VIDEO,  20 }, /* MPEG HD */
00097     { CODEC_ID_MPEG1VIDEO,  22 }, /* NTSC */
00098     { CODEC_ID_MPEG1VIDEO,  23 }, /* PAL */
00099     { CODEC_ID_NONE,         0 },
00100 };
00101 
00102 #define SERVER_PATH "EXT:/PDR/default/"
00103 #define ES_NAME_PATTERN "EXT:/PDR/default/ES."
00104 
00105 static int gxf_find_lines_index(AVStream *st)
00106 {
00107     GXFStreamContext *sc = st->priv_data;
00108     int i;
00109 
00110     for (i = 0; i < 6; ++i) {
00111         if (st->codec->height == gxf_lines_tab[i].height) {
00112             sc->lines_index = gxf_lines_tab[i].index;
00113             return 0;
00114         }
00115     }
00116     return -1;
00117 }
00118 
00119 static void gxf_write_padding(AVIOContext *pb, int64_t to_pad)
00120 {
00121     for (; to_pad > 0; to_pad--) {
00122         avio_w8(pb, 0);
00123     }
00124 }
00125 
00126 static int64_t updatePacketSize(AVIOContext *pb, int64_t pos)
00127 {
00128     int64_t curpos;
00129     int size;
00130 
00131     size = avio_tell(pb) - pos;
00132     if (size % 4) {
00133         gxf_write_padding(pb, 4 - size % 4);
00134         size = avio_tell(pb) - pos;
00135     }
00136     curpos = avio_tell(pb);
00137     avio_seek(pb, pos + 6, SEEK_SET);
00138     avio_wb32(pb, size);
00139     avio_seek(pb, curpos, SEEK_SET);
00140     return curpos - pos;
00141 }
00142 
00143 static int64_t updateSize(AVIOContext *pb, int64_t pos)
00144 {
00145     int64_t curpos;
00146 
00147     curpos = avio_tell(pb);
00148     avio_seek(pb, pos, SEEK_SET);
00149     avio_wb16(pb, curpos - pos - 2);
00150     avio_seek(pb, curpos, SEEK_SET);
00151     return curpos - pos;
00152 }
00153 
00154 static void gxf_write_packet_header(AVIOContext *pb, GXFPktType type)
00155 {
00156     avio_wb32(pb, 0);  /* packet leader for synchro */
00157     avio_w8(pb, 1);
00158     avio_w8(pb, type); /* map packet */
00159     avio_wb32(pb, 0);  /* size */
00160     avio_wb32(pb, 0);  /* reserved */
00161     avio_w8(pb, 0xE1); /* trailer 1 */
00162     avio_w8(pb, 0xE2); /* trailer 2 */
00163 }
00164 
00165 static int gxf_write_mpeg_auxiliary(AVIOContext *pb, AVStream *st)
00166 {
00167     GXFStreamContext *sc = st->priv_data;
00168     char buffer[1024];
00169     int size, starting_line;
00170 
00171     if (sc->iframes) {
00172         sc->p_per_gop = sc->pframes / sc->iframes;
00173         if (sc->pframes % sc->iframes)
00174             sc->p_per_gop++;
00175         if (sc->pframes) {
00176             sc->b_per_i_or_p = sc->bframes / sc->pframes;
00177             if (sc->bframes % sc->pframes)
00178                 sc->b_per_i_or_p++;
00179         }
00180         if (sc->p_per_gop > 9)
00181             sc->p_per_gop = 9; /* ensure value won't take more than one char */
00182         if (sc->b_per_i_or_p > 9)
00183             sc->b_per_i_or_p = 9; /* ensure value won't take more than one char */
00184     }
00185     if (st->codec->height == 512 || st->codec->height == 608)
00186         starting_line = 7; // VBI
00187     else if (st->codec->height == 480)
00188         starting_line = 20;
00189     else
00190         starting_line = 23; // default PAL
00191 
00192     size = snprintf(buffer, 1024, "Ver 1\nBr %.6f\nIpg 1\nPpi %d\nBpiop %d\n"
00193                     "Pix 0\nCf %d\nCg %d\nSl %d\nnl16 %d\nVi 1\nf1 1\n",
00194                     (float)st->codec->bit_rate, sc->p_per_gop, sc->b_per_i_or_p,
00195                     st->codec->pix_fmt == PIX_FMT_YUV422P ? 2 : 1, sc->first_gop_closed == 1,
00196                     starting_line, (st->codec->height + 15) / 16);
00197     avio_w8(pb, TRACK_MPG_AUX);
00198     avio_w8(pb, size + 1);
00199     avio_write(pb, (uint8_t *)buffer, size + 1);
00200     return size + 3;
00201 }
00202 
00203 static int gxf_write_timecode_auxiliary(AVIOContext *pb, GXFStreamContext *sc)
00204 {
00205     avio_w8(pb, 0); /* fields */
00206     avio_w8(pb, 0); /* seconds */
00207     avio_w8(pb, 0); /* minutes */
00208     avio_w8(pb, 0); /* flags + hours */
00209     /* reserved */
00210     avio_wb32(pb, 0);
00211     return 8;
00212 }
00213 
00214 static int gxf_write_track_description(AVFormatContext *s, GXFStreamContext *sc, int index)
00215 {
00216     AVIOContext *pb = s->pb;
00217     int64_t pos;
00218     int mpeg = sc->track_type == 4 || sc->track_type == 9;
00219 
00220     /* track description section */
00221     avio_w8(pb, sc->media_type + 0x80);
00222     avio_w8(pb, index + 0xC0);
00223 
00224     pos = avio_tell(pb);
00225     avio_wb16(pb, 0); /* size */
00226 
00227     /* media file name */
00228     avio_w8(pb, TRACK_NAME);
00229     avio_w8(pb, strlen(ES_NAME_PATTERN) + 3);
00230     avio_write(pb, ES_NAME_PATTERN, sizeof(ES_NAME_PATTERN) - 1);
00231     avio_wb16(pb, sc->media_info);
00232     avio_w8(pb, 0);
00233 
00234     if (!mpeg) {
00235         /* auxiliary information */
00236         avio_w8(pb, TRACK_AUX);
00237         avio_w8(pb, 8);
00238         if (sc->track_type == 3)
00239             gxf_write_timecode_auxiliary(pb, sc);
00240         else
00241             avio_wl64(pb, 0);
00242     }
00243 
00244     /* file system version */
00245     avio_w8(pb, TRACK_VER);
00246     avio_w8(pb, 4);
00247     avio_wb32(pb, 0);
00248 
00249     if (mpeg)
00250         gxf_write_mpeg_auxiliary(pb, s->streams[index]);
00251 
00252     /* frame rate */
00253     avio_w8(pb, TRACK_FPS);
00254     avio_w8(pb, 4);
00255     avio_wb32(pb, sc->frame_rate_index);
00256 
00257     /* lines per frame */
00258     avio_w8(pb, TRACK_LINES);
00259     avio_w8(pb, 4);
00260     avio_wb32(pb, sc->lines_index);
00261 
00262     /* fields per frame */
00263     avio_w8(pb, TRACK_FPF);
00264     avio_w8(pb, 4);
00265     avio_wb32(pb, sc->fields);
00266 
00267     return updateSize(pb, pos);
00268 }
00269 
00270 static int gxf_write_material_data_section(AVFormatContext *s)
00271 {
00272     GXFContext *gxf = s->priv_data;
00273     AVIOContext *pb = s->pb;
00274     int64_t pos;
00275     int len;
00276     const char *filename = strrchr(s->filename, '/');
00277 
00278     pos = avio_tell(pb);
00279     avio_wb16(pb, 0); /* size */
00280 
00281     /* name */
00282     if (filename)
00283         filename++;
00284     else
00285         filename = s->filename;
00286     len = strlen(filename);
00287 
00288     avio_w8(pb, MAT_NAME);
00289     avio_w8(pb, strlen(SERVER_PATH) + len + 1);
00290     avio_write(pb, SERVER_PATH, sizeof(SERVER_PATH) - 1);
00291     avio_write(pb, filename, len);
00292     avio_w8(pb, 0);
00293 
00294     /* first field */
00295     avio_w8(pb, MAT_FIRST_FIELD);
00296     avio_w8(pb, 4);
00297     avio_wb32(pb, 0);
00298 
00299     /* last field */
00300     avio_w8(pb, MAT_LAST_FIELD);
00301     avio_w8(pb, 4);
00302     avio_wb32(pb, gxf->nb_fields);
00303 
00304     /* reserved */
00305     avio_w8(pb, MAT_MARK_IN);
00306     avio_w8(pb, 4);
00307     avio_wb32(pb, 0);
00308 
00309     avio_w8(pb, MAT_MARK_OUT);
00310     avio_w8(pb, 4);
00311     avio_wb32(pb, gxf->nb_fields);
00312 
00313     /* estimated size */
00314     avio_w8(pb, MAT_SIZE);
00315     avio_w8(pb, 4);
00316     avio_wb32(pb, avio_size(pb) / 1024);
00317 
00318     return updateSize(pb, pos);
00319 }
00320 
00321 static int gxf_write_track_description_section(AVFormatContext *s)
00322 {
00323     GXFContext *gxf = s->priv_data;
00324     AVIOContext *pb = s->pb;
00325     int64_t pos;
00326     int i;
00327 
00328     pos = avio_tell(pb);
00329     avio_wb16(pb, 0); /* size */
00330     for (i = 0; i < s->nb_streams; ++i)
00331         gxf_write_track_description(s, s->streams[i]->priv_data, i);
00332 
00333     gxf_write_track_description(s, &gxf->timecode_track, s->nb_streams);
00334 
00335     return updateSize(pb, pos);
00336 }
00337 
00338 static int gxf_write_map_packet(AVFormatContext *s, int rewrite)
00339 {
00340     GXFContext *gxf = s->priv_data;
00341     AVIOContext *pb = s->pb;
00342     int64_t pos = avio_tell(pb);
00343 
00344     if (!rewrite) {
00345         if (!(gxf->map_offsets_nb % 30)) {
00346             gxf->map_offsets = av_realloc(gxf->map_offsets,
00347                                           (gxf->map_offsets_nb+30)*sizeof(*gxf->map_offsets));
00348             if (!gxf->map_offsets) {
00349                 av_log(s, AV_LOG_ERROR, "could not realloc map offsets\n");
00350                 return -1;
00351             }
00352         }
00353         gxf->map_offsets[gxf->map_offsets_nb++] = pos; // do not increment here
00354     }
00355 
00356     gxf_write_packet_header(pb, PKT_MAP);
00357 
00358     /* preamble */
00359     avio_w8(pb, 0xE0); /* version */
00360     avio_w8(pb, 0xFF); /* reserved */
00361 
00362     gxf_write_material_data_section(s);
00363     gxf_write_track_description_section(s);
00364 
00365     return updatePacketSize(pb, pos);
00366 }
00367 
00368 static int gxf_write_flt_packet(AVFormatContext *s)
00369 {
00370     GXFContext *gxf = s->priv_data;
00371     AVIOContext *pb = s->pb;
00372     int64_t pos = avio_tell(pb);
00373     int fields_per_flt = (gxf->nb_fields+1) / 1000 + 1;
00374     int flt_entries = gxf->nb_fields / fields_per_flt;
00375     int i = 0;
00376 
00377     gxf_write_packet_header(pb, PKT_FLT);
00378 
00379     avio_wl32(pb, fields_per_flt); /* number of fields */
00380     avio_wl32(pb, flt_entries); /* number of active flt entries */
00381 
00382     if (gxf->flt_entries) {
00383         for (i = 0; i < flt_entries; i++)
00384             avio_wl32(pb, gxf->flt_entries[(i*fields_per_flt)>>1]);
00385     }
00386 
00387     for (; i < 1000; i++)
00388         avio_wl32(pb, 0);
00389 
00390     return updatePacketSize(pb, pos);
00391 }
00392 
00393 static int gxf_write_umf_material_description(AVFormatContext *s)
00394 {
00395     GXFContext *gxf = s->priv_data;
00396     AVIOContext *pb = s->pb;
00397     int timecode_base = gxf->time_base.den == 60000 ? 60 : 50;
00398     int64_t timestamp = 0;
00399     AVDictionaryEntry *t;
00400     uint32_t timecode;
00401 
00402 #if FF_API_TIMESTAMP
00403     if (s->timestamp)
00404         timestamp = s->timestamp;
00405     else
00406 #endif
00407     if (t = av_dict_get(s->metadata, "creation_time", NULL, 0))
00408         timestamp = ff_iso8601_to_unix_time(t->value);
00409 
00410     // XXX drop frame
00411     timecode =
00412         gxf->nb_fields / (timecode_base * 3600) % 24 << 24 | // hours
00413         gxf->nb_fields / (timecode_base * 60) % 60   << 16 | // minutes
00414         gxf->nb_fields /  timecode_base % 60         <<  8 | // seconds
00415         gxf->nb_fields %  timecode_base;                     // fields
00416 
00417     avio_wl32(pb, gxf->flags);
00418     avio_wl32(pb, gxf->nb_fields); /* length of the longest track */
00419     avio_wl32(pb, gxf->nb_fields); /* length of the shortest track */
00420     avio_wl32(pb, 0); /* mark in */
00421     avio_wl32(pb, gxf->nb_fields); /* mark out */
00422     avio_wl32(pb, 0); /* timecode mark in */
00423     avio_wl32(pb, timecode); /* timecode mark out */
00424     avio_wl64(pb, timestamp); /* modification time */
00425     avio_wl64(pb, timestamp); /* creation time */
00426     avio_wl16(pb, 0); /* reserved */
00427     avio_wl16(pb, 0); /* reserved */
00428     avio_wl16(pb, gxf->audio_tracks);
00429     avio_wl16(pb, 1); /* timecode track count */
00430     avio_wl16(pb, 0); /* reserved */
00431     avio_wl16(pb, gxf->mpeg_tracks);
00432     return 48;
00433 }
00434 
00435 static int gxf_write_umf_payload(AVFormatContext *s)
00436 {
00437     GXFContext *gxf = s->priv_data;
00438     AVIOContext *pb = s->pb;
00439 
00440     avio_wl32(pb, gxf->umf_length); /* total length of the umf data */
00441     avio_wl32(pb, 3); /* version */
00442     avio_wl32(pb, s->nb_streams+1);
00443     avio_wl32(pb, gxf->umf_track_offset); /* umf track section offset */
00444     avio_wl32(pb, gxf->umf_track_size);
00445     avio_wl32(pb, s->nb_streams+1);
00446     avio_wl32(pb, gxf->umf_media_offset);
00447     avio_wl32(pb, gxf->umf_media_size);
00448     avio_wl32(pb, gxf->umf_length); /* user data offset */
00449     avio_wl32(pb, 0); /* user data size */
00450     avio_wl32(pb, 0); /* reserved */
00451     avio_wl32(pb, 0); /* reserved */
00452     return 48;
00453 }
00454 
00455 static int gxf_write_umf_track_description(AVFormatContext *s)
00456 {
00457     AVIOContext *pb = s->pb;
00458     GXFContext *gxf = s->priv_data;
00459     int64_t pos = avio_tell(pb);
00460     int i;
00461 
00462     gxf->umf_track_offset = pos - gxf->umf_start_offset;
00463     for (i = 0; i < s->nb_streams; ++i) {
00464         GXFStreamContext *sc = s->streams[i]->priv_data;
00465         avio_wl16(pb, sc->media_info);
00466         avio_wl16(pb, 1);
00467     }
00468 
00469     avio_wl16(pb, gxf->timecode_track.media_info);
00470     avio_wl16(pb, 1);
00471 
00472     return avio_tell(pb) - pos;
00473 }
00474 
00475 static int gxf_write_umf_media_mpeg(AVIOContext *pb, AVStream *st)
00476 {
00477     GXFStreamContext *sc = st->priv_data;
00478 
00479     if (st->codec->pix_fmt == PIX_FMT_YUV422P)
00480         avio_wl32(pb, 2);
00481     else
00482         avio_wl32(pb, 1); /* default to 420 */
00483     avio_wl32(pb, sc->first_gop_closed == 1); /* closed = 1, open = 0, unknown = 255 */
00484     avio_wl32(pb, 3); /* top = 1, bottom = 2, frame = 3, unknown = 0 */
00485     avio_wl32(pb, 1); /* I picture per GOP */
00486     avio_wl32(pb, sc->p_per_gop);
00487     avio_wl32(pb, sc->b_per_i_or_p);
00488     if (st->codec->codec_id == CODEC_ID_MPEG2VIDEO)
00489         avio_wl32(pb, 2);
00490     else if (st->codec->codec_id == CODEC_ID_MPEG1VIDEO)
00491         avio_wl32(pb, 1);
00492     else
00493         avio_wl32(pb, 0);
00494     avio_wl32(pb, 0); /* reserved */
00495     return 32;
00496 }
00497 
00498 static int gxf_write_umf_media_timecode(AVIOContext *pb, GXFStreamContext *sc)
00499 {
00500     avio_wl32(pb, 1); /* non drop frame */
00501     avio_wl32(pb, 0); /* reserved */
00502     avio_wl32(pb, 0); /* reserved */
00503     avio_wl32(pb, 0); /* reserved */
00504     avio_wl32(pb, 0); /* reserved */
00505     avio_wl32(pb, 0); /* reserved */
00506     avio_wl32(pb, 0); /* reserved */
00507     avio_wl32(pb, 0); /* reserved */
00508     return 32;
00509 }
00510 
00511 static int gxf_write_umf_media_dv(AVIOContext *pb, GXFStreamContext *sc)
00512 {
00513     int i;
00514 
00515     for (i = 0; i < 8; i++) {
00516         avio_wb32(pb, 0);
00517     }
00518     return 32;
00519 }
00520 
00521 static int gxf_write_umf_media_audio(AVIOContext *pb, GXFStreamContext *sc)
00522 {
00523     avio_wl64(pb, av_double2int(1)); /* sound level to begin to */
00524     avio_wl64(pb, av_double2int(1)); /* sound level to begin to */
00525     avio_wl32(pb, 0); /* number of fields over which to ramp up sound level */
00526     avio_wl32(pb, 0); /* number of fields over which to ramp down sound level */
00527     avio_wl32(pb, 0); /* reserved */
00528     avio_wl32(pb, 0); /* reserved */
00529     return 32;
00530 }
00531 
00532 #if 0
00533 static int gxf_write_umf_media_mjpeg(AVIOContext *pb, GXFStreamContext *sc)
00534 {
00535     avio_wb64(pb, 0); /* FIXME FLOAT max chroma quant level */
00536     avio_wb64(pb, 0); /* FIXME FLOAT max luma quant level */
00537     avio_wb64(pb, 0); /* FIXME FLOAT min chroma quant level */
00538     avio_wb64(pb, 0); /* FIXME FLOAT min luma quant level */
00539     return 32;
00540 }
00541 #endif
00542 
00543 static int gxf_write_umf_media_description(AVFormatContext *s)
00544 {
00545     GXFContext *gxf = s->priv_data;
00546     AVIOContext *pb = s->pb;
00547     int64_t pos;
00548     int i, j;
00549 
00550     pos = avio_tell(pb);
00551     gxf->umf_media_offset = pos - gxf->umf_start_offset;
00552     for (i = 0; i <= s->nb_streams; ++i) {
00553         GXFStreamContext *sc;
00554         int64_t startpos, curpos;
00555 
00556         if (i == s->nb_streams)
00557             sc = &gxf->timecode_track;
00558         else
00559             sc = s->streams[i]->priv_data;
00560 
00561         startpos = avio_tell(pb);
00562         avio_wl16(pb, 0); /* length */
00563         avio_wl16(pb, sc->media_info);
00564         avio_wl16(pb, 0); /* reserved */
00565         avio_wl16(pb, 0); /* reserved */
00566         avio_wl32(pb, gxf->nb_fields);
00567         avio_wl32(pb, 0); /* attributes rw, ro */
00568         avio_wl32(pb, 0); /* mark in */
00569         avio_wl32(pb, gxf->nb_fields); /* mark out */
00570         avio_write(pb, ES_NAME_PATTERN, strlen(ES_NAME_PATTERN));
00571         avio_wb16(pb, sc->media_info);
00572         for (j = strlen(ES_NAME_PATTERN)+2; j < 88; j++)
00573             avio_w8(pb, 0);
00574         avio_wl32(pb, sc->track_type);
00575         avio_wl32(pb, sc->sample_rate);
00576         avio_wl32(pb, sc->sample_size);
00577         avio_wl32(pb, 0); /* reserved */
00578 
00579         if (sc == &gxf->timecode_track)
00580             gxf_write_umf_media_timecode(pb, sc); /* 8 0bytes */
00581         else {
00582             AVStream *st = s->streams[i];
00583             switch (st->codec->codec_id) {
00584             case CODEC_ID_MPEG1VIDEO:
00585             case CODEC_ID_MPEG2VIDEO:
00586                 gxf_write_umf_media_mpeg(pb, st);
00587                 break;
00588             case CODEC_ID_PCM_S16LE:
00589                 gxf_write_umf_media_audio(pb, sc);
00590                 break;
00591             case CODEC_ID_DVVIDEO:
00592                 gxf_write_umf_media_dv(pb, sc);
00593                 break;
00594             }
00595         }
00596 
00597         curpos = avio_tell(pb);
00598         avio_seek(pb, startpos, SEEK_SET);
00599         avio_wl16(pb, curpos - startpos);
00600         avio_seek(pb, curpos, SEEK_SET);
00601     }
00602     return avio_tell(pb) - pos;
00603 }
00604 
00605 static int gxf_write_umf_packet(AVFormatContext *s)
00606 {
00607     GXFContext *gxf = s->priv_data;
00608     AVIOContext *pb = s->pb;
00609     int64_t pos = avio_tell(pb);
00610 
00611     gxf_write_packet_header(pb, PKT_UMF);
00612 
00613     /* preamble */
00614     avio_w8(pb, 3); /* first and last (only) packet */
00615     avio_wb32(pb, gxf->umf_length); /* data length */
00616 
00617     gxf->umf_start_offset = avio_tell(pb);
00618     gxf_write_umf_payload(s);
00619     gxf_write_umf_material_description(s);
00620     gxf->umf_track_size = gxf_write_umf_track_description(s);
00621     gxf->umf_media_size = gxf_write_umf_media_description(s);
00622     gxf->umf_length = avio_tell(pb) - gxf->umf_start_offset;
00623     return updatePacketSize(pb, pos);
00624 }
00625 
00626 static const int GXF_samples_per_frame[] = { 32768, 0 };
00627 
00628 static void gxf_init_timecode_track(GXFStreamContext *sc, GXFStreamContext *vsc)
00629 {
00630     if (!vsc)
00631         return;
00632 
00633     sc->media_type = vsc->sample_rate == 60 ? 7 : 8;
00634     sc->sample_rate = vsc->sample_rate;
00635     sc->media_info = ('T'<<8) | '0';
00636     sc->track_type = 3;
00637     sc->frame_rate_index = vsc->frame_rate_index;
00638     sc->lines_index = vsc->lines_index;
00639     sc->sample_size = 16;
00640     sc->fields = vsc->fields;
00641 }
00642 
00643 static int gxf_write_header(AVFormatContext *s)
00644 {
00645     AVIOContext *pb = s->pb;
00646     GXFContext *gxf = s->priv_data;
00647     GXFStreamContext *vsc = NULL;
00648     uint8_t tracks[255] = {0};
00649     int i, media_info = 0;
00650 
00651     if (!pb->seekable) {
00652         av_log(s, AV_LOG_ERROR, "gxf muxer does not support streamed output, patch welcome");
00653         return -1;
00654     }
00655 
00656     gxf->flags |= 0x00080000; /* material is simple clip */
00657     for (i = 0; i < s->nb_streams; ++i) {
00658         AVStream *st = s->streams[i];
00659         GXFStreamContext *sc = av_mallocz(sizeof(*sc));
00660         if (!sc)
00661             return AVERROR(ENOMEM);
00662         st->priv_data = sc;
00663 
00664         sc->media_type = ff_codec_get_tag(gxf_media_types, st->codec->codec_id);
00665         if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
00666             if (st->codec->codec_id != CODEC_ID_PCM_S16LE) {
00667                 av_log(s, AV_LOG_ERROR, "only 16 BIT PCM LE allowed for now\n");
00668                 return -1;
00669             }
00670             if (st->codec->sample_rate != 48000) {
00671                 av_log(s, AV_LOG_ERROR, "only 48000hz sampling rate is allowed\n");
00672                 return -1;
00673             }
00674             if (st->codec->channels != 1) {
00675                 av_log(s, AV_LOG_ERROR, "only mono tracks are allowed\n");
00676                 return -1;
00677             }
00678             sc->track_type = 2;
00679             sc->sample_rate = st->codec->sample_rate;
00680             avpriv_set_pts_info(st, 64, 1, sc->sample_rate);
00681             sc->sample_size = 16;
00682             sc->frame_rate_index = -2;
00683             sc->lines_index = -2;
00684             sc->fields = -2;
00685             gxf->audio_tracks++;
00686             gxf->flags |= 0x04000000; /* audio is 16 bit pcm */
00687             media_info = 'A';
00688         } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
00689             if (i != 0) {
00690                 av_log(s, AV_LOG_ERROR, "video stream must be the first track\n");
00691                 return -1;
00692             }
00693             /* FIXME check from time_base ? */
00694             if (st->codec->height == 480 || st->codec->height == 512) { /* NTSC or NTSC+VBI */
00695                 sc->frame_rate_index = 5;
00696                 sc->sample_rate = 60;
00697                 gxf->flags |= 0x00000080;
00698                 gxf->time_base = (AVRational){ 1001, 60000 };
00699             } else if (st->codec->height == 576 || st->codec->height == 608) { /* PAL or PAL+VBI */
00700                 sc->frame_rate_index = 6;
00701                 sc->media_type++;
00702                 sc->sample_rate = 50;
00703                 gxf->flags |= 0x00000040;
00704                 gxf->time_base = (AVRational){ 1, 50 };
00705             } else {
00706                 av_log(s, AV_LOG_ERROR, "unsupported video resolution, "
00707                        "gxf muxer only accepts PAL or NTSC resolutions currently\n");
00708                 return -1;
00709             }
00710             avpriv_set_pts_info(st, 64, gxf->time_base.num, gxf->time_base.den);
00711             if (gxf_find_lines_index(st) < 0)
00712                 sc->lines_index = -1;
00713             sc->sample_size = st->codec->bit_rate;
00714             sc->fields = 2; /* interlaced */
00715 
00716             vsc = sc;
00717 
00718             switch (st->codec->codec_id) {
00719             case CODEC_ID_MJPEG:
00720                 sc->track_type = 1;
00721                 gxf->flags |= 0x00004000;
00722                 media_info = 'J';
00723                 break;
00724             case CODEC_ID_MPEG1VIDEO:
00725                 sc->track_type = 9;
00726                 gxf->mpeg_tracks++;
00727                 media_info = 'L';
00728                 break;
00729             case CODEC_ID_MPEG2VIDEO:
00730                 sc->first_gop_closed = -1;
00731                 sc->track_type = 4;
00732                 gxf->mpeg_tracks++;
00733                 gxf->flags |= 0x00008000;
00734                 media_info = 'M';
00735                 break;
00736             case CODEC_ID_DVVIDEO:
00737                 if (st->codec->pix_fmt == PIX_FMT_YUV422P) {
00738                     sc->media_type += 2;
00739                     sc->track_type = 6;
00740                     gxf->flags |= 0x00002000;
00741                     media_info = 'E';
00742                 } else {
00743                     sc->track_type = 5;
00744                     gxf->flags |= 0x00001000;
00745                     media_info = 'D';
00746                 }
00747                 break;
00748             default:
00749                 av_log(s, AV_LOG_ERROR, "video codec not supported\n");
00750                 return -1;
00751             }
00752         }
00753         /* FIXME first 10 audio tracks are 0 to 9 next 22 are A to V */
00754         sc->media_info = media_info<<8 | ('0'+tracks[media_info]++);
00755         sc->order = s->nb_streams - st->index;
00756     }
00757 
00758     if (ff_audio_interleave_init(s, GXF_samples_per_frame, (AVRational){ 1, 48000 }) < 0)
00759         return -1;
00760 
00761     gxf_init_timecode_track(&gxf->timecode_track, vsc);
00762     gxf->flags |= 0x200000; // time code track is non-drop frame
00763 
00764     gxf_write_map_packet(s, 0);
00765     gxf_write_flt_packet(s);
00766     gxf_write_umf_packet(s);
00767 
00768     gxf->packet_count = 3;
00769 
00770     avio_flush(pb);
00771     return 0;
00772 }
00773 
00774 static int gxf_write_eos_packet(AVIOContext *pb)
00775 {
00776     int64_t pos = avio_tell(pb);
00777 
00778     gxf_write_packet_header(pb, PKT_EOS);
00779     return updatePacketSize(pb, pos);
00780 }
00781 
00782 static int gxf_write_trailer(AVFormatContext *s)
00783 {
00784     GXFContext *gxf = s->priv_data;
00785     AVIOContext *pb = s->pb;
00786     int64_t end;
00787     int i;
00788 
00789     ff_audio_interleave_close(s);
00790 
00791     gxf_write_eos_packet(pb);
00792     end = avio_tell(pb);
00793     avio_seek(pb, 0, SEEK_SET);
00794     /* overwrite map, flt and umf packets with new values */
00795     gxf_write_map_packet(s, 1);
00796     gxf_write_flt_packet(s);
00797     gxf_write_umf_packet(s);
00798     avio_flush(pb);
00799     /* update duration in all map packets */
00800     for (i = 1; i < gxf->map_offsets_nb; i++) {
00801         avio_seek(pb, gxf->map_offsets[i], SEEK_SET);
00802         gxf_write_map_packet(s, 1);
00803         avio_flush(pb);
00804     }
00805 
00806     avio_seek(pb, end, SEEK_SET);
00807 
00808     av_freep(&gxf->flt_entries);
00809     av_freep(&gxf->map_offsets);
00810 
00811     return 0;
00812 }
00813 
00814 static int gxf_parse_mpeg_frame(GXFStreamContext *sc, const uint8_t *buf, int size)
00815 {
00816     uint32_t c=-1;
00817     int i;
00818     for(i=0; i<size-4 && c!=0x100; i++){
00819         c = (c<<8) + buf[i];
00820         if(c == 0x1B8 && sc->first_gop_closed == -1) /* GOP start code */
00821             sc->first_gop_closed= (buf[i+4]>>6)&1;
00822     }
00823     return (buf[i+1]>>3)&7;
00824 }
00825 
00826 static int gxf_write_media_preamble(AVFormatContext *s, AVPacket *pkt, int size)
00827 {
00828     GXFContext *gxf = s->priv_data;
00829     AVIOContext *pb = s->pb;
00830     AVStream *st = s->streams[pkt->stream_index];
00831     GXFStreamContext *sc = st->priv_data;
00832     unsigned field_nb;
00833     /* If the video is frame-encoded, the frame numbers shall be represented by
00834      * even field numbers.
00835      * see SMPTE360M-2004  6.4.2.1.3 Media field number */
00836     if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
00837         field_nb = gxf->nb_fields;
00838     } else {
00839         field_nb = av_rescale_rnd(pkt->dts, gxf->time_base.den,
00840                                   (int64_t)48000*gxf->time_base.num, AV_ROUND_UP);
00841     }
00842 
00843     avio_w8(pb, sc->media_type);
00844     avio_w8(pb, st->index);
00845     avio_wb32(pb, field_nb);
00846     if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
00847         avio_wb16(pb, 0);
00848         avio_wb16(pb, size / 2);
00849     } else if (st->codec->codec_id == CODEC_ID_MPEG2VIDEO) {
00850         int frame_type = gxf_parse_mpeg_frame(sc, pkt->data, pkt->size);
00851         if (frame_type == AV_PICTURE_TYPE_I) {
00852             avio_w8(pb, 0x0d);
00853             sc->iframes++;
00854         } else if (frame_type == AV_PICTURE_TYPE_B) {
00855             avio_w8(pb, 0x0f);
00856             sc->bframes++;
00857         } else {
00858             avio_w8(pb, 0x0e);
00859             sc->pframes++;
00860         }
00861         avio_wb24(pb, size);
00862     } else if (st->codec->codec_id == CODEC_ID_DVVIDEO) {
00863         avio_w8(pb, size / 4096);
00864         avio_wb24(pb, 0);
00865     } else
00866         avio_wb32(pb, size);
00867     avio_wb32(pb, field_nb);
00868     avio_w8(pb, 1); /* flags */
00869     avio_w8(pb, 0); /* reserved */
00870     return 16;
00871 }
00872 
00873 static int gxf_write_packet(AVFormatContext *s, AVPacket *pkt)
00874 {
00875     GXFContext *gxf = s->priv_data;
00876     AVIOContext *pb = s->pb;
00877     AVStream *st = s->streams[pkt->stream_index];
00878     int64_t pos = avio_tell(pb);
00879     int padding = 0;
00880     int packet_start_offset = avio_tell(pb) / 1024;
00881 
00882     gxf_write_packet_header(pb, PKT_MEDIA);
00883     if (st->codec->codec_id == CODEC_ID_MPEG2VIDEO && pkt->size % 4) /* MPEG-2 frames must be padded */
00884         padding = 4 - pkt->size % 4;
00885     else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
00886         padding = GXF_AUDIO_PACKET_SIZE - pkt->size;
00887     gxf_write_media_preamble(s, pkt, pkt->size + padding);
00888     avio_write(pb, pkt->data, pkt->size);
00889     gxf_write_padding(pb, padding);
00890 
00891     if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
00892         if (!(gxf->flt_entries_nb % 500)) {
00893             gxf->flt_entries = av_realloc(gxf->flt_entries,
00894                                           (gxf->flt_entries_nb+500)*sizeof(*gxf->flt_entries));
00895             if (!gxf->flt_entries) {
00896                 av_log(s, AV_LOG_ERROR, "could not reallocate flt entries\n");
00897                 return -1;
00898             }
00899         }
00900         gxf->flt_entries[gxf->flt_entries_nb++] = packet_start_offset;
00901         gxf->nb_fields += 2; // count fields
00902     }
00903 
00904     updatePacketSize(pb, pos);
00905 
00906     gxf->packet_count++;
00907     if (gxf->packet_count == 100) {
00908         gxf_write_map_packet(s, 0);
00909         gxf->packet_count = 0;
00910     }
00911 
00912     avio_flush(pb);
00913 
00914     return 0;
00915 }
00916 
00917 static int gxf_compare_field_nb(AVFormatContext *s, AVPacket *next, AVPacket *cur)
00918 {
00919     GXFContext *gxf = s->priv_data;
00920     AVPacket *pkt[2] = { cur, next };
00921     int i, field_nb[2];
00922     GXFStreamContext *sc[2];
00923 
00924     for (i = 0; i < 2; i++) {
00925         AVStream *st = s->streams[pkt[i]->stream_index];
00926         sc[i] = st->priv_data;
00927         if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
00928             field_nb[i] = av_rescale_rnd(pkt[i]->dts, gxf->time_base.den,
00929                                          (int64_t)48000*gxf->time_base.num, AV_ROUND_UP);
00930             field_nb[i] &= ~1; // compare against even field number because audio must be before video
00931         } else
00932             field_nb[i] = pkt[i]->dts; // dts are field based
00933     }
00934 
00935     return field_nb[1] > field_nb[0] ||
00936         (field_nb[1] == field_nb[0] && sc[1]->order > sc[0]->order);
00937 }
00938 
00939 static int gxf_interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush)
00940 {
00941     if (pkt && s->streams[pkt->stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
00942         pkt->duration = 2; // enforce 2 fields
00943     return ff_audio_rechunk_interleave(s, out, pkt, flush,
00944                                av_interleave_packet_per_dts, gxf_compare_field_nb);
00945 }
00946 
00947 AVOutputFormat ff_gxf_muxer = {
00948     .name              = "gxf",
00949     .long_name         = NULL_IF_CONFIG_SMALL("GXF format"),
00950     .extensions        = "gxf",
00951     .priv_data_size    = sizeof(GXFContext),
00952     .audio_codec       = CODEC_ID_PCM_S16LE,
00953     .video_codec       = CODEC_ID_MPEG2VIDEO,
00954     .write_header      = gxf_write_header,
00955     .write_packet      = gxf_write_packet,
00956     .write_trailer     = gxf_write_trailer,
00957     .interleave_packet = gxf_interleave_packet,
00958 };