diff options
author | Martin Storsjö <martin@martin.st> | 2014-11-04 16:28:48 +0200 |
---|---|---|
committer | Martin Storsjö <martin@martin.st> | 2014-11-07 12:11:46 +0200 |
commit | 1d8a0c1b43e58332a3a15c67d4adc161713cade8 (patch) | |
tree | 0ae9f768a10ecf7f8fdd1b1ebc891fe845cb2115 | |
parent | 897d5c3a4296f3da80b8699d1487328ca2de8e55 (diff) | |
download | ffmpeg-1d8a0c1b43e58332a3a15c67d4adc161713cade8.tar.gz |
movenc: Allow to request not to use edit lists
In this case, shift tracks to start from zero instead (potentially
stretching the first sample in tracks that start later than the
first one).
Some software does not support edit lists at all, the adobe flash
player seems to be one of these. This results in AV sync errors when
edit lists are used to adjust AV sync.
Some players, such as QuickTime, don't respect the duration for
audio packets, so if an audio track starts later than the video
track and the first audio sample gets a duration longer than the
actual amount of data in it, the result will be out of sync.
Based on patches by Michael Niedermayer.
Signed-off-by: Martin Storsjö <martin@martin.st>
-rw-r--r-- | libavformat/movenc.c | 33 | ||||
-rw-r--r-- | libavformat/movenc.h | 2 |
2 files changed, 34 insertions, 1 deletions
diff --git a/libavformat/movenc.c b/libavformat/movenc.c index c6c683fe33..7a0d9f1150 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -68,6 +68,7 @@ static const AVOption options[] = { { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext, max_fragment_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, { "ism_lookahead", "Number of lookahead entries for ISM files", offsetof(MOVMuxContext, ism_lookahead), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, { "brand", "Override major brand", offsetof(MOVMuxContext, major_brand), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM }, + { "use_editlist", "use edit list", offsetof(MOVMuxContext, use_editlist), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM}, { NULL }, }; @@ -1773,7 +1774,11 @@ static int mov_write_trak_tag(AVIOContext *pb, MOVMuxContext *mov, if (track->mode == MODE_PSP || track->flags & MOV_TRACK_CTTS || (track->entry && track->cluster[0].dts) || is_clcp_track(track)) { - mov_write_edts_tag(pb, mov, track); // PSP Movies require edts box + if (mov->use_editlist) + mov_write_edts_tag(pb, mov, track); // PSP Movies require edts box + else if ((track->entry && track->cluster[0].dts) || track->mode == MODE_PSP || is_clcp_track(track)) + av_log(mov->fc, AV_LOG_WARNING, + "Not writing any edit list even though one would have been required\n"); } if (track->tref_tag) mov_write_tref_tag(pb, track); @@ -3148,6 +3153,15 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) * of this packet to be what the previous packets duration implies. */ trk->cluster[trk->entry].dts = trk->start_dts + trk->track_duration; } + if (!trk->entry && trk->start_dts == AV_NOPTS_VALUE && !mov->use_editlist && + s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) { + /* Not using edit lists and shifting the first track to start from zero. + * If the other streams start from a later timestamp, we won't be able + * to signal the difference in starting time without an edit list. + * Thus move the timestamp for this first sample to 0, increasing + * its duration instead. */ + trk->cluster[trk->entry].dts = trk->start_dts = 0; + } if (trk->start_dts == AV_NOPTS_VALUE) { trk->start_dts = pkt->dts; if (pkt->dts && mov->flags & FF_MOV_FLAG_EMPTY_MOOV) @@ -3462,6 +3476,23 @@ static int mov_write_header(AVFormatContext *s) } } + if (mov->use_editlist < 0) { + mov->use_editlist = 1; + if (mov->flags & FF_MOV_FLAG_FRAGMENT) { + // If we can avoid needing an edit list by shifting the + // tracks, prefer that over (trying to) write edit lists + // in fragmented output. + if (s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO || + s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) + mov->use_editlist = 0; + } + } + if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV && mov->use_editlist) + av_log(s, AV_LOG_WARNING, "No meaningful edit list will be written when using empty_moov\n"); + + if (!mov->use_editlist && s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO) + s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_ZERO; + /* Non-seekable output is ok if using fragmentation. If ism_lookahead * is enabled, we don't support non-seekable output at all. */ if (!s->pb->seekable && diff --git a/libavformat/movenc.h b/libavformat/movenc.h index e9056275ef..8349a18c1d 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -166,6 +166,8 @@ typedef struct MOVMuxContext { int per_stream_grouping; AVFormatContext *fc; + + int use_editlist; } MOVMuxContext; #define FF_MOV_FLAG_RTP_HINT (1 << 0) |