]> git.sesse.net Git - ffmpeg/blobdiff - libswscale/swscale_unscaled.c
swscale: add endian conversion for RGB555 and RGB444 pixel formats
[ffmpeg] / libswscale / swscale_unscaled.c
index e6dac22cfe4990c4ca948edd1ea7d5eed96d479d..3dc2929a5aca924aa38b87bf3d676507b345bf4c 100644 (file)
@@ -252,6 +252,27 @@ static void gray8aToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, c
     }
 }
 
+static int packed_16bpc_bswap(SwsContext *c, const uint8_t* src[],
+                              int srcStride[], int srcSliceY, int srcSliceH,
+                              uint8_t* dst[], int dstStride[])
+{
+    int i, j;
+    int srcstr = srcStride[0] >> 1;
+    int dststr = dstStride[0] >> 1;
+    uint16_t       *dstPtr =       (uint16_t *)dst[0];
+    const uint16_t *srcPtr = (const uint16_t *)src[0];
+
+    for (i = 0; i < srcSliceH; i++) {
+        for (j = 0; j < srcstr; j++) {
+            dstPtr[j] = av_bswap16(srcPtr[j]);
+        }
+        srcPtr += srcstr;
+        dstPtr += dststr;
+    }
+
+    return srcSliceH;
+}
+
 static int palToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
                            int srcSliceH, uint8_t* dst[], int dstStride[])
 {
@@ -382,7 +403,7 @@ static int rgbToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[],
         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)
+        if (dstStride[0]*srcBpp == srcStride[0]*dstBpp && srcStride[0] > 0 && !(srcStride[0] % srcBpp))
             conv(srcPtr, dstPtr + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]);
         else {
             int i;
@@ -454,18 +475,20 @@ static int packedCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[
     return srcSliceH;
 }
 
-#define DITHER_COPY(dst, dstStride, wfunc, src, srcStride, rfunc, dithers, shift) \
+#define clip9(x)  av_clip_uintp2(x,  9)
+#define clip10(x) av_clip_uintp2(x, 10)
+#define DITHER_COPY(dst, dstStride, wfunc, src, srcStride, rfunc, dithers, shift, clip) \
     for (i = 0; i < height; i++) { \
         const uint8_t *dither = dithers[i & 7]; \
         for (j = 0; j < length - 7; j += 8) { \
-            wfunc(&dst[j + 0], (rfunc(&src[j + 0]) + dither[0]) >> shift); \
-            wfunc(&dst[j + 1], (rfunc(&src[j + 1]) + dither[1]) >> shift); \
-            wfunc(&dst[j + 2], (rfunc(&src[j + 2]) + dither[2]) >> shift); \
-            wfunc(&dst[j + 3], (rfunc(&src[j + 3]) + dither[3]) >> shift); \
-            wfunc(&dst[j + 4], (rfunc(&src[j + 4]) + dither[4]) >> shift); \
-            wfunc(&dst[j + 5], (rfunc(&src[j + 5]) + dither[5]) >> shift); \
-            wfunc(&dst[j + 6], (rfunc(&src[j + 6]) + dither[6]) >> shift); \
-            wfunc(&dst[j + 7], (rfunc(&src[j + 7]) + dither[7]) >> shift); \
+            wfunc(&dst[j + 0], clip((rfunc(&src[j + 0]) + dither[0]) >> shift)); \
+            wfunc(&dst[j + 1], clip((rfunc(&src[j + 1]) + dither[1]) >> shift)); \
+            wfunc(&dst[j + 2], clip((rfunc(&src[j + 2]) + dither[2]) >> shift)); \
+            wfunc(&dst[j + 3], clip((rfunc(&src[j + 3]) + dither[3]) >> shift)); \
+            wfunc(&dst[j + 4], clip((rfunc(&src[j + 4]) + dither[4]) >> shift)); \
+            wfunc(&dst[j + 5], clip((rfunc(&src[j + 5]) + dither[5]) >> shift)); \
+            wfunc(&dst[j + 6], clip((rfunc(&src[j + 6]) + dither[6]) >> shift)); \
+            wfunc(&dst[j + 7], clip((rfunc(&src[j + 7]) + dither[7]) >> shift)); \
         } \
         for (; j < length; j++) \
             wfunc(&dst[j],     (rfunc(&src[j]) + dither[j & 7]) >> shift); \
@@ -538,7 +561,7 @@ static int planarCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[
                     } else if (dst_depth < src_depth) { \
                         DITHER_COPY(dstPtr2, dstStride[plane]/2, wfunc, \
                                     srcPtr2, srcStride[plane]/2, rfunc, \
-                                    dither_8x8_1, 1); \
+                                    dither_8x8_1, 1, clip9); \
                     } else { \
                         COPY9_OR_10TO9_OR_10(wfunc(&dstPtr2[j], rfunc(&srcPtr2[j]))); \
                     }
@@ -561,11 +584,11 @@ static int planarCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[
                     if (src_depth == 9) { \
                         DITHER_COPY(dstPtr,  dstStride[plane],   W8, \
                                     srcPtr2, srcStride[plane]/2, rfunc, \
-                                    dither_8x8_1, 1); \
+                                    dither_8x8_1, 1, av_clip_uint8); \
                     } else { \
                         DITHER_COPY(dstPtr,  dstStride[plane],   W8, \
                                     srcPtr2, srcStride[plane]/2, rfunc, \
-                                    dither_8x8_3, 2); \
+                                    dither_8x8_3, 2, av_clip_uint8); \
                     }
                     if (isBE(c->srcFormat)) {
                         COPY9_OR_10TO8(AV_RB16);
@@ -583,11 +606,11 @@ static int planarCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[
                     if (dst_depth == 9) { \
                         DITHER_COPY(dstPtr2, dstStride[plane]/2, wfunc, \
                                     srcPtr2, srcStride[plane]/2, rfunc, \
-                                    dither_8x8_128, 7); \
+                                    dither_8x8_128, 7, clip9); \
                     } else { \
                         DITHER_COPY(dstPtr2, dstStride[plane]/2, wfunc, \
                                     srcPtr2, srcStride[plane]/2, rfunc, \
-                                    dither_8x8_64, 6); \
+                                    dither_8x8_64, 6, clip10); \
                     }
                     if (isBE(c->dstFormat)) {
                         if (isBE(c->srcFormat)) {
@@ -623,7 +646,7 @@ static int planarCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[
 #define COPY16TO8(rfunc) \
                     DITHER_COPY(dstPtr,  dstStride[plane],   W8, \
                                 srcPtr2, srcStride[plane]/2, rfunc, \
-                                dither_8x8_256, 8);
+                                dither_8x8_256, 8, av_clip_uint8);
                 if (isBE(c->srcFormat)) {
                     COPY16TO8(AV_RB16);
                 } else {
@@ -665,6 +688,12 @@ static int planarCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[
     return srcSliceH;
 }
 
+
+#define IS_DIFFERENT_ENDIANESS(src_fmt, dst_fmt, pix_fmt)          \
+    ((src_fmt == pix_fmt ## BE && dst_fmt == pix_fmt ## LE) ||     \
+     (src_fmt == pix_fmt ## LE && dst_fmt == pix_fmt ## BE))
+
+
 void ff_get_unscaled_swscale(SwsContext *c)
 {
     const enum PixelFormat srcFormat = c->srcFormat;
@@ -713,6 +742,18 @@ void ff_get_unscaled_swscale(SwsContext *c)
         && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT))))
         c->swScale= rgbToRgbWrapper;
 
+    /* bswap 16 bits per pixel/component packed formats */
+    if (IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR444) ||
+        IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR48)  ||
+        IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR555) ||
+        IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR565) ||
+        IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_GRAY16) ||
+        IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB444) ||
+        IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB48)  ||
+        IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB555) ||
+        IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB565))
+        c->swScale = packed_16bpc_bswap;
+
     if ((usePal(srcFormat) && (
         dstFormat == PIX_FMT_RGB32   ||
         dstFormat == PIX_FMT_RGB32_1 ||
@@ -777,7 +818,7 @@ static void reset_ptr(const uint8_t* src[], int format)
 {
     if(!isALPHA(format))
         src[3]=NULL;
-    if(!isPlanarYUV(format)) {
+    if (!isPlanar(format)) {
         src[3]=src[2]=NULL;
 
         if (!usePal(format))
@@ -804,7 +845,7 @@ static int check_image_pointers(uint8_t *data[4], enum PixelFormat pix_fmt,
  * swscale wrapper, so we don't need to export the SwsContext.
  * Assumes planar YUV to be in YUV order instead of YVU.
  */
-int sws_scale(struct SwsContext *c, const uint8_t* const srcSlice[],
+int attribute_align_arg sws_scale(struct SwsContext *c, const uint8_t* const srcSlice[],
               const int srcStride[], int srcSliceY, int srcSliceH,
               uint8_t* const dst[], const int dstStride[])
 {