From ef627bf9ecddfa888d4c6e4fd633852798c3b4a9 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 19 Nov 2013 14:17:26 +0100 Subject: [PATCH] swscale: add nv12/nv21->yuv420 converter Signed-off-by: Michael Niedermayer --- libswscale/rgb2rgb.c | 3 +++ libswscale/rgb2rgb.h | 4 ++++ libswscale/rgb2rgb_template.c | 19 +++++++++++++++++++ libswscale/swscale_unscaled.c | 26 ++++++++++++++++++++++++++ 4 files changed, 52 insertions(+) diff --git a/libswscale/rgb2rgb.c b/libswscale/rgb2rgb.c index ec9ff7151f..cf877fbae0 100644 --- a/libswscale/rgb2rgb.c +++ b/libswscale/rgb2rgb.c @@ -83,6 +83,9 @@ void (*planar2x)(const uint8_t *src, uint8_t *dst, int width, int height, void (*interleaveBytes)(const uint8_t *src1, const uint8_t *src2, uint8_t *dst, int width, int height, int src1Stride, int src2Stride, int dstStride); +void (*deinterleaveBytes)(const uint8_t *src, uint8_t *dst1, uint8_t *dst2, + int width, int height, int srcStride, + int dst1Stride, int dst2Stride); void (*vu9_to_vu12)(const uint8_t *src1, const uint8_t *src2, uint8_t *dst1, uint8_t *dst2, int width, int height, diff --git a/libswscale/rgb2rgb.h b/libswscale/rgb2rgb.h index 340cc70205..5df5dea420 100644 --- a/libswscale/rgb2rgb.h +++ b/libswscale/rgb2rgb.h @@ -135,6 +135,10 @@ extern void (*interleaveBytes)(const uint8_t *src1, const uint8_t *src2, uint8_t int width, int height, int src1Stride, int src2Stride, int dstStride); +extern void (*deinterleaveBytes)(const uint8_t *src, uint8_t *dst1, uint8_t *dst2, + int width, int height, int srcStride, + int dst1Stride, int dst2Stride); + extern void (*vu9_to_vu12)(const uint8_t *src1, const uint8_t *src2, uint8_t *dst1, uint8_t *dst2, int width, int height, diff --git a/libswscale/rgb2rgb_template.c b/libswscale/rgb2rgb_template.c index 98e3a1472e..56e735f6ca 100644 --- a/libswscale/rgb2rgb_template.c +++ b/libswscale/rgb2rgb_template.c @@ -693,6 +693,24 @@ static void interleaveBytes_c(const uint8_t *src1, const uint8_t *src2, } } +static void deinterleaveBytes_c(const uint8_t *src, uint8_t *dst1, uint8_t *dst2, + int width, int height, int srcStride, + int dst1Stride, int dst2Stride) +{ + int h; + + for (h = 0; h < height; h++) { + int w; + for (w = 0; w < width; w++) { + dst1[w] = src[2 * w + 0]; + dst2[w] = src[2 * w + 1]; + } + src += srcStride; + dst1 += dst1Stride; + dst2 += dst2Stride; + } +} + static inline void vu9_to_vu12_c(const uint8_t *src1, const uint8_t *src2, uint8_t *dst1, uint8_t *dst2, int width, int height, @@ -922,6 +940,7 @@ static av_cold void rgb2rgb_init_c(void) planar2x = planar2x_c; ff_rgb24toyv12 = ff_rgb24toyv12_c; interleaveBytes = interleaveBytes_c; + deinterleaveBytes = deinterleaveBytes_c; vu9_to_vu12 = vu9_to_vu12_c; yvu9_to_yuy2 = yvu9_to_yuy2_c; diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index 9f6d8193d8..bd9e7a59e2 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -176,6 +176,27 @@ static int planarToNv12Wrapper(SwsContext *c, const uint8_t *src[], return srcSliceH; } +static int nv12ToPlanarWrapper(SwsContext *c, const uint8_t *src[], + int srcStride[], int srcSliceY, + int srcSliceH, uint8_t *dstParam[], + int dstStride[]) +{ + uint8_t *dst1 = dstParam[1] + dstStride[1] * srcSliceY / 2; + uint8_t *dst2 = dstParam[2] + dstStride[2] * srcSliceY / 2; + + copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, + dstParam[0], dstStride[0]); + + if (c->srcFormat == AV_PIX_FMT_NV12) + deinterleaveBytes(src[1], dst1, dst2,c->srcW / 2, srcSliceH / 2, + srcStride[1], dstStride[1], dstStride[2]); + else + deinterleaveBytes(src[1], dst2, dst1, c->srcW / 2, srcSliceH / 2, + srcStride[1], dstStride[2], dstStride[1]); + + return srcSliceH; +} + static int planarToYuy2Wrapper(SwsContext *c, const uint8_t *src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t *dstParam[], int dstStride[]) @@ -1212,6 +1233,11 @@ void ff_get_unscaled_swscale(SwsContext *c) (dstFormat == AV_PIX_FMT_NV12 || dstFormat == AV_PIX_FMT_NV21)) { c->swscale = planarToNv12Wrapper; } + /* nv12_to_yv12 */ + if (dstFormat == AV_PIX_FMT_YUV420P && + (srcFormat == AV_PIX_FMT_NV12 || srcFormat == AV_PIX_FMT_NV21)) { + c->swscale = nv12ToPlanarWrapper; + } /* yuv2bgr */ if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUV422P || srcFormat == AV_PIX_FMT_YUVA420P) && isAnyRGB(dstFormat) &&