mirror of https://git.ffmpeg.org/ffmpeg.git
swscale: add support for planar RGB input.
This commit is contained in:
parent
db431f7efe
commit
185655c601
|
@ -1807,6 +1807,91 @@ static void rgb24ToUV_half_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
|
|||
}
|
||||
}
|
||||
|
||||
static void planar_rgb_to_y(uint8_t *dst, const uint8_t *src[4], int width)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < width; i++) {
|
||||
int g = src[0][i];
|
||||
int b = src[1][i];
|
||||
int r = src[2][i];
|
||||
|
||||
dst[i] = ((RY * r + GY * g + BY * b + (33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
static void planar_rgb16le_to_y(uint8_t *_dst, const uint8_t *_src[4], int width)
|
||||
{
|
||||
int i;
|
||||
const uint16_t **src = (const uint16_t **) _src;
|
||||
uint16_t *dst = (uint16_t *) _dst;
|
||||
for (i = 0; i < width; i++) {
|
||||
int g = AV_RL16(src[0] + i);
|
||||
int b = AV_RL16(src[1] + i);
|
||||
int r = AV_RL16(src[2] + i);
|
||||
|
||||
dst[i] = ((RY * r + GY * g + BY * b + (33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
static void planar_rgb16be_to_y(uint8_t *_dst, const uint8_t *_src[4], int width)
|
||||
{
|
||||
int i;
|
||||
const uint16_t **src = (const uint16_t **) _src;
|
||||
uint16_t *dst = (uint16_t *) _dst;
|
||||
for (i = 0; i < width; i++) {
|
||||
int g = AV_RB16(src[0] + i);
|
||||
int b = AV_RB16(src[1] + i);
|
||||
int r = AV_RB16(src[2] + i);
|
||||
|
||||
dst[i] = ((RY * r + GY * g + BY * b + (33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
static void planar_rgb_to_uv(uint8_t *dstU, uint8_t *dstV, const uint8_t *src[4], int width)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < width; i++) {
|
||||
int g = src[0][i];
|
||||
int b = src[1][i];
|
||||
int r = src[2][i];
|
||||
|
||||
dstU[i] = (RU * r + GU * g + BU * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
|
||||
dstV[i] = (RV * r + GV * g + BV * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void planar_rgb16le_to_uv(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *_src[4], int width)
|
||||
{
|
||||
int i;
|
||||
const uint16_t **src = (const uint16_t **) _src;
|
||||
uint16_t *dstU = (uint16_t *) _dstU;
|
||||
uint16_t *dstV = (uint16_t *) _dstV;
|
||||
for (i = 0; i < width; i++) {
|
||||
int g = AV_RL16(src[0] + i);
|
||||
int b = AV_RL16(src[1] + i);
|
||||
int r = AV_RL16(src[2] + i);
|
||||
|
||||
dstU[i] = (RU * r + GU * g + BU * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
|
||||
dstV[i] = (RV * r + GV * g + BV * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void planar_rgb16be_to_uv(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *_src[4], int width)
|
||||
{
|
||||
int i;
|
||||
const uint16_t **src = (const uint16_t **) _src;
|
||||
uint16_t *dstU = (uint16_t *) _dstU;
|
||||
uint16_t *dstV = (uint16_t *) _dstV;
|
||||
for (i = 0; i < width; i++) {
|
||||
int g = AV_RB16(src[0] + i);
|
||||
int b = AV_RB16(src[1] + i);
|
||||
int r = AV_RB16(src[2] + i);
|
||||
|
||||
dstU[i] = (RU * r + GU * g + BU * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
|
||||
dstV[i] = (RV * r + GV * g + BV * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void hScale16To19_c(SwsContext *c, int16_t *_dst, int dstW, const uint8_t *_src,
|
||||
const int16_t *filter,
|
||||
const int16_t *filterPos, int filterSize)
|
||||
|
@ -1970,7 +2055,7 @@ static void hyscale_fast_c(SwsContext *c, int16_t *dst, int dstWidth,
|
|||
|
||||
// *** horizontal scale Y line to temp buffer
|
||||
static av_always_inline void hyscale(SwsContext *c, int16_t *dst, int dstWidth,
|
||||
const uint8_t *src, int srcW, int xInc,
|
||||
const uint8_t *src_in[4], int srcW, int xInc,
|
||||
const int16_t *hLumFilter,
|
||||
const int16_t *hLumFilterPos, int hLumFilterSize,
|
||||
uint8_t *formatConvBuffer,
|
||||
|
@ -1978,10 +2063,14 @@ static av_always_inline void hyscale(SwsContext *c, int16_t *dst, int dstWidth,
|
|||
{
|
||||
void (*toYV12)(uint8_t *, const uint8_t *, int, uint32_t *) = isAlpha ? c->alpToYV12 : c->lumToYV12;
|
||||
void (*convertRange)(int16_t *, int) = isAlpha ? NULL : c->lumConvertRange;
|
||||
const uint8_t *src = src_in[isAlpha ? 3 : 0];
|
||||
|
||||
if (toYV12) {
|
||||
toYV12(formatConvBuffer, src, srcW, pal);
|
||||
src= formatConvBuffer;
|
||||
} else if (c->readLumPlanar && !isAlpha) {
|
||||
c->readLumPlanar(formatConvBuffer, src_in, srcW);
|
||||
src = formatConvBuffer;
|
||||
}
|
||||
|
||||
if (!c->hyscale_fast) {
|
||||
|
@ -2010,16 +2099,22 @@ static void hcscale_fast_c(SwsContext *c, int16_t *dst1, int16_t *dst2,
|
|||
}
|
||||
|
||||
static av_always_inline void hcscale(SwsContext *c, int16_t *dst1, int16_t *dst2, int dstWidth,
|
||||
const uint8_t *src1, const uint8_t *src2,
|
||||
const uint8_t *src_in[4],
|
||||
int srcW, int xInc, const int16_t *hChrFilter,
|
||||
const int16_t *hChrFilterPos, int hChrFilterSize,
|
||||
uint8_t *formatConvBuffer, uint32_t *pal)
|
||||
{
|
||||
const uint8_t *src1 = src_in[1], *src2 = src_in[2];
|
||||
if (c->chrToYV12) {
|
||||
uint8_t *buf2 = formatConvBuffer + FFALIGN(srcW * FFALIGN(c->srcBpc, 8) >> 3, 16);
|
||||
c->chrToYV12(formatConvBuffer, buf2, src1, src2, srcW, pal);
|
||||
src1= formatConvBuffer;
|
||||
src2= buf2;
|
||||
} else if (c->readChrPlanar) {
|
||||
uint8_t *buf2 = formatConvBuffer + FFALIGN(srcW * FFALIGN(c->srcBpc, 8) >> 3, 16);
|
||||
c->readChrPlanar(formatConvBuffer, buf2, src_in, srcW);
|
||||
src1= formatConvBuffer;
|
||||
src2= buf2;
|
||||
}
|
||||
|
||||
if (!c->hcscale_fast) {
|
||||
|
@ -2420,8 +2515,12 @@ static int swScale(SwsContext *c, const uint8_t* src[],
|
|||
|
||||
//Do horizontal scaling
|
||||
while(lastInLumBuf < lastLumSrcY) {
|
||||
const uint8_t *src1= src[0]+(lastInLumBuf + 1 - srcSliceY)*srcStride[0];
|
||||
const uint8_t *src2= src[3]+(lastInLumBuf + 1 - srcSliceY)*srcStride[3];
|
||||
const uint8_t *src1[4] = {
|
||||
src[0] + (lastInLumBuf + 1 - srcSliceY) * srcStride[0],
|
||||
src[1] + (lastInLumBuf + 1 - srcSliceY) * srcStride[1],
|
||||
src[2] + (lastInLumBuf + 1 - srcSliceY) * srcStride[2],
|
||||
src[3] + (lastInLumBuf + 1 - srcSliceY) * srcStride[3],
|
||||
};
|
||||
lumBufIndex++;
|
||||
assert(lumBufIndex < 2*vLumBufSize);
|
||||
assert(lastInLumBuf + 1 - srcSliceY < srcSliceH);
|
||||
|
@ -2431,7 +2530,7 @@ static int swScale(SwsContext *c, const uint8_t* src[],
|
|||
formatConvBuffer,
|
||||
pal, 0);
|
||||
if (CONFIG_SWSCALE_ALPHA && alpPixBuf)
|
||||
hyscale(c, alpPixBuf[ lumBufIndex ], dstW, src2, srcW,
|
||||
hyscale(c, alpPixBuf[ lumBufIndex ], dstW, src1, srcW,
|
||||
lumXInc, hLumFilter, hLumFilterPos, hLumFilterSize,
|
||||
formatConvBuffer,
|
||||
pal, 1);
|
||||
|
@ -2440,8 +2539,12 @@ static int swScale(SwsContext *c, const uint8_t* src[],
|
|||
lumBufIndex, lastInLumBuf);
|
||||
}
|
||||
while(lastInChrBuf < lastChrSrcY) {
|
||||
const uint8_t *src1= src[1]+(lastInChrBuf + 1 - chrSrcSliceY)*srcStride[1];
|
||||
const uint8_t *src2= src[2]+(lastInChrBuf + 1 - chrSrcSliceY)*srcStride[2];
|
||||
const uint8_t *src1[4] = {
|
||||
src[0] + (lastInChrBuf + 1 - chrSrcSliceY) * srcStride[0],
|
||||
src[1] + (lastInChrBuf + 1 - chrSrcSliceY) * srcStride[1],
|
||||
src[2] + (lastInChrBuf + 1 - chrSrcSliceY) * srcStride[2],
|
||||
src[3] + (lastInChrBuf + 1 - chrSrcSliceY) * srcStride[3],
|
||||
};
|
||||
chrBufIndex++;
|
||||
assert(chrBufIndex < 2*vChrBufSize);
|
||||
assert(lastInChrBuf + 1 - chrSrcSliceY < (chrSrcSliceH));
|
||||
|
@ -2450,7 +2553,7 @@ static int swScale(SwsContext *c, const uint8_t* src[],
|
|||
|
||||
if (c->needs_hcscale)
|
||||
hcscale(c, chrUPixBuf[chrBufIndex], chrVPixBuf[chrBufIndex],
|
||||
chrDstW, src1, src2, chrSrcW, chrXInc,
|
||||
chrDstW, src1, chrSrcW, chrXInc,
|
||||
hChrFilter, hChrFilterPos, hChrFilterSize,
|
||||
formatConvBuffer, pal);
|
||||
lastInChrBuf++;
|
||||
|
@ -2580,6 +2683,13 @@ static av_cold void sws_init_swScale_c(SwsContext *c)
|
|||
case PIX_FMT_PAL8 :
|
||||
case PIX_FMT_BGR4_BYTE:
|
||||
case PIX_FMT_RGB4_BYTE: c->chrToYV12 = palToUV_c; break;
|
||||
case PIX_FMT_GBRP9LE:
|
||||
case PIX_FMT_GBRP10LE:
|
||||
case PIX_FMT_GBRP16LE: c->readChrPlanar = planar_rgb16le_to_uv; break;
|
||||
case PIX_FMT_GBRP9BE:
|
||||
case PIX_FMT_GBRP10BE:
|
||||
case PIX_FMT_GBRP16BE: c->readChrPlanar = planar_rgb16be_to_uv; break;
|
||||
case PIX_FMT_GBRP: c->readChrPlanar = planar_rgb_to_uv; break;
|
||||
#if HAVE_BIGENDIAN
|
||||
case PIX_FMT_YUV444P9LE:
|
||||
case PIX_FMT_YUV422P9LE:
|
||||
|
@ -2649,6 +2759,13 @@ static av_cold void sws_init_swScale_c(SwsContext *c)
|
|||
c->lumToYV12 = NULL;
|
||||
c->alpToYV12 = NULL;
|
||||
switch (srcFormat) {
|
||||
case PIX_FMT_GBRP9LE:
|
||||
case PIX_FMT_GBRP10LE:
|
||||
case PIX_FMT_GBRP16LE: c->readLumPlanar = planar_rgb16le_to_y; break;
|
||||
case PIX_FMT_GBRP9BE:
|
||||
case PIX_FMT_GBRP10BE:
|
||||
case PIX_FMT_GBRP16BE: c->readLumPlanar = planar_rgb16be_to_y; break;
|
||||
case PIX_FMT_GBRP: c->readLumPlanar = planar_rgb_to_y; break;
|
||||
#if HAVE_BIGENDIAN
|
||||
case PIX_FMT_YUV444P9LE:
|
||||
case PIX_FMT_YUV422P9LE:
|
||||
|
|
|
@ -427,6 +427,16 @@ typedef struct SwsContext {
|
|||
void (*chrToYV12)(uint8_t *dstU, uint8_t *dstV,
|
||||
const uint8_t *src1, const uint8_t *src2,
|
||||
int width, uint32_t *pal); ///< Unscaled conversion of chroma planes to YV12 for horizontal scaler.
|
||||
|
||||
/**
|
||||
* Functions to read planar input, such as planar RGB, and convert
|
||||
* internally to Y/UV.
|
||||
*/
|
||||
/** @{ */
|
||||
void (*readLumPlanar)(uint8_t *dst, const uint8_t *src[4], int width);
|
||||
void (*readChrPlanar)(uint8_t *dstU, uint8_t *dstV, const uint8_t *src[4], int width);
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* Scale one horizontal line of input data using a bilinear filter
|
||||
* to produce one line of output data. Compared to SwsContext->hScale(),
|
||||
|
@ -594,6 +604,10 @@ const char *sws_format_name(enum PixelFormat format);
|
|||
(av_pix_fmt_descriptors[x].nb_components >= 2 && \
|
||||
!(av_pix_fmt_descriptors[x].flags & PIX_FMT_PLANAR))
|
||||
|
||||
#define isPlanar(x) \
|
||||
(av_pix_fmt_descriptors[x].nb_components >= 2 && \
|
||||
(av_pix_fmt_descriptors[x].flags & PIX_FMT_PLANAR))
|
||||
|
||||
#define usePal(x) ((av_pix_fmt_descriptors[x].flags & PIX_FMT_PAL) || (x) == PIX_FMT_Y400A)
|
||||
|
||||
extern const uint64_t ff_dither4[2];
|
||||
|
|
|
@ -779,7 +779,7 @@ static void reset_ptr(const uint8_t* src[], int format)
|
|||
{
|
||||
if(!isALPHA(format))
|
||||
src[3]=NULL;
|
||||
if(!isPlanarYUV(format)) {
|
||||
if (!isPlanar(format)) {
|
||||
src[3]=src[2]=NULL;
|
||||
|
||||
if (!usePal(format))
|
||||
|
|
|
@ -137,6 +137,13 @@ const static FormatEntry format_entries[PIX_FMT_NB] = {
|
|||
[PIX_FMT_YUV444P9LE] = { 1 , 1 },
|
||||
[PIX_FMT_YUV444P10BE] = { 1 , 1 },
|
||||
[PIX_FMT_YUV444P10LE] = { 1 , 1 },
|
||||
[PIX_FMT_GBRP] = { 1 , 0 },
|
||||
[PIX_FMT_GBRP9LE] = { 1 , 0 },
|
||||
[PIX_FMT_GBRP9BE] = { 1 , 0 },
|
||||
[PIX_FMT_GBRP10LE] = { 1 , 0 },
|
||||
[PIX_FMT_GBRP10BE] = { 1 , 0 },
|
||||
[PIX_FMT_GBRP16LE] = { 1 , 0 },
|
||||
[PIX_FMT_GBRP16BE] = { 1 , 0 },
|
||||
};
|
||||
|
||||
int sws_isSupportedInput(enum PixelFormat pix_fmt)
|
||||
|
|
Loading…
Reference in New Issue