diff options
-rw-r--r-- | libavformat/avformat.h | 9 | ||||
-rw-r--r-- | libavformat/mp3dec.c | 6 | ||||
-rw-r--r-- | libavformat/utils.c | 7 |
3 files changed, 16 insertions, 6 deletions
diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 2370cb08da..78054debca 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1036,7 +1036,14 @@ typedef struct AVStream { * avoided for broken by design formats such as mp3 with ad-hoc gapless * audio support. */ - int64_t end_discard_sample; + int64_t first_discard_sample; + + /** + * The sample after last sample that is intended to be discarded after + * first_discard_sample. Works on frame boundaries only. Used to prevent + * early EOF if the gapless info is broken (considered concatenated mp3s). + */ + int64_t last_discard_sample; /** * Number of internally decoded frames, used internally in libavformat, do not access diff --git a/libavformat/mp3dec.c b/libavformat/mp3dec.c index 639c78d405..8745f209d3 100644 --- a/libavformat/mp3dec.c +++ b/libavformat/mp3dec.c @@ -219,8 +219,10 @@ static void mp3_parse_info_tag(AVFormatContext *s, AVStream *st, mp3->start_pad = v>>12; mp3-> end_pad = v&4095; st->skip_samples = mp3->start_pad + 528 + 1; - if (mp3->frames) - st->end_discard_sample = -mp3->end_pad + 528 + 1 + mp3->frames * (int64_t)spf; + if (mp3->frames) { + st->first_discard_sample = -mp3->end_pad + 528 + 1 + mp3->frames * (int64_t)spf; + st->last_discard_sample = mp3->frames * (int64_t)spf; + } if (!st->start_time) st->start_time = av_rescale_q(st->skip_samples, (AVRational){1, c->sample_rate}, diff --git a/libavformat/utils.c b/libavformat/utils.c index 58533f88e9..e0e78a78f1 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1358,13 +1358,14 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) if (ret >= 0) { AVStream *st = s->streams[pkt->stream_index]; int discard_padding = 0; - if (st->end_discard_sample && pkt->pts != AV_NOPTS_VALUE) { + if (st->first_discard_sample && pkt->pts != AV_NOPTS_VALUE) { int64_t pts = pkt->pts - (is_relative(pkt->pts) ? RELATIVE_TS_BASE : 0); int64_t sample = ts_to_samples(st, pts); int duration = ts_to_samples(st, pkt->duration); int64_t end_sample = sample + duration; - if (duration > 0 && end_sample >= st->end_discard_sample) - discard_padding = FFMIN(end_sample - st->end_discard_sample, duration); + if (duration > 0 && end_sample >= st->first_discard_sample && + sample < st->last_discard_sample) + discard_padding = FFMIN(end_sample - st->first_discard_sample, duration); } if (st->skip_samples || discard_padding) { uint8_t *p = av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10); |