[FFmpeg-devel] [PATCH 3/3] avcodec/decode: prevent discarding skip_samples side data if the decoder didn't generate a frame
James Almer
jamrial at gmail.com
Tue Jul 11 00:54:53 EEST 2023
Accumulate it instead, to be applied once a frame is returned.
This change also prevents decoder set values from being potentially overwritten
by side data.
Signed-off-by: James Almer <jamrial at gmail.com>
---
libavcodec/decode.c | 18 ++++++++++--------
libavcodec/internal.h | 2 +-
2 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 1270acaa50..8b0f506d24 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -300,11 +300,12 @@ static int discard_samples(AVCodecContext *avctx, AVFrame *frame, int64_t *disca
side = av_packet_get_side_data(avci->last_pkt_props, AV_PKT_DATA_SKIP_SAMPLES, &side_size);
if (side && side_size >= 10) {
- avci->skip_samples = AV_RL32(side);
- avci->skip_samples = FFMAX(0, avci->skip_samples);
+ uint32_t skip = AV_RL32(side);
+ skip = FFMIN(skip, INT64_MAX - avci->skip_samples);
+ avci->skip_samples += skip;
discard_padding = AV_RL32(side + 4);
- av_log(avctx, AV_LOG_DEBUG, "skip %d / discard %d samples due to side data\n",
- avci->skip_samples, (int)discard_padding);
+ av_log(avctx, AV_LOG_DEBUG, "skip %u / discard %d samples due to side data\n",
+ skip, (int)discard_padding);
skip_reason = AV_RL8(side + 8);
discard_reason = AV_RL8(side + 9);
}
@@ -324,7 +325,7 @@ static int discard_samples(AVCodecContext *avctx, AVFrame *frame, int64_t *disca
if (frame->nb_samples <= avci->skip_samples){
*discarded_samples += frame->nb_samples;
avci->skip_samples -= frame->nb_samples;
- av_log(avctx, AV_LOG_DEBUG, "skip whole frame, skip left: %d\n",
+ av_log(avctx, AV_LOG_DEBUG, "skip whole frame, skip left: %"PRId64"\n",
avci->skip_samples);
return AVERROR(EAGAIN);
} else {
@@ -343,7 +344,7 @@ static int discard_samples(AVCodecContext *avctx, AVFrame *frame, int64_t *disca
} else
av_log(avctx, AV_LOG_WARNING, "Could not update timestamps for skipped samples.\n");
- av_log(avctx, AV_LOG_DEBUG, "skip %d/%d samples\n",
+ av_log(avctx, AV_LOG_DEBUG, "skip %"PRId64"/%d samples\n",
avci->skip_samples, frame->nb_samples);
*discarded_samples += avci->skip_samples;
frame->nb_samples -= avci->skip_samples;
@@ -374,11 +375,12 @@ static int discard_samples(AVCodecContext *avctx, AVFrame *frame, int64_t *disca
if ((avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL)) {
AVFrameSideData *fside = av_frame_new_side_data(frame, AV_FRAME_DATA_SKIP_SAMPLES, 10);
if (fside) {
- AV_WL32(fside->data, avci->skip_samples);
+ uint32_t skip = FFMIN(avci->skip_samples, UINT32_MAX);
+ AV_WL32(fside->data, skip);
AV_WL32(fside->data + 4, discard_padding);
AV_WL8(fside->data + 8, skip_reason);
AV_WL8(fside->data + 9, discard_reason);
- avci->skip_samples = 0;
+ avci->skip_samples -= skip;
}
}
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index 868dd46b48..33c9bf9d9b 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -116,7 +116,7 @@ typedef struct AVCodecInternal {
/**
* Number of audio samples to skip at the start of the next decoded frame
*/
- int skip_samples;
+ int64_t skip_samples;
/**
* hwaccel-specific private data
--
2.41.0
More information about the ffmpeg-devel
mailing list