swscale: re-enable gamma
authorPedro Arthur <bygrandao@gmail.com>
Fri, 4 Sep 2015 21:11:21 +0000 (18:11 -0300)
committerPedro Arthur <bygrandao@gmail.com>
Fri, 4 Sep 2015 22:00:20 +0000 (19:00 -0300)
+added gamma conversion to refactored code

libswscale/Makefile
libswscale/gamma.c [new file with mode: 0644]
libswscale/slice.c
libswscale/swscale.c
libswscale/swscale_internal.h
libswscale/utils.c
libswscale/vscale.c

index e70e358..a9f9e03 100644 (file)
@@ -18,6 +18,7 @@ OBJS = alphablend.o                                     \
        slice.o                                          \
        hscale.o                                         \
        vscale.o                                         \
+       gamma.o                                          \
 
 OBJS-$(CONFIG_SHARED)        += log2_tab.o
 
diff --git a/libswscale/gamma.c b/libswscale/gamma.c
new file mode 100644 (file)
index 0000000..d7470cb
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 Pedro Arthur <bygrandao@gmail.com>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "swscale_internal.h"
+
+typedef struct GammaContext
+{
+    uint16_t *table;
+} GammaContext;
+
+// gamma_convert expects 16 bit rgb format
+// it writes directly in src slice thus it must be modifiable (done through cascade context)
+static int gamma_convert(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
+{
+    GammaContext *instance = desc->instance;
+    uint16_t *table = instance->table;
+    int srcW = desc->src->width;
+
+    int i;
+    for (i = 0; i < sliceH; ++i) {
+        uint8_t ** src = desc->src->plane[0].line;
+        int src_pos = sliceY+i - desc->src->plane[0].sliceY;
+
+        uint16_t *src1 = (uint16_t*)*(src+src_pos);
+        int j;
+        for (j = 0; j < srcW; ++j) {
+            uint16_t r = AV_RL16(src1 + j*4 + 0);
+            uint16_t g = AV_RL16(src1 + j*4 + 1);
+            uint16_t b = AV_RL16(src1 + j*4 + 2);
+
+            AV_WL16(src1 + j*4 + 0, table[r]);
+            AV_WL16(src1 + j*4 + 1, table[g]);
+            AV_WL16(src1 + j*4 + 2, table[b]);
+        }
+
+    }
+    return sliceH;
+}
+
+
+int ff_init_gamma_convert(SwsFilterDescriptor *desc, SwsSlice * src, uint16_t *table)
+{
+    GammaContext *li = av_malloc(sizeof(GammaContext));
+    if (!li)
+        return AVERROR(ENOMEM);
+    li->table = table;
+
+    desc->instance = li;
+    desc->src = src;
+    desc->dst = NULL;
+    desc->process = &gamma_convert;
+
+    return 0;
+}
+
index 4437672..94841e5 100644 (file)
@@ -217,6 +217,7 @@ int ff_init_filters(SwsContext * c)
     int num_vdesc = isPlanarYUV(c->dstFormat) && !isGray(c->dstFormat) ? 2 : 1;
     int need_lum_conv = c->lumToYV12 || c->readLumPlanar || c->alpToYV12 || c->readAlpPlanar;
     int need_chr_conv = c->chrToYV12 || c->readChrPlanar;
+    int need_gamma = c->is_internal_gamma;
     int srcIdx, dstIdx;
     int dst_stride = FFALIGN(c->dstW * sizeof(int16_t) + 66, 16);
 
@@ -230,9 +231,9 @@ int ff_init_filters(SwsContext * c)
     num_cdesc = need_chr_conv ? 2 : 1;
 
     c->numSlice = FFMAX(num_ydesc, num_cdesc) + 2;
-    c->numDesc = num_ydesc + num_cdesc + num_vdesc;
-    c->descIndex[0] = num_ydesc;
-    c->descIndex[1] = num_ydesc + num_cdesc;
+    c->numDesc = num_ydesc + num_cdesc + num_vdesc + (need_gamma ? 2 : 0);
+    c->descIndex[0] = num_ydesc + (need_gamma ? 1 : 0);
+    c->descIndex[1] = num_ydesc + num_cdesc + (need_gamma ? 1 : 0);
 
 
 
@@ -267,6 +268,12 @@ int ff_init_filters(SwsContext * c)
     srcIdx = 0;
     dstIdx = 1;
 
+    if (need_gamma) {
+        res = ff_init_gamma_convert(c->desc + index, c->slice + srcIdx, c->inv_gamma);
+        if (res < 0) goto cleanup;
+        ++index;
+    }
+
     if (need_lum_conv) {
         res = ff_init_desc_fmt_convert(&c->desc[index], &c->slice[srcIdx], &c->slice[dstIdx], pal);
         if (res < 0) goto cleanup;
@@ -309,6 +316,12 @@ int ff_init_filters(SwsContext * c)
         if (res < 0) goto cleanup;
     }
 
+    ++index;
+    if (need_gamma) {
+        res = ff_init_gamma_convert(c->desc + index, c->slice + dstIdx, c->gamma);
+        if (res < 0) goto cleanup;
+    }
+
     return 0;
 
 cleanup:
index 4008210..e9e4f62 100644 (file)
@@ -379,7 +379,7 @@ static int swscale(SwsContext *c, const uint8_t *src[],
     int chrBufIndex  = c->chrBufIndex;
     int lastInLumBuf = c->lastInLumBuf;
     int lastInChrBuf = c->lastInChrBuf;
-//    int perform_gamma = c->is_internal_gamma;
+    int perform_gamma = c->is_internal_gamma;
 
 #ifdef NEW_FILTER
     int lumStart = 0;
@@ -392,9 +392,10 @@ static int swscale(SwsContext *c, const uint8_t *src[],
     SwsSlice *hout_slice = &c->slice[c->numSlice-2];
     SwsSlice *vout_slice = &c->slice[c->numSlice-1];
     SwsFilterDescriptor *desc = c->desc;
-#endif
+
     int hasLumHoles = 1;
     int hasChrHoles = 1;
+#endif
 
 #ifndef NEW_FILTER
     if (!usePal(c->srcFormat)) {
@@ -612,8 +613,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,
@@ -783,9 +784,9 @@ 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);
 #endif
-            //if (perform_gamma)
-            //    gamma_convert(dest, dstW, c->gamma);
         }
     }
     if (isPlanar(dstFormat) && isALPHA(dstFormat) && !alpPixBuf) {
index 0d4ce33..608cc3e 100644 (file)
@@ -1028,6 +1028,9 @@ int ff_free_filters(SwsContext *c);
 */
 int ff_rotate_slice(SwsSlice *s, int lum, int chr);
 
+/// initializes gamma conversion descriptor
+int ff_init_gamma_convert(SwsFilterDescriptor *desc, SwsSlice * src, uint16_t *table);
+
 /// initializes lum pixel format conversion descriptor
 int ff_init_desc_fmt_convert(SwsFilterDescriptor *desc, SwsSlice * src, SwsSlice *dst, uint32_t *pal);
 
index 4664de4..0c4b4d7 100644 (file)
@@ -1419,6 +1419,15 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
         if (!c2->gamma || !c2->inv_gamma)
             return AVERROR(ENOMEM);
 
+        // is_internal_flag is set after creating the context
+        // to properly create the gamma convert FilterDescriptor
+        // we have to re-initialize it
+        ff_free_filters(c2);
+        if (ff_init_filters(c2) < 0) {
+            sws_freeContext(c2);
+            return -1;
+        }
+
         c->cascaded_context[2] = NULL;
         if (dstFormat != tmpFmt) {
             ret = av_image_alloc(c->cascaded1_tmp, c->cascaded1_tmpStride,
index 18d5ad1..3d6e81a 100644 (file)
@@ -229,7 +229,7 @@ void ff_init_vscale_pfn(SwsContext *c,
 {
     VScalerContext *lumCtx = NULL;
     VScalerContext *chrCtx = NULL;
-    int idx = c->numDesc - 1;
+    int idx = c->numDesc - (c->is_internal_gamma ? 2 : 1);
 
     if (isPlanarYUV(c->dstFormat) || (isGray(c->dstFormat) && !isALPHA(c->dstFormat))) {
         if (!isGray(c->dstFormat)) {