aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec/qtrle.c
diff options
context:
space:
mode:
authorJames Almer <jamrial@gmail.com>2019-08-26 14:29:59 -0300
committerJames Almer <jamrial@gmail.com>2019-08-27 15:24:21 -0300
commitd70bbdc5fa05e1c0ce381eacc6e987b5e0701d1c (patch)
treecc0a25aad251e7fe2d9cf6fb6149a510c735570f /libavcodec/qtrle.c
parent8b71cc3363b5d5b01a56f334e8b6318374192076 (diff)
downloadffmpeg-d70bbdc5fa05e1c0ce381eacc6e987b5e0701d1c.tar.gz
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@niedermayer.cc> Signed-off-by: James Almer <jamrial@gmail.com>
Diffstat (limited to 'libavcodec/qtrle.c')
-rw-r--r--libavcodec/qtrle.c28
1 files 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;