diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 3ba1cc81aa..80531d09f7 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -60,6 +60,7 @@ static const AVOption options[] = { { "disable_chpl", "Disable Nero chapter atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DISABLE_CHPL}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "default_base_moof", "Set the default-base-is-moof flag in tfhd atoms", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DEFAULT_BASE_MOOF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "dash", "Write DASH compatible fragmented MP4", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DASH}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, + { "frag_discont", "Signal that the next fragment is discontinuous from earlier ones", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_DISCONT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags), { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, { "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext, iods_audio_profile), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM}, @@ -3282,11 +3283,19 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) trk->cluster[trk->entry].entries = samples_in_chunk; trk->cluster[trk->entry].dts = pkt->dts; if (!trk->entry && trk->start_dts != AV_NOPTS_VALUE) { - /* First packet of a new fragment. We already wrote the duration - * of the last packet of the previous fragment based on track_duration, - * which might not exactly match our dts. Therefore adjust the dts - * of this packet to be what the previous packets duration implies. */ - trk->cluster[trk->entry].dts = trk->start_dts + trk->track_duration; + if (!trk->frag_discont) { + /* First packet of a new fragment. We already wrote the duration + * of the last packet of the previous fragment based on track_duration, + * which might not exactly match our dts. Therefore adjust the dts + * of this packet to be what the previous packets duration implies. */ + trk->cluster[trk->entry].dts = trk->start_dts + trk->track_duration; + } else { + /* New fragment, but discontinuous from previous fragments. + * Pretend the duration sum of the earlier fragments is + * pkt->dts - trk->start_dts. */ + trk->frag_start = pkt->dts - trk->start_dts; + trk->frag_discont = 0; + } } if (!trk->entry && trk->start_dts == AV_NOPTS_VALUE && !mov->use_editlist && s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) { @@ -3299,7 +3308,13 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) } if (trk->start_dts == AV_NOPTS_VALUE) { trk->start_dts = pkt->dts; - if (pkt->dts && mov->flags & FF_MOV_FLAG_EMPTY_MOOV) + if (trk->frag_discont) { + /* Pretend the whole stream started at dts=0, with earlier framgents + * already written, with a duration summing up to pkt->dts. */ + trk->frag_start = pkt->dts; + trk->start_dts = 0; + trk->frag_discont = 0; + } else if (pkt->dts && mov->flags & FF_MOV_FLAG_EMPTY_MOOV) av_log(s, AV_LOG_WARNING, "Track %d starts with a nonzero dts %"PRId64". This " "currently isn't handled correctly in combination with " @@ -3357,6 +3372,13 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt) if (!pkt->size) return 0; /* Discard 0 sized packets */ + if (mov->flags & FF_MOV_FLAG_FRAG_DISCONT) { + int i; + for (i = 0; i < s->nb_streams; i++) + mov->tracks[i].frag_discont = 1; + mov->flags &= ~FF_MOV_FLAG_FRAG_DISCONT; + } + if (trk->entry) frag_duration = av_rescale_q(pkt->dts - trk->cluster[0].dts, s->streams[pkt->stream_index]->time_base, diff --git a/libavformat/movenc.h b/libavformat/movenc.h index 4483b69e04..c13a834c7d 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -121,6 +121,7 @@ typedef struct MOVTrack { AVIOContext *mdat_buf; int64_t data_offset; int64_t frag_start; + int frag_discont; int nb_frag_info; MOVFragmentInfo *frag_info; @@ -182,6 +183,7 @@ typedef struct MOVMuxContext { #define FF_MOV_FLAG_DISABLE_CHPL (1 << 9) #define FF_MOV_FLAG_DEFAULT_BASE_MOOF (1 << 10) #define FF_MOV_FLAG_DASH (1 << 11) +#define FF_MOV_FLAG_FRAG_DISCONT (1 << 12) int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt);