Mercurial > libavformat.hg
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; |