comparison movenc.c @ 5993:51b194d7393f libavformat

movenc: Write QuickTime chapters
author conrad
date Wed, 05 May 2010 08:41:10 +0000
parents 391e3ca10474
children 97fdefab56cd
comparison
equal deleted inserted replaced
5992:391e3ca10474 5993:51b194d7393f
75 int vosLen; 75 int vosLen;
76 uint8_t *vosData; 76 uint8_t *vosData;
77 MOVIentry *cluster; 77 MOVIentry *cluster;
78 int audio_vbr; 78 int audio_vbr;
79 int height; ///< active picture (w/o VBI) height for D-10/IMX 79 int height; ///< active picture (w/o VBI) height for D-10/IMX
80 uint32_t tref_tag;
81 int tref_id; ///< trackID of the referenced track
80 } MOVTrack; 82 } MOVTrack;
81 83
82 typedef struct MOVMuxContext { 84 typedef struct MOVMuxContext {
83 int mode; 85 int mode;
84 int64_t time; 86 int64_t time;
85 int nb_streams; 87 int nb_streams;
88 int chapter_track; ///< qt chapter track number
86 int64_t mdat_pos; 89 int64_t mdat_pos;
87 uint64_t mdat_size; 90 uint64_t mdat_size;
88 MOVTrack *tracks; 91 MOVTrack *tracks;
89 } MOVMuxContext; 92 } MOVMuxContext;
90 93
1181 put_be32(pb, 0x0); /* reserved */ 1184 put_be32(pb, 0x0); /* reserved */
1182 put_be32(pb, 0x0); /* reserved */ 1185 put_be32(pb, 0x0); /* reserved */
1183 put_be32(pb, 0x40000000); /* reserved */ 1186 put_be32(pb, 0x40000000); /* reserved */
1184 1187
1185 /* Track width and height, for visual only */ 1188 /* Track width and height, for visual only */
1186 if(track->enc->codec_type == AVMEDIA_TYPE_VIDEO || 1189 if(st && (track->enc->codec_type == AVMEDIA_TYPE_VIDEO ||
1187 track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) { 1190 track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
1188 double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio); 1191 double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
1189 if(!sample_aspect_ratio || track->height != track->enc->height) 1192 if(!sample_aspect_ratio || track->height != track->enc->height)
1190 sample_aspect_ratio = 1; 1193 sample_aspect_ratio = 1;
1191 put_be32(pb, sample_aspect_ratio * track->enc->width*0x10000); 1194 put_be32(pb, sample_aspect_ratio * track->enc->width*0x10000);
1192 put_be32(pb, track->height*0x10000); 1195 put_be32(pb, track->height*0x10000);
1213 track->timescale, AV_ROUND_UP)); 1216 track->timescale, AV_ROUND_UP));
1214 1217
1215 put_be32(pb, track->cluster[0].cts); /* first pts is cts since dts is 0 */ 1218 put_be32(pb, track->cluster[0].cts); /* first pts is cts since dts is 0 */
1216 put_be32(pb, 0x00010000); 1219 put_be32(pb, 0x00010000);
1217 return 0x24; 1220 return 0x24;
1221 }
1222
1223 static int mov_write_tref_tag(ByteIOContext *pb, MOVTrack *track)
1224 {
1225 put_be32(pb, 20); // size
1226 put_tag(pb, "tref");
1227 put_be32(pb, 12); // size (subatom)
1228 put_le32(pb, track->tref_tag);
1229 put_be32(pb, track->tref_id);
1230 return 20;
1218 } 1231 }
1219 1232
1220 // goes at the end of each track! ... Critical for PSP playback ("Incompatible data" without it) 1233 // goes at the end of each track! ... Critical for PSP playback ("Incompatible data" without it)
1221 static int mov_write_uuid_tag_psp(ByteIOContext *pb, MOVTrack *mov) 1234 static int mov_write_uuid_tag_psp(ByteIOContext *pb, MOVTrack *mov)
1222 { 1235 {
1242 put_be32(pb, 0); /* size */ 1255 put_be32(pb, 0); /* size */
1243 put_tag(pb, "trak"); 1256 put_tag(pb, "trak");
1244 mov_write_tkhd_tag(pb, track, st); 1257 mov_write_tkhd_tag(pb, track, st);
1245 if (track->mode == MODE_PSP || track->flags & MOV_TRACK_CTTS) 1258 if (track->mode == MODE_PSP || track->flags & MOV_TRACK_CTTS)
1246 mov_write_edts_tag(pb, track); // PSP Movies require edts box 1259 mov_write_edts_tag(pb, track); // PSP Movies require edts box
1260 if (track->tref_tag)
1261 mov_write_tref_tag(pb, track);
1247 mov_write_mdia_tag(pb, track); 1262 mov_write_mdia_tag(pb, track);
1248 if (track->mode == MODE_PSP) 1263 if (track->mode == MODE_PSP)
1249 mov_write_uuid_tag_psp(pb,track); // PSP Movies require this uuid box 1264 mov_write_uuid_tag_psp(pb,track); // PSP Movies require this uuid box
1250 return updateSize(pb, pos); 1265 return updateSize(pb, pos);
1251 } 1266 }
1654 1669
1655 mov->tracks[i].time = mov->time; 1670 mov->tracks[i].time = mov->time;
1656 mov->tracks[i].trackID = i+1; 1671 mov->tracks[i].trackID = i+1;
1657 } 1672 }
1658 1673
1674 if (mov->chapter_track)
1675 for (i=0; i<s->nb_streams; i++) {
1676 mov->tracks[i].tref_tag = MKTAG('c','h','a','p');
1677 mov->tracks[i].tref_id = mov->tracks[mov->chapter_track].trackID;
1678 }
1679
1659 mov_write_mvhd_tag(pb, mov); 1680 mov_write_mvhd_tag(pb, mov);
1660 //mov_write_iods_tag(pb, mov); 1681 //mov_write_iods_tag(pb, mov);
1661 for (i=0; i<mov->nb_streams; i++) { 1682 for (i=0; i<mov->nb_streams; i++) {
1662 if(mov->tracks[i].entry > 0) { 1683 if(mov->tracks[i].entry > 0) {
1663 mov_write_trak_tag(pb, &(mov->tracks[i]), s->streams[i]); 1684 mov_write_trak_tag(pb, &(mov->tracks[i]), i < s->nb_streams ? s->streams[i] : NULL);
1664 } 1685 }
1665 } 1686 }
1666 1687
1667 if (mov->mode == MODE_PSP) 1688 if (mov->mode == MODE_PSP)
1668 mov_write_uuidusmt_tag(pb, s); 1689 mov_write_uuidusmt_tag(pb, s);
1916 1937
1917 put_flush_packet(pb); 1938 put_flush_packet(pb);
1918 return 0; 1939 return 0;
1919 } 1940 }
1920 1941
1942 // QuickTime chapters involve an additional text track with the chapter names
1943 // as samples, and a tref pointing from the other tracks to the chapter one.
1944 static void mov_create_chapter_track(AVFormatContext *s, int tracknum)
1945 {
1946 MOVMuxContext *mov = s->priv_data;
1947 MOVTrack *track = &mov->tracks[tracknum];
1948 AVPacket pkt = { .stream_index = tracknum, .flags = AV_PKT_FLAG_KEY };
1949 int i, len;
1950
1951 track->mode = mov->mode;
1952 track->tag = MKTAG('t','e','x','t');
1953 track->timescale = MOV_TIMESCALE;
1954 track->enc = avcodec_alloc_context();
1955 track->enc->codec_type = AVMEDIA_TYPE_SUBTITLE;
1956
1957 for (i = 0; i < s->nb_chapters; i++) {
1958 AVChapter *c = s->chapters[i];
1959 AVMetadataTag *t;
1960
1961 int64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,MOV_TIMESCALE});
1962 pkt.pts = pkt.dts = av_rescale_q(c->start, c->time_base, (AVRational){1,MOV_TIMESCALE});
1963 pkt.duration = end - pkt.dts;
1964
1965 if ((t = av_metadata_get(c->metadata, "title", NULL, 0))) {
1966 len = strlen(t->value);
1967 pkt.size = len+2;
1968 pkt.data = av_malloc(pkt.size);
1969 AV_WB16(pkt.data, len);
1970 memcpy(pkt.data+2, t->value, len);
1971 mov_write_packet(s, &pkt);
1972 av_freep(&pkt.data);
1973 }
1974 }
1975 }
1976
1921 static int mov_write_header(AVFormatContext *s) 1977 static int mov_write_header(AVFormatContext *s)
1922 { 1978 {
1923 ByteIOContext *pb = s->pb; 1979 ByteIOContext *pb = s->pb;
1924 MOVMuxContext *mov = s->priv_data; 1980 MOVMuxContext *mov = s->priv_data;
1925 int i; 1981 int i;
1947 } 2003 }
1948 mov_write_uuidprof_tag(pb,s); 2004 mov_write_uuidprof_tag(pb,s);
1949 } 2005 }
1950 } 2006 }
1951 2007
1952 mov->tracks = av_mallocz(s->nb_streams*sizeof(*mov->tracks)); 2008 mov->nb_streams = s->nb_streams;
2009 if (mov->mode & (MODE_MOV|MODE_IPOD) && s->nb_chapters)
2010 mov->chapter_track = mov->nb_streams++;
2011
2012 mov->tracks = av_mallocz(mov->nb_streams*sizeof(*mov->tracks));
1953 if (!mov->tracks) 2013 if (!mov->tracks)
1954 return AVERROR(ENOMEM); 2014 return AVERROR(ENOMEM);
1955 2015
1956 for(i=0; i<s->nb_streams; i++){ 2016 for(i=0; i<s->nb_streams; i++){
1957 AVStream *st= s->streams[i]; 2017 AVStream *st= s->streams[i];
2017 av_set_pts_info(st, 64, 1, track->timescale); 2077 av_set_pts_info(st, 64, 1, track->timescale);
2018 } 2078 }
2019 2079
2020 mov_write_mdat_tag(pb, mov); 2080 mov_write_mdat_tag(pb, mov);
2021 mov->time = s->timestamp + 0x7C25B080; //1970 based -> 1904 based 2081 mov->time = s->timestamp + 0x7C25B080; //1970 based -> 1904 based
2022 mov->nb_streams = s->nb_streams; 2082
2083 if (mov->chapter_track)
2084 mov_create_chapter_track(s, mov->chapter_track);
2023 2085
2024 put_flush_packet(pb); 2086 put_flush_packet(pb);
2025 2087
2026 return 0; 2088 return 0;
2027 error: 2089 error:
2050 put_be64(pb, mov->mdat_size+16); 2112 put_be64(pb, mov->mdat_size+16);
2051 } 2113 }
2052 url_fseek(pb, moov_pos, SEEK_SET); 2114 url_fseek(pb, moov_pos, SEEK_SET);
2053 2115
2054 mov_write_moov_tag(pb, mov, s); 2116 mov_write_moov_tag(pb, mov, s);
2117
2118 if (mov->chapter_track)
2119 av_freep(&mov->tracks[mov->chapter_track].enc);
2055 2120
2056 for (i=0; i<mov->nb_streams; i++) { 2121 for (i=0; i<mov->nb_streams; i++) {
2057 av_freep(&mov->tracks[i].cluster); 2122 av_freep(&mov->tracks[i].cluster);
2058 2123
2059 if(mov->tracks[i].vosLen) av_free(mov->tracks[i].vosData); 2124 if(mov->tracks[i].vosLen) av_free(mov->tracks[i].vosData);