mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-21 10:55:51 +02:00
sws: support xyz input
The implementation is heavily based on Matthias Buerchers and Nicolas Bertrands vf_xyz2rgb.c Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
parent
45f1cf88a8
commit
0c47c9028b
@ -791,6 +791,62 @@ static int check_image_pointers(const uint8_t * const data[4], enum AVPixelForma
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void xyz12Torgb48(struct SwsContext *c, uint16_t *dst,
|
||||
const uint16_t *src, int stride, int h)
|
||||
{
|
||||
int xp,yp;
|
||||
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
|
||||
|
||||
for (yp=0; yp<h; yp++) {
|
||||
for (xp=0; xp+2<stride; xp+=3) {
|
||||
int x, y, z, r, g, b;
|
||||
|
||||
if (desc->flags & PIX_FMT_BE) {
|
||||
x = AV_RB16(src + xp + 0);
|
||||
y = AV_RB16(src + xp + 1);
|
||||
z = AV_RB16(src + xp + 2);
|
||||
} else {
|
||||
x = AV_RL16(src + xp + 0);
|
||||
y = AV_RL16(src + xp + 1);
|
||||
z = AV_RL16(src + xp + 2);
|
||||
}
|
||||
|
||||
x = c->xyzgamma[x>>4];
|
||||
y = c->xyzgamma[y>>4];
|
||||
z = c->xyzgamma[z>>4];
|
||||
|
||||
// convert from XYZlinear to sRGBlinear
|
||||
r = c->xyz2rgb_matrix[0][0] * x +
|
||||
c->xyz2rgb_matrix[0][1] * y +
|
||||
c->xyz2rgb_matrix[0][2] * z >> 12;
|
||||
g = c->xyz2rgb_matrix[1][0] * x +
|
||||
c->xyz2rgb_matrix[1][1] * y +
|
||||
c->xyz2rgb_matrix[1][2] * z >> 12;
|
||||
b = c->xyz2rgb_matrix[2][0] * x +
|
||||
c->xyz2rgb_matrix[1][2] * y +
|
||||
c->xyz2rgb_matrix[2][2] * z >> 12;
|
||||
|
||||
// limit values to 12-bit depth
|
||||
r = av_clip_c(r,0,4095);
|
||||
g = av_clip_c(g,0,4095);
|
||||
b = av_clip_c(b,0,4095);
|
||||
|
||||
// convert from sRGBlinear to RGB and scale from 12bit to 16bit
|
||||
if (desc->flags & PIX_FMT_BE) {
|
||||
AV_WB16(dst + xp + 0, c->rgbgamma[r] << 4);
|
||||
AV_WB16(dst + xp + 1, c->rgbgamma[g] << 4);
|
||||
AV_WB16(dst + xp + 2, c->rgbgamma[b] << 4);
|
||||
} else {
|
||||
AV_WL16(dst + xp + 0, c->rgbgamma[r] << 4);
|
||||
AV_WL16(dst + xp + 1, c->rgbgamma[g] << 4);
|
||||
AV_WL16(dst + xp + 2, c->rgbgamma[b] << 4);
|
||||
}
|
||||
}
|
||||
src += stride;
|
||||
dst += stride;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* swscale wrapper, so we don't need to export the SwsContext.
|
||||
* Assumes planar YUV to be in YUV order instead of YVU.
|
||||
@ -922,6 +978,15 @@ int attribute_align_arg sws_scale(struct SwsContext *c,
|
||||
src2[0] = base;
|
||||
}
|
||||
|
||||
if (c->srcXYZ && !(c->dstXYZ && c->srcW==c->dstW && c->srcH==c->dstH)) {
|
||||
uint8_t *base;
|
||||
rgb0_tmp = av_malloc(FFABS(srcStride[0]) * srcSliceH + 32);
|
||||
base = srcStride[0] < 0 ? rgb0_tmp - srcStride[0] * (srcSliceH-1) : rgb0_tmp;
|
||||
|
||||
xyz12Torgb48(c, base, src2[0], srcStride[0]/2, srcSliceH);
|
||||
src2[0] = base;
|
||||
}
|
||||
|
||||
if (!srcSliceY && (c->flags & SWS_BITEXACT) && (c->flags & SWS_ERROR_DIFFUSION) && c->dither_error[0])
|
||||
for (i = 0; i < 4; i++)
|
||||
memset(c->dither_error[i], 0, sizeof(c->dither_error[0][0]) * (c->dstW+2));
|
||||
|
@ -380,6 +380,8 @@ typedef struct SwsContext {
|
||||
int dstRange; ///< 0 = MPG YUV range, 1 = JPG YUV range (destination image).
|
||||
int src0Alpha;
|
||||
int dst0Alpha;
|
||||
int srcXYZ;
|
||||
int dstXYZ;
|
||||
int yuv2rgb_y_offset;
|
||||
int yuv2rgb_y_coeff;
|
||||
int yuv2rgb_v2r_coeff;
|
||||
@ -473,6 +475,13 @@ typedef struct SwsContext {
|
||||
#endif
|
||||
int use_mmx_vfilter;
|
||||
|
||||
/* pre defined color-spaces gamma */
|
||||
#define XYZ_GAMMA (2.6f)
|
||||
#define RGB_GAMMA (2.2f)
|
||||
int16_t xyzgamma[4096];
|
||||
int16_t rgbgamma[4096];
|
||||
int16_t xyz2rgb_matrix[3][4];
|
||||
|
||||
/* function pointers for swScale() */
|
||||
yuv2planar1_fn yuv2plane1;
|
||||
yuv2planarX_fn yuv2planeX;
|
||||
|
@ -196,6 +196,8 @@ static const FormatEntry format_entries[AV_PIX_FMT_NB] = {
|
||||
[AV_PIX_FMT_GBRP14BE] = { 1, 1 },
|
||||
[AV_PIX_FMT_GBRP16LE] = { 1, 0 },
|
||||
[AV_PIX_FMT_GBRP16BE] = { 1, 0 },
|
||||
[AV_PIX_FMT_XYZ12BE] = { 1, 0 },
|
||||
[AV_PIX_FMT_XYZ12LE] = { 1, 0 },
|
||||
};
|
||||
|
||||
int sws_isSupportedInput(enum AVPixelFormat pix_fmt)
|
||||
@ -893,6 +895,24 @@ static void fill_rgb2yuv_table(SwsContext *c, const int table[4], int dstRange)
|
||||
AV_WL16(p + 16*4 + 2*i, map[i] >= 0 ? c->input_rgb2yuv_table[map[i]] : 0);
|
||||
}
|
||||
|
||||
static void fill_xyztables(struct SwsContext *c)
|
||||
{
|
||||
int i;
|
||||
double xyzgamma = XYZ_GAMMA;
|
||||
double rgbgamma = 1.0 / RGB_GAMMA;
|
||||
static const int16_t xyz2rgb_matrix[3][4] = {
|
||||
{13270, -6295, -2041},
|
||||
{-3969, 7682, 170},
|
||||
{ 228, -835, 4329} };
|
||||
|
||||
/* set gamma vectors */
|
||||
for (i = 0; i < 4096; i++) {
|
||||
c->xyzgamma[i] = lrint(pow(i / 4095.0, xyzgamma) * 4095.0);
|
||||
c->rgbgamma[i] = lrint(pow(i / 4095.0, rgbgamma) * 4095.0);
|
||||
}
|
||||
memcpy(c->xyz2rgb_matrix, xyz2rgb_matrix, sizeof(c->xyz2rgb_matrix));
|
||||
}
|
||||
|
||||
int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4],
|
||||
int srcRange, const int table[4], int dstRange,
|
||||
int brightness, int contrast, int saturation)
|
||||
@ -913,6 +933,8 @@ int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4],
|
||||
c->srcRange = srcRange;
|
||||
c->dstRange = dstRange;
|
||||
|
||||
fill_xyztables(c);
|
||||
|
||||
if ((isYUV(c->dstFormat) || isGray(c->dstFormat)) && (isYUV(c->srcFormat) || isGray(c->srcFormat)))
|
||||
return -1;
|
||||
|
||||
@ -983,6 +1005,15 @@ static int handle_0alpha(enum AVPixelFormat *format)
|
||||
}
|
||||
}
|
||||
|
||||
static int handle_xyz(enum AVPixelFormat *format)
|
||||
{
|
||||
switch (*format) {
|
||||
case AV_PIX_FMT_XYZ12BE : *format = AV_PIX_FMT_RGB48BE; return 1;
|
||||
case AV_PIX_FMT_XYZ12LE : *format = AV_PIX_FMT_RGB48LE; return 1;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
SwsContext *sws_alloc_context(void)
|
||||
{
|
||||
SwsContext *c = av_mallocz(sizeof(SwsContext));
|
||||
@ -1025,6 +1056,8 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
|
||||
handle_jpeg(&dstFormat);
|
||||
handle_0alpha(&srcFormat);
|
||||
handle_0alpha(&dstFormat);
|
||||
handle_xyz(&srcFormat);
|
||||
handle_xyz(&dstFormat);
|
||||
|
||||
if(srcFormat!=c->srcFormat || dstFormat!=c->dstFormat){
|
||||
av_log(c, AV_LOG_WARNING, "deprecated pixel format used, make sure you did set range correctly\n");
|
||||
@ -1518,6 +1551,8 @@ SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,
|
||||
c->dstRange = handle_jpeg(&dstFormat);
|
||||
c->src0Alpha = handle_0alpha(&srcFormat);
|
||||
c->dst0Alpha = handle_0alpha(&dstFormat);
|
||||
c->srcXYZ = handle_xyz(&srcFormat);
|
||||
c->dstXYZ = handle_xyz(&dstFormat);
|
||||
c->srcFormat = srcFormat;
|
||||
c->dstFormat = dstFormat;
|
||||
|
||||
@ -1959,11 +1994,13 @@ struct SwsContext *sws_getCachedContext(struct SwsContext *context, int srcW,
|
||||
context->srcH = srcH;
|
||||
context->srcRange = handle_jpeg(&srcFormat);
|
||||
context->src0Alpha = handle_0alpha(&srcFormat);
|
||||
context->srcXYZ = handle_xyz(&srcFormat);
|
||||
context->srcFormat = srcFormat;
|
||||
context->dstW = dstW;
|
||||
context->dstH = dstH;
|
||||
context->dstRange = handle_jpeg(&dstFormat);
|
||||
context->dst0Alpha = handle_0alpha(&dstFormat);
|
||||
context->dstXYZ = handle_xyz(&dstFormat);
|
||||
context->dstFormat = dstFormat;
|
||||
context->flags = flags;
|
||||
context->param[0] = param[0];
|
||||
|
Loading…
Reference in New Issue
Block a user