annotate ffmpeg/libavformat/gxfenc.c @ 13:844d341cf643 tip

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