]> git.sesse.net Git - ffmpeg/blobdiff - libswscale/swscale.c
swscale: fix crash in 8-bpc bilinear output without alpha.
[ffmpeg] / libswscale / swscale.c
index ef8fc39c48dfba4bac9f45f7e336b69a7ab43f6a..527dd80e0c7a7b749ec2ed1821baf85e17743aec 100644 (file)
@@ -80,17 +80,6 @@ untested special converters
 #define RV ( (int)(0.500*224/255*(1<<RGB2YUV_SHIFT)+0.5))
 #define RU (-(int)(0.169*224/255*(1<<RGB2YUV_SHIFT)+0.5))
 
-static const double rgb2yuv_table[8][9]={
-    {0.7152, 0.0722, 0.2126, -0.386, 0.5, -0.115, -0.454, -0.046, 0.5}, //ITU709
-    {0.7152, 0.0722, 0.2126, -0.386, 0.5, -0.115, -0.454, -0.046, 0.5}, //ITU709
-    {0.587 , 0.114 , 0.299 , -0.331, 0.5, -0.169, -0.419, -0.081, 0.5}, //DEFAULT / ITU601 / ITU624 / SMPTE 170M
-    {0.587 , 0.114 , 0.299 , -0.331, 0.5, -0.169, -0.419, -0.081, 0.5}, //DEFAULT / ITU601 / ITU624 / SMPTE 170M
-    {0.59  , 0.11  , 0.30  , -0.331, 0.5, -0.169, -0.421, -0.079, 0.5}, //FCC
-    {0.587 , 0.114 , 0.299 , -0.331, 0.5, -0.169, -0.419, -0.081, 0.5}, //DEFAULT / ITU601 / ITU624 / SMPTE 170M
-    {0.587 , 0.114 , 0.299 , -0.331, 0.5, -0.169, -0.419, -0.081, 0.5}, //DEFAULT / ITU601 / ITU624 / SMPTE 170M
-    {0.701 , 0.087 , 0.212 , -0.384, 0.5, -0.116, -0.445, -0.055, 0.5}, //SMPTE 240M
-};
-
 /*
 NOTES
 Special versions: fast Y 1:1 scaling (no interpolation in y direction)
@@ -1147,7 +1136,8 @@ yuv2rgb_2_c_template(SwsContext *c, const int16_t *buf[2],
     const int16_t *buf0  = buf[0],  *buf1  = buf[1],
                   *ubuf0 = ubuf[0], *ubuf1 = ubuf[1],
                   *vbuf0 = vbuf[0], *vbuf1 = vbuf[1],
-                  *abuf0 = abuf[0], *abuf1 = abuf[1];
+                  *abuf0 = hasAlpha ? abuf[0] : NULL,
+                  *abuf1 = hasAlpha ? abuf[1] : NULL;
     int  yalpha1 = 4095 - yalpha;
     int uvalpha1 = 4095 - uvalpha;
     int i;
@@ -1766,59 +1756,6 @@ static void nv21ToUV_c(uint8_t *dstU, uint8_t *dstV,
 
 #define input_pixel(pos) (isBE(origin) ? AV_RB16(pos) : AV_RL16(pos))
 
-// FIXME Maybe dither instead.
-static av_always_inline void
-yuv9_OR_10ToUV_c_template(uint16_t *dstU, uint16_t *dstV,
-                          const uint16_t *srcU, const uint16_t *srcV,
-                          int width, enum PixelFormat origin, int depth)
-{
-    int i;
-
-    for (i = 0; i < width; i++) {
-        int upx = input_pixel(&srcU[i]);
-        int vpx = input_pixel(&srcV[i]);
-        dstU[i] =  (upx << (16 - depth)) | (upx >> (2 * depth - 16));
-        dstV[i] =  (vpx << (16 - depth)) | (vpx >> (2 * depth - 16));
-    }
-}
-
-static av_always_inline void
-yuv9_or_10ToY_c_template(uint16_t *dstY, const uint16_t *srcY,
-                         int width, enum PixelFormat origin, int depth)
-{
-    int i;
-
-    for (i = 0; i < width; i++) {
-        int px = input_pixel(&srcY[i]);
-        dstY[i] =  (px << (16 - depth)) | (px >> (2 * depth - 16));
-    }
-}
-
-#undef input_pixel
-
-#define YUV_NBPS(depth, BE_LE, origin) \
-static void BE_LE ## depth ## ToUV_c(uint8_t *_dstU, uint8_t *_dstV, \
-                                     const uint8_t *_srcU, const uint8_t *_srcV, \
-                                     int width, uint32_t *unused) \
-{ \
-    uint16_t *dstU = (uint16_t *) _dstU, *dstV = (uint16_t *) _dstV; \
-    const uint16_t *srcU = (const uint16_t *) _srcU, \
-                   *srcV = (const uint16_t *) _srcV; \
-    yuv9_OR_10ToUV_c_template(dstU, dstV, srcU, srcV, width, origin, depth); \
-} \
-static void BE_LE ## depth ## ToY_c(uint8_t *_dstY, const uint8_t *_srcY, \
-                                    int width, uint32_t *unused) \
-{ \
-    uint16_t *dstY = (uint16_t *) _dstY; \
-    const uint16_t *srcY = (const uint16_t *) _srcY; \
-    yuv9_or_10ToY_c_template(dstY, srcY, width, origin, depth); \
-}
-
-YUV_NBPS( 9, LE, PIX_FMT_YUV420P9LE);
-YUV_NBPS( 9, BE, PIX_FMT_YUV420P9BE);
-YUV_NBPS(10, LE, PIX_FMT_YUV420P10LE);
-YUV_NBPS(10, BE, PIX_FMT_YUV420P10BE);
-
 static void bgr24ToY_c(uint8_t *dst, const uint8_t *src,
                        int width, uint32_t *unused)
 {
@@ -1905,29 +1842,31 @@ static void rgb24ToUV_half_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
     }
 }
 
-static void hScale16_c(int16_t *_dst, int dstW, const uint8_t *_src,
+static void hScale16_c(SwsContext *c, int16_t *_dst, int dstW, const uint8_t *_src,
                        const int16_t *filter,
                        const int16_t *filterPos, int filterSize)
 {
     int i;
     int32_t *dst = (int32_t *) _dst;
     const uint16_t *src = (const uint16_t *) _src;
+    int bits = av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1;
+    int sh = (bits <= 7) ? 11 : (bits - 4);
 
     for (i = 0; i < dstW; i++) {
         int j;
         int srcPos = filterPos[i];
-        unsigned int val = 0;
+        int val = 0;
 
         for (j = 0; j < filterSize; j++) {
             val += src[srcPos + j] * filter[filterSize * i + j];
         }
         // filter=14 bit, input=16 bit, output=30 bit, >> 11 makes 19 bit
-        dst[i] = FFMIN(val >> 11, (1 << 19) - 1);
+        dst[i] = FFMIN(val >> sh, (1 << 19) - 1);
     }
 }
 
 // bilinear / bicubic scaling
-static void hScale_c(int16_t *dst, int dstW, const uint8_t *src,
+static void hScale_c(SwsContext *c, int16_t *dst, int dstW, const uint8_t *src,
                      const int16_t *filter, const int16_t *filterPos,
                      int filterSize)
 {
@@ -2063,7 +2002,7 @@ static av_always_inline void hyscale(SwsContext *c, int16_t *dst, int dstWidth,
     }
 
     if (!c->hyscale_fast) {
-        c->hScale(dst, dstWidth, src, hLumFilter, hLumFilterPos, hLumFilterSize);
+        c->hScale(c, dst, dstWidth, src, hLumFilter, hLumFilterPos, hLumFilterSize);
     } else { // fast bilinear upscale / crap downscale
         c->hyscale_fast(c, dst, dstWidth, src, srcW, xInc);
     }
@@ -2113,8 +2052,8 @@ static av_always_inline void hcscale(SwsContext *c, int16_t *dst1, int16_t *dst2
     }
 
     if (!c->hcscale_fast) {
-        c->hScale(dst1, dstWidth, src1, hChrFilter, hChrFilterPos, hChrFilterSize);
-        c->hScale(dst2, dstWidth, src2, hChrFilter, hChrFilterPos, hChrFilterSize);
+        c->hScale(c, dst1, dstWidth, src1, hChrFilter, hChrFilterPos, hChrFilterSize);
+        c->hScale(c, dst2, dstWidth, src2, hChrFilter, hChrFilterPos, hChrFilterSize);
     } else { // fast bilinear upscale / crap downscale
         c->hcscale_fast(c, dst1, dst2, dstWidth, src1, src2, srcW, xInc);
     }
@@ -2645,21 +2584,21 @@ static av_cold void sws_init_swScale_c(SwsContext *c)
         case PIX_FMT_PAL8     :
         case PIX_FMT_BGR4_BYTE:
         case PIX_FMT_RGB4_BYTE: c->chrToYV12 = palToUV_c; break;
+#if HAVE_BIGENDIAN
         case PIX_FMT_YUV444P9LE:
-        case PIX_FMT_YUV420P9LE:  c->chrToYV12 = LE9ToUV_c; break;
+        case PIX_FMT_YUV420P9LE:
         case PIX_FMT_YUV422P10LE:
         case PIX_FMT_YUV444P10LE:
-        case PIX_FMT_YUV420P10LE: c->chrToYV12 = LE10ToUV_c; break;
-        case PIX_FMT_YUV444P9BE:
-        case PIX_FMT_YUV420P9BE:  c->chrToYV12 = BE9ToUV_c; break;
-        case PIX_FMT_YUV444P10BE:
-        case PIX_FMT_YUV422P10BE:
-        case PIX_FMT_YUV420P10BE: c->chrToYV12 = BE10ToUV_c; break;
-#if HAVE_BIGENDIAN
+        case PIX_FMT_YUV420P10LE:
         case PIX_FMT_YUV420P16LE:
         case PIX_FMT_YUV422P16LE:
         case PIX_FMT_YUV444P16LE: c->chrToYV12 = bswap16UV_c; break;
 #else
+        case PIX_FMT_YUV444P9BE:
+        case PIX_FMT_YUV420P9BE:
+        case PIX_FMT_YUV444P10BE:
+        case PIX_FMT_YUV422P10BE:
+        case PIX_FMT_YUV420P10BE:
         case PIX_FMT_YUV420P16BE:
         case PIX_FMT_YUV422P16BE:
         case PIX_FMT_YUV444P16BE: c->chrToYV12 = bswap16UV_c; break;
@@ -2712,22 +2651,22 @@ static av_cold void sws_init_swScale_c(SwsContext *c)
     c->lumToYV12 = NULL;
     c->alpToYV12 = NULL;
     switch (srcFormat) {
+#if HAVE_BIGENDIAN
     case PIX_FMT_YUV444P9LE:
-    case PIX_FMT_YUV420P9LE:  c->lumToYV12 = LE9ToY_c; break;
+    case PIX_FMT_YUV420P9LE:
     case PIX_FMT_YUV444P10LE:
     case PIX_FMT_YUV422P10LE:
-    case PIX_FMT_YUV420P10LE: c->lumToYV12 = LE10ToY_c; break;
-    case PIX_FMT_YUV444P9BE:
-    case PIX_FMT_YUV420P9BE:  c->lumToYV12 = BE9ToY_c; break;
-    case PIX_FMT_YUV444P10BE:
-    case PIX_FMT_YUV422P10BE:
-    case PIX_FMT_YUV420P10BE: c->lumToYV12 = BE10ToY_c; break;
-#if HAVE_BIGENDIAN
+    case PIX_FMT_YUV420P10LE:
     case PIX_FMT_YUV420P16LE:
     case PIX_FMT_YUV422P16LE:
     case PIX_FMT_YUV444P16LE:
     case PIX_FMT_GRAY16LE: c->lumToYV12 = bswap16Y_c; break;
 #else
+    case PIX_FMT_YUV444P9BE:
+    case PIX_FMT_YUV420P9BE:
+    case PIX_FMT_YUV444P10BE:
+    case PIX_FMT_YUV422P10BE:
+    case PIX_FMT_YUV420P10BE:
     case PIX_FMT_YUV420P16BE:
     case PIX_FMT_YUV422P16BE:
     case PIX_FMT_YUV444P16BE: