X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fmovenc.c;h=d84ddbea96be8fd55f694a10a907ff675a726c8a;hb=7207dd8f829baee58b4df6c97c19ffde77039e8d;hp=4017a56158d3cac95f57da09eac1d5c96e00d1d1;hpb=72f801619a1ae91969fee9a7d72519422433c998;p=ffmpeg diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 4017a56158d..d84ddbea96b 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -1595,7 +1595,8 @@ static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track) } // This box seems important for the psp playback ... without it the movie seems to hang -static int mov_write_edts_tag(AVIOContext *pb, MOVTrack *track) +static int mov_write_edts_tag(AVIOContext *pb, MOVMuxContext *mov, + MOVTrack *track) { int64_t duration = av_rescale_rnd(track->track_duration, MOV_TIMESCALE, track->timescale, AV_ROUND_UP); @@ -1620,6 +1621,11 @@ static int mov_write_edts_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, entry_count); if (delay > 0) { /* add an empty edit to delay presentation */ + /* In the positive delay case, the delay includes the cts + * offset, and the second edit list entry below trims out + * the same amount from the actual content. This makes sure + * that the offsetted last sample is included in the edit + * list duration as well. */ if (version == 1) { avio_wb64(pb, delay); avio_wb64(pb, -1); @@ -1634,9 +1640,19 @@ static int mov_write_edts_tag(AVIOContext *pb, MOVTrack *track) * here, but use FFMIN in case dts is a a small positive integer * rounded to 0 when represented in MOV_TIMESCALE units. */ start_ct = -FFMIN(track->cluster[0].dts, 0); + /* Note, this delay is calculated from the pts of the first sample, + * ensuring that we don't reduce the duration for cases with + * dts<0 pts=0. */ duration += delay; } + /* For fragmented files, we don't know the full length yet. Setting + * duration to 0 allows us to only specify the offset, including + * the rest of the content (from all future fragments) without specifying + * an explicit duration. */ + if (mov->flags & FF_MOV_FLAG_FRAGMENT) + duration = 0; + /* duration */ if (version == 1) { avio_wb64(pb, duration); @@ -1750,8 +1766,7 @@ 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)) { - if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) - mov_write_edts_tag(pb, track); // PSP Movies require edts box + mov_write_edts_tag(pb, mov, track); // PSP Movies require edts box } if (track->tref_tag) mov_write_tref_tag(pb, track); @@ -2535,6 +2550,18 @@ static int mov_write_tfrf_tags(AVIOContext *pb, MOVMuxContext *mov, return 0; } +static int mov_write_tfdt_tag(AVIOContext *pb, MOVTrack *track) +{ + int64_t pos = avio_tell(pb); + + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "tfdt"); + avio_w8(pb, 1); /* version */ + avio_wb24(pb, 0); + avio_wb64(pb, track->frag_start); + return update_size(pb, pos); +} + static int mov_write_traf_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track, int64_t moof_offset, int moof_size) @@ -2544,6 +2571,7 @@ static int mov_write_traf_tag(AVIOContext *pb, MOVMuxContext *mov, ffio_wfourcc(pb, "traf"); mov_write_tfhd_tag(pb, mov, track, moof_offset); + mov_write_tfdt_tag(pb, track); mov_write_trun_tag(pb, mov, track, moof_size); if (mov->mode == MODE_ISM) { mov_write_tfxd_tag(pb, track); @@ -2964,7 +2992,7 @@ static int mov_flush_fragment(AVFormatContext *s) } info = &track->frag_info[track->nb_frag_info - 1]; info->offset = avio_tell(s->pb); - info->time = mov->tracks[i].frag_start; + info->time = track->frag_start; info->duration = duration; mov_write_tfrf_tags(s->pb, mov, track); @@ -3100,8 +3128,14 @@ 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->start_dts == AV_NOPTS_VALUE) + if (trk->start_dts == AV_NOPTS_VALUE) { trk->start_dts = pkt->dts; + 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 " + "empty_moov.\n", pkt->stream_index, pkt->dts); + } trk->track_duration = pkt->dts - trk->start_dts + pkt->duration; if (pkt->pts == AV_NOPTS_VALUE) {