comparison movenc.c @ 6013:332ad5f30c0e libavformat

Add initial support for RTP hinting in the mov muxer
author mstorsjo
date Tue, 18 May 2010 19:47:24 +0000
parents 8298cc054242
children 2bab410094e0
comparison
equal deleted inserted replaced
6012:8298cc054242 6013:332ad5f30c0e
27 #include "avio.h" 27 #include "avio.h"
28 #include "isom.h" 28 #include "isom.h"
29 #include "avc.h" 29 #include "avc.h"
30 #include "libavcodec/get_bits.h" 30 #include "libavcodec/get_bits.h"
31 #include "libavcodec/put_bits.h" 31 #include "libavcodec/put_bits.h"
32 #include "internal.h"
33 #include "libavutil/avstring.h"
32 34
33 #undef NDEBUG 35 #undef NDEBUG
34 #include <assert.h> 36 #include <assert.h>
35 37
36 //FIXME support 64 bit variant with wide placeholders 38 //FIXME support 64 bit variant with wide placeholders
804 mov_write_glbl_tag(pb, track); 806 mov_write_glbl_tag(pb, track);
805 807
806 return updateSize(pb, pos); 808 return updateSize(pb, pos);
807 } 809 }
808 810
811 static int mov_write_rtp_tag(ByteIOContext *pb, MOVTrack *track)
812 {
813 int64_t pos = url_ftell(pb);
814 put_be32(pb, 0); /* size */
815 put_tag(pb, "rtp ");
816 put_be32(pb, 0); /* Reserved */
817 put_be16(pb, 0); /* Reserved */
818 put_be16(pb, 1); /* Data-reference index */
819
820 put_be16(pb, 1); /* Hint track version */
821 put_be16(pb, 1); /* Highest compatible version */
822 put_be32(pb, track->max_packet_size); /* Max packet size */
823
824 put_be32(pb, 12); /* size */
825 put_tag(pb, "tims");
826 put_be32(pb, track->timescale);
827
828 return updateSize(pb, pos);
829 }
830
809 static int mov_write_stsd_tag(ByteIOContext *pb, MOVTrack *track) 831 static int mov_write_stsd_tag(ByteIOContext *pb, MOVTrack *track)
810 { 832 {
811 int64_t pos = url_ftell(pb); 833 int64_t pos = url_ftell(pb);
812 put_be32(pb, 0); /* size */ 834 put_be32(pb, 0); /* size */
813 put_tag(pb, "stsd"); 835 put_tag(pb, "stsd");
817 mov_write_video_tag(pb, track); 839 mov_write_video_tag(pb, track);
818 else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) 840 else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
819 mov_write_audio_tag(pb, track); 841 mov_write_audio_tag(pb, track);
820 else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) 842 else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)
821 mov_write_subtitle_tag(pb, track); 843 mov_write_subtitle_tag(pb, track);
844 else if (track->enc->codec_tag == MKTAG('r','t','p',' '))
845 mov_write_rtp_tag(pb, track);
822 return updateSize(pb, pos); 846 return updateSize(pb, pos);
823 } 847 }
824 848
825 static int mov_write_ctts_tag(ByteIOContext *pb, MOVTrack *track) 849 static int mov_write_ctts_tag(ByteIOContext *pb, MOVTrack *track)
826 { 850 {
916 int64_t pos = url_ftell(pb); 940 int64_t pos = url_ftell(pb);
917 put_be32(pb, 0); /* size */ 941 put_be32(pb, 0); /* size */
918 put_tag(pb, "stbl"); 942 put_tag(pb, "stbl");
919 mov_write_stsd_tag(pb, track); 943 mov_write_stsd_tag(pb, track);
920 mov_write_stts_tag(pb, track); 944 mov_write_stts_tag(pb, track);
921 if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO && 945 if ((track->enc->codec_type == AVMEDIA_TYPE_VIDEO ||
946 track->enc->codec_tag == MKTAG('r','t','p',' ')) &&
922 track->hasKeyframes && track->hasKeyframes < track->entry) 947 track->hasKeyframes && track->hasKeyframes < track->entry)
923 mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE); 948 mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE);
924 if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS) 949 if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS)
925 mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE); 950 mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE);
926 if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO && 951 if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO &&
1003 descr = "SoundHandler"; 1028 descr = "SoundHandler";
1004 } else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) { 1029 } else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) {
1005 if (track->tag == MKTAG('t','x','3','g')) hdlr_type = "sbtl"; 1030 if (track->tag == MKTAG('t','x','3','g')) hdlr_type = "sbtl";
1006 else hdlr_type = "text"; 1031 else hdlr_type = "text";
1007 descr = "SubtitleHandler"; 1032 descr = "SubtitleHandler";
1033 } else if (track->enc->codec_tag == MKTAG('r','t','p',' ')) {
1034 hdlr_type = "hint";
1035 descr = "HintHandler";
1008 } 1036 }
1009 } 1037 }
1010 1038
1011 put_be32(pb, 0); /* size */ 1039 put_be32(pb, 0); /* size */
1012 put_tag(pb, "hdlr"); 1040 put_tag(pb, "hdlr");
1022 if (track && track->mode != MODE_MOV) 1050 if (track && track->mode != MODE_MOV)
1023 put_byte(pb, 0); /* c string */ 1051 put_byte(pb, 0); /* c string */
1024 return updateSize(pb, pos); 1052 return updateSize(pb, pos);
1025 } 1053 }
1026 1054
1055 static int mov_write_hmhd_tag(ByteIOContext *pb)
1056 {
1057 /* This atom must be present, but leaving the values at zero
1058 * seems harmless. */
1059 put_be32(pb, 28); /* size */
1060 put_tag(pb, "hmhd");
1061 put_be32(pb, 0); /* version, flags */
1062 put_be16(pb, 0); /* maxPDUsize */
1063 put_be16(pb, 0); /* avgPDUsize */
1064 put_be32(pb, 0); /* maxbitrate */
1065 put_be32(pb, 0); /* avgbitrate */
1066 put_be32(pb, 0); /* reserved */
1067 return 28;
1068 }
1069
1027 static int mov_write_minf_tag(ByteIOContext *pb, MOVTrack *track) 1070 static int mov_write_minf_tag(ByteIOContext *pb, MOVTrack *track)
1028 { 1071 {
1029 int64_t pos = url_ftell(pb); 1072 int64_t pos = url_ftell(pb);
1030 put_be32(pb, 0); /* size */ 1073 put_be32(pb, 0); /* size */
1031 put_tag(pb, "minf"); 1074 put_tag(pb, "minf");
1034 else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) 1077 else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
1035 mov_write_smhd_tag(pb); 1078 mov_write_smhd_tag(pb);
1036 else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) { 1079 else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) {
1037 if (track->tag == MKTAG('t','e','x','t')) mov_write_gmhd_tag(pb); 1080 if (track->tag == MKTAG('t','e','x','t')) mov_write_gmhd_tag(pb);
1038 else mov_write_nmhd_tag(pb); 1081 else mov_write_nmhd_tag(pb);
1082 } else if (track->tag == MKTAG('r','t','p',' ')) {
1083 mov_write_hmhd_tag(pb);
1039 } 1084 }
1040 if (track->mode == MODE_MOV) /* FIXME: Why do it for MODE_MOV only ? */ 1085 if (track->mode == MODE_MOV) /* FIXME: Why do it for MODE_MOV only ? */
1041 mov_write_hdlr_tag(pb, NULL); 1086 mov_write_hdlr_tag(pb, NULL);
1042 mov_write_dinf_tag(pb); 1087 mov_write_dinf_tag(pb);
1043 mov_write_stbl_tag(pb, track); 1088 mov_write_stbl_tag(pb, track);
1189 put_be32(pb, 0x1); 1234 put_be32(pb, 0x1);
1190 put_be32(pb, 0x0); 1235 put_be32(pb, 0x0);
1191 return 0x34; 1236 return 0x34;
1192 } 1237 }
1193 1238
1239 static int mov_write_udta_sdp(ByteIOContext *pb, AVCodecContext *ctx, int index)
1240 {
1241 char buf[1000] = "";
1242 int len;
1243
1244 ff_sdp_write_media(buf, sizeof(buf), ctx, NULL, 0, 0);
1245 av_strlcatf(buf, sizeof(buf), "a=control:streamid=%d\r\n", index);
1246 len = strlen(buf);
1247
1248 put_be32(pb, len + 24);
1249 put_tag (pb, "udta");
1250 put_be32(pb, len + 16);
1251 put_tag (pb, "hnti");
1252 put_be32(pb, len + 8);
1253 put_tag (pb, "sdp ");
1254 put_buffer(pb, buf, len);
1255 return len + 24;
1256 }
1257
1194 static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack *track, AVStream *st) 1258 static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack *track, AVStream *st)
1195 { 1259 {
1196 int64_t pos = url_ftell(pb); 1260 int64_t pos = url_ftell(pb);
1197 put_be32(pb, 0); /* size */ 1261 put_be32(pb, 0); /* size */
1198 put_tag(pb, "trak"); 1262 put_tag(pb, "trak");
1202 if (track->tref_tag) 1266 if (track->tref_tag)
1203 mov_write_tref_tag(pb, track); 1267 mov_write_tref_tag(pb, track);
1204 mov_write_mdia_tag(pb, track); 1268 mov_write_mdia_tag(pb, track);
1205 if (track->mode == MODE_PSP) 1269 if (track->mode == MODE_PSP)
1206 mov_write_uuid_tag_psp(pb,track); // PSP Movies require this uuid box 1270 mov_write_uuid_tag_psp(pb,track); // PSP Movies require this uuid box
1271 if (track->tag == MKTAG('r','t','p',' '))
1272 mov_write_udta_sdp(pb, track->rtp_ctx->streams[0]->codec, track->trackID);
1207 return updateSize(pb, pos); 1273 return updateSize(pb, pos);
1208 } 1274 }
1209 1275
1210 #if 0 1276 #if 0
1211 /* TODO: Not sorted out, but not necessary either */ 1277 /* TODO: Not sorted out, but not necessary either */
1616 if (mov->chapter_track) 1682 if (mov->chapter_track)
1617 for (i=0; i<s->nb_streams; i++) { 1683 for (i=0; i<s->nb_streams; i++) {
1618 mov->tracks[i].tref_tag = MKTAG('c','h','a','p'); 1684 mov->tracks[i].tref_tag = MKTAG('c','h','a','p');
1619 mov->tracks[i].tref_id = mov->tracks[mov->chapter_track].trackID; 1685 mov->tracks[i].tref_id = mov->tracks[mov->chapter_track].trackID;
1620 } 1686 }
1687 for (i = 0; i < mov->nb_streams; i++) {
1688 if (mov->tracks[i].tag == MKTAG('r','t','p',' ')) {
1689 mov->tracks[i].tref_tag = MKTAG('h','i','n','t');
1690 mov->tracks[i].tref_id =
1691 mov->tracks[mov->tracks[i].src_track].trackID;
1692 }
1693 }
1621 1694
1622 mov_write_mvhd_tag(pb, mov); 1695 mov_write_mvhd_tag(pb, mov);
1623 //mov_write_iods_tag(pb, mov); 1696 //mov_write_iods_tag(pb, mov);
1624 for (i=0; i<mov->nb_streams; i++) { 1697 for (i=0; i<mov->nb_streams; i++) {
1625 if(mov->tracks[i].entry > 0) { 1698 if(mov->tracks[i].entry > 0) {
1876 trk->entry++; 1949 trk->entry++;
1877 trk->sampleCount += samplesInChunk; 1950 trk->sampleCount += samplesInChunk;
1878 mov->mdat_size += size; 1951 mov->mdat_size += size;
1879 1952
1880 put_flush_packet(pb); 1953 put_flush_packet(pb);
1954
1955 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams)
1956 ff_mov_add_hinted_packet(s, pkt, trk->hint_track, trk->entry);
1881 return 0; 1957 return 0;
1882 } 1958 }
1883 1959
1884 // QuickTime chapters involve an additional text track with the chapter names 1960 // QuickTime chapters involve an additional text track with the chapter names
1885 // as samples, and a tref pointing from the other tracks to the chapter one. 1961 // as samples, and a tref pointing from the other tracks to the chapter one.
1918 1994
1919 static int mov_write_header(AVFormatContext *s) 1995 static int mov_write_header(AVFormatContext *s)
1920 { 1996 {
1921 ByteIOContext *pb = s->pb; 1997 ByteIOContext *pb = s->pb;
1922 MOVMuxContext *mov = s->priv_data; 1998 MOVMuxContext *mov = s->priv_data;
1923 int i; 1999 int i, hint_track = 0;
1924 2000
1925 if (url_is_streamed(s->pb)) { 2001 if (url_is_streamed(s->pb)) {
1926 av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n"); 2002 av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
1927 return -1; 2003 return -1;
1928 } 2004 }
1948 } 2024 }
1949 2025
1950 mov->nb_streams = s->nb_streams; 2026 mov->nb_streams = s->nb_streams;
1951 if (mov->mode & (MODE_MOV|MODE_IPOD) && s->nb_chapters) 2027 if (mov->mode & (MODE_MOV|MODE_IPOD) && s->nb_chapters)
1952 mov->chapter_track = mov->nb_streams++; 2028 mov->chapter_track = mov->nb_streams++;
2029
2030 if (s->flags & AVFMT_FLAG_RTP_HINT) {
2031 /* Add hint tracks for each audio and video stream */
2032 hint_track = mov->nb_streams;
2033 for (i = 0; i < s->nb_streams; i++) {
2034 AVStream *st = s->streams[i];
2035 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
2036 st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
2037 mov->nb_streams++;
2038 }
2039 }
2040 }
1953 2041
1954 mov->tracks = av_mallocz(mov->nb_streams*sizeof(*mov->tracks)); 2042 mov->tracks = av_mallocz(mov->nb_streams*sizeof(*mov->tracks));
1955 if (!mov->tracks) 2043 if (!mov->tracks)
1956 return AVERROR(ENOMEM); 2044 return AVERROR(ENOMEM);
1957 2045
1969 if (!track->tag) { 2057 if (!track->tag) {
1970 av_log(s, AV_LOG_ERROR, "track %d: could not find tag, " 2058 av_log(s, AV_LOG_ERROR, "track %d: could not find tag, "
1971 "codec not currently supported in container\n", i); 2059 "codec not currently supported in container\n", i);
1972 goto error; 2060 goto error;
1973 } 2061 }
2062 /* If hinting of this track is enabled by a later hint track,
2063 * this is updated. */
2064 track->hint_track = -1;
1974 if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO){ 2065 if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO){
1975 if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') || 2066 if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') ||
1976 track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') || 2067 track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') ||
1977 track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) { 2068 track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) {
1978 if (st->codec->width != 720 || (st->codec->height != 608 && st->codec->height != 512)) { 2069 if (st->codec->width != 720 || (st->codec->height != 608 && st->codec->height != 512)) {
2023 mov->time = s->timestamp + 0x7C25B080; //1970 based -> 1904 based 2114 mov->time = s->timestamp + 0x7C25B080; //1970 based -> 1904 based
2024 2115
2025 if (mov->chapter_track) 2116 if (mov->chapter_track)
2026 mov_create_chapter_track(s, mov->chapter_track); 2117 mov_create_chapter_track(s, mov->chapter_track);
2027 2118
2119 if (s->flags & AVFMT_FLAG_RTP_HINT) {
2120 /* Initialize the hint tracks for each audio and video stream */
2121 for (i = 0; i < s->nb_streams; i++) {
2122 AVStream *st = s->streams[i];
2123 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
2124 st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
2125 ff_mov_init_hinting(s, hint_track, i);
2126 hint_track++;
2127 }
2128 }
2129 }
2130
2028 put_flush_packet(pb); 2131 put_flush_packet(pb);
2029 2132
2030 return 0; 2133 return 0;
2031 error: 2134 error:
2032 av_freep(&mov->tracks); 2135 av_freep(&mov->tracks);
2059 2162
2060 if (mov->chapter_track) 2163 if (mov->chapter_track)
2061 av_freep(&mov->tracks[mov->chapter_track].enc); 2164 av_freep(&mov->tracks[mov->chapter_track].enc);
2062 2165
2063 for (i=0; i<mov->nb_streams; i++) { 2166 for (i=0; i<mov->nb_streams; i++) {
2167 if (mov->tracks[i].tag == MKTAG('r','t','p',' '))
2168 ff_mov_close_hinting(&mov->tracks[i]);
2064 av_freep(&mov->tracks[i].cluster); 2169 av_freep(&mov->tracks[i].cluster);
2065 2170
2066 if(mov->tracks[i].vosLen) av_free(mov->tracks[i].vosData); 2171 if(mov->tracks[i].vosLen) av_free(mov->tracks[i].vosData);
2067 2172
2068 } 2173 }