[FFmpeg-cvslog] swscale: support internal scaler cascades

Michael Niedermayer git at videolan.org
Thu Nov 20 02:04:20 CET 2014


ffmpeg | branch: release/2.4 | Michael Niedermayer <michaelni at gmx.at> | Wed Oct  8 02:05:54 2014 +0200| [633a2a082fc1b1b50a70992a181ff48db7acdab4] | committer: Carl Eugen Hoyos

swscale: support internal scaler cascades

Fixes Ticket3170

Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
(cherry picked from commit fba894615d694584057adb0ddb4d609486cad807)

Conflicts:
	libswscale/version.h

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=633a2a082fc1b1b50a70992a181ff48db7acdab4
---

 libswscale/swscale.c          |   13 ++++++++++
 libswscale/swscale_internal.h |   10 ++++++++
 libswscale/utils.c            |   54 ++++++++++++++++++++++++++++++++---------
 3 files changed, 66 insertions(+), 11 deletions(-)

diff --git a/libswscale/swscale.c b/libswscale/swscale.c
index 59ead12..43b8740 100644
--- a/libswscale/swscale.c
+++ b/libswscale/swscale.c
@@ -27,6 +27,7 @@
 #include "libavutil/avutil.h"
 #include "libavutil/bswap.h"
 #include "libavutil/cpu.h"
+#include "libavutil/imgutils.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/pixdesc.h"
@@ -899,6 +900,18 @@ int attribute_align_arg sws_scale(struct SwsContext *c,
         av_log(c, AV_LOG_ERROR, "One of the input parameters to sws_scale() is NULL, please check the calling code\n");
         return 0;
     }
+    if (c->cascaded_context[0] && srcSliceY == 0 && srcSliceH == c->cascaded_context[0]->srcH) {
+        ret = sws_scale(c->cascaded_context[0],
+                        srcSlice, srcStride, srcSliceY, srcSliceH,
+                        c->cascaded_tmp, c->cascaded_tmpStride);
+        if (ret < 0)
+            return ret;
+        ret = sws_scale(c->cascaded_context[1],
+                        (const uint8_t * const * )c->cascaded_tmp, c->cascaded_tmpStride, 0, c->cascaded_context[0]->dstH,
+                        dst, dstStride);
+        return ret;
+    }
+
     memcpy(src2, srcSlice, sizeof(src2));
     memcpy(dst2, dst, sizeof(dst2));
 
diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h
index 335e1f8..f693294 100644
--- a/libswscale/swscale_internal.h
+++ b/libswscale/swscale_internal.h
@@ -61,6 +61,8 @@
 #   define APCK_SIZE 16
 #endif
 
+#define RETCODE_USE_CASCADE -12345
+
 struct SwsContext;
 
 typedef enum SwsDither {
@@ -301,6 +303,14 @@ typedef struct SwsContext {
     int sliceDir;                 ///< Direction that slices are fed to the scaler (1 = top-to-bottom, -1 = bottom-to-top).
     double param[2];              ///< Input parameters for scaling algorithms that need them.
 
+    /* The cascaded_* fields allow spliting a scaler task into multiple
+     * sequential steps, this is for example used to limit the maximum
+     * downscaling factor that needs to be supported in one scaler.
+     */
+    struct SwsContext *cascaded_context[2];
+    int cascaded_tmpStride[4];
+    uint8_t *cascaded_tmp[4];
+
     uint32_t pal_yuv[256];
     uint32_t pal_rgb[256];
 
diff --git a/libswscale/utils.c b/libswscale/utils.c
index 5615700..01e056a 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -42,6 +42,7 @@
 #include "libavutil/avutil.h"
 #include "libavutil/bswap.h"
 #include "libavutil/cpu.h"
+#include "libavutil/imgutils.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/opt.h"
@@ -582,8 +583,7 @@ static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos,
         goto fail;
     if (filterSize >= MAX_FILTER_SIZE * 16 /
                       ((flags & SWS_ACCURATE_RND) ? APCK_SIZE : 16)) {
-        av_log(NULL, AV_LOG_ERROR, "sws: filterSize %d is too large, try less extreme scaling or set --sws-max-filter-size and recompile\n",
-               FF_CEIL_RSHIFT((filterSize+1) * ((flags & SWS_ACCURATE_RND) ? APCK_SIZE : 16), 4));
+        ret = RETCODE_USE_CASCADE;
         goto fail;
     }
     *outFilterSize = filterSize;
@@ -675,7 +675,7 @@ static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos,
 
 fail:
     if(ret < 0)
-        av_log(NULL, AV_LOG_ERROR, "sws: initFilter failed\n");
+        av_log(NULL, ret == RETCODE_USE_CASCADE ? AV_LOG_DEBUG : AV_LOG_ERROR, "sws: initFilter failed\n");
     av_free(filter);
     av_free(filter2);
     return ret;
@@ -970,6 +970,7 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
     enum AVPixelFormat dstFormat = c->dstFormat;
     const AVPixFmtDescriptor *desc_src;
     const AVPixFmtDescriptor *desc_dst;
+    int ret = 0;
 
     cpu_flags = av_get_cpu_flags();
     flags     = c->flags;
@@ -1295,23 +1296,23 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
             const int filterAlign = X86_MMX(cpu_flags)     ? 4 :
                                     PPC_ALTIVEC(cpu_flags) ? 8 : 1;
 
-            if (initFilter(&c->hLumFilter, &c->hLumFilterPos,
+            if ((ret = initFilter(&c->hLumFilter, &c->hLumFilterPos,
                            &c->hLumFilterSize, c->lumXInc,
                            srcW, dstW, filterAlign, 1 << 14,
                            (flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags,
                            cpu_flags, srcFilter->lumH, dstFilter->lumH,
                            c->param,
                            get_local_pos(c, 0, 0, 0),
-                           get_local_pos(c, 0, 0, 0)) < 0)
+                           get_local_pos(c, 0, 0, 0))) < 0)
                 goto fail;
-            if (initFilter(&c->hChrFilter, &c->hChrFilterPos,
+            if ((ret = initFilter(&c->hChrFilter, &c->hChrFilterPos,
                            &c->hChrFilterSize, c->chrXInc,
                            c->chrSrcW, c->chrDstW, filterAlign, 1 << 14,
                            (flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags,
                            cpu_flags, srcFilter->chrH, dstFilter->chrH,
                            c->param,
                            get_local_pos(c, c->chrSrcHSubSample, c->src_h_chr_pos, 0),
-                           get_local_pos(c, c->chrDstHSubSample, c->dst_h_chr_pos, 0)) < 0)
+                           get_local_pos(c, c->chrDstHSubSample, c->dst_h_chr_pos, 0))) < 0)
                 goto fail;
         }
     } // initialize horizontal stuff
@@ -1321,22 +1322,22 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
         const int filterAlign = X86_MMX(cpu_flags)     ? 2 :
                                 PPC_ALTIVEC(cpu_flags) ? 8 : 1;
 
-        if (initFilter(&c->vLumFilter, &c->vLumFilterPos, &c->vLumFilterSize,
+        if ((ret = initFilter(&c->vLumFilter, &c->vLumFilterPos, &c->vLumFilterSize,
                        c->lumYInc, srcH, dstH, filterAlign, (1 << 12),
                        (flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags,
                        cpu_flags, srcFilter->lumV, dstFilter->lumV,
                        c->param,
                        get_local_pos(c, 0, 0, 1),
-                       get_local_pos(c, 0, 0, 1)) < 0)
+                       get_local_pos(c, 0, 0, 1))) < 0)
             goto fail;
-        if (initFilter(&c->vChrFilter, &c->vChrFilterPos, &c->vChrFilterSize,
+        if ((ret = initFilter(&c->vChrFilter, &c->vChrFilterPos, &c->vChrFilterSize,
                        c->chrYInc, c->chrSrcH, c->chrDstH,
                        filterAlign, (1 << 12),
                        (flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags,
                        cpu_flags, srcFilter->chrV, dstFilter->chrV,
                        c->param,
                        get_local_pos(c, c->chrSrcVSubSample, c->src_v_chr_pos, 1),
-                       get_local_pos(c, c->chrDstVSubSample, c->dst_v_chr_pos, 1)) < 0)
+                       get_local_pos(c, c->chrDstVSubSample, c->dst_v_chr_pos, 1))) < 0)
 
             goto fail;
 
@@ -1490,6 +1491,32 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
     c->swscale = ff_getSwsFunc(c);
     return 0;
 fail: // FIXME replace things by appropriate error codes
+    if (ret == RETCODE_USE_CASCADE)  {
+        int tmpW = sqrt(srcW * (int64_t)dstW);
+        int tmpH = sqrt(srcH * (int64_t)dstH);
+        enum AVPixelFormat tmpFormat = AV_PIX_FMT_YUV420P;
+
+        if (srcW*(int64_t)srcH <= 4LL*dstW*dstH)
+            return AVERROR(EINVAL);
+
+        ret = av_image_alloc(c->cascaded_tmp, c->cascaded_tmpStride,
+                             tmpW, tmpH, tmpFormat, 64);
+        if (ret < 0)
+            return ret;
+
+        c->cascaded_context[0] = sws_getContext(srcW, srcH, srcFormat,
+                                                tmpW, tmpH, tmpFormat,
+                                                flags, srcFilter, NULL, c->param);
+        if (!c->cascaded_context[0])
+            return -1;
+
+        c->cascaded_context[1] = sws_getContext(tmpW, tmpH, tmpFormat,
+                                                dstW, dstH, dstFormat,
+                                                flags, NULL, dstFilter, c->param);
+        if (!c->cascaded_context[1])
+            return -1;
+        return 0;
+    }
     return -1;
 }
 
@@ -1901,6 +1928,11 @@ void sws_freeContext(SwsContext *c)
     av_freep(&c->yuvTable);
     av_freep(&c->formatConvBuffer);
 
+    sws_freeContext(c->cascaded_context[0]);
+    sws_freeContext(c->cascaded_context[1]);
+    memset(c->cascaded_context, 0, sizeof(c->cascaded_context));
+    av_freep(&c->cascaded_tmp[0]);
+
     av_free(c);
 }
 



More information about the ffmpeg-cvslog mailing list