comparison movenc.c @ 4193:2d3be324c648 libavformat

Add support for muxing mov/mp4/3gp timed text streams
author conrad
date Sun, 11 Jan 2009 10:26:44 +0000
parents 82cbec030af5
children 67ab85a3611d
comparison
equal deleted inserted replaced
4192:a48a6a414dfe 4193:2d3be324c648
548 { CODEC_ID_H264, MKTAG('a','v','c','1') }, 548 { CODEC_ID_H264, MKTAG('a','v','c','1') },
549 { CODEC_ID_MPEG4, MKTAG('m','p','4','v') }, 549 { CODEC_ID_MPEG4, MKTAG('m','p','4','v') },
550 { CODEC_ID_AAC, MKTAG('m','p','4','a') }, 550 { CODEC_ID_AAC, MKTAG('m','p','4','a') },
551 { CODEC_ID_AMR_NB, MKTAG('s','a','m','r') }, 551 { CODEC_ID_AMR_NB, MKTAG('s','a','m','r') },
552 { CODEC_ID_AMR_WB, MKTAG('s','a','w','b') }, 552 { CODEC_ID_AMR_WB, MKTAG('s','a','w','b') },
553 { CODEC_ID_MOV_TEXT, MKTAG('t', 'x', '3', 'g') },
553 { CODEC_ID_NONE, 0 }, 554 { CODEC_ID_NONE, 0 },
554 }; 555 };
555 556
556 static const AVCodecTag mov_pix_fmt_tags[] = { 557 static const AVCodecTag mov_pix_fmt_tags[] = {
557 { PIX_FMT_YUYV422, MKTAG('y','u','v','s') }, 558 { PIX_FMT_YUYV422, MKTAG('y','u','v','s') },
565 { CODEC_ID_H264, MKTAG('a','v','c','1') }, 566 { CODEC_ID_H264, MKTAG('a','v','c','1') },
566 { CODEC_ID_MPEG4, MKTAG('m','p','4','v') }, 567 { CODEC_ID_MPEG4, MKTAG('m','p','4','v') },
567 { CODEC_ID_AAC, MKTAG('m','p','4','a') }, 568 { CODEC_ID_AAC, MKTAG('m','p','4','a') },
568 { CODEC_ID_ALAC, MKTAG('a','l','a','c') }, 569 { CODEC_ID_ALAC, MKTAG('a','l','a','c') },
569 { CODEC_ID_AC3, MKTAG('a','c','-','3') }, 570 { CODEC_ID_AC3, MKTAG('a','c','-','3') },
571 { CODEC_ID_MOV_TEXT, MKTAG('t', 'x', '3', 'g') },
570 { CODEC_ID_NONE, 0 }, 572 { CODEC_ID_NONE, 0 },
571 }; 573 };
572 574
573 static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track) 575 static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)
574 { 576 {
577 if (!codec_get_tag(ff_mp4_obj_type, track->enc->codec_id)) 579 if (!codec_get_tag(ff_mp4_obj_type, track->enc->codec_id))
578 return 0; 580 return 0;
579 if (track->enc->codec_id == CODEC_ID_H264) tag = MKTAG('a','v','c','1'); 581 if (track->enc->codec_id == CODEC_ID_H264) tag = MKTAG('a','v','c','1');
580 else if (track->enc->codec_id == CODEC_ID_AC3) tag = MKTAG('a','c','-','3'); 582 else if (track->enc->codec_id == CODEC_ID_AC3) tag = MKTAG('a','c','-','3');
581 else if (track->enc->codec_id == CODEC_ID_DIRAC) tag = MKTAG('d','r','a','c'); 583 else if (track->enc->codec_id == CODEC_ID_DIRAC) tag = MKTAG('d','r','a','c');
584 else if (track->enc->codec_id == CODEC_ID_MOV_TEXT) tag = MKTAG('t','x','3','g');
582 else if (track->enc->codec_type == CODEC_TYPE_VIDEO) tag = MKTAG('m','p','4','v'); 585 else if (track->enc->codec_type == CODEC_TYPE_VIDEO) tag = MKTAG('m','p','4','v');
583 else if (track->enc->codec_type == CODEC_TYPE_AUDIO) tag = MKTAG('m','p','4','a'); 586 else if (track->enc->codec_type == CODEC_TYPE_AUDIO) tag = MKTAG('m','p','4','a');
584 } else if (track->mode == MODE_IPOD) { 587 } else if (track->mode == MODE_IPOD) {
585 tag = codec_get_tag(codec_ipod_tags, track->enc->codec_id); 588 tag = codec_get_tag(codec_ipod_tags, track->enc->codec_id);
586 if (!match_ext(s->filename, "m4a") && !match_ext(s->filename, "m4v")) 589 if (!match_ext(s->filename, "m4a") && !match_ext(s->filename, "m4v"))
619 tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff)); 622 tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff));
620 av_log(s, AV_LOG_INFO, "Warning, using MS style audio codec tag, " 623 av_log(s, AV_LOG_INFO, "Warning, using MS style audio codec tag, "
621 "the file may be unplayable!\n"); 624 "the file may be unplayable!\n");
622 } 625 }
623 } 626 }
627 } else if (track->enc->codec_type == CODEC_TYPE_SUBTITLE) {
628 tag = codec_get_tag(ff_codec_movsubtitle_tags, track->enc->codec_id);
624 } 629 }
625 } 630 }
626 } 631 }
627 return tag; 632 return tag;
628 } 633 }
639 put_be32(pb, 0x5f244fc5); 644 put_be32(pb, 0x5f244fc5);
640 put_be32(pb, 0xba39a51b); 645 put_be32(pb, 0xba39a51b);
641 put_be32(pb, 0xcf0323f3); 646 put_be32(pb, 0xcf0323f3);
642 put_be32(pb, 0x0); 647 put_be32(pb, 0x0);
643 return 28; 648 return 28;
649 }
650
651 static int mov_write_subtitle_tag(ByteIOContext *pb, MOVTrack *track)
652 {
653 int64_t pos = url_ftell(pb);
654 put_be32(pb, 0); /* size */
655 put_le32(pb, track->tag); // store it byteswapped
656 put_be32(pb, 0); /* Reserved */
657 put_be16(pb, 0); /* Reserved */
658 put_be16(pb, 1); /* Data-reference index */
659
660 if (track->enc->extradata_size)
661 put_buffer(pb, track->enc->extradata, track->enc->extradata_size);
662
663 return updateSize(pb, pos);
644 } 664 }
645 665
646 static int mov_write_video_tag(ByteIOContext *pb, MOVTrack *track) 666 static int mov_write_video_tag(ByteIOContext *pb, MOVTrack *track)
647 { 667 {
648 int64_t pos = url_ftell(pb); 668 int64_t pos = url_ftell(pb);
716 put_be32(pb, 1); /* entry count */ 736 put_be32(pb, 1); /* entry count */
717 if (track->enc->codec_type == CODEC_TYPE_VIDEO) 737 if (track->enc->codec_type == CODEC_TYPE_VIDEO)
718 mov_write_video_tag(pb, track); 738 mov_write_video_tag(pb, track);
719 else if (track->enc->codec_type == CODEC_TYPE_AUDIO) 739 else if (track->enc->codec_type == CODEC_TYPE_AUDIO)
720 mov_write_audio_tag(pb, track); 740 mov_write_audio_tag(pb, track);
741 else if (track->enc->codec_type == CODEC_TYPE_SUBTITLE)
742 mov_write_subtitle_tag(pb, track);
721 return updateSize(pb, pos); 743 return updateSize(pb, pos);
722 } 744 }
723 745
724 static int mov_write_ctts_tag(ByteIOContext *pb, MOVTrack *track) 746 static int mov_write_ctts_tag(ByteIOContext *pb, MOVTrack *track)
725 { 747 {
836 put_tag(pb, "dinf"); 858 put_tag(pb, "dinf");
837 mov_write_dref_tag(pb); 859 mov_write_dref_tag(pb);
838 return updateSize(pb, pos); 860 return updateSize(pb, pos);
839 } 861 }
840 862
863 static int mov_write_nmhd_tag(ByteIOContext *pb)
864 {
865 put_be32(pb, 12);
866 put_tag(pb, "nmhd");
867 put_be32(pb, 0);
868 return 12;
869 }
870
871 static int mov_write_gmhd_tag(ByteIOContext *pb)
872 {
873 put_be32(pb, 0x20); /* size */
874 put_tag(pb, "gmhd");
875 put_be32(pb, 0x18); /* gmin size */
876 put_tag(pb, "gmin"); /* generic media info */
877 put_be32(pb, 0); /* version & flags */
878 put_be16(pb, 0x40); /* graphics mode = */
879 put_be16(pb, 0x8000); /* opColor (r?) */
880 put_be16(pb, 0x8000); /* opColor (g?) */
881 put_be16(pb, 0x8000); /* opColor (b?) */
882 put_be16(pb, 0); /* balance */
883 put_be16(pb, 0); /* reserved */
884 return 0x20;
885 }
886
841 static int mov_write_smhd_tag(ByteIOContext *pb) 887 static int mov_write_smhd_tag(ByteIOContext *pb)
842 { 888 {
843 put_be32(pb, 16); /* size */ 889 put_be32(pb, 16); /* size */
844 put_tag(pb, "smhd"); 890 put_tag(pb, "smhd");
845 put_be32(pb, 0); /* version & flags */ 891 put_be32(pb, 0); /* version & flags */
869 } else { 915 } else {
870 hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0"; 916 hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
871 if (track->enc->codec_type == CODEC_TYPE_VIDEO) { 917 if (track->enc->codec_type == CODEC_TYPE_VIDEO) {
872 hdlr_type = "vide"; 918 hdlr_type = "vide";
873 descr = "VideoHandler"; 919 descr = "VideoHandler";
874 } else { 920 } else if (track->enc->codec_type == CODEC_TYPE_AUDIO){
875 hdlr_type = "soun"; 921 hdlr_type = "soun";
876 descr = "SoundHandler"; 922 descr = "SoundHandler";
923 } else if (track->enc->codec_type == CODEC_TYPE_SUBTITLE){
924 if (track->mode == MODE_IPOD) hdlr_type = "sbtl";
925 else hdlr_type = "text";
926 descr = "SubtitleHandler";
877 } 927 }
878 } 928 }
879 929
880 put_be32(pb, 0); /* size */ 930 put_be32(pb, 0); /* size */
881 put_tag(pb, "hdlr"); 931 put_tag(pb, "hdlr");
895 int64_t pos = url_ftell(pb); 945 int64_t pos = url_ftell(pb);
896 put_be32(pb, 0); /* size */ 946 put_be32(pb, 0); /* size */
897 put_tag(pb, "minf"); 947 put_tag(pb, "minf");
898 if(track->enc->codec_type == CODEC_TYPE_VIDEO) 948 if(track->enc->codec_type == CODEC_TYPE_VIDEO)
899 mov_write_vmhd_tag(pb); 949 mov_write_vmhd_tag(pb);
900 else 950 else if (track->enc->codec_type == CODEC_TYPE_AUDIO)
901 mov_write_smhd_tag(pb); 951 mov_write_smhd_tag(pb);
952 else if (track->enc->codec_type == CODEC_TYPE_SUBTITLE) {
953 if (track->mode == MODE_MOV)
954 mov_write_gmhd_tag(pb);
955 else
956 mov_write_nmhd_tag(pb);
957 }
902 if (track->mode == MODE_MOV) /* FIXME: Why do it for MODE_MOV only ? */ 958 if (track->mode == MODE_MOV) /* FIXME: Why do it for MODE_MOV only ? */
903 mov_write_hdlr_tag(pb, NULL); 959 mov_write_hdlr_tag(pb, NULL);
904 mov_write_dinf_tag(pb); 960 mov_write_dinf_tag(pb);
905 mov_write_stbl_tag(pb, track); 961 mov_write_stbl_tag(pb, track);
906 return updateSize(pb, pos); 962 return updateSize(pb, pos);
987 put_be32(pb, 0x0); /* reserved */ 1043 put_be32(pb, 0x0); /* reserved */
988 put_be32(pb, 0x0); /* reserved */ 1044 put_be32(pb, 0x0); /* reserved */
989 put_be32(pb, 0x40000000); /* reserved */ 1045 put_be32(pb, 0x40000000); /* reserved */
990 1046
991 /* Track width and height, for visual only */ 1047 /* Track width and height, for visual only */
992 if(track->enc->codec_type == CODEC_TYPE_VIDEO) { 1048 if(track->enc->codec_type == CODEC_TYPE_VIDEO ||
1049 track->enc->codec_type == CODEC_TYPE_SUBTITLE) {
993 double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio); 1050 double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
994 if(!sample_aspect_ratio) sample_aspect_ratio = 1; 1051 if(!sample_aspect_ratio) sample_aspect_ratio = 1;
995 put_be32(pb, sample_aspect_ratio * track->enc->width*0x10000); 1052 put_be32(pb, sample_aspect_ratio * track->enc->width*0x10000);
996 put_be32(pb, track->enc->height*0x10000); 1053 put_be32(pb, track->enc->height*0x10000);
997 } 1054 }
1622 track->enc->codec_id == CODEC_ID_MP3 && track->enc->sample_rate < 16000){ 1679 track->enc->codec_id == CODEC_ID_MP3 && track->enc->sample_rate < 16000){
1623 av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not supported\n", 1680 av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not supported\n",
1624 i, track->enc->sample_rate); 1681 i, track->enc->sample_rate);
1625 return -1; 1682 return -1;
1626 } 1683 }
1684 }else if(st->codec->codec_type == CODEC_TYPE_SUBTITLE){
1685 track->timescale = st->codec->time_base.den;
1686 av_set_pts_info(st, 64, 1, st->codec->time_base.den);
1627 } 1687 }
1628 } 1688 }
1629 1689
1630 mov_write_mdat_tag(pb, mov); 1690 mov_write_mdat_tag(pb, mov);
1631 mov->time = s->timestamp + 0x7C25B080; //1970 based -> 1904 based 1691 mov->time = s->timestamp + 0x7C25B080; //1970 based -> 1904 based