comparison gxfenc.c @ 4676:0e45c20bbb9e libavformat

write timecode track in gxf
author bcoudurier
date Mon, 09 Mar 2009 00:14:55 +0000
parents f036a151abf8
children 96c24e93b7d8
comparison
equal deleted inserted replaced
4675:f036a151abf8 4676:0e45c20bbb9e
56 uint32_t umf_length; 56 uint32_t umf_length;
57 uint16_t umf_track_size; 57 uint16_t umf_track_size;
58 uint16_t umf_media_size; 58 uint16_t umf_media_size;
59 int sample_rate; 59 int sample_rate;
60 int flags; 60 int flags;
61 GXFStreamContext timecode_track;
61 } GXFContext; 62 } GXFContext;
62 63
63 typedef struct GXF_Lines { 64 typedef struct GXF_Lines {
64 int height; 65 int height;
65 int index; 66 int index;
196 return size + 3; 197 return size + 3;
197 } 198 }
198 199
199 static int gxf_write_timecode_auxiliary(ByteIOContext *pb, GXFStreamContext *sc) 200 static int gxf_write_timecode_auxiliary(ByteIOContext *pb, GXFStreamContext *sc)
200 { 201 {
201 /* FIXME implement that */
202 put_byte(pb, 0); /* fields */ 202 put_byte(pb, 0); /* fields */
203 put_byte(pb, 0); /* seconds */ 203 put_byte(pb, 0); /* seconds */
204 put_byte(pb, 0); /* minutes */ 204 put_byte(pb, 0); /* minutes */
205 put_byte(pb, 0); /* flags + hours */ 205 put_byte(pb, 0); /* flags + hours */
206 /* reserved */ 206 /* reserved */
207 put_be32(pb, 0); 207 put_be32(pb, 0);
208 return 8; 208 return 8;
209 } 209 }
210 210
211 static int gxf_write_track_description(ByteIOContext *pb, AVStream *st) 211 static int gxf_write_track_description(AVFormatContext *s, GXFStreamContext *sc, int index)
212 { 212 {
213 GXFStreamContext *sc = st->priv_data; 213 ByteIOContext *pb = s->pb;
214 int64_t pos; 214 int64_t pos;
215 int mpeg = sc->track_type == 4 || sc->track_type == 9;
215 216
216 /* track description section */ 217 /* track description section */
217 put_byte(pb, sc->media_type + 0x80); 218 put_byte(pb, sc->media_type + 0x80);
218 put_byte(pb, st->index + 0xC0); 219 put_byte(pb, index + 0xC0);
219 220
220 pos = url_ftell(pb); 221 pos = url_ftell(pb);
221 put_be16(pb, 0); /* size */ 222 put_be16(pb, 0); /* size */
222 223
223 /* media file name */ 224 /* media file name */
225 put_byte(pb, strlen(ES_NAME_PATTERN) + 3); 226 put_byte(pb, strlen(ES_NAME_PATTERN) + 3);
226 put_tag(pb, ES_NAME_PATTERN); 227 put_tag(pb, ES_NAME_PATTERN);
227 put_be16(pb, sc->media_info); 228 put_be16(pb, sc->media_info);
228 put_byte(pb, 0); 229 put_byte(pb, 0);
229 230
230 if (st->codec->codec_id != CODEC_ID_MPEG2VIDEO) { 231 if (!mpeg) {
231 /* auxiliary information */ 232 /* auxiliary information */
232 put_byte(pb, TRACK_AUX); 233 put_byte(pb, TRACK_AUX);
233 put_byte(pb, 8); 234 put_byte(pb, 8);
234 if (st->codec->codec_id == CODEC_ID_NONE) 235 if (sc->track_type == 3)
235 gxf_write_timecode_auxiliary(pb, sc); 236 gxf_write_timecode_auxiliary(pb, sc);
236 else 237 else
237 put_le64(pb, 0); 238 put_le64(pb, 0);
238 } 239 }
239 240
240 /* file system version */ 241 /* file system version */
241 put_byte(pb, TRACK_VER); 242 put_byte(pb, TRACK_VER);
242 put_byte(pb, 4); 243 put_byte(pb, 4);
243 put_be32(pb, 0); 244 put_be32(pb, 0);
244 245
245 if (st->codec->codec_id == CODEC_ID_MPEG2VIDEO) 246 if (mpeg)
246 gxf_write_mpeg_auxiliary(pb, st); 247 gxf_write_mpeg_auxiliary(pb, s->streams[index]);
247 248
248 /* frame rate */ 249 /* frame rate */
249 put_byte(pb, TRACK_FPS); 250 put_byte(pb, TRACK_FPS);
250 put_byte(pb, 4); 251 put_byte(pb, 4);
251 put_be32(pb, sc->frame_rate_index); 252 put_be32(pb, sc->frame_rate_index);
311 return updateSize(pb, pos); 312 return updateSize(pb, pos);
312 } 313 }
313 314
314 static int gxf_write_track_description_section(AVFormatContext *s) 315 static int gxf_write_track_description_section(AVFormatContext *s)
315 { 316 {
317 GXFContext *gxf = s->priv_data;
316 ByteIOContext *pb = s->pb; 318 ByteIOContext *pb = s->pb;
317 int64_t pos; 319 int64_t pos;
318 int i; 320 int i;
319 321
320 pos = url_ftell(pb); 322 pos = url_ftell(pb);
321 put_be16(pb, 0); /* size */ 323 put_be16(pb, 0); /* size */
322 for (i = 0; i < s->nb_streams; ++i) 324 for (i = 0; i < s->nb_streams; ++i)
323 gxf_write_track_description(pb, s->streams[i]); 325 gxf_write_track_description(s, s->streams[i]->priv_data, i);
326
327 gxf_write_track_description(s, &gxf->timecode_track, s->nb_streams);
328
324 return updateSize(pb, pos); 329 return updateSize(pb, pos);
325 } 330 }
326 331
327 static int gxf_write_map_packet(AVFormatContext *s) 332 static int gxf_write_map_packet(AVFormatContext *s)
328 { 333 {
383 put_le64(pb, s->timestamp); /* modification time */ 388 put_le64(pb, s->timestamp); /* modification time */
384 put_le64(pb, s->timestamp); /* creation time */ 389 put_le64(pb, s->timestamp); /* creation time */
385 put_le16(pb, 0); /* reserved */ 390 put_le16(pb, 0); /* reserved */
386 put_le16(pb, 0); /* reserved */ 391 put_le16(pb, 0); /* reserved */
387 put_le16(pb, gxf->audio_tracks); 392 put_le16(pb, gxf->audio_tracks);
388 put_le16(pb, 0); /* timecode track count */ 393 put_le16(pb, 1); /* timecode track count */
389 put_le16(pb, 0); /* reserved */ 394 put_le16(pb, 0); /* reserved */
390 put_le16(pb, gxf->mpeg_tracks); 395 put_le16(pb, gxf->mpeg_tracks);
391 return 48; 396 return 48;
392 } 397 }
393 398
396 GXFContext *gxf = s->priv_data; 401 GXFContext *gxf = s->priv_data;
397 ByteIOContext *pb = s->pb; 402 ByteIOContext *pb = s->pb;
398 403
399 put_le32(pb, gxf->umf_length); /* total length of the umf data */ 404 put_le32(pb, gxf->umf_length); /* total length of the umf data */
400 put_le32(pb, 3); /* version */ 405 put_le32(pb, 3); /* version */
401 put_le32(pb, s->nb_streams); 406 put_le32(pb, s->nb_streams+1);
402 put_le32(pb, gxf->umf_track_offset); /* umf track section offset */ 407 put_le32(pb, gxf->umf_track_offset); /* umf track section offset */
403 put_le32(pb, gxf->umf_track_size); 408 put_le32(pb, gxf->umf_track_size);
404 put_le32(pb, s->nb_streams); 409 put_le32(pb, s->nb_streams+1);
405 put_le32(pb, gxf->umf_media_offset); 410 put_le32(pb, gxf->umf_media_offset);
406 put_le32(pb, gxf->umf_media_size); 411 put_le32(pb, gxf->umf_media_size);
407 put_le32(pb, gxf->umf_length); /* user data offset */ 412 put_le32(pb, gxf->umf_length); /* user data offset */
408 put_le32(pb, 0); /* user data size */ 413 put_le32(pb, 0); /* user data size */
409 put_le32(pb, 0); /* reserved */ 414 put_le32(pb, 0); /* reserved */
422 for (i = 0; i < s->nb_streams; ++i) { 427 for (i = 0; i < s->nb_streams; ++i) {
423 GXFStreamContext *sc = s->streams[i]->priv_data; 428 GXFStreamContext *sc = s->streams[i]->priv_data;
424 put_le16(pb, sc->media_info); 429 put_le16(pb, sc->media_info);
425 put_le16(pb, 1); 430 put_le16(pb, 1);
426 } 431 }
432
433 put_le16(pb, gxf->timecode_track.media_info);
434 put_le16(pb, 1);
435
427 return url_ftell(pb) - pos; 436 return url_ftell(pb) - pos;
428 } 437 }
429 438
430 static int gxf_write_umf_media_mpeg(ByteIOContext *pb, AVStream *st) 439 static int gxf_write_umf_media_mpeg(ByteIOContext *pb, AVStream *st)
431 { 440 {
450 return 32; 459 return 32;
451 } 460 }
452 461
453 static int gxf_write_umf_media_timecode(ByteIOContext *pb, GXFStreamContext *sc) 462 static int gxf_write_umf_media_timecode(ByteIOContext *pb, GXFStreamContext *sc)
454 { 463 {
455 /* FIXME implement */ 464 put_le32(pb, 1); /* non drop frame */
456 put_be32(pb, 0); /* drop frame flag */ 465 put_le32(pb, 0); /* reserved */
457 put_be32(pb, 0); /* reserved */ 466 put_le32(pb, 0); /* reserved */
458 put_be32(pb, 0); /* reserved */ 467 put_le32(pb, 0); /* reserved */
459 put_be32(pb, 0); /* reserved */ 468 put_le32(pb, 0); /* reserved */
460 put_be32(pb, 0); /* reserved */ 469 put_le32(pb, 0); /* reserved */
461 put_be32(pb, 0); /* reserved */ 470 put_le32(pb, 0); /* reserved */
462 put_be32(pb, 0); /* reserved */ 471 put_le32(pb, 0); /* reserved */
463 put_be32(pb, 0); /* reserved */
464 return 32; 472 return 32;
465 } 473 }
466 474
467 static int gxf_write_umf_media_dv(ByteIOContext *pb, GXFStreamContext *sc) 475 static int gxf_write_umf_media_dv(ByteIOContext *pb, GXFStreamContext *sc)
468 { 476 {
503 int64_t pos; 511 int64_t pos;
504 int i; 512 int i;
505 513
506 pos = url_ftell(pb); 514 pos = url_ftell(pb);
507 gxf->umf_media_offset = pos - gxf->umf_start_offset; 515 gxf->umf_media_offset = pos - gxf->umf_start_offset;
508 for (i = 0; i < s->nb_streams; ++i) { 516 for (i = 0; i <= s->nb_streams; ++i) {
509 AVStream *st = s->streams[i]; 517 GXFStreamContext *sc;
510 GXFStreamContext *sc = st->priv_data;
511 char buffer[88]; 518 char buffer[88];
512 int64_t startpos, curpos; 519 int64_t startpos, curpos;
513 int path_size = strlen(ES_NAME_PATTERN); 520 int path_size = strlen(ES_NAME_PATTERN);
521
522 if (i == s->nb_streams)
523 sc = &gxf->timecode_track;
524 else
525 sc = s->streams[i]->priv_data;
514 526
515 memset(buffer, 0, 88); 527 memset(buffer, 0, 88);
516 startpos = url_ftell(pb); 528 startpos = url_ftell(pb);
517 put_le16(pb, 0); /* length */ 529 put_le16(pb, 0); /* length */
518 put_le16(pb, sc->media_info); 530 put_le16(pb, sc->media_info);
528 put_buffer(pb, (uint8_t *)buffer + path_size + 2, 88 - path_size - 2); 540 put_buffer(pb, (uint8_t *)buffer + path_size + 2, 88 - path_size - 2);
529 put_le32(pb, sc->track_type); 541 put_le32(pb, sc->track_type);
530 put_le32(pb, sc->sample_rate); 542 put_le32(pb, sc->sample_rate);
531 put_le32(pb, sc->sample_size); 543 put_le32(pb, sc->sample_size);
532 put_le32(pb, 0); /* reserved */ 544 put_le32(pb, 0); /* reserved */
545
546 if (sc == &gxf->timecode_track)
547 gxf_write_umf_media_timecode(pb, sc); /* 8 0bytes */
548 else {
549 AVStream *st = s->streams[i];
533 switch (st->codec->codec_id) { 550 switch (st->codec->codec_id) {
534 case CODEC_ID_MPEG2VIDEO: 551 case CODEC_ID_MPEG2VIDEO:
535 gxf_write_umf_media_mpeg(pb, st); 552 gxf_write_umf_media_mpeg(pb, st);
536 break; 553 break;
537 case CODEC_ID_PCM_S16LE: 554 case CODEC_ID_PCM_S16LE:
538 gxf_write_umf_media_audio(pb, sc); 555 gxf_write_umf_media_audio(pb, sc);
539 break; 556 break;
540 case CODEC_ID_DVVIDEO: 557 case CODEC_ID_DVVIDEO:
541 gxf_write_umf_media_dv(pb, sc); 558 gxf_write_umf_media_dv(pb, sc);
542 break; 559 break;
543 default:
544 gxf_write_umf_media_timecode(pb, sc); /* 8 0bytes */
545 } 560 }
561 }
562
546 curpos = url_ftell(pb); 563 curpos = url_ftell(pb);
547 url_fseek(pb, startpos, SEEK_SET); 564 url_fseek(pb, startpos, SEEK_SET);
548 put_le16(pb, curpos - startpos); 565 put_le16(pb, curpos - startpos);
549 url_fseek(pb, curpos, SEEK_SET); 566 url_fseek(pb, curpos, SEEK_SET);
550 } 567 }
572 return updatePacketSize(pb, pos); 589 return updatePacketSize(pb, pos);
573 } 590 }
574 591
575 static const int GXF_samples_per_frame[] = { 32768, 0 }; 592 static const int GXF_samples_per_frame[] = { 32768, 0 };
576 593
594 static void gxf_init_timecode_track(GXFStreamContext *sc, GXFStreamContext *vsc)
595 {
596 if (!vsc)
597 return;
598
599 sc->media_type = vsc->sample_rate == 60 ? 7 : 8;
600 sc->sample_rate = vsc->sample_rate;
601 sc->media_info = ('T'<<8) | '0';
602 sc->track_type = 3;
603 sc->frame_rate_index = vsc->frame_rate_index;
604 sc->lines_index = vsc->lines_index;
605 sc->sample_size = 16;
606 sc->fields = vsc->fields;
607 }
608
577 static int gxf_write_header(AVFormatContext *s) 609 static int gxf_write_header(AVFormatContext *s)
578 { 610 {
579 ByteIOContext *pb = s->pb; 611 ByteIOContext *pb = s->pb;
580 GXFContext *gxf = s->priv_data; 612 GXFContext *gxf = s->priv_data;
613 GXFStreamContext *vsc = NULL;
581 uint8_t tracks[255] = {0}; 614 uint8_t tracks[255] = {0};
582 int i, media_info = 0; 615 int i, media_info = 0;
583 616
584 gxf->flags |= 0x00080000; /* material is simple clip */ 617 gxf->flags |= 0x00080000; /* material is simple clip */
585 for (i = 0; i < s->nb_streams; ++i) { 618 for (i = 0; i < s->nb_streams; ++i) {
629 av_set_pts_info(st, 64, 1, st->codec->time_base.den); 662 av_set_pts_info(st, 64, 1, st->codec->time_base.den);
630 if (gxf_find_lines_index(st) < 0) 663 if (gxf_find_lines_index(st) < 0)
631 sc->lines_index = -1; 664 sc->lines_index = -1;
632 sc->sample_size = st->codec->bit_rate; 665 sc->sample_size = st->codec->bit_rate;
633 sc->fields = 2; /* interlaced */ 666 sc->fields = 2; /* interlaced */
667
668 vsc = sc;
669
634 switch (st->codec->codec_id) { 670 switch (st->codec->codec_id) {
635 case CODEC_ID_MJPEG: 671 case CODEC_ID_MJPEG:
636 sc->track_type = 1; 672 sc->track_type = 1;
637 gxf->flags |= 0x00004000; 673 gxf->flags |= 0x00004000;
638 media_info = 'J'; 674 media_info = 'J';
671 } 707 }
672 708
673 if (ff_audio_interleave_init(s, GXF_samples_per_frame, (AVRational){ 1, 48000 }) < 0) 709 if (ff_audio_interleave_init(s, GXF_samples_per_frame, (AVRational){ 1, 48000 }) < 0)
674 return -1; 710 return -1;
675 711
712 gxf_init_timecode_track(&gxf->timecode_track, vsc);
713 gxf->flags |= 0x200000; // time code track is non-drop frame
714
676 gxf_write_map_packet(s); 715 gxf_write_map_packet(s);
677 //gxf_write_flt_packet(s); 716 //gxf_write_flt_packet(s);
678 gxf_write_umf_packet(s); 717 gxf_write_umf_packet(s);
679 put_flush_packet(pb); 718 put_flush_packet(pb);
680 return 0; 719 return 0;