|
|
@@ -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; |
|
|
|