From d5978c8678ba31bd0fa4f7be337a9208d356d70d Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Thu, 6 Jun 2013 23:57:50 +0200 Subject: Add unscaled converter from GBRP > 8bit to RGBx48/64. Fixes ticket #2633. Tested-by: Michael Cinquin --- libswscale/swscale_unscaled.c | 156 ++++++++++++++++++++++++++++++++++++++++++ tests/ref/lavf/dpx | 2 +- 2 files changed, 157 insertions(+), 1 deletion(-) diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index cdd8401189..7c65daccae 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -389,6 +389,151 @@ static int palToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[], return srcSliceH; } +static void gbr16ptopacked16(const uint16_t *src[], int srcStride[], + uint8_t *dst, int dstStride, int srcSliceH, + int alpha, int swap, int bpp, int width) +{ + int x, h, i; + int scale_high = 16 - bpp, scale_low = (bpp - 8) * 2; + for (h = 0; h < srcSliceH; h++) { + uint16_t *dest = (uint16_t *)(dst + dstStride * h); + uint16_t component; + + switch(swap) { + case 3: + if (alpha) { + for (x = 0; x < width; x++) { + component = av_bswap16(src[0][x]); + *dest++ = av_bswap16(component << scale_high | component >> scale_low); + component = av_bswap16(src[1][x]); + *dest++ = av_bswap16(component << scale_high | component >> scale_low); + component = av_bswap16(src[2][x]); + *dest++ = av_bswap16(component << scale_high | component >> scale_low); + *dest++ = 0xffff; + } + } else { + for (x = 0; x < width; x++) { + component = av_bswap16(src[0][x]); + *dest++ = av_bswap16(component << scale_high | component >> scale_low); + component = av_bswap16(src[1][x]); + *dest++ = av_bswap16(component << scale_high | component >> scale_low); + component = av_bswap16(src[2][x]); + *dest++ = av_bswap16(component << scale_high | component >> scale_low); + } + } + break; + case 2: + if (alpha) { + for (x = 0; x < width; x++) { + *dest++ = av_bswap16(src[0][x] << scale_high | src[0][x] >> scale_low); + *dest++ = av_bswap16(src[1][x] << scale_high | src[1][x] >> scale_low); + *dest++ = av_bswap16(src[2][x] << scale_high | src[2][x] >> scale_low); + *dest++ = 0xffff; + } + } else { + for (x = 0; x < width; x++) { + *dest++ = av_bswap16(src[0][x] << scale_high | src[0][x] >> scale_low); + *dest++ = av_bswap16(src[1][x] << scale_high | src[1][x] >> scale_low); + *dest++ = av_bswap16(src[2][x] << scale_high | src[2][x] >> scale_low); + } + } + break; + case 1: + if (alpha) { + for (x = 0; x < width; x++) { + *dest++ = av_bswap16(src[0][x]) << scale_high | av_bswap16(src[0][x]) >> scale_low; + *dest++ = av_bswap16(src[1][x]) << scale_high | av_bswap16(src[1][x]) >> scale_low; + *dest++ = av_bswap16(src[2][x]) << scale_high | av_bswap16(src[2][x]) >> scale_low; + *dest++ = 0xffff; + } + } else { + for (x = 0; x < width; x++) { + *dest++ = av_bswap16(src[0][x]) << scale_high | av_bswap16(src[0][x]) >> scale_low; + *dest++ = av_bswap16(src[1][x]) << scale_high | av_bswap16(src[1][x]) >> scale_low; + *dest++ = av_bswap16(src[2][x]) << scale_high | av_bswap16(src[2][x]) >> scale_low; + } + } + break; + default: + if (alpha) { + for (x = 0; x < width; x++) { + *dest++ = src[0][x] << scale_high | src[0][x] >> scale_low; + *dest++ = src[1][x] << scale_high | src[1][x] >> scale_low; + *dest++ = src[2][x] << scale_high | src[2][x] >> scale_low; + *dest++ = 0xffff; + } + } else { + for (x = 0; x < width; x++) { + *dest++ = src[0][x] << scale_high | src[0][x] >> scale_low; + *dest++ = src[1][x] << scale_high | src[1][x] >> scale_low; + *dest++ = src[2][x] << scale_high | src[2][x] >> scale_low; + } + } + } + for (i = 0; i < 3; i++) + src[i] += srcStride[i] >> 1; + } +} + +static int planarRgb16ToRgb16Wrapper(SwsContext *c, const uint8_t *src[], + int srcStride[], int srcSliceY, int srcSliceH, + uint8_t *dst[], int dstStride[]) +{ + const uint16_t *src102[] = { (uint16_t *)src[1], (uint16_t *)src[0], (uint16_t *)src[2] }; + const uint16_t *src201[] = { (uint16_t *)src[2], (uint16_t *)src[0], (uint16_t *)src[1] }; + int stride102[] = { srcStride[1], srcStride[0], srcStride[2] }; + int stride201[] = { srcStride[2], srcStride[0], srcStride[1] }; + const AVPixFmtDescriptor *src_format = av_pix_fmt_desc_get(c->srcFormat); + const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->dstFormat); + int bits_per_sample = src_format->comp[0].depth_minus1 + 1; + int swap = 0; + if ( HAVE_BIGENDIAN && !(src_format->flags & AV_PIX_FMT_FLAG_BE) || + !HAVE_BIGENDIAN && src_format->flags & AV_PIX_FMT_FLAG_BE) + swap++; + if ( HAVE_BIGENDIAN && !(dst_format->flags & AV_PIX_FMT_FLAG_BE) || + !HAVE_BIGENDIAN && dst_format->flags & AV_PIX_FMT_FLAG_BE) + swap += 2; + + if (src_format->flags & (AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB) != + (AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB)) { + av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n", + src_format->name, dst_format->name); + return srcSliceH; + } + switch (c->dstFormat) { + case AV_PIX_FMT_BGR48LE: + case AV_PIX_FMT_BGR48BE: + gbr16ptopacked16(src102, stride102, + dst[0] + srcSliceY * dstStride[0], dstStride[0], + srcSliceH, 0, swap, bits_per_sample, c->srcW); + break; + case AV_PIX_FMT_RGB48LE: + case AV_PIX_FMT_RGB48BE: + gbr16ptopacked16(src201, stride201, + dst[0] + srcSliceY * dstStride[0], dstStride[0], + srcSliceH, 0, swap, bits_per_sample, c->srcW); + break; + case AV_PIX_FMT_RGBA64LE: + case AV_PIX_FMT_RGBA64BE: + gbr16ptopacked16(src201, stride201, + dst[0] + srcSliceY * dstStride[0], dstStride[0], + srcSliceH, 1, swap, bits_per_sample, c->srcW); + break; + case AV_PIX_FMT_BGRA64LE: + case AV_PIX_FMT_BGRA64BE: + gbr16ptopacked16(src102, stride102, + dst[0] + srcSliceY * dstStride[0], dstStride[0], + srcSliceH, 1, swap, bits_per_sample, c->srcW); + break; + default: + av_log(c, AV_LOG_ERROR, + "unsupported planar RGB conversion %s -> %s\n", + src_format->name, dst_format->name); + } + + return srcSliceH; +} + static void gbr24ptopacked24(const uint8_t *src[], int srcStride[], uint8_t *dst, int dstStride, int srcSliceH, int width) @@ -1070,6 +1215,17 @@ void ff_get_unscaled_swscale(SwsContext *c) if (srcFormat == AV_PIX_FMT_GBRP && isPlanar(srcFormat) && isByteRGB(dstFormat)) c->swScale = planarRgbToRgbWrapper; + if ((srcFormat == AV_PIX_FMT_GBRP9LE || srcFormat == AV_PIX_FMT_GBRP9BE || + srcFormat == AV_PIX_FMT_GBRP16LE || srcFormat == AV_PIX_FMT_GBRP16BE || + srcFormat == AV_PIX_FMT_GBRP10LE || srcFormat == AV_PIX_FMT_GBRP10BE || + srcFormat == AV_PIX_FMT_GBRP12LE || srcFormat == AV_PIX_FMT_GBRP12BE || + srcFormat == AV_PIX_FMT_GBRP14LE || srcFormat == AV_PIX_FMT_GBRP14BE) && + (dstFormat == AV_PIX_FMT_RGB48LE || dstFormat == AV_PIX_FMT_RGB48BE || + dstFormat == AV_PIX_FMT_BGR48LE || dstFormat == AV_PIX_FMT_BGR48BE || + dstFormat == AV_PIX_FMT_RGBA64LE || dstFormat == AV_PIX_FMT_RGBA64BE || + dstFormat == AV_PIX_FMT_BGRA64LE || dstFormat == AV_PIX_FMT_BGRA64BE)) + c->swScale = planarRgb16ToRgb16Wrapper; + if (av_pix_fmt_desc_get(srcFormat)->comp[0].depth_minus1 == 7 && isPackedRGB(srcFormat) && dstFormat == AV_PIX_FMT_GBRP) c->swScale = rgbToPlanarRgbWrapper; diff --git a/tests/ref/lavf/dpx b/tests/ref/lavf/dpx index 7bedde321f..591ef1b4c4 100644 --- a/tests/ref/lavf/dpx +++ b/tests/ref/lavf/dpx @@ -11,7 +11,7 @@ ./tests/data/images/dpx/%02d.dpx CRC=0xe5b9c023 609920 ./tests/data/images/dpx/02.dpx b9f22728f8ff393bf30cf6cbd624fa95 *./tests/data/images/dpx/02.dpx -./tests/data/images/dpx/%02d.dpx CRC=0xb6310a70 +./tests/data/images/dpx/%02d.dpx CRC=0xf38d5830 407168 ./tests/data/images/dpx/02.dpx 545603630f30dec2768c8ae8d12eb8ea *./tests/data/images/dpx/02.dpx ./tests/data/images/dpx/%02d.dpx CRC=0xe72ce131 -- cgit v1.2.3