[FFmpeg-cvslog] avcodec/qtrle: call ff_reget_buffer() only when the picture data is going to change

James Almer git at videolan.org
Tue Aug 27 21:31:19 EEST 2019


ffmpeg | branch: master | James Almer <jamrial at gmail.com> | Mon Aug 26 14:29:59 2019 -0300| [d70bbdc5fa05e1c0ce381eacc6e987b5e0701d1c] | committer: James Almer

avcodec/qtrle: call ff_reget_buffer() only when the picture data is going to change

ff_reget_buffer() will attempt to create a writable copy of the frame,
which is not needed when the decoder intends to return a reference to
the same buffer as the previous frame.

Should reduce data copy, hopefully achieving a similar speed up as
a9dacdeea6168787a142209bd19fdd74aefc9dd6 without dropping frames.

Reviewed-by: Michael Niedermayer <michael at niedermayer.cc>
Signed-off-by: James Almer <jamrial at gmail.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=d70bbdc5fa05e1c0ce381eacc6e987b5e0701d1c
---

 libavcodec/qtrle.c | 28 +++++++++++++++++++++++-----
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/libavcodec/qtrle.c b/libavcodec/qtrle.c
index 443dd88f71..2793eb91f6 100644
--- a/libavcodec/qtrle.c
+++ b/libavcodec/qtrle.c
@@ -452,15 +452,16 @@ static int qtrle_decode_frame(AVCodecContext *avctx,
     int header, start_line;
     int height, row_ptr;
     int has_palette = 0;
+    int duplicate = 0;
     int ret, size;
 
     bytestream2_init(&s->g, avpkt->data, avpkt->size);
-    if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
-        return ret;
 
     /* check if this frame is even supposed to change */
-    if (avpkt->size < 8)
+    if (avpkt->size < 8) {
+        duplicate = 1;
         goto done;
+    }
 
     /* start after the chunk size */
     size = bytestream2_get_be32(&s->g) & 0x3FFFFFFF;
@@ -473,18 +474,25 @@ static int qtrle_decode_frame(AVCodecContext *avctx,
 
     /* if a header is present, fetch additional decoding parameters */
     if (header & 0x0008) {
-        if (avpkt->size < 14)
+        if (avpkt->size < 14) {
+            duplicate = 1;
             goto done;
+        }
         start_line = bytestream2_get_be16(&s->g);
         bytestream2_skip(&s->g, 2);
         height     = bytestream2_get_be16(&s->g);
         bytestream2_skip(&s->g, 2);
-        if (height > s->avctx->height - start_line)
+        if (height > s->avctx->height - start_line) {
+            duplicate = 1;
             goto done;
+        }
     } else {
         start_line = 0;
         height     = s->avctx->height;
     }
+    if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
+        return ret;
+
     row_ptr = s->frame->linesize[0] * start_line;
 
     switch (avctx->bits_per_coded_sample) {
@@ -546,6 +554,16 @@ static int qtrle_decode_frame(AVCodecContext *avctx,
     }
 
 done:
+    if (!s->frame->data[0])
+        return AVERROR_INVALIDDATA;
+    if (duplicate) {
+        // ff_reget_buffer() isn't needed when frames don't change, so just update
+        // frame props.
+        ret = ff_decode_frame_props(avctx, s->frame);
+        if (ret < 0)
+            return ret;
+    }
+
     if ((ret = av_frame_ref(data, s->frame)) < 0)
         return ret;
     *got_frame      = 1;



More information about the ffmpeg-cvslog mailing list