swscale: refactor horizontal scaling
[ffmpeg.git] / libswscale / swscale.c
index 1945e1d..e96c7ee 100644 (file)
@@ -371,6 +371,15 @@ static int swscale(SwsContext *c, const uint8_t *src[],
     int lastInChrBuf = c->lastInChrBuf;
     int perform_gamma = c->is_internal_gamma;
 
+    int numDesc = c->numDesc;
+    int lumStart = 0;
+    int lumEnd = c->descIndex[0];
+    int chrStart = lumEnd;
+    int chrEnd = c->descIndex[1];
+    SwsSlice *src_slice = &c->slice[lumStart];
+    SwsSlice *dst_slice = &c->slice[c->numSlice-1];
+    SwsFilterDescriptor *desc = c->desc;
+
 
     if (!usePal(c->srcFormat)) {
         pal = c->input_rgb2yuv_table;
@@ -439,6 +448,23 @@ static int swscale(SwsContext *c, const uint8_t *src[],
     }
     lastDstY = dstY;
 
+#define NEW_FILTER 1
+
+    ff_init_slice_from_src(src_slice, (uint8_t**)src, srcStride, c->srcW,
+            srcSliceY, srcSliceH,
+            chrSrcSliceY, chrSrcSliceH);
+
+    dst_slice->plane[0].sliceY = lastInLumBuf + 1;
+    dst_slice->plane[1].sliceY = lastInChrBuf + 1;
+    dst_slice->plane[2].sliceY = lastInChrBuf + 1;
+    dst_slice->plane[3].sliceY = lastInLumBuf + 1;
+
+    dst_slice->plane[0].sliceH =
+    dst_slice->plane[1].sliceH =
+    dst_slice->plane[2].sliceH =
+    dst_slice->plane[3].sliceH = 0;
+    dst_slice->width = dstW;
+
     for (; dstY < dstH; dstY++) {
         const int chrDstY = dstY >> c->chrDstVSubSample;
         uint8_t *dest[4]  = {
@@ -460,12 +486,23 @@ static int swscale(SwsContext *c, const uint8_t *src[],
         int lastLumSrcY2 = FFMIN(c->srcH,    firstLumSrcY2 + vLumFilterSize) - 1;
         int lastChrSrcY  = FFMIN(c->chrSrcH, firstChrSrcY  + vChrFilterSize) - 1;
         int enough_lines;
+        int i;
 
         // handle holes (FAST_BILINEAR & weird filters)
-        if (firstLumSrcY > lastInLumBuf)
+        if (firstLumSrcY > lastInLumBuf) {
             lastInLumBuf = firstLumSrcY - 1;
-        if (firstChrSrcY > lastInChrBuf)
+            dst_slice->plane[0].sliceY = lastInLumBuf + 1;
+            dst_slice->plane[3].sliceY = lastInLumBuf + 1;
+            dst_slice->plane[0].sliceH =
+            dst_slice->plane[3].sliceH = 0;
+        }
+        if (firstChrSrcY > lastInChrBuf) {
             lastInChrBuf = firstChrSrcY - 1;
+            dst_slice->plane[1].sliceY = lastInChrBuf + 1;
+            dst_slice->plane[2].sliceY = lastInChrBuf + 1;
+            dst_slice->plane[1].sliceH =
+            dst_slice->plane[2].sliceH = 0;
+        }
         av_assert0(firstLumSrcY >= lastInLumBuf - vLumBufSize + 1);
         av_assert0(firstChrSrcY >= lastInChrBuf - vChrBufSize + 1);
 
@@ -486,6 +523,22 @@ static int swscale(SwsContext *c, const uint8_t *src[],
                           lastLumSrcY, lastChrSrcY);
         }
 
+#if NEW_FILTER
+        ff_rotate_slice(dst_slice, lastLumSrcY, lastChrSrcY);
+
+        if (lastInLumBuf < lastLumSrcY)
+            for (i = lumStart; i < lumEnd; ++i)
+                desc[i].process(c, &desc[i], lastInLumBuf + 1, lastLumSrcY - lastInLumBuf);
+        lumBufIndex += lastLumSrcY - lastInLumBuf;
+        lastInLumBuf = lastLumSrcY;
+
+        if (lastInChrBuf < lastChrSrcY)
+            for (i = chrStart; i < chrEnd; ++i)
+                desc[i].process(c, &desc[i], lastInChrBuf + 1, lastChrSrcY - lastInChrBuf);
+        chrBufIndex += lastChrSrcY - lastInChrBuf;
+        lastInChrBuf = lastChrSrcY;
+
+#else
         // Do horizontal scaling
         while (lastInLumBuf < lastLumSrcY) {
             const uint8_t *src1[4] = {
@@ -499,8 +552,8 @@ static int swscale(SwsContext *c, const uint8_t *src[],
             av_assert0(lastInLumBuf + 1 - srcSliceY < srcSliceH);
             av_assert0(lastInLumBuf + 1 - srcSliceY >= 0);
 
-            if (perform_gamma)
-                gamma_convert((uint8_t **)src1, srcW, c->inv_gamma);
+            //if (perform_gamma)
+            //    gamma_convert((uint8_t **)src1, srcW, c->inv_gamma);
 
             hyscale(c, lumPixBuf[lumBufIndex], dstW, src1, srcW, lumXInc,
                     hLumFilter, hLumFilterPos, hLumFilterSize,
@@ -535,6 +588,7 @@ static int swscale(SwsContext *c, const uint8_t *src[],
             DEBUG_BUFFERS("\t\tchrBufIndex %d: lastInChrBuf: %d\n",
                           chrBufIndex, lastInChrBuf);
         }
+#endif
         // wrap buf index around to stay inside the ring buffer
         if (lumBufIndex >= vLumBufSize)
             lumBufIndex -= vLumBufSize;
@@ -560,11 +614,19 @@ static int swscale(SwsContext *c, const uint8_t *src[],
         }
 
         {
+#if NEW_FILTER
+            const int16_t **lumSrcPtr  = (const int16_t **)(void*) dst_slice->plane[0].line + firstLumSrcY - dst_slice->plane[0].sliceY;
+            const int16_t **chrUSrcPtr = (const int16_t **)(void*) dst_slice->plane[1].line + firstChrSrcY - dst_slice->plane[1].sliceY;
+            const int16_t **chrVSrcPtr = (const int16_t **)(void*) dst_slice->plane[2].line + firstChrSrcY - dst_slice->plane[2].sliceY;
+            const int16_t **alpSrcPtr  = (CONFIG_SWSCALE_ALPHA && alpPixBuf) ?
+                                         (const int16_t **)(void*) dst_slice->plane[3].line + firstLumSrcY - dst_slice->plane[3].sliceY : NULL;
+#else
             const int16_t **lumSrcPtr  = (const int16_t **)(void*) lumPixBuf  + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize;
             const int16_t **chrUSrcPtr = (const int16_t **)(void*) chrUPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
             const int16_t **chrVSrcPtr = (const int16_t **)(void*) chrVPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
             const int16_t **alpSrcPtr  = (CONFIG_SWSCALE_ALPHA && alpPixBuf) ?
                                          (const int16_t **)(void*) alpPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize : NULL;
+#endif
             int16_t *vLumFilter = c->vLumFilter;
             int16_t *vChrFilter = c->vChrFilter;
 
@@ -629,8 +691,10 @@ static int swscale(SwsContext *c, const uint8_t *src[],
                     }
                 }
             } else if (yuv2packedX) {
+#if !NEW_FILTER
                 av_assert1(lumSrcPtr  + vLumFilterSize - 1 < (const int16_t **)lumPixBuf  + vLumBufSize * 2);
                 av_assert1(chrUSrcPtr + vChrFilterSize - 1 < (const int16_t **)chrUPixBuf + vChrBufSize * 2);
+#endif
                 if (c->yuv2packed1 && vLumFilterSize == 1 &&
                     vChrFilterSize <= 2) { // unscaled RGB
                     int chrAlpha = vChrFilterSize == 1 ? 0 : vChrFilter[2 * dstY + 1];
@@ -663,8 +727,8 @@ static int swscale(SwsContext *c, const uint8_t *src[],
                          chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
                          alpSrcPtr, dest, dstW, dstY);
             }
-            if (perform_gamma)
-                gamma_convert(dest, dstW, c->gamma);
+            //if (perform_gamma)
+            //    gamma_convert(dest, dstW, c->gamma);
         }
     }
     if (isPlanar(dstFormat) && isALPHA(dstFormat) && !alpPixBuf) {
@@ -1151,4 +1215,3 @@ int attribute_align_arg sws_scale(struct SwsContext *c,
     av_free(rgb0_tmp);
     return ret;
 }
-