# HG changeset patch # User stefano # Date 1265240760 0 # Node ID 9bb2ebbb52bed2a79663a18cb6c507e16de97747 # Parent f6721168aee85ef7fa0fa9d670a1f1ac15df76ea Implement shuffle_bytes_abcd() functions and use them for shuffling bytes when converting between RGB32 variants. In particular fix the argb -> rgba and abgr -> bgra conversions. See the thread: Subject: [FFmpeg-devel] [RFC] RGB32 / BGR32 ethernal bug Date: Tue, 26 Jan 2010 01:06:18 +0100 diff -r f6721168aee8 -r 9bb2ebbb52be libswscale/rgb2rgb.c --- a/libswscale/rgb2rgb.c Wed Feb 03 22:36:47 2010 +0000 +++ b/libswscale/rgb2rgb.c Wed Feb 03 23:46:00 2010 +0000 @@ -442,3 +442,23 @@ dst[i] = ((b<<1)&0x07) | ((g&0x07)<<3) | ((r&0x03)<<6); } } + +#define DEFINE_SHUFFLE_BYTES(a, b, c, d) \ +void shuffle_bytes_##a##b##c##d(const uint8_t *src, uint8_t *dst, long src_size) \ +{ \ + long i; \ + \ + for (i = 0; i < src_size; i+=4) { \ + dst[i + 0] = src[i + a]; \ + dst[i + 1] = src[i + b]; \ + dst[i + 2] = src[i + c]; \ + dst[i + 3] = src[i + d]; \ + } \ +} + +DEFINE_SHUFFLE_BYTES(0, 3, 2, 1); +DEFINE_SHUFFLE_BYTES(1, 2, 3, 0); +DEFINE_SHUFFLE_BYTES(2, 1, 0, 3); +DEFINE_SHUFFLE_BYTES(3, 0, 1, 2); +DEFINE_SHUFFLE_BYTES(3, 2, 1, 0); + diff -r f6721168aee8 -r 9bb2ebbb52be libswscale/rgb2rgb.h --- a/libswscale/rgb2rgb.h Wed Feb 03 22:36:47 2010 +0000 +++ b/libswscale/rgb2rgb.h Wed Feb 03 23:46:00 2010 +0000 @@ -60,6 +60,11 @@ void rgb15tobgr15(const uint8_t *src, uint8_t *dst, long src_size); void bgr8torgb8 (const uint8_t *src, uint8_t *dst, long src_size); +void shuffle_bytes_0321(const uint8_t *src, uint8_t *dst, long src_size); +void shuffle_bytes_1230(const uint8_t *src, uint8_t *dst, long src_size); +void shuffle_bytes_2103(const uint8_t *src, uint8_t *dst, long src_size); +void shuffle_bytes_3012(const uint8_t *src, uint8_t *dst, long src_size); +void shuffle_bytes_3210(const uint8_t *src, uint8_t *dst, long src_size); void palette8topacked32(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette); void palette8topacked24(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette); diff -r f6721168aee8 -r 9bb2ebbb52be libswscale/swscale.c --- a/libswscale/swscale.c Wed Feb 03 22:36:47 2010 +0000 +++ b/libswscale/swscale.c Wed Feb 03 23:46:00 2010 +0000 @@ -1423,6 +1423,13 @@ return srcSliceH; } +#define isRGBA32(x) ( \ + (x) == PIX_FMT_ARGB \ + || (x) == PIX_FMT_RGBA \ + || (x) == PIX_FMT_BGRA \ + || (x) == PIX_FMT_ABGR \ + ) + /* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */ static int rgbToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t* dst[], int dstStride[]) @@ -1435,6 +1442,22 @@ const int dstId= c->dstFormatBpp >> 2; void (*conv)(const uint8_t *src, uint8_t *dst, long src_size)=NULL; +#define CONV_IS(src, dst) (srcFormat == PIX_FMT_##src && dstFormat == PIX_FMT_##dst) + + if (isRGBA32(srcFormat) && isRGBA32(dstFormat)) { + if ( CONV_IS(ABGR, RGBA) + || CONV_IS(ARGB, BGRA) + || CONV_IS(BGRA, ARGB) + || CONV_IS(RGBA, ABGR)) conv = shuffle_bytes_3210; + else if (CONV_IS(ABGR, ARGB) + || CONV_IS(ARGB, ABGR)) conv = shuffle_bytes_0321; + else if (CONV_IS(ABGR, BGRA) + || CONV_IS(ARGB, RGBA)) conv = shuffle_bytes_1230; + else if (CONV_IS(BGRA, RGBA) + || CONV_IS(RGBA, BGRA)) conv = shuffle_bytes_2103; + else if (CONV_IS(BGRA, ABGR) + || CONV_IS(RGBA, ARGB)) conv = shuffle_bytes_3012; + } else /* BGR -> BGR */ if ( (isBGRinInt(srcFormat) && isBGRinInt(dstFormat)) || (isRGBinInt(srcFormat) && isRGBinInt(dstFormat))) { @@ -1470,7 +1493,6 @@ case 0x83: conv= rgb15tobgr32; break; case 0x84: conv= rgb16tobgr32; break; case 0x86: conv= rgb24tobgr32; break; - case 0x88: conv= rgb32tobgr32; break; } } @@ -1479,14 +1501,18 @@ sws_format_name(srcFormat), sws_format_name(dstFormat)); } else { const uint8_t *srcPtr= src[0]; - if(srcFormat == PIX_FMT_RGB32_1 || srcFormat == PIX_FMT_BGR32_1) + uint8_t *dstPtr= dst[0]; + if ((srcFormat == PIX_FMT_RGB32_1 || srcFormat == PIX_FMT_BGR32_1) && !isRGBA32(dstFormat)) srcPtr += ALT32_CORR; + if ((dstFormat == PIX_FMT_RGB32_1 || dstFormat == PIX_FMT_BGR32_1) && !isRGBA32(srcFormat)) + dstPtr += ALT32_CORR; + if (dstStride[0]*srcBpp == srcStride[0]*dstBpp && srcStride[0] > 0) - conv(srcPtr, dst[0] + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]); + conv(srcPtr, dstPtr + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]); else { int i; - uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY; + dstPtr += dstStride[0]*srcSliceY; for (i=0; isrcW*srcBpp); @@ -1692,8 +1718,6 @@ && srcFormat != PIX_FMT_RGB4_BYTE && dstFormat != PIX_FMT_RGB4_BYTE && srcFormat != PIX_FMT_MONOBLACK && dstFormat != PIX_FMT_MONOBLACK && srcFormat != PIX_FMT_MONOWHITE && dstFormat != PIX_FMT_MONOWHITE - && dstFormat != PIX_FMT_RGB32_1 - && dstFormat != PIX_FMT_BGR32_1 && srcFormat != PIX_FMT_RGB48LE && dstFormat != PIX_FMT_RGB48LE && srcFormat != PIX_FMT_RGB48BE && dstFormat != PIX_FMT_RGB48BE && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT))))