[FFmpeg-devel] [PATCH v2] swscale/unscaled: add pal8 -> gbr(a)p special converter

James Almer jamrial at gmail.com
Sun Dec 22 18:43:36 EET 2024


On 12/20/2024 8:06 AM, Niklas Haas wrote:
> From: Niklas Haas <git at haasn.dev>
> 
> Fixes: ticket #9520
> Signed-off-by: Niklas Haas <git at haasn.dev>
> Sponsored-by: Sovereign Tech Fund
> ---
>   libswscale/swscale.c          |  8 ++++
>   libswscale/swscale_unscaled.c | 81 ++++++++++++++++++++++++++++++++++-
>   2 files changed, 87 insertions(+), 2 deletions(-)
> 
> diff --git a/libswscale/swscale.c b/libswscale/swscale.c
> index da3a082905..34fb52d88f 100644
> --- a/libswscale/swscale.c
> +++ b/libswscale/swscale.c
> @@ -923,6 +923,14 @@ void ff_update_palette(SwsInternal *c, const uint32_t *pal)
>   #if !HAVE_BIGENDIAN
>           case AV_PIX_FMT_BGR24:
>   #endif

This is meant to fallback to the default case, but after this change it 
will use the GBR case you added instead.
It's the cause for the fate failure Michael reported.

> +        case AV_PIX_FMT_GBRP:
> +        case AV_PIX_FMT_GBRAP:
> +#if HAVE_BIGENDIAN
> +            c->pal_rgb[i]= a + (r<<8) + (b<<16) + ((unsigned)g<<24);
> +#else
> +            c->pal_rgb[i]= g + (b<<8) + (r<<16) + ((unsigned)a<<24);
> +#endif
> +            break;
>           default:
>               c->pal_rgb[i]=  b + (g<<8) + (r<<16) + ((unsigned)a<<24);
>           }
> diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c
> index f0fe8304f5..1819feeaa2 100644
> --- a/libswscale/swscale_unscaled.c
> +++ b/libswscale/swscale_unscaled.c
> @@ -509,6 +509,34 @@ static void gray8aToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels,
>       }
>   }
>   
> +static void gray8aToPlanar8(const uint8_t *src, uint8_t *dst0, uint8_t *dst1,
> +                            uint8_t *dst2, uint8_t *dstA, int num_pixels,
> +                            const uint8_t *palette)
> +{
> +    for (int i = 0; i < num_pixels; i++) {
> +        const uint8_t *rgb = &palette[src[i << 1] * 4];
> +        dst0[i] = rgb[0];
> +        dst1[i] = rgb[1];
> +        dst2[i] = rgb[2];
> +        if (dstA)
> +            dstA[i] = src[(i << 1) + 1];
> +    }
> +}
> +
> +static void pal8ToPlanar8(const uint8_t *src, uint8_t *dst0, uint8_t *dst1,
> +                          uint8_t *dst2, uint8_t *dstA, int num_pixels,
> +                          const uint8_t *palette)
> +{
> +    for (int i = 0; i < num_pixels; i++) {
> +        const uint8_t *rgba = &palette[src[i] * 4];
> +        dst0[i] = rgba[0];
> +        dst1[i] = rgba[1];
> +        dst2[i] = rgba[2];
> +        if (dstA)
> +            dstA[i] = rgba[3];
> +    }
> +}
> +
>   static int bswap_16bpc(SwsInternal *c, const uint8_t *const src[],
>                                 const int srcStride[], int srcSliceY, int srcSliceH,
>                                 uint8_t *const dst[], const int dstStride[])
> @@ -610,6 +638,45 @@ static int palToRgbWrapper(SwsInternal *c, const uint8_t *const src[], const int
>       return srcSliceH;
>   }
>   
> +static int palToGbrpWrapper(SwsInternal *c, const uint8_t *const src[],
> +                            const int srcStride[], int srcSliceY, int srcSliceH,
> +                            uint8_t *const dst[], const int dstStride[])
> +{
> +    const enum AVPixelFormat srcFormat = c->opts.src_format;
> +    const enum AVPixelFormat dstFormat = c->opts.dst_format;
> +    void (*conv)(const uint8_t *src, uint8_t *dstG, uint8_t *dstB, uint8_t *dstR,
> +                 uint8_t *dstA, int num_pixels, const uint8_t *palette) = NULL;
> +
> +    const int num_planes = isALPHA(dstFormat) ? 4 : 3;
> +    const uint8_t *srcPtr = src[0];
> +    uint8_t *dstPtr[4] = {0};
> +    for (int i = 0; i < num_planes; i++)
> +        dstPtr[i] = dst[i] + dstStride[i] * srcSliceY;
> +
> +    if (srcFormat == AV_PIX_FMT_YA8) {
> +        switch (dstFormat) {
> +        case AV_PIX_FMT_GBRP:  conv = gray8aToPlanar8; break;
> +        case AV_PIX_FMT_GBRAP: conv = gray8aToPlanar8; break;
> +        }
> +    } else if (usePal(srcFormat)) {
> +        switch (dstFormat) {
> +        case AV_PIX_FMT_GBRP:  conv = pal8ToPlanar8; break;
> +        case AV_PIX_FMT_GBRAP: conv = pal8ToPlanar8; break;
> +        }
> +    }
> +
> +    av_assert1(conv);
> +    for (int y = 0; y < srcSliceH; y++) {
> +        conv(srcPtr, dstPtr[0], dstPtr[1], dstPtr[2], dstPtr[3], c->opts.src_w,
> +            (uint8_t *) c->pal_rgb);
> +        srcPtr += srcStride[0];
> +        for (int i = 0; i < num_planes; i++)
> +            dstPtr[i] += dstStride[i];
> +    }
> +
> +    return srcSliceH;
> +}
> +
>   static void packed16togbra16(const uint8_t *src, int srcStride,
>                                uint16_t *dst[], const int dstStride[], int srcSliceH,
>                                int src_alpha, int swap, int shift, int width)
> @@ -2531,8 +2598,18 @@ void ff_get_unscaled_swscale(SwsInternal *c)
>           IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRAPF32))
>           c->convert_unscaled = bswap_32bpc;
>   
> -    if (usePal(srcFormat) && isByteRGB(dstFormat))
> -        c->convert_unscaled = palToRgbWrapper;
> +    if (usePal(srcFormat)) {
> +        switch (dstFormat) {
> +        case AV_PIX_FMT_GBRP:
> +        case AV_PIX_FMT_GBRAP:
> +            c->convert_unscaled = palToGbrpWrapper;
> +            break;
> +        default:
> +            if (isByteRGB(dstFormat))
> +                c->convert_unscaled = palToRgbWrapper;
> +            break;
> +        }
> +    }
>   
>       if (srcFormat == AV_PIX_FMT_YUV422P) {
>           if (dstFormat == AV_PIX_FMT_YUYV422)

-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature.asc
Type: application/pgp-signature
Size: 495 bytes
Desc: OpenPGP digital signature
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20241222/b73b8626/attachment.sig>


More information about the ffmpeg-devel mailing list