slice.o \
hscale.o \
vscale.o \
+ gamma.o \
OBJS-$(CONFIG_SHARED) += log2_tab.o
--- /dev/null
+/*
+ * 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;
+}
+
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);
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);
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;
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:
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;
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)) {
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,
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) {
*/
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);
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,
{
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)) {