mirror of
https://mirror.skon.top/https://github.com/FFmpeg/FFmpeg
synced 2026-04-20 12:50:49 +08:00
avformat/movenc: check if a packet is to be discarded when calculating edit list durations
Demuxers like mov will export packets not meant for presentation (e.g. because an edit list doesn't include them) by flagging them as discard, but the mov muxer completely ignored this, resulting in output edit lists considering every packet. Fixes issue #22552 Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
@@ -3835,13 +3835,13 @@ static int mov_write_minf_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext
|
||||
}
|
||||
|
||||
static void get_pts_range(MOVMuxContext *mov, MOVTrack *track,
|
||||
int64_t *start, int64_t *end)
|
||||
int64_t *start, int64_t *end, int elst)
|
||||
{
|
||||
if (track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd) {
|
||||
// tmcd tracks gets track_duration set in mov_write_moov_tag from
|
||||
// another track's duration, while the end_pts may be left at zero.
|
||||
// Calculate the pts duration for that track instead.
|
||||
get_pts_range(mov, &mov->tracks[track->src_track], start, end);
|
||||
get_pts_range(mov, &mov->tracks[track->src_track], start, end, elst);
|
||||
*start = av_rescale(*start, track->timescale,
|
||||
mov->tracks[track->src_track].timescale);
|
||||
*end = av_rescale(*end, track->timescale,
|
||||
@@ -3852,7 +3852,7 @@ static void get_pts_range(MOVMuxContext *mov, MOVTrack *track,
|
||||
track->start_dts != AV_NOPTS_VALUE &&
|
||||
track->start_cts != AV_NOPTS_VALUE) {
|
||||
*start = track->start_dts + track->start_cts;
|
||||
*end = track->end_pts;
|
||||
*end = elst ? track->elst_end_pts : track->end_pts;
|
||||
return;
|
||||
}
|
||||
*start = 0;
|
||||
@@ -3862,7 +3862,7 @@ static void get_pts_range(MOVMuxContext *mov, MOVTrack *track,
|
||||
static int64_t calc_samples_pts_duration(MOVMuxContext *mov, MOVTrack *track)
|
||||
{
|
||||
int64_t start, end;
|
||||
get_pts_range(mov, track, &start, &end);
|
||||
get_pts_range(mov, track, &start, &end, 0);
|
||||
return end - start;
|
||||
}
|
||||
|
||||
@@ -3874,12 +3874,19 @@ static int64_t calc_samples_pts_duration(MOVMuxContext *mov, MOVTrack *track)
|
||||
static int64_t calc_pts_duration(MOVMuxContext *mov, MOVTrack *track)
|
||||
{
|
||||
int64_t start, end;
|
||||
get_pts_range(mov, track, &start, &end);
|
||||
get_pts_range(mov, track, &start, &end, 0);
|
||||
if (mov->use_editlist != 0)
|
||||
start = 0;
|
||||
return end - start;
|
||||
}
|
||||
|
||||
static int64_t calc_elst_duration(MOVMuxContext *mov, MOVTrack *track)
|
||||
{
|
||||
int64_t start, end;
|
||||
get_pts_range(mov, track, &start, &end, 1);
|
||||
return end - start;
|
||||
}
|
||||
|
||||
static int mov_mdhd_mvhd_tkhd_version(MOVMuxContext *mov, MOVTrack *track, int64_t duration)
|
||||
{
|
||||
if (track && track->mode == MODE_ISM)
|
||||
@@ -4105,7 +4112,7 @@ static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track)
|
||||
static int mov_write_edts_tag(AVIOContext *pb, MOVMuxContext *mov,
|
||||
MOVTrack *track)
|
||||
{
|
||||
int64_t duration = av_rescale_rnd(calc_samples_pts_duration(mov, track),
|
||||
int64_t duration = av_rescale_rnd(calc_elst_duration(mov, track),
|
||||
mov->movie_timescale, track->timescale,
|
||||
AV_ROUND_UP);
|
||||
int version = duration < INT32_MAX ? 0 : 1;
|
||||
@@ -6549,6 +6556,8 @@ static int mov_flush_fragment(AVFormatContext *s, int force)
|
||||
track->end_pts = pts;
|
||||
else
|
||||
track->end_pts = dts;
|
||||
if (!(pkt->flags & AV_PKT_FLAG_DISCARD))
|
||||
track->elst_end_pts = track->end_pts;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7111,7 +7120,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
/* New fragment, but discontinuous from previous fragments.
|
||||
* Pretend the duration sum of the earlier fragments is
|
||||
* pkt->dts - trk->start_dts. */
|
||||
trk->end_pts = AV_NOPTS_VALUE;
|
||||
trk->end_pts = trk->elst_end_pts = AV_NOPTS_VALUE;
|
||||
trk->frag_discont = 0;
|
||||
}
|
||||
}
|
||||
@@ -7166,6 +7175,8 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
trk->end_pts = FFMAX(trk->end_pts, trk->cluster[trk->entry].dts +
|
||||
trk->cluster[trk->entry].cts +
|
||||
pkt->duration);
|
||||
if (!(pkt->flags & AV_PKT_FLAG_DISCARD))
|
||||
trk->elst_end_pts = trk->end_pts;
|
||||
|
||||
if (par->codec_id == AV_CODEC_ID_VC1) {
|
||||
mov_parse_vc1_frame(pkt, trk);
|
||||
@@ -7291,6 +7302,8 @@ static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
trk->end_pts = pkt->pts;
|
||||
else
|
||||
trk->end_pts = pkt->dts;
|
||||
if (!(pkt->flags & AV_PKT_FLAG_DISCARD))
|
||||
trk->elst_end_pts = trk->end_pts;
|
||||
trk->end_reliable = 1;
|
||||
}
|
||||
mov_auto_flush_fragment(s, 0);
|
||||
|
||||
@@ -130,6 +130,7 @@ typedef struct MOVTrack {
|
||||
int64_t start_dts;
|
||||
int64_t start_cts;
|
||||
int64_t end_pts;
|
||||
int64_t elst_end_pts;
|
||||
int end_reliable;
|
||||
int64_t dts_shift;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
6cd6b45a88881e85dfe7ad9582ffbeff *tests/data/fate/filter-meta-4560-rotate0.mov
|
||||
b03cf24561b152da246df6d0d6cf9b81 *tests/data/fate/filter-meta-4560-rotate0.mov
|
||||
347425 tests/data/fate/filter-meta-4560-rotate0.mov
|
||||
#tb 0: 1/30
|
||||
#media_type 0: video
|
||||
@@ -266,4 +266,3 @@
|
||||
1, 152576, 152576, 1024, 2048, 0x26721b75
|
||||
0, 104, 104, 1, 195840, 0x46851b87
|
||||
1, 153600, 153600, 1024, 2048, 0x97a2f42c
|
||||
0, 105, 105, 1, 195840, 0x02d97dc4
|
||||
|
||||
Reference in New Issue
Block a user