[FFmpeg-cvslog] swscale: add support for planar RGB input.
Ronald S. Bultje
git at videolan.org
Fri Nov 25 04:43:28 CET 2011
ffmpeg | branch: master | Ronald S. Bultje <rsbultje at gmail.com> | Thu Nov 24 10:40:05 2011 -0800| [185655c601cd893866fee42acab19a481f44941e] | committer: Ronald S. Bultje
swscale: add support for planar RGB input.
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=185655c601cd893866fee42acab19a481f44941e
---
libswscale/swscale.c | 133 ++++++++++++++++++++++++++++++++++++++---
libswscale/swscale_internal.h | 14 ++++
libswscale/swscale_unscaled.c | 2 +-
libswscale/utils.c | 7 ++
4 files changed, 147 insertions(+), 9 deletions(-)
diff --git a/libswscale/swscale.c b/libswscale/swscale.c
index ac06731..98daf22 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:
diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h
index 7048265..b20e0a3 100644
--- a/libswscale/swscale_internal.h
+++ b/libswscale/swscale_internal.h
@@ -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];
diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c
index c7e6a28..86bc5ac 100644
--- a/libswscale/swscale_unscaled.c
+++ b/libswscale/swscale_unscaled.c
@@ -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))
diff --git a/libswscale/utils.c b/libswscale/utils.c
index 51bec62..7a96986 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -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)
More information about the ffmpeg-cvslog
mailing list