From 185655c601cd893866fee42acab19a481f44941e Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Thu, 24 Nov 2011 10:40:05 -0800 Subject: swscale: add support for planar RGB input. --- libswscale/swscale.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 125 insertions(+), 8 deletions(-) (limited to 'libswscale/swscale.c') diff --git a/libswscale/swscale.c b/libswscale/swscale.c index ac067317d3..98daf22cbd 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -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: -- cgit v1.2.3