diff mbox series

[FFmpeg-devel,3/5] avcodec: Factor updating palette out

Message ID 20210317235958.1308987-3-andreas.rheinhardt@gmail.com
State Superseded
Headers show
Series [FFmpeg-devel,1/5] avcodec/avpacket: Improve overflow checks when packing dictionary | expand

Checks

Context Check Description
andriy/x86_make success Make finished
andriy/x86_make_fate success Make fate finished
andriy/PPC64_make success Make finished
andriy/PPC64_make_fate success Make fate finished

Commit Message

Andreas Rheinhardt March 17, 2021, 11:59 p.m. UTC
Because the properties of frames returned from ff_get/reget_buffer
are not reset at all, lots of returned frames had palette_has_changed
wrongly set to 1. This has been changed, too.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
---
 libavcodec/8bps.c           | 11 +----------
 libavcodec/cinepak.c        |  9 +--------
 libavcodec/decode.c         | 14 ++++++++++++++
 libavcodec/gdv.c            |  5 +----
 libavcodec/idcinvideo.c     |  9 +--------
 libavcodec/imx.c            |  5 +----
 libavcodec/internal.h       |  9 +++++++++
 libavcodec/interplayvideo.c |  9 +--------
 libavcodec/kmvc.c           |  8 +-------
 libavcodec/msrle.c          | 11 ++---------
 libavcodec/msvideo1.c       | 10 +---------
 libavcodec/qpeg.c           |  9 +--------
 libavcodec/qtrle.c          | 10 +---------
 libavcodec/rawdec.c         | 13 ++-----------
 libavcodec/rscc.c           | 13 ++-----------
 libavcodec/smc.c            |  9 +--------
 libavcodec/tscc.c           | 10 +---------
 17 files changed, 41 insertions(+), 123 deletions(-)

Comments

James Almer March 18, 2021, 1:28 a.m. UTC | #1
On 3/17/2021 8:59 PM, Andreas Rheinhardt wrote:
> Because the properties of frames returned from ff_get/reget_buffer
> are not reset at all, lots of returned frames had palette_has_changed
> wrongly set to 1. This has been changed, too.
> 
> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
> ---
>   libavcodec/8bps.c           | 11 +----------
>   libavcodec/cinepak.c        |  9 +--------
>   libavcodec/decode.c         | 14 ++++++++++++++
>   libavcodec/gdv.c            |  5 +----
>   libavcodec/idcinvideo.c     |  9 +--------
>   libavcodec/imx.c            |  5 +----
>   libavcodec/internal.h       |  9 +++++++++
>   libavcodec/interplayvideo.c |  9 +--------
>   libavcodec/kmvc.c           |  8 +-------
>   libavcodec/msrle.c          | 11 ++---------
>   libavcodec/msvideo1.c       | 10 +---------
>   libavcodec/qpeg.c           |  9 +--------
>   libavcodec/qtrle.c          | 10 +---------
>   libavcodec/rawdec.c         | 13 ++-----------
>   libavcodec/rscc.c           | 13 ++-----------
>   libavcodec/smc.c            |  9 +--------
>   libavcodec/tscc.c           | 10 +---------
>   17 files changed, 41 insertions(+), 123 deletions(-)
> 

[...]

> diff --git a/libavcodec/decode.c b/libavcodec/decode.c
> index 5a00aeedae..efa8a9ac8d 100644
> --- a/libavcodec/decode.c
> +++ b/libavcodec/decode.c
> @@ -2051,3 +2051,17 @@ FF_ENABLE_DEPRECATION_WARNINGS
>   
>       return 0;
>   }
> +
> +int ff_copy_palette(void *dst, const AVPacket *src, void *logctx)

All the arguments for dst are uint8_t*.

> +{
> +    buffer_size_t size;
> +    const void *pal = av_packet_get_side_data(src, AV_PKT_DATA_PALETTE, &size);

Same, av_packet_get_side_data() returns an uint8_t*.

> +
> +    if (pal && size == AVPALETTE_SIZE) {
> +        memcpy(dst, pal, AVPALETTE_SIZE);
> +        return 1;
> +    } else if (pal) {
> +        av_log(logctx, AV_LOG_ERROR, "Palette size %d is wrong\n", size);
> +    }
> +    return 0;
> +}

[...]

> diff --git a/libavcodec/internal.h b/libavcodec/internal.h
> index b57b996816..0fb3107979 100644
> --- a/libavcodec/internal.h
> +++ b/libavcodec/internal.h
> @@ -393,6 +393,15 @@ int ff_int_from_list_or_default(void *ctx, const char * val_name, int val,
>   
>   void ff_dvdsub_parse_palette(uint32_t *palette, const char *p);
>   
> +/**
> + * Check whether the side-data of src contains a palette of
> + * size AVPALETTE_SIZE; if so, copy it to dst and return 1;
> + * else return 0.
> + * Also emit an error message upon encountering a palette
> + * with invalid size.
> + */
> +int ff_copy_palette(void *dst, const AVPacket *src, void *logctx);

Should be in libavcodec/decode.h instead.

Or maybe avpacket.c and packet_internal.h, for that matter.

> +
>   #if defined(_WIN32) && CONFIG_SHARED && !defined(BUILDING_avcodec)
>   #    define av_export_avcodec __declspec(dllimport)
>   #else
Andreas Rheinhardt March 18, 2021, 1:40 a.m. UTC | #2
James Almer:
> On 3/17/2021 8:59 PM, Andreas Rheinhardt wrote:
>> Because the properties of frames returned from ff_get/reget_buffer
>> are not reset at all, lots of returned frames had palette_has_changed
>> wrongly set to 1. This has been changed, too.
>>
>> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
>> ---
>>   libavcodec/8bps.c           | 11 +----------
>>   libavcodec/cinepak.c        |  9 +--------
>>   libavcodec/decode.c         | 14 ++++++++++++++
>>   libavcodec/gdv.c            |  5 +----
>>   libavcodec/idcinvideo.c     |  9 +--------
>>   libavcodec/imx.c            |  5 +----
>>   libavcodec/internal.h       |  9 +++++++++
>>   libavcodec/interplayvideo.c |  9 +--------
>>   libavcodec/kmvc.c           |  8 +-------
>>   libavcodec/msrle.c          | 11 ++---------
>>   libavcodec/msvideo1.c       | 10 +---------
>>   libavcodec/qpeg.c           |  9 +--------
>>   libavcodec/qtrle.c          | 10 +---------
>>   libavcodec/rawdec.c         | 13 ++-----------
>>   libavcodec/rscc.c           | 13 ++-----------
>>   libavcodec/smc.c            |  9 +--------
>>   libavcodec/tscc.c           | 10 +---------
>>   17 files changed, 41 insertions(+), 123 deletions(-)
>>
> 
> [...]
> 
>> diff --git a/libavcodec/decode.c b/libavcodec/decode.c
>> index 5a00aeedae..efa8a9ac8d 100644
>> --- a/libavcodec/decode.c
>> +++ b/libavcodec/decode.c
>> @@ -2051,3 +2051,17 @@ FF_ENABLE_DEPRECATION_WARNINGS
>>         return 0;
>>   }
>> +
>> +int ff_copy_palette(void *dst, const AVPacket *src, void *logctx)
> 
> All the arguments for dst are uint8_t*.

Actually, most of them are uint32_t*. The only (?) exception is
rawdec.c. (An earlier version of this patch used "uint32_t
dst[AVPALETTE_SIZE]" with a cast for rawdec, but then I noticed that
this is of by a factor of sizeof(uint32_t).)

> 
>> +{
>> +    buffer_size_t size;
>> +    const void *pal = av_packet_get_side_data(src,
>> AV_PKT_DATA_PALETTE, &size);
> 
> Same, av_packet_get_side_data() returns an uint8_t*.

Yes, but it actually is an array of uint32_t, hence void*. (void* is a
better return value for av_packet_get_side_data() anyway, as most of the
side data types are structures. Maybe we should change that.)

> 
>> +
>> +    if (pal && size == AVPALETTE_SIZE) {
>> +        memcpy(dst, pal, AVPALETTE_SIZE);
>> +        return 1;
>> +    } else if (pal) {
>> +        av_log(logctx, AV_LOG_ERROR, "Palette size %d is wrong\n",
>> size);
>> +    }
>> +    return 0;
>> +}
> 
> [...]
> 
>> diff --git a/libavcodec/internal.h b/libavcodec/internal.h
>> index b57b996816..0fb3107979 100644
>> --- a/libavcodec/internal.h
>> +++ b/libavcodec/internal.h
>> @@ -393,6 +393,15 @@ int ff_int_from_list_or_default(void *ctx, const
>> char * val_name, int val,
>>     void ff_dvdsub_parse_palette(uint32_t *palette, const char *p);
>>   +/**
>> + * Check whether the side-data of src contains a palette of
>> + * size AVPALETTE_SIZE; if so, copy it to dst and return 1;
>> + * else return 0.
>> + * Also emit an error message upon encountering a palette
>> + * with invalid size.
>> + */
>> +int ff_copy_palette(void *dst, const AVPacket *src, void *logctx);
> 
> Should be in libavcodec/decode.h instead.

It was in decode.h until I noticed that most decoders don't include that
header. internal.h includes several other functions that are only used
by decoders (like ff_reget_buffer). But, yes, will move it.

> 
> Or maybe avpacket.c and packet_internal.h, for that matter.

Given that it is only used by decoders, decode.c seems the appropriate
place (is it noticeable that I dream of a day when all the decoding code
is really disabled when there are no decoders enabled?).

> 
>> +
>>   #if defined(_WIN32) && CONFIG_SHARED && !defined(BUILDING_avcodec)
>>   #    define av_export_avcodec __declspec(dllimport)
>>   #else
Andreas Rheinhardt March 18, 2021, 2:19 a.m. UTC | #3
Andreas Rheinhardt:
> James Almer:
>> On 3/17/2021 8:59 PM, Andreas Rheinhardt wrote:
>>> Because the properties of frames returned from ff_get/reget_buffer
>>> are not reset at all, lots of returned frames had palette_has_changed
>>> wrongly set to 1. This has been changed, too.
>>>
>>> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
>>> ---
>>>   libavcodec/8bps.c           | 11 +----------
>>>   libavcodec/cinepak.c        |  9 +--------
>>>   libavcodec/decode.c         | 14 ++++++++++++++
>>>   libavcodec/gdv.c            |  5 +----
>>>   libavcodec/idcinvideo.c     |  9 +--------
>>>   libavcodec/imx.c            |  5 +----
>>>   libavcodec/internal.h       |  9 +++++++++
>>>   libavcodec/interplayvideo.c |  9 +--------
>>>   libavcodec/kmvc.c           |  8 +-------
>>>   libavcodec/msrle.c          | 11 ++---------
>>>   libavcodec/msvideo1.c       | 10 +---------
>>>   libavcodec/qpeg.c           |  9 +--------
>>>   libavcodec/qtrle.c          | 10 +---------
>>>   libavcodec/rawdec.c         | 13 ++-----------
>>>   libavcodec/rscc.c           | 13 ++-----------
>>>   libavcodec/smc.c            |  9 +--------
>>>   libavcodec/tscc.c           | 10 +---------
>>>   17 files changed, 41 insertions(+), 123 deletions(-)
>>>
>>
>> [...]
>>
>>> diff --git a/libavcodec/decode.c b/libavcodec/decode.c
>>> index 5a00aeedae..efa8a9ac8d 100644
>>> --- a/libavcodec/decode.c
>>> +++ b/libavcodec/decode.c
>>> @@ -2051,3 +2051,17 @@ FF_ENABLE_DEPRECATION_WARNINGS
>>>         return 0;
>>>   }
>>> +
>>> +int ff_copy_palette(void *dst, const AVPacket *src, void *logctx)
>>
>> All the arguments for dst are uint8_t*.
> 
> Actually, most of them are uint32_t*. The only (?) exception is
> rawdec.c. (An earlier version of this patch used "uint32_t
> dst[AVPALETTE_SIZE]" with a cast for rawdec, but then I noticed that
> this is of by a factor of sizeof(uint32_t).)
> 

rscc.c is also an exception.

>>
>>> +{
>>> +    buffer_size_t size;
>>> +    const void *pal = av_packet_get_side_data(src,
>>> AV_PKT_DATA_PALETTE, &size);
>>
>> Same, av_packet_get_side_data() returns an uint8_t*.
> 
> Yes, but it actually is an array of uint32_t, hence void*. (void* is a
> better return value for av_packet_get_side_data() anyway, as most of the
> side data types are structures. Maybe we should change that.)
> 
>>
>>> +
>>> +    if (pal && size == AVPALETTE_SIZE) {
>>> +        memcpy(dst, pal, AVPALETTE_SIZE);
>>> +        return 1;
>>> +    } else if (pal) {
>>> +        av_log(logctx, AV_LOG_ERROR, "Palette size %d is wrong\n",
>>> size);
>>> +    }
>>> +    return 0;
>>> +}
>>
>> [...]
>>
>>> diff --git a/libavcodec/internal.h b/libavcodec/internal.h
>>> index b57b996816..0fb3107979 100644
>>> --- a/libavcodec/internal.h
>>> +++ b/libavcodec/internal.h
>>> @@ -393,6 +393,15 @@ int ff_int_from_list_or_default(void *ctx, const
>>> char * val_name, int val,
>>>     void ff_dvdsub_parse_palette(uint32_t *palette, const char *p);
>>>   +/**
>>> + * Check whether the side-data of src contains a palette of
>>> + * size AVPALETTE_SIZE; if so, copy it to dst and return 1;
>>> + * else return 0.
>>> + * Also emit an error message upon encountering a palette
>>> + * with invalid size.
>>> + */
>>> +int ff_copy_palette(void *dst, const AVPacket *src, void *logctx);
>>
>> Should be in libavcodec/decode.h instead.
> 
> It was in decode.h until I noticed that most decoders don't include that
> header. internal.h includes several other functions that are only used
> by decoders (like ff_reget_buffer). But, yes, will move it.
> 
>>
>> Or maybe avpacket.c and packet_internal.h, for that matter.
> 
> Given that it is only used by decoders, decode.c seems the appropriate
> place (is it noticeable that I dream of a day when all the decoding code
> is really disabled when there are no decoders enabled?).
> 
>>
>>> +
>>>   #if defined(_WIN32) && CONFIG_SHARED && !defined(BUILDING_avcodec)
>>>   #    define av_export_avcodec __declspec(dllimport)
>>>   #else
>
diff mbox series

Patch

diff --git a/libavcodec/8bps.c b/libavcodec/8bps.c
index 53e939d35d..9d19e21342 100644
--- a/libavcodec/8bps.c
+++ b/libavcodec/8bps.c
@@ -122,16 +122,7 @@  static int decode_frame(AVCodecContext *avctx, void *data,
     }
 
     if (avctx->bits_per_coded_sample <= 8) {
-        buffer_size_t size;
-        const uint8_t *pal = av_packet_get_side_data(avpkt,
-                                                     AV_PKT_DATA_PALETTE,
-                                                     &size);
-        if (pal && size == AVPALETTE_SIZE) {
-            frame->palette_has_changed = 1;
-            memcpy(c->pal, pal, AVPALETTE_SIZE);
-        } else if (pal) {
-            av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", size);
-        }
+        frame->palette_has_changed = ff_copy_palette(c->pal, avpkt, avctx);
 
         memcpy (frame->data[1], c->pal, AVPALETTE_SIZE);
     }
diff --git a/libavcodec/cinepak.c b/libavcodec/cinepak.c
index d70cb4b694..61e2991d04 100644
--- a/libavcodec/cinepak.c
+++ b/libavcodec/cinepak.c
@@ -477,14 +477,7 @@  static int cinepak_decode_frame(AVCodecContext *avctx,
         return ret;
 
     if (s->palette_video) {
-        buffer_size_t size;
-        const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size);
-        if (pal && size == AVPALETTE_SIZE) {
-            s->frame->palette_has_changed = 1;
-            memcpy(s->pal, pal, AVPALETTE_SIZE);
-        } else if (pal) {
-            av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", size);
-        }
+        s->frame->palette_has_changed = ff_copy_palette(s->pal, avpkt, avctx);
     }
 
     if ((ret = cinepak_decode(s)) < 0) {
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 5a00aeedae..efa8a9ac8d 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -2051,3 +2051,17 @@  FF_ENABLE_DEPRECATION_WARNINGS
 
     return 0;
 }
+
+int ff_copy_palette(void *dst, const AVPacket *src, void *logctx)
+{
+    buffer_size_t size;
+    const void *pal = av_packet_get_side_data(src, AV_PKT_DATA_PALETTE, &size);
+
+    if (pal && size == AVPALETTE_SIZE) {
+        memcpy(dst, pal, AVPALETTE_SIZE);
+        return 1;
+    } else if (pal) {
+        av_log(logctx, AV_LOG_ERROR, "Palette size %d is wrong\n", size);
+    }
+    return 0;
+}
diff --git a/libavcodec/gdv.c b/libavcodec/gdv.c
index 860634c9ec..cda284a32a 100644
--- a/libavcodec/gdv.c
+++ b/libavcodec/gdv.c
@@ -462,8 +462,6 @@  static int gdv_decode_frame(AVCodecContext *avctx, void *data,
     PutByteContext *pb = &gdv->pb;
     AVFrame *frame = data;
     int ret, i;
-    buffer_size_t pal_size;
-    const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &pal_size);
     int compression;
     unsigned flags;
     uint8_t *dst;
@@ -479,8 +477,7 @@  static int gdv_decode_frame(AVCodecContext *avctx, void *data,
 
     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
         return ret;
-    if (pal && pal_size == AVPALETTE_SIZE)
-        memcpy(gdv->pal, pal, AVPALETTE_SIZE);
+    ff_copy_palette(gdv->pal, avpkt, avctx);
 
     if (compression < 2 && bytestream2_get_bytes_left(gb) < 256*3)
         return AVERROR_INVALIDDATA;
diff --git a/libavcodec/idcinvideo.c b/libavcodec/idcinvideo.c
index 569191511f..02d5957bc7 100644
--- a/libavcodec/idcinvideo.c
+++ b/libavcodec/idcinvideo.c
@@ -214,8 +214,6 @@  static int idcin_decode_frame(AVCodecContext *avctx,
     const uint8_t *buf = avpkt->data;
     int buf_size = avpkt->size;
     IdcinContext *s = avctx->priv_data;
-    buffer_size_t pal_size;
-    const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &pal_size);
     AVFrame *frame = data;
     int ret;
 
@@ -228,12 +226,7 @@  static int idcin_decode_frame(AVCodecContext *avctx,
     if (idcin_decode_vlcs(s, frame))
         return AVERROR_INVALIDDATA;
 
-    if (pal && pal_size == AVPALETTE_SIZE) {
-        frame->palette_has_changed = 1;
-        memcpy(s->pal, pal, AVPALETTE_SIZE);
-    } else if (pal) {
-        av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", pal_size);
-    }
+    frame->palette_has_changed = ff_copy_palette(s->pal, avpkt, avctx);
     /* make the palette available on the way out */
     memcpy(frame->data[1], s->pal, AVPALETTE_SIZE);
 
diff --git a/libavcodec/imx.c b/libavcodec/imx.c
index 0d6c99e5bf..59edd427cd 100644
--- a/libavcodec/imx.c
+++ b/libavcodec/imx.c
@@ -50,16 +50,13 @@  static int imx_decode_frame(AVCodecContext *avctx, void *data,
 {
     SimbiosisIMXContext *imx = avctx->priv_data;
     int ret, x, y;
-    buffer_size_t pal_size;
-    const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &pal_size);
     AVFrame *frame = imx->frame;
     GetByteContext gb;
 
     if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0)
         return ret;
 
-    if (pal && pal_size == AVPALETTE_SIZE) {
-        memcpy(imx->pal, pal, pal_size);
+    if (ff_copy_palette(imx->pal, avpkt, avctx)) {
         frame->palette_has_changed = 1;
         frame->key_frame = 1;
     } else {
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index b57b996816..0fb3107979 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -393,6 +393,15 @@  int ff_int_from_list_or_default(void *ctx, const char * val_name, int val,
 
 void ff_dvdsub_parse_palette(uint32_t *palette, const char *p);
 
+/**
+ * Check whether the side-data of src contains a palette of
+ * size AVPALETTE_SIZE; if so, copy it to dst and return 1;
+ * else return 0.
+ * Also emit an error message upon encountering a palette
+ * with invalid size.
+ */
+int ff_copy_palette(void *dst, const AVPacket *src, void *logctx);
+
 #if defined(_WIN32) && CONFIG_SHARED && !defined(BUILDING_avcodec)
 #    define av_export_avcodec __declspec(dllimport)
 #else
diff --git a/libavcodec/interplayvideo.c b/libavcodec/interplayvideo.c
index 4d16fdf619..b1e0145e30 100644
--- a/libavcodec/interplayvideo.c
+++ b/libavcodec/interplayvideo.c
@@ -1317,14 +1317,7 @@  static int ipvideo_decode_frame(AVCodecContext *avctx,
         return ret;
 
     if (!s->is_16bpp) {
-        buffer_size_t size;
-        const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size);
-        if (pal && size == AVPALETTE_SIZE) {
-            frame->palette_has_changed = 1;
-            memcpy(s->pal, pal, AVPALETTE_SIZE);
-        } else if (pal) {
-            av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", size);
-        }
+        frame->palette_has_changed = ff_copy_palette(s->pal, avpkt, avctx);
     }
 
     switch (frame_format) {
diff --git a/libavcodec/kmvc.c b/libavcodec/kmvc.c
index 0d96139220..02caae346c 100644
--- a/libavcodec/kmvc.c
+++ b/libavcodec/kmvc.c
@@ -268,8 +268,6 @@  static int decode_frame(AVCodecContext * avctx, void *data, int *got_frame,
     int i, ret;
     int header;
     int blocksize;
-    buffer_size_t pal_size;
-    const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &pal_size);
 
     bytestream2_init(&ctx->g, avpkt->data, avpkt->size);
 
@@ -304,12 +302,8 @@  static int decode_frame(AVCodecContext * avctx, void *data, int *got_frame,
         }
     }
 
-    if (pal && pal_size == AVPALETTE_SIZE) {
+    if (ff_copy_palette(ctx->pal, avpkt, avctx))
         frame->palette_has_changed = 1;
-        memcpy(ctx->pal, pal, AVPALETTE_SIZE);
-    } else if (pal) {
-        av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", pal_size);
-    }
 
     if (ctx->setpal) {
         ctx->setpal = 0;
diff --git a/libavcodec/msrle.c b/libavcodec/msrle.c
index feea2b60bb..7bfb29e58e 100644
--- a/libavcodec/msrle.c
+++ b/libavcodec/msrle.c
@@ -97,15 +97,8 @@  static int msrle_decode_frame(AVCodecContext *avctx,
         return ret;
 
     if (avctx->bits_per_coded_sample > 1 && avctx->bits_per_coded_sample <= 8) {
-        buffer_size_t size;
-        const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size);
-
-        if (pal && size == AVPALETTE_SIZE) {
-            s->frame->palette_has_changed = 1;
-            memcpy(s->pal, pal, AVPALETTE_SIZE);
-        } else if (pal) {
-            av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", size);
-        }
+        s->frame->palette_has_changed = ff_copy_palette(s->pal, avpkt, avctx);
+
         /* make the palette available */
         memcpy(s->frame->data[1], s->pal, AVPALETTE_SIZE);
     }
diff --git a/libavcodec/msvideo1.c b/libavcodec/msvideo1.c
index b4b5ea4666..782e5cae00 100644
--- a/libavcodec/msvideo1.c
+++ b/libavcodec/msvideo1.c
@@ -314,15 +314,7 @@  static int msvideo1_decode_frame(AVCodecContext *avctx,
         return ret;
 
     if (s->mode_8bit) {
-        buffer_size_t size;
-        const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size);
-
-        if (pal && size == AVPALETTE_SIZE) {
-            memcpy(s->pal, pal, AVPALETTE_SIZE);
-            s->frame->palette_has_changed = 1;
-        } else if (pal) {
-            av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", size);
-        }
+        s->frame->palette_has_changed = ff_copy_palette(s->pal, avpkt, avctx);
     }
 
     if (s->mode_8bit)
diff --git a/libavcodec/qpeg.c b/libavcodec/qpeg.c
index f4edc4b16f..ca8a0b01d6 100644
--- a/libavcodec/qpeg.c
+++ b/libavcodec/qpeg.c
@@ -274,8 +274,6 @@  static int decode_frame(AVCodecContext *avctx,
     AVFrame * const ref = a->ref;
     uint8_t* outdata;
     int delta, intra, ret;
-    buffer_size_t pal_size;
-    const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &pal_size);
 
     if (avpkt->size < 0x86) {
         av_log(avctx, AV_LOG_ERROR, "Packet is too small\n");
@@ -300,12 +298,7 @@  static int decode_frame(AVCodecContext *avctx,
     }
 
     /* make the palette available on the way out */
-    if (pal && pal_size == AVPALETTE_SIZE) {
-        p->palette_has_changed = 1;
-        memcpy(a->pal, pal, AVPALETTE_SIZE);
-    } else if (pal) {
-        av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", pal_size);
-    }
+    p->palette_has_changed = ff_copy_palette(a->pal, avpkt, avctx);
     memcpy(p->data[1], a->pal, AVPALETTE_SIZE);
 
     av_frame_unref(ref);
diff --git a/libavcodec/qtrle.c b/libavcodec/qtrle.c
index e04fd31431..33da393bd1 100644
--- a/libavcodec/qtrle.c
+++ b/libavcodec/qtrle.c
@@ -540,15 +540,7 @@  static int qtrle_decode_frame(AVCodecContext *avctx,
     }
 
     if(has_palette) {
-        buffer_size_t size;
-        const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size);
-
-        if (pal && size == AVPALETTE_SIZE) {
-            s->frame->palette_has_changed = 1;
-            memcpy(s->pal, pal, AVPALETTE_SIZE);
-        } else if (pal) {
-            av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", size);
-        }
+        s->frame->palette_has_changed = ff_copy_palette(s->pal, avpkt, avctx);
 
         /* make the palette available on the way out */
         memcpy(s->frame->data[1], s->pal, AVPALETTE_SIZE);
diff --git a/libavcodec/rawdec.c b/libavcodec/rawdec.c
index c18c3dd3e1..1badb69180 100644
--- a/libavcodec/rawdec.c
+++ b/libavcodec/rawdec.c
@@ -367,16 +367,8 @@  static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame,
     }
 
     if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
-        buffer_size_t pal_size;
-        const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE,
-                                                     &pal_size);
         int ret;
 
-        if (pal && pal_size != AVPALETTE_SIZE) {
-            av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", pal_size);
-            pal = NULL;
-        }
-
         if (!context->palette)
             context->palette = av_buffer_alloc(AVPALETTE_SIZE);
         if (!context->palette) {
@@ -389,15 +381,14 @@  static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame,
             return ret;
         }
 
-        if (pal) {
-            memcpy(context->palette->data, pal, AVPALETTE_SIZE);
+        if (ff_copy_palette(context->palette->data, avpkt, avctx)) {
             frame->palette_has_changed = 1;
         } else if (context->is_nut_pal8) {
             int vid_size = avctx->width * avctx->height;
             int pal_size = avpkt->size - vid_size;
 
             if (avpkt->size > vid_size && pal_size <= AVPALETTE_SIZE) {
-                pal = avpkt->data + vid_size;
+                const uint8_t *pal = avpkt->data + vid_size;
                 memcpy(context->palette->data, pal, pal_size);
                 frame->palette_has_changed = 1;
             }
diff --git a/libavcodec/rscc.c b/libavcodec/rscc.c
index 79b02da441..372c35b603 100644
--- a/libavcodec/rscc.c
+++ b/libavcodec/rscc.c
@@ -346,17 +346,8 @@  static int rscc_decode_frame(AVCodecContext *avctx, void *data,
 
     /* Palette handling */
     if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
-        buffer_size_t size;
-        const uint8_t *palette = av_packet_get_side_data(avpkt,
-                                                         AV_PKT_DATA_PALETTE,
-                                                         &size);
-        if (palette && size == AVPALETTE_SIZE) {
-            frame->palette_has_changed = 1;
-            memcpy(ctx->palette, palette, AVPALETTE_SIZE);
-        } else if (palette) {
-            av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", size);
-        }
-        memcpy (frame->data[1], ctx->palette, AVPALETTE_SIZE);
+        frame->palette_has_changed = ff_copy_palette(ctx->palette, avpkt, avctx);
+        memcpy(frame->data[1], ctx->palette, AVPALETTE_SIZE);
     }
     // We only return a picture when enough of it is undamaged, this avoids copying nearly broken frames around
     if (ctx->valid_pixels < ctx->inflated_size)
diff --git a/libavcodec/smc.c b/libavcodec/smc.c
index 33581bbf81..73ee6d6ebc 100644
--- a/libavcodec/smc.c
+++ b/libavcodec/smc.c
@@ -435,8 +435,6 @@  static int smc_decode_frame(AVCodecContext *avctx,
     const uint8_t *buf = avpkt->data;
     int buf_size = avpkt->size;
     SmcContext *s = avctx->priv_data;
-    buffer_size_t pal_size;
-    const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &pal_size);
     int ret;
     int total_blocks = ((s->avctx->width + 3) / 4) * ((s->avctx->height + 3) / 4);
 
@@ -448,12 +446,7 @@  static int smc_decode_frame(AVCodecContext *avctx,
     if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0)
         return ret;
 
-    if (pal && pal_size == AVPALETTE_SIZE) {
-        s->frame->palette_has_changed = 1;
-        memcpy(s->pal, pal, AVPALETTE_SIZE);
-    } else if (pal) {
-        av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", pal_size);
-    }
+    s->frame->palette_has_changed = ff_copy_palette(s->pal, avpkt, avctx);
 
     smc_decode_stream(s);
 
diff --git a/libavcodec/tscc.c b/libavcodec/tscc.c
index d33639f3a4..482c2966a0 100644
--- a/libavcodec/tscc.c
+++ b/libavcodec/tscc.c
@@ -72,15 +72,7 @@  static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
     int palette_has_changed = 0;
 
     if (c->avctx->pix_fmt == AV_PIX_FMT_PAL8) {
-        buffer_size_t size;
-        const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size);
-
-        if (pal && size == AVPALETTE_SIZE) {
-            palette_has_changed = 1;
-            memcpy(c->pal, pal, AVPALETTE_SIZE);
-        } else if (pal) {
-            av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", size);
-        }
+        palette_has_changed = ff_copy_palette(c->pal, avpkt, avctx);
     }
 
     ret = inflateReset(&c->zstream);