Commit 4eb93bed authored by Michael Niedermayer's avatar Michael Niedermayer Committed by Derek Buitenhuis

swscale: GBRP output support

Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
Signed-off-by: 's avatarDerek Buitenhuis <derek.buitenhuis@gmail.com>
parent 2026eb14
...@@ -1261,13 +1261,75 @@ YUV2RGBWRAPPERX(yuv2, rgb_full, xrgb32_full, AV_PIX_FMT_ARGB, 0) ...@@ -1261,13 +1261,75 @@ YUV2RGBWRAPPERX(yuv2, rgb_full, xrgb32_full, AV_PIX_FMT_ARGB, 0)
YUV2RGBWRAPPERX(yuv2, rgb_full, bgr24_full, AV_PIX_FMT_BGR24, 0) YUV2RGBWRAPPERX(yuv2, rgb_full, bgr24_full, AV_PIX_FMT_BGR24, 0)
YUV2RGBWRAPPERX(yuv2, rgb_full, rgb24_full, AV_PIX_FMT_RGB24, 0) YUV2RGBWRAPPERX(yuv2, rgb_full, rgb24_full, AV_PIX_FMT_RGB24, 0)
static void
yuv2gbrp_full_X_c(SwsContext *c, const int16_t *lumFilter,
const int16_t **lumSrc, int lumFilterSize,
const int16_t *chrFilter, const int16_t **chrUSrc,
const int16_t **chrVSrc, int chrFilterSize,
const int16_t **alpSrc, uint8_t **dest,
int dstW, int y)
{
int i;
int hasAlpha = 0;
for (i = 0; i < dstW; i++) {
int j;
int Y = 1 << 9;
int U = (1 << 9) - (128 << 19);
int V = (1 << 9) - (128 << 19);
int R, G, B, A;
for (j = 0; j < lumFilterSize; j++)
Y += lumSrc[j][i] * lumFilter[j];
for (j = 0; j < chrFilterSize; j++) {
U += chrUSrc[j][i] * chrFilter[j];
V += chrVSrc[j][i] * chrFilter[j];
}
Y >>= 10;
U >>= 10;
V >>= 10;
if (hasAlpha) {
A = 1 << 18;
for (j = 0; j < lumFilterSize; j++)
A += alpSrc[j][i] * lumFilter[j];
A >>= 19;
if (A & 0x100)
A = av_clip_uint8(A);
}
Y -= c->yuv2rgb_y_offset;
Y *= c->yuv2rgb_y_coeff;
Y += 1 << 21;
R = Y + V * c->yuv2rgb_v2r_coeff;
G = Y + V * c->yuv2rgb_v2g_coeff + U * c->yuv2rgb_u2g_coeff;
B = Y + U * c->yuv2rgb_u2b_coeff;
if ((R | G | B) & 0xC0000000) {
R = av_clip_uintp2(R, 30);
G = av_clip_uintp2(G, 30);
B = av_clip_uintp2(B, 30);
}
dest[0][i] = G >> 22;
dest[1][i] = B >> 22;
dest[2][i] = R >> 22;
}
}
av_cold void ff_sws_init_output_funcs(SwsContext *c, av_cold void ff_sws_init_output_funcs(SwsContext *c,
yuv2planar1_fn *yuv2plane1, yuv2planar1_fn *yuv2plane1,
yuv2planarX_fn *yuv2planeX, yuv2planarX_fn *yuv2planeX,
yuv2interleavedX_fn *yuv2nv12cX, yuv2interleavedX_fn *yuv2nv12cX,
yuv2packed1_fn *yuv2packed1, yuv2packed1_fn *yuv2packed1,
yuv2packed2_fn *yuv2packed2, yuv2packed2_fn *yuv2packed2,
yuv2packedX_fn *yuv2packedX) yuv2packedX_fn *yuv2packedX,
yuv2anyX_fn *yuv2anyX)
{ {
enum AVPixelFormat dstFormat = c->dstFormat; enum AVPixelFormat dstFormat = c->dstFormat;
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat); const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat);
...@@ -1354,6 +1416,9 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c, ...@@ -1354,6 +1416,9 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c,
case AV_PIX_FMT_BGR24: case AV_PIX_FMT_BGR24:
*yuv2packedX = yuv2bgr24_full_X_c; *yuv2packedX = yuv2bgr24_full_X_c;
break; break;
case AV_PIX_FMT_GBRP:
*yuv2anyX = yuv2gbrp_full_X_c;
break;
} }
} else { } else {
switch (dstFormat) { switch (dstFormat) {
......
...@@ -380,6 +380,7 @@ static int swScale(SwsContext *c, const uint8_t *src[], ...@@ -380,6 +380,7 @@ static int swScale(SwsContext *c, const uint8_t *src[],
yuv2packed1_fn yuv2packed1 = c->yuv2packed1; yuv2packed1_fn yuv2packed1 = c->yuv2packed1;
yuv2packed2_fn yuv2packed2 = c->yuv2packed2; yuv2packed2_fn yuv2packed2 = c->yuv2packed2;
yuv2packedX_fn yuv2packedX = c->yuv2packedX; yuv2packedX_fn yuv2packedX = c->yuv2packedX;
yuv2anyX_fn yuv2anyX = c->yuv2anyX;
const int chrSrcSliceY = srcSliceY >> c->chrSrcVSubSample; const int chrSrcSliceY = srcSliceY >> c->chrSrcVSubSample;
const int chrSrcSliceH = -((-srcSliceH) >> c->chrSrcVSubSample); const int chrSrcSliceH = -((-srcSliceH) >> c->chrSrcVSubSample);
int should_dither = is9_OR_10BPS(c->srcFormat) || int should_dither = is9_OR_10BPS(c->srcFormat) ||
...@@ -554,7 +555,7 @@ static int swScale(SwsContext *c, const uint8_t *src[], ...@@ -554,7 +555,7 @@ static int swScale(SwsContext *c, const uint8_t *src[],
/* hmm looks like we can't use MMX here without overwriting /* hmm looks like we can't use MMX here without overwriting
* this array's tail */ * this array's tail */
ff_sws_init_output_funcs(c, &yuv2plane1, &yuv2planeX, &yuv2nv12cX, ff_sws_init_output_funcs(c, &yuv2plane1, &yuv2planeX, &yuv2nv12cX,
&yuv2packed1, &yuv2packed2, &yuv2packedX); &yuv2packed1, &yuv2packed2, &yuv2packedX, &yuv2anyX);
} }
{ {
...@@ -651,7 +652,7 @@ static int swScale(SwsContext *c, const uint8_t *src[], ...@@ -651,7 +652,7 @@ static int swScale(SwsContext *c, const uint8_t *src[],
dstW, c->lumDither8, 0); dstW, c->lumDither8, 0);
} }
} }
} else { } else if (yuv2packedX) {
if (c->yuv2packed1 && vLumFilterSize == 1 && if (c->yuv2packed1 && vLumFilterSize == 1 &&
vChrFilterSize <= 2) { // unscaled RGB vChrFilterSize <= 2) { // unscaled RGB
int chrAlpha = vChrFilterSize == 1 ? 0 : vChrFilter[2 * dstY + 1]; int chrAlpha = vChrFilterSize == 1 ? 0 : vChrFilter[2 * dstY + 1];
...@@ -676,6 +677,12 @@ static int swScale(SwsContext *c, const uint8_t *src[], ...@@ -676,6 +677,12 @@ static int swScale(SwsContext *c, const uint8_t *src[],
chrUSrcPtr, chrVSrcPtr, vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
alpSrcPtr, dest[0], dstW, dstY); alpSrcPtr, dest[0], dstW, dstY);
} }
} else {
yuv2anyX(c, vLumFilter + dstY * vLumFilterSize,
lumSrcPtr, vLumFilterSize,
vChrFilter + dstY * vChrFilterSize,
chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
alpSrcPtr, dest, dstW, dstY);
} }
} }
} }
...@@ -717,7 +724,7 @@ static av_cold void sws_init_swScale_c(SwsContext *c) ...@@ -717,7 +724,7 @@ static av_cold void sws_init_swScale_c(SwsContext *c)
ff_sws_init_output_funcs(c, &c->yuv2plane1, &c->yuv2planeX, ff_sws_init_output_funcs(c, &c->yuv2plane1, &c->yuv2planeX,
&c->yuv2nv12cX, &c->yuv2packed1, &c->yuv2nv12cX, &c->yuv2packed1,
&c->yuv2packed2, &c->yuv2packedX); &c->yuv2packed2, &c->yuv2packedX, &c->yuv2anyX);
ff_sws_init_input_funcs(c); ff_sws_init_input_funcs(c);
......
...@@ -218,6 +218,40 @@ typedef void (*yuv2packedX_fn)(struct SwsContext *c, const int16_t *lumFilter, ...@@ -218,6 +218,40 @@ typedef void (*yuv2packedX_fn)(struct SwsContext *c, const int16_t *lumFilter,
const int16_t **alpSrc, uint8_t *dest, const int16_t **alpSrc, uint8_t *dest,
int dstW, int y); int dstW, int y);
/**
* Write one line of horizontally scaled Y/U/V/A to YUV/RGB
* output by doing multi-point vertical scaling between input pixels.
*
* @param c SWS scaling context
* @param lumFilter vertical luma/alpha scaling coefficients, 12bit [0,4096]
* @param lumSrc scaled luma (Y) source data, 15bit for 8-10bit output,
* 19-bit for 16bit output (in int32_t)
* @param lumFilterSize number of vertical luma/alpha input lines to scale
* @param chrFilter vertical chroma scaling coefficients, 12bit [0,4096]
* @param chrUSrc scaled chroma (U) source data, 15bit for 8-10bit output,
* 19-bit for 16bit output (in int32_t)
* @param chrVSrc scaled chroma (V) source data, 15bit for 8-10bit output,
* 19-bit for 16bit output (in int32_t)
* @param chrFilterSize number of vertical chroma input lines to scale
* @param alpSrc scaled alpha (A) source data, 15bit for 8-10bit output,
* 19-bit for 16bit output (in int32_t)
* @param dest pointer to the output planes. For 16bit output, this is
* uint16_t
* @param dstW width of lumSrc and alpSrc in pixels, number of pixels
* to write into dest[]
* @param y vertical line number for this output. This does not need
* to be used to calculate the offset in the destination,
* but can be used to generate comfort noise using dithering
* or some output formats.
*/
typedef void (*yuv2anyX_fn)(struct SwsContext *c, const int16_t *lumFilter,
const int16_t **lumSrc, int lumFilterSize,
const int16_t *chrFilter,
const int16_t **chrUSrc,
const int16_t **chrVSrc, int chrFilterSize,
const int16_t **alpSrc, uint8_t **dest,
int dstW, int y);
/* This struct should be aligned on at least a 32-byte boundary. */ /* This struct should be aligned on at least a 32-byte boundary. */
typedef struct SwsContext { typedef struct SwsContext {
/** /**
...@@ -427,6 +461,7 @@ typedef struct SwsContext { ...@@ -427,6 +461,7 @@ typedef struct SwsContext {
yuv2packed1_fn yuv2packed1; yuv2packed1_fn yuv2packed1;
yuv2packed2_fn yuv2packed2; yuv2packed2_fn yuv2packed2;
yuv2packedX_fn yuv2packedX; yuv2packedX_fn yuv2packedX;
yuv2anyX_fn yuv2anyX;
/// Unscaled conversion of luma plane to YV12 for horizontal scaler. /// Unscaled conversion of luma plane to YV12 for horizontal scaler.
void (*lumToYV12)(uint8_t *dst, const uint8_t *src, void (*lumToYV12)(uint8_t *dst, const uint8_t *src,
...@@ -708,7 +743,8 @@ void ff_sws_init_output_funcs(SwsContext *c, ...@@ -708,7 +743,8 @@ void ff_sws_init_output_funcs(SwsContext *c,
yuv2interleavedX_fn *yuv2nv12cX, yuv2interleavedX_fn *yuv2nv12cX,
yuv2packed1_fn *yuv2packed1, yuv2packed1_fn *yuv2packed1,
yuv2packed2_fn *yuv2packed2, yuv2packed2_fn *yuv2packed2,
yuv2packedX_fn *yuv2packedX); yuv2packedX_fn *yuv2packedX,
yuv2anyX_fn *yuv2anyX);
void ff_sws_init_swScale_altivec(SwsContext *c); void ff_sws_init_swScale_altivec(SwsContext *c);
void ff_sws_init_swScale_mmx(SwsContext *c); void ff_sws_init_swScale_mmx(SwsContext *c);
......
...@@ -163,7 +163,7 @@ static const FormatEntry format_entries[AV_PIX_FMT_NB] = { ...@@ -163,7 +163,7 @@ static const FormatEntry format_entries[AV_PIX_FMT_NB] = {
[AV_PIX_FMT_YUV444P9LE] = { 1, 1 }, [AV_PIX_FMT_YUV444P9LE] = { 1, 1 },
[AV_PIX_FMT_YUV444P10BE] = { 1, 1 }, [AV_PIX_FMT_YUV444P10BE] = { 1, 1 },
[AV_PIX_FMT_YUV444P10LE] = { 1, 1 }, [AV_PIX_FMT_YUV444P10LE] = { 1, 1 },
[AV_PIX_FMT_GBRP] = { 1, 0 }, [AV_PIX_FMT_GBRP] = { 1, 1 },
[AV_PIX_FMT_GBRP9LE] = { 1, 0 }, [AV_PIX_FMT_GBRP9LE] = { 1, 0 },
[AV_PIX_FMT_GBRP9BE] = { 1, 0 }, [AV_PIX_FMT_GBRP9BE] = { 1, 0 },
[AV_PIX_FMT_GBRP10LE] = { 1, 0 }, [AV_PIX_FMT_GBRP10LE] = { 1, 0 },
...@@ -938,10 +938,21 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, ...@@ -938,10 +938,21 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
getSubSampleFactors(&c->chrSrcHSubSample, &c->chrSrcVSubSample, srcFormat); getSubSampleFactors(&c->chrSrcHSubSample, &c->chrSrcVSubSample, srcFormat);
getSubSampleFactors(&c->chrDstHSubSample, &c->chrDstVSubSample, dstFormat); getSubSampleFactors(&c->chrDstHSubSample, &c->chrDstVSubSample, dstFormat);
if (dstFormat == AV_PIX_FMT_GBRP) {
if (!(flags & SWS_FULL_CHR_H_INT)) {
av_log(c, AV_LOG_DEBUG,
"%s output is not supported with half chroma resolution, switching to full\n",
av_get_pix_fmt_name(dstFormat));
flags |= SWS_FULL_CHR_H_INT;
c->flags = flags;
}
}
/* reuse chroma for 2 pixels RGB/BGR unless user wants full /* reuse chroma for 2 pixels RGB/BGR unless user wants full
* chroma interpolation */ * chroma interpolation */
if (flags & SWS_FULL_CHR_H_INT && if (flags & SWS_FULL_CHR_H_INT &&
isAnyRGB(dstFormat) && isAnyRGB(dstFormat) &&
dstFormat != AV_PIX_FMT_GBRP &&
dstFormat != AV_PIX_FMT_RGBA && dstFormat != AV_PIX_FMT_RGBA &&
dstFormat != AV_PIX_FMT_ARGB && dstFormat != AV_PIX_FMT_ARGB &&
dstFormat != AV_PIX_FMT_BGRA && dstFormat != AV_PIX_FMT_BGRA &&
......
...@@ -12,6 +12,7 @@ bgr565be 257cf78afa35dc31e9696f139c916715 ...@@ -12,6 +12,7 @@ bgr565be 257cf78afa35dc31e9696f139c916715
bgr565le 1dfdd03995c287e3c754b164bf26a355 bgr565le 1dfdd03995c287e3c754b164bf26a355
bgr8 24bd566170343d06fec6fccfff5abc54 bgr8 24bd566170343d06fec6fccfff5abc54
bgra 76a18a5151242fa137133f604cd624d2 bgra 76a18a5151242fa137133f604cd624d2
gbrp 76204621e200a3cc633012f6720c7005
gray db08f7f0751900347e6b8649e4164d21 gray db08f7f0751900347e6b8649e4164d21
gray16be 7becf34ae825a3df3969bf4c6bfeb5e2 gray16be 7becf34ae825a3df3969bf4c6bfeb5e2
gray16le 10bd87059b5c189f3caef2837f4f2b5c gray16le 10bd87059b5c189f3caef2837f4f2b5c
......
...@@ -12,6 +12,7 @@ bgr565be 257cf78afa35dc31e9696f139c916715 ...@@ -12,6 +12,7 @@ bgr565be 257cf78afa35dc31e9696f139c916715
bgr565le 1dfdd03995c287e3c754b164bf26a355 bgr565le 1dfdd03995c287e3c754b164bf26a355
bgr8 24bd566170343d06fec6fccfff5abc54 bgr8 24bd566170343d06fec6fccfff5abc54
bgra 76a18a5151242fa137133f604cd624d2 bgra 76a18a5151242fa137133f604cd624d2
gbrp 76204621e200a3cc633012f6720c7005
gray db08f7f0751900347e6b8649e4164d21 gray db08f7f0751900347e6b8649e4164d21
gray16be 7becf34ae825a3df3969bf4c6bfeb5e2 gray16be 7becf34ae825a3df3969bf4c6bfeb5e2
gray16le 10bd87059b5c189f3caef2837f4f2b5c gray16le 10bd87059b5c189f3caef2837f4f2b5c
......
...@@ -12,6 +12,7 @@ bgr565be 257cf78afa35dc31e9696f139c916715 ...@@ -12,6 +12,7 @@ bgr565be 257cf78afa35dc31e9696f139c916715
bgr565le 1dfdd03995c287e3c754b164bf26a355 bgr565le 1dfdd03995c287e3c754b164bf26a355
bgr8 24bd566170343d06fec6fccfff5abc54 bgr8 24bd566170343d06fec6fccfff5abc54
bgra 76a18a5151242fa137133f604cd624d2 bgra 76a18a5151242fa137133f604cd624d2
gbrp 76204621e200a3cc633012f6720c7005
gray db08f7f0751900347e6b8649e4164d21 gray db08f7f0751900347e6b8649e4164d21
gray16be 7becf34ae825a3df3969bf4c6bfeb5e2 gray16be 7becf34ae825a3df3969bf4c6bfeb5e2
gray16le 10bd87059b5c189f3caef2837f4f2b5c gray16le 10bd87059b5c189f3caef2837f4f2b5c
......
...@@ -12,6 +12,7 @@ bgr565be 922a2503767036ae9536f4f7823c04ee ...@@ -12,6 +12,7 @@ bgr565be 922a2503767036ae9536f4f7823c04ee
bgr565le 3a514a298c6161a071ddf9963c06509d bgr565le 3a514a298c6161a071ddf9963c06509d
bgr8 7f007fa6c153a16e808a9c51605a4016 bgr8 7f007fa6c153a16e808a9c51605a4016
bgra a5e7040f9a80cccd65e5acf2ca09ace5 bgra a5e7040f9a80cccd65e5acf2ca09ace5
gbrp 205c50f8359cb4ba2827a7711dea2cc6
gray d7786a7d9d99ac74230cc045cab5632c gray d7786a7d9d99ac74230cc045cab5632c
gray16be b554d6c1cc8da23967445be4dd3e4a86 gray16be b554d6c1cc8da23967445be4dd3e4a86
gray16le 715a33aa1c19cb26b14f5cc000e7a3d1 gray16le 715a33aa1c19cb26b14f5cc000e7a3d1
......
...@@ -12,6 +12,7 @@ bgr565be f19e9a4786395e1ddcd51399c98c9f6c ...@@ -12,6 +12,7 @@ bgr565be f19e9a4786395e1ddcd51399c98c9f6c
bgr565le fdb617533e1e7ff512ea5b6b6233e738 bgr565le fdb617533e1e7ff512ea5b6b6233e738
bgr8 c60f93fd152c6903391d1fe9decd3547 bgr8 c60f93fd152c6903391d1fe9decd3547
bgra 7f9b799fb48544e49ce93e91d7f9fca8 bgra 7f9b799fb48544e49ce93e91d7f9fca8
gbrp 25c1bce192daefab910d51a56b52199e
gray 30d9014a9d43b5f37e7aa64be3a3ecfc gray 30d9014a9d43b5f37e7aa64be3a3ecfc
gray16be 6b84b85d3326182fa1217e138249edc5 gray16be 6b84b85d3326182fa1217e138249edc5
gray16le 66bb8faa09dc149734aca3c768a6d4e1 gray16le 66bb8faa09dc149734aca3c768a6d4e1
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment