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:
parent
d7815df402
commit
2e2e08a35b
@ -23,6 +23,7 @@ version <next>:
|
|||||||
- aix demuxer
|
- aix demuxer
|
||||||
- remap filter
|
- remap filter
|
||||||
- hash and framehash muxers
|
- hash and framehash muxers
|
||||||
|
- colorspace filter
|
||||||
|
|
||||||
version 3.0:
|
version 3.0:
|
||||||
- Common Encryption (CENC) MP4 encoding and decoding support
|
- Common Encryption (CENC) MP4 encoding and decoding support
|
||||||
|
183
doc/filters.texi
183
doc/filters.texi
@ -4937,6 +4937,189 @@ For example to convert from BT.601 to SMPTE-240M, use the command:
|
|||||||
colormatrix=bt601:smpte240m
|
colormatrix=bt601:smpte240m
|
||||||
@end example
|
@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
|
@section convolution
|
||||||
|
|
||||||
Apply convolution 3x3 or 5x5 filter.
|
Apply convolution 3x3 or 5x5 filter.
|
||||||
|
@ -131,6 +131,7 @@ OBJS-$(CONFIG_COLORCHANNELMIXER_FILTER) += vf_colorchannelmixer.o
|
|||||||
OBJS-$(CONFIG_COLORKEY_FILTER) += vf_colorkey.o
|
OBJS-$(CONFIG_COLORKEY_FILTER) += vf_colorkey.o
|
||||||
OBJS-$(CONFIG_COLORLEVELS_FILTER) += vf_colorlevels.o
|
OBJS-$(CONFIG_COLORLEVELS_FILTER) += vf_colorlevels.o
|
||||||
OBJS-$(CONFIG_COLORMATRIX_FILTER) += vf_colormatrix.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_CONVOLUTION_FILTER) += vf_convolution.o
|
||||||
OBJS-$(CONFIG_COPY_FILTER) += vf_copy.o
|
OBJS-$(CONFIG_COPY_FILTER) += vf_copy.o
|
||||||
OBJS-$(CONFIG_COREIMAGE_FILTER) += vf_coreimage.o
|
OBJS-$(CONFIG_COREIMAGE_FILTER) += vf_coreimage.o
|
||||||
|
@ -152,6 +152,7 @@ void avfilter_register_all(void)
|
|||||||
REGISTER_FILTER(COLORKEY, colorkey, vf);
|
REGISTER_FILTER(COLORKEY, colorkey, vf);
|
||||||
REGISTER_FILTER(COLORLEVELS, colorlevels, vf);
|
REGISTER_FILTER(COLORLEVELS, colorlevels, vf);
|
||||||
REGISTER_FILTER(COLORMATRIX, colormatrix, vf);
|
REGISTER_FILTER(COLORMATRIX, colormatrix, vf);
|
||||||
|
REGISTER_FILTER(COLORSPACE, colorspace, vf);
|
||||||
REGISTER_FILTER(CONVOLUTION, convolution, vf);
|
REGISTER_FILTER(CONVOLUTION, convolution, vf);
|
||||||
REGISTER_FILTER(COPY, copy, vf);
|
REGISTER_FILTER(COPY, copy, vf);
|
||||||
REGISTER_FILTER(COREIMAGE, coreimage, vf);
|
REGISTER_FILTER(COREIMAGE, coreimage, vf);
|
||||||
|
131
libavfilter/colorspacedsp.c
Normal file
131
libavfilter/colorspacedsp.c
Normal 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;
|
||||||
|
}
|
51
libavfilter/colorspacedsp.h
Normal file
51
libavfilter/colorspacedsp.h
Normal 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 */
|
214
libavfilter/colorspacedsp_template.c
Normal file
214
libavfilter/colorspacedsp_template.c
Normal 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"
|
98
libavfilter/colorspacedsp_yuv2yuv_template.c
Normal file
98
libavfilter/colorspacedsp_yuv2yuv_template.c
Normal 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
1024
libavfilter/vf_colorspace.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user