diff options
author | Baptiste Coudurier <baptiste.coudurier@gmail.com> | 2006-11-01 17:27:39 +0000 |
---|---|---|
committer | Baptiste Coudurier <baptiste.coudurier@gmail.com> | 2006-11-01 17:27:39 +0000 |
commit | aa90239fd972dbfc853ce127844531a9f423fc38 (patch) | |
tree | 3a99d3556483bdfd58923c0f93c04cebb2563290 | |
parent | d55f46e5a87fa1c347a94af1c05ae691537881de (diff) | |
download | ffmpeg-aa90239fd972dbfc853ce127844531a9f423fc38.tar.gz |
mov vfr muxing
Originally committed as revision 6854 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r-- | doc/TODO | 1 | ||||
-rw-r--r-- | libavformat/movenc.c | 60 |
2 files changed, 50 insertions, 11 deletions
@@ -69,7 +69,6 @@ unassigned TODO: (unordered) - MPEG4 GMC encoding support - macroblock based pixel format (better cache locality, somewhat complex, one paper claimed it faster for high res) - finish NUT implementation -- movenc.c fix stts so that variable framerate files work - seeking regression test - regression tests for codecs which dont have an encoder (I+P frame bitstream in svn) - add support for using mplayers video filters to ffmpeg diff --git a/libavformat/movenc.c b/libavformat/movenc.c index ddb19088c6..2956326368 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -44,6 +44,7 @@ typedef struct MOVIentry { char key_frame; unsigned int entries; int64_t cts; + int64_t dts; } MOVIentry; typedef struct MOVIndex { @@ -65,6 +66,7 @@ typedef struct MOVIndex { int vosLen; uint8_t *vosData; MOVIentry *cluster; + int audio_vbr; } MOVTrack; typedef struct MOVContext { @@ -704,18 +706,46 @@ static int mov_write_ctts_tag(ByteIOContext *pb, MOVTrack* track) return atom_size; } -/* TODO: */ /* Time to sample atom */ static int mov_write_stts_tag(ByteIOContext *pb, MOVTrack* track) { - put_be32(pb, 0x18); /* size */ + Time2Sample *stts_entries; + uint32_t entries = -1; + uint32_t atom_size; + int i; + + if (track->enc->codec_type == CODEC_TYPE_AUDIO && !track->audio_vbr) { + stts_entries = av_malloc(sizeof(*stts_entries)); /* one entry */ + stts_entries[0].count = track->sampleCount; + stts_entries[0].duration = 1; + entries = 1; + } else { + stts_entries = av_malloc(track->entry * sizeof(*stts_entries)); /* worst case */ + for (i=0; i<track->entry; i++) { + int64_t duration = i + 1 == track->entry ? + track->trackDuration - track->cluster[i].dts + track->cluster[0].dts : /* readjusting */ + track->cluster[i+1].dts - track->cluster[i].dts; + if (i && duration == stts_entries[entries].duration) { + stts_entries[entries].count++; /* compress */ + } else { + entries++; + stts_entries[entries].duration = duration; + stts_entries[entries].count = 1; + } + } + entries++; /* last one */ + } + atom_size = 16 + (entries * 8); + put_be32(pb, atom_size); /* size */ put_tag(pb, "stts"); put_be32(pb, 0); /* version & flags */ - put_be32(pb, 1); /* entry count */ - - put_be32(pb, track->sampleCount); /* sample count */ - put_be32(pb, track->sampleDuration); /* sample duration */ - return 0x18; + put_be32(pb, entries); /* entry count */ + for (i=0; i<entries; i++) { + put_be32(pb, stts_entries[i].count); + put_be32(pb, stts_entries[i].duration); + } + av_free(stts_entries); + return atom_size; } static int mov_write_dref_tag(ByteIOContext *pb) @@ -1301,8 +1331,6 @@ static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov, for (i=0; i<mov->nb_streams; i++) { if(mov->tracks[i].entry <= 0) continue; - mov->tracks[i].trackDuration = - (int64_t)mov->tracks[i].sampleCount * mov->tracks[i].sampleDuration; mov->tracks[i].time = mov->time; mov->tracks[i].trackID = i+1; } @@ -1470,7 +1498,16 @@ static int mov_write_header(AVFormatContext *s) track->timescale = st->codec->sample_rate; track->sampleDuration = st->codec->frame_size; av_set_pts_info(st, 64, 1, st->codec->sample_rate); - track->sampleSize = (av_get_bits_per_sample(st->codec->codec_id) >> 3) * st->codec->channels; + switch(track->enc->codec_id){ + case CODEC_ID_MP3: + case CODEC_ID_AAC: + case CODEC_ID_AMR_NB: + case CODEC_ID_AMR_WB: + track->audio_vbr = 1; + break; + default: + track->sampleSize = (av_get_bits_per_sample(st->codec->codec_id) >> 3) * st->codec->channels; + } } if (!track->sampleDuration) { av_log(s, AV_LOG_ERROR, "track %d: sample duration is not set\n", i); @@ -1543,6 +1580,9 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt) trk->cluster[trk->entry].samplesInChunk = samplesInChunk; trk->cluster[trk->entry].size = size; trk->cluster[trk->entry].entries = samplesInChunk; + trk->cluster[trk->entry].dts = pkt->dts; + trk->trackDuration = pkt->dts - trk->cluster[0].dts + pkt->duration; + if(enc->codec_type == CODEC_TYPE_VIDEO) { if (pkt->dts != pkt->pts) trk->hasBframes = 1; |