summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavformat/avformat.h9
-rw-r--r--libavformat/mp3dec.c6
-rw-r--r--libavformat/utils.c7
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);