lavfi: new colorspace conversion filter.

The intent here is similar to colormatrix, but it's LGPLv2.1-or-later
(instead of GPLv2.0) and supports gamma/chromaticity correction.
This commit is contained in:
Ronald S. Bultje 2016-04-06 14:08:21 -04:00
parent d7815df402
commit 2e2e08a35b
9 changed files with 1704 additions and 0 deletions

View File

@ -23,6 +23,7 @@ version <next>:
- aix demuxer
- remap filter
- hash and framehash muxers
- colorspace filter
version 3.0:
- Common Encryption (CENC) MP4 encoding and decoding support

View File

@ -4937,6 +4937,189 @@ For example to convert from BT.601 to SMPTE-240M, use the command:
colormatrix=bt601:smpte240m
@end example
@section colorspace
Convert colorspace, transfer characteristics or color primaries.
The filter accepts the following options:
@table @option
@item all
Specify all color properties at once.
The accepted values are:
@table @samp
@item bt470m
BT.470M
@item bt470bg
BT.470BG
@item bt601-6-525
BT.601-6 525
@item bt601-6-625
BT.601-6 625
@item bt709
BT.709
@item smpte170m
SMPTE-170M
@item smpte240m
SMPTE-240M
@item bt2020
BT.2020
@end table
@item space
Specify output colorspace.
The accepted values are:
@table @samp
@item bt709
BT.709
@item fcc
FCC
@item bt470bg
BT.470BG or BT.601-6 625
@item smpte170m
SMPTE-170M or BT.601-6 525
@item smpte240m
SMPTE-240M
@item bt2020ncl
BT.2020 with non-constant luminance
@end table
@item trc
Specify output transfer characteristics.
The accepted values are:
@table @samp
@item bt709
BT.709
@item gamma22
Constant gamma of 2.2
@item gamma28
Constant gamma of 2.8
@item smpte170m
SMPTE-170M, BT.601-6 625 or BT.601-6 525
@item smpte240m
SMPTE-240M
@item bt2020-10
BT.2020 for 10-bits content
@item bt2020-12
BT.2020 for 12-bits content
@end table
@item prm
Specify output color primaries.
The accepted values are:
@table @samp
@item bt709
BT.709
@item bt470m
BT.470M
@item bt470bg
BT.470BG or BT.601-6 625
@item smpte170m
SMPTE-170M or BT.601-6 525
@item smpte240m
SMPTE-240M
@item bt2020
BT.2020
@end table
@item rng
Specify output color range.
The accepted values are:
@table @samp
@item mpeg
MPEG (restricted) range
@item jpeg
JPEG (full) range
@end table
@item format
Specify output color format.
The accepted values are:
@table @samp
@item yuv420p
YUV 4:2:0 planar 8-bits
@item yuv420p10
YUV 4:2:0 planar 10-bits
@item yuv420p12
YUV 4:2:0 planar 12-bits
@item yuv422p
YUV 4:2:2 planar 8-bits
@item yuv422p10
YUV 4:2:2 planar 10-bits
@item yuv422p12
YUV 4:2:2 planar 12-bits
@item yuv444p
YUV 4:4:4 planar 8-bits
@item yuv444p10
YUV 4:4:4 planar 10-bits
@item yuv444p12
YUV 4:4:4 planar 12-bits
@end table
@item fast
Do a fast conversion, which skips gamma/primary correction. This will take
significantly less CPU, but will be mathematically incorrect. To get output
compatible with that produced by the colormatrix filter, use fast=1.
@end table
The filter converts the transfer characteristics, color space and color
primaries to the specified user values. The output value, if not specified,
is set to a default value based on the "all" property. If that property is
also not specified, the filter will log an error. The output color range and
format default to the same value as the input color range and format. The
input transfer characteristics, color space, color primaries and color range
should be set on the input data. If any of these are missing, the filter will
log an error and no conversion will take place.
For example to convert the input to SMPTE-240M, use the command:
@example
colorspace=smpte240m
@end example
@section convolution
Apply convolution 3x3 or 5x5 filter.

View File

@ -131,6 +131,7 @@ OBJS-$(CONFIG_COLORCHANNELMIXER_FILTER) += vf_colorchannelmixer.o
OBJS-$(CONFIG_COLORKEY_FILTER) += vf_colorkey.o
OBJS-$(CONFIG_COLORLEVELS_FILTER) += vf_colorlevels.o
OBJS-$(CONFIG_COLORMATRIX_FILTER) += vf_colormatrix.o
OBJS-$(CONFIG_COLORSPACE_FILTER) += vf_colorspace.o colorspacedsp.o
OBJS-$(CONFIG_CONVOLUTION_FILTER) += vf_convolution.o
OBJS-$(CONFIG_COPY_FILTER) += vf_copy.o
OBJS-$(CONFIG_COREIMAGE_FILTER) += vf_coreimage.o

View File

@ -152,6 +152,7 @@ void avfilter_register_all(void)
REGISTER_FILTER(COLORKEY, colorkey, vf);
REGISTER_FILTER(COLORLEVELS, colorlevels, vf);
REGISTER_FILTER(COLORMATRIX, colormatrix, vf);
REGISTER_FILTER(COLORSPACE, colorspace, vf);
REGISTER_FILTER(CONVOLUTION, convolution, vf);
REGISTER_FILTER(COPY, copy, vf);
REGISTER_FILTER(COREIMAGE, coreimage, vf);

131
libavfilter/colorspacedsp.c Normal file
View File

@ -0,0 +1,131 @@
/*
* Copyright (c) 2016 Ronald S. Bultje <rsbultje@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 "colorspacedsp.h"
#define SS_W 0
#define SS_H 0
#define BIT_DEPTH 8
#include "colorspacedsp_template.c"
#undef BIT_DEPTH
#define BIT_DEPTH 10
#include "colorspacedsp_template.c"
#undef BIT_DEPTH
#define BIT_DEPTH 12
#include "colorspacedsp_template.c"
#undef SS_W
#undef SS_H
#define SS_W 1
#define SS_H 0
#undef BIT_DEPTH
#define BIT_DEPTH 8
#include "colorspacedsp_template.c"
#undef BIT_DEPTH
#define BIT_DEPTH 10
#include "colorspacedsp_template.c"
#undef BIT_DEPTH
#define BIT_DEPTH 12
#include "colorspacedsp_template.c"
#undef SS_W
#undef SS_H
#define SS_W 1
#define SS_H 1
#undef BIT_DEPTH
#define BIT_DEPTH 8
#include "colorspacedsp_template.c"
#undef BIT_DEPTH
#define BIT_DEPTH 10
#include "colorspacedsp_template.c"
#undef BIT_DEPTH
#define BIT_DEPTH 12
#include "colorspacedsp_template.c"
static void multiply3x3_c(int16_t *buf[3], ptrdiff_t stride,
int w, int h, const int16_t m[3][3][8])
{
int y, x;
int16_t *buf0 = buf[0], *buf1 = buf[1], *buf2 = buf[2];
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
int v0 = buf0[x], v1 = buf1[x], v2 = buf2[x];
buf0[x] = av_clip_int16((m[0][0][0] * v0 + m[0][1][0] * v1 +
m[0][2][0] * v2 + 8192) >> 14);
buf1[x] = av_clip_int16((m[1][0][0] * v0 + m[1][1][0] * v1 +
m[1][2][0] * v2 + 8192) >> 14);
buf2[x] = av_clip_int16((m[2][0][0] * v0 + m[2][1][0] * v1 +
m[2][2][0] * v2 + 8192) >> 14);
}
buf0 += stride;
buf1 += stride;
buf2 += stride;
}
}
void ff_colorspacedsp_init(ColorSpaceDSPContext *dsp)
{
#define init_yuv2rgb_fn(idx, bit) \
dsp->yuv2rgb[idx][0] = yuv2rgb_444p##bit##_c; \
dsp->yuv2rgb[idx][1] = yuv2rgb_422p##bit##_c; \
dsp->yuv2rgb[idx][2] = yuv2rgb_420p##bit##_c
init_yuv2rgb_fn(0, 8);
init_yuv2rgb_fn(1, 10);
init_yuv2rgb_fn(2, 12);
#define init_rgb2yuv_fn(idx, bit) \
dsp->rgb2yuv[idx][0] = rgb2yuv_444p##bit##_c; \
dsp->rgb2yuv[idx][1] = rgb2yuv_422p##bit##_c; \
dsp->rgb2yuv[idx][2] = rgb2yuv_420p##bit##_c
init_rgb2yuv_fn(0, 8);
init_rgb2yuv_fn(1, 10);
init_rgb2yuv_fn(2, 12);
#define init_yuv2yuv_fn(idx1, idx2, bit1, bit2) \
dsp->yuv2yuv[idx1][idx2][0] = yuv2yuv_444p##bit1##to##bit2##_c; \
dsp->yuv2yuv[idx1][idx2][1] = yuv2yuv_422p##bit1##to##bit2##_c; \
dsp->yuv2yuv[idx1][idx2][2] = yuv2yuv_420p##bit1##to##bit2##_c
#define init_yuv2yuv_fns(idx1, bit1) \
init_yuv2yuv_fn(idx1, 0, bit1, 8); \
init_yuv2yuv_fn(idx1, 1, bit1, 10); \
init_yuv2yuv_fn(idx1, 2, bit1, 12)
init_yuv2yuv_fns(0, 8);
init_yuv2yuv_fns(1, 10);
init_yuv2yuv_fns(2, 12);
dsp->multiply3x3 = multiply3x3_c;
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2016 Ronald S. Bultje <rsbultje@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
*/
#ifndef AVFILTER_COLORSPACEDSP_H
#define AVFILTER_COLORSPACEDSP_H
#include <stddef.h>
#include <stdint.h>
typedef void (*yuv2rgb_fn)(int16_t *rgb[3], ptrdiff_t rgb_stride,
uint8_t *yuv[3], ptrdiff_t yuv_stride[3],
int w, int h, const int16_t yuv2rgb_coeffs[3][3][8],
const int16_t yuv_offset[8]);
typedef void (*rgb2yuv_fn)(uint8_t *yuv[3], ptrdiff_t yuv_stride[3],
int16_t *rgb[3], ptrdiff_t rgb_stride,
int w, int h, const int16_t rgb2yuv_coeffs[3][3][8],
const int16_t yuv_offset[8]);
typedef void (*yuv2yuv_fn)(uint8_t *yuv_out[3], ptrdiff_t yuv_out_stride[3],
uint8_t *yuv_in[3], ptrdiff_t yuv_in_stride[3],
int w, int h, const int16_t yuv2yuv_coeffs[3][3][8],
const int16_t yuv_offset[2][8]);
typedef struct ColorSpaceDSPContext {
yuv2rgb_fn yuv2rgb[3 /* 0: 8bit, 1: 10bit, 2: 12bit */][3 /* 0: 444, 1: 422, 2: 420 */];
rgb2yuv_fn rgb2yuv[3 /* 0: 8bit, 1: 10bit, 2: 12bit */][3 /* 0: 444, 1: 422, 2: 420 */];
yuv2yuv_fn yuv2yuv[3 /* in_depth */][3 /* out_depth */][3 /* 0: 444, 1: 422, 2: 420 */];
void (*multiply3x3)(int16_t *data[3], ptrdiff_t stride,
int w, int h, const int16_t m[3][3][8]);
} ColorSpaceDSPContext;
void ff_colorspacedsp_init(ColorSpaceDSPContext *dsp);
#endif /* AVFILTER_COLORSPACEDSP_H */

View File

@ -0,0 +1,214 @@
/*
* Copyright (c) 2016 Ronald S. Bultje <rsbultje@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 "libavutil/avassert.h"
#undef avg
#undef ss
#if SS_W == 0
#define ss 444
#define avg(a,b,c,d) (a)
#elif SS_H == 0
#define ss 422
#define avg(a,b,c,d) ((a + b + 1) >> 1)
#else
#define ss 420
#define avg(a,b,c,d) ((a + b + c + d + 2) >> 2)
#endif
#undef fn
#undef fn2
#undef fn3
#define fn3(a,b,c) a##_##c##p##b##_c
#define fn2(a,b,c) fn3(a,b,c)
#define fn(a) fn2(a, BIT_DEPTH, ss)
#undef pixel
#undef av_clip_pixel
#if BIT_DEPTH == 8
#define pixel uint8_t
#define av_clip_pixel(x) av_clip_uint8(x)
#else
#define pixel uint16_t
#define av_clip_pixel(x) av_clip_uintp2(x, BIT_DEPTH)
#endif
static void fn(yuv2rgb)(int16_t *rgb[3], ptrdiff_t rgb_stride,
uint8_t *_yuv[3], ptrdiff_t yuv_stride[3],
int w, int h, const int16_t yuv2rgb_coeffs[3][3][8],
const int16_t yuv_offset[8])
{
pixel **yuv = (pixel **) _yuv;
const pixel *yuv0 = yuv[0], *yuv1 = yuv[1], *yuv2 = yuv[2];
int16_t *rgb0 = rgb[0], *rgb1 = rgb[1], *rgb2 = rgb[2];
int y, x;
int cy = yuv2rgb_coeffs[0][0][0];
int crv = yuv2rgb_coeffs[0][2][0];
int cgu = yuv2rgb_coeffs[1][1][0];
int cgv = yuv2rgb_coeffs[1][2][0];
int cbu = yuv2rgb_coeffs[2][1][0];
const int sh = BIT_DEPTH - 1, rnd = 1 << (sh - 1);
const int uv_offset = 128 << (BIT_DEPTH - 8);
av_assert2(yuv2rgb_coeffs[0][1][0] == 0);
av_assert2(yuv2rgb_coeffs[2][2][0] == 0);
av_assert2(yuv2rgb_coeffs[1][0][0] == cy && yuv2rgb_coeffs[2][0][0] == cy);
w = AV_CEIL_RSHIFT(w, SS_W);
h = AV_CEIL_RSHIFT(h, SS_H);
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
int y00 = yuv0[x << SS_W] - yuv_offset[0];
#if SS_W == 1
int y01 = yuv0[2 * x + 1] - yuv_offset[0];
#if SS_H == 1
int y10 = yuv0[yuv_stride[0] / sizeof(pixel) + 2 * x] - yuv_offset[0];
int y11 = yuv0[yuv_stride[0] / sizeof(pixel) + 2 * x + 1] - yuv_offset[0];
#endif
#endif
int u = yuv1[x] - uv_offset, v = yuv2[x] - uv_offset;
rgb0[x << SS_W] = av_clip_int16((y00 * cy + crv * v + rnd) >> sh);
#if SS_W == 1
rgb0[2 * x + 1] = av_clip_int16((y01 * cy + crv * v + rnd) >> sh);
#if SS_H == 1
rgb0[2 * x + rgb_stride] = av_clip_int16((y10 * cy + crv * v + rnd) >> sh);
rgb0[2 * x + rgb_stride + 1] = av_clip_int16((y11 * cy + crv * v + rnd) >> sh);
#endif
#endif
rgb1[x << SS_W] = av_clip_int16((y00 * cy + cgu * u +
cgv * v + rnd) >> sh);
#if SS_W == 1
rgb1[2 * x + 1] = av_clip_int16((y01 * cy + cgu * u +
cgv * v + rnd) >> sh);
#if SS_H == 1
rgb1[2 * x + rgb_stride] = av_clip_int16((y10 * cy + cgu * u +
cgv * v + rnd) >> sh);
rgb1[2 * x + rgb_stride + 1] = av_clip_int16((y11 * cy + cgu * u +
cgv * v + rnd) >> sh);
#endif
#endif
rgb2[x << SS_W] = av_clip_int16((y00 * cy + cbu * u + rnd) >> sh);
#if SS_W == 1
rgb2[2 * x + 1] = av_clip_int16((y01 * cy + cbu * u + rnd) >> sh);
#if SS_H == 1
rgb2[2 * x + rgb_stride] = av_clip_int16((y10 * cy + cbu * u + rnd) >> sh);
rgb2[2 * x + rgb_stride + 1] = av_clip_int16((y11 * cy + cbu * u + rnd) >> sh);
#endif
#endif
}
yuv0 += (yuv_stride[0] * (1 << SS_H)) / sizeof(pixel);
yuv1 += yuv_stride[1] / sizeof(pixel);
yuv2 += yuv_stride[2] / sizeof(pixel);
rgb0 += rgb_stride * (1 << SS_H);
rgb1 += rgb_stride * (1 << SS_H);
rgb2 += rgb_stride * (1 << SS_H);
}
}
static void fn(rgb2yuv)(uint8_t *_yuv[3], ptrdiff_t yuv_stride[3],
int16_t *rgb[3], ptrdiff_t s,
int w, int h, const int16_t rgb2yuv_coeffs[3][3][8],
const int16_t yuv_offset[8])
{
pixel **yuv = (pixel **) _yuv;
pixel *yuv0 = yuv[0], *yuv1 = yuv[1], *yuv2 = yuv[2];
const int16_t *rgb0 = rgb[0], *rgb1 = rgb[1], *rgb2 = rgb[2];
int y, x;
const int sh = 29 - BIT_DEPTH;
const int rnd = 1 << (sh - 1);
int cry = rgb2yuv_coeffs[0][0][0];
int cgy = rgb2yuv_coeffs[0][1][0];
int cby = rgb2yuv_coeffs[0][2][0];
int cru = rgb2yuv_coeffs[1][0][0];
int cgu = rgb2yuv_coeffs[1][1][0];
int cburv = rgb2yuv_coeffs[1][2][0];
int cgv = rgb2yuv_coeffs[2][1][0];
int cbv = rgb2yuv_coeffs[2][2][0];
ptrdiff_t s0 = yuv_stride[0] / sizeof(pixel);
const int uv_offset = 128 << (BIT_DEPTH - 8);
av_assert2(rgb2yuv_coeffs[1][2][0] == rgb2yuv_coeffs[2][0][0]);
w = AV_CEIL_RSHIFT(w, SS_W);
h = AV_CEIL_RSHIFT(h, SS_H);
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
int r00 = rgb0[x << SS_W], g00 = rgb1[x << SS_W], b00 = rgb2[x << SS_W];
#if SS_W == 1
int r01 = rgb0[x * 2 + 1], g01 = rgb1[x * 2 + 1], b01 = rgb2[x * 2 + 1];
#if SS_H == 1
int r10 = rgb0[x * 2 + 0 + s], g10 = rgb1[x * 2 + 0 + s], b10 = rgb2[x * 2 + 0 + s];
int r11 = rgb0[x * 2 + 1 + s], g11 = rgb1[x * 2 + 1 + s], b11 = rgb2[x * 2 + 1 + s];
#endif
#endif
yuv0[x << SS_W] = av_clip_pixel(yuv_offset[0] +
((r00 * cry + g00 * cgy +
b00 * cby + rnd) >> sh));
#if SS_W == 1
yuv0[x * 2 + 1] = av_clip_pixel(yuv_offset[0] +
((r01 * cry + g01 * cgy +
b01 * cby + rnd) >> sh));
#if SS_H == 1
yuv0[x * 2 + 0 + s0] = av_clip_pixel(yuv_offset[0] +
((r10 * cry + g10 * cgy +
b10 * cby + rnd) >> sh));
yuv0[x * 2 + 1 + s0] = av_clip_pixel(yuv_offset[0] +
((r11 * cry + g11 * cgy +
b11 * cby + rnd) >> sh));
#endif
#endif
yuv1[x] = av_clip_pixel(uv_offset +
((avg(r00, r01, r10, r11) * cru +
avg(g00, g01, g10, g11) * cgu +
avg(b00, b01, b10, b11) * cburv + rnd) >> sh));
yuv2[x] = av_clip_pixel(uv_offset +
((avg(r00, r01, r10, r11) * cburv +
avg(g00, g01, g10, g11) * cgv +
avg(b00, b01, b10, b11) * cbv + rnd) >> sh));
}
yuv0 += s0 * (1 << SS_H);
yuv1 += yuv_stride[1] / sizeof(pixel);
yuv2 += yuv_stride[2] / sizeof(pixel);
rgb0 += s * (1 << SS_H);
rgb1 += s * (1 << SS_H);
rgb2 += s * (1 << SS_H);
}
}
#undef IN_BIT_DEPTH
#undef OUT_BIT_DEPTH
#define OUT_BIT_DEPTH BIT_DEPTH
#define IN_BIT_DEPTH 8
#include "colorspacedsp_yuv2yuv_template.c"
#undef IN_BIT_DEPTH
#define IN_BIT_DEPTH 10
#include "colorspacedsp_yuv2yuv_template.c"
#undef IN_BIT_DEPTH
#define IN_BIT_DEPTH 12
#include "colorspacedsp_yuv2yuv_template.c"

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2016 Ronald S. Bultje <rsbultje@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 "libavutil/avassert.h"
#undef opixel
#define opixel pixel
#undef ipixel
#if IN_BIT_DEPTH == 8
#define ipixel uint8_t
#else
#define ipixel uint16_t
#endif
#undef fn
#undef fn2
#undef fn3
#define fn3(a,b,c,d) a##_##d##p##b##to##c##_c
#define fn2(a,b,c,d) fn3(a,b,c,d)
#define fn(a) fn2(a, IN_BIT_DEPTH, OUT_BIT_DEPTH, ss)
static void fn(yuv2yuv)(uint8_t *_dst[3], ptrdiff_t dst_stride[3],
uint8_t *_src[3], ptrdiff_t src_stride[3],
int w, int h, const int16_t c[3][3][8],
const int16_t yuv_offset[2][8])
{
opixel **dst = (opixel **) _dst;
ipixel **src = (ipixel **) _src;
const ipixel *src0 = src[0], *src1 = src[1], *src2 = src[2];
opixel *dst0 = dst[0], *dst1 = dst[1], *dst2 = dst[2];
int y, x;
const int sh = 14 + IN_BIT_DEPTH - OUT_BIT_DEPTH;
const int rnd = 1 << (sh - 1);
int y_off_in = yuv_offset[0][0];
int y_off_out = yuv_offset[1][0] << sh;
const int uv_off_in = 128 << (IN_BIT_DEPTH - 8);
const int uv_off_out = rnd + (128 << (OUT_BIT_DEPTH - 8 + sh));
int cyy = c[0][0][0], cyu = c[0][1][0], cyv = c[0][2][0];
int cuu = c[1][1][0], cuv = c[1][2][0], cvu = c[2][1][0], cvv = c[2][2][0];
av_assert2(c[1][0][0] == 0);
av_assert2(c[2][0][0] == 0);
w = AV_CEIL_RSHIFT(w, SS_W);
h = AV_CEIL_RSHIFT(h, SS_H);
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
int y00 = src0[x << SS_W] - y_off_in;
#if SS_W == 1
int y01 = src0[2 * x + 1] - y_off_in;
#if SS_H == 1
int y10 = src0[src_stride[0] / sizeof(ipixel) + 2 * x] - y_off_in;
int y11 = src0[src_stride[0] / sizeof(ipixel) + 2 * x + 1] - y_off_in;
#endif
#endif
int u = src1[x] - uv_off_in, v = src2[x] - uv_off_in;
int uv_val = cyu * u + cyv * v + rnd + y_off_out;
dst0[x << SS_W] = av_clip_pixel((cyy * y00 + uv_val) >> sh);
#if SS_W == 1
dst0[x * 2 + 1] = av_clip_pixel((cyy * y01 + uv_val) >> sh);
#if SS_H == 1
dst0[x * 2 + 0 + dst_stride[0] / sizeof(opixel)] =
av_clip_pixel((cyy * y10 + uv_val) >> sh);
dst0[x * 2 + 1 + dst_stride[0] / sizeof(opixel)] =
av_clip_pixel((cyy * y11 + uv_val) >> sh);
#endif
#endif
dst1[x] = av_clip_pixel((u * cuu + v * cuv + uv_off_out) >> sh);
dst2[x] = av_clip_pixel((u * cvu + v * cvv + uv_off_out) >> sh);
}
dst0 += (dst_stride[0] * (1 << SS_H)) / sizeof(opixel);
dst1 += dst_stride[1] / sizeof(opixel);
dst2 += dst_stride[2] / sizeof(opixel);
src0 += (src_stride[0] * (1 << SS_H)) / sizeof(ipixel);
src1 += src_stride[1] / sizeof(ipixel);
src2 += src_stride[2] / sizeof(ipixel);
}
}

1024
libavfilter/vf_colorspace.c Normal file

File diff suppressed because it is too large Load Diff