diff mbox series

[FFmpeg-devel,3/3] avcodec/decode: prevent discarding skip_samples side data if the decoder didn't generate a frame

Message ID 20230710215453.34421-3-jamrial@gmail.com
State New
Headers show
Series [FFmpeg-devel,v3,1/3] avcodec/decode: move processing discard samples to its own function | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

James Almer July 10, 2023, 9:54 p.m. UTC
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@gmail.com>
---
 libavcodec/decode.c   | 18 ++++++++++--------
 libavcodec/internal.h |  2 +-
 2 files changed, 11 insertions(+), 9 deletions(-)
diff mbox series

Patch

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