aboutsummaryrefslogtreecommitdiffstats
path: root/libswscale
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2011-07-11 04:00:41 +0200
committerMichael Niedermayer <michaelni@gmx.at>2011-07-11 04:01:01 +0200
commit3b2d285afbd6304505a96b71877cdfda13f4565c (patch)
tree95ec289a13aae12e8bbb9e880031f02f6ee46dd2 /libswscale
parent3743ea1fe3761ddbf8bfaae31c6acbf59a8cdc0a (diff)
parent46b32b51979af94f645f8780c78bb12944d04790 (diff)
downloadffmpeg-3b2d285afbd6304505a96b71877cdfda13f4565c.tar.gz
Merge branch 'sws_32bit_integration'
* sws_32bit_integration: regtests/sws: update checksums for recent changes sws: dont mess with XInc when the code needing it isnt used sws: Fix chroma init for 32bit buffers. swscale: error dithering for 16/9/10-bit to 8-bit. swscale: fix overflow in 16-bit vertical scaling. swscale: fix crash in 8-bpc bilinear output without alpha. swscale: fix 16-bit scaling when output is 8-bits. sws: fix non native endian 9-15 bit input with 16bit out sws: disable scale16 when int32 is used sws: fix rgb -> 16bit sws: fix uv overwrite in 32bt sws: fix gray16_1 sws:ix yuv2rgb48_1_c_template() sws: fix 16/32 bug from merge swscale: for >8bit scaling, read in native bit-depth. swscale: fix another yuv range conversion overflow in 16bit scaling. (cherry picked from commit 81cc7d0bd1eab0aa782ff8dd49e087025a42cdee) swscale: fix yuv range correction when using 16-bit scaling. (cherry picked from commit e0b8fff6c7a293e35079ba1931bd19372686b3f6) swscale: implement >8bit scaling support. Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libswscale')
-rw-r--r--libswscale/ppc/swscale_altivec.c6
-rw-r--r--libswscale/swscale.c734
-rw-r--r--libswscale/swscale_internal.h21
-rw-r--r--libswscale/utils.c27
-rw-r--r--libswscale/x86/swscale_template.c234
5 files changed, 668 insertions, 354 deletions
diff --git a/libswscale/ppc/swscale_altivec.c b/libswscale/ppc/swscale_altivec.c
index 924c67d191..8bc0ddd9d8 100644
--- a/libswscale/ppc/swscale_altivec.c
+++ b/libswscale/ppc/swscale_altivec.c
@@ -220,7 +220,7 @@ yuv2yuvX_altivec_real(SwsContext *c,
}
}
-static void hScale_altivec_real(int16_t *dst, int dstW,
+static void hScale_altivec_real(SwsContext *c, int16_t *dst, int dstW,
const uint8_t *src, const int16_t *filter,
const int16_t *filterPos, int filterSize)
{
@@ -406,7 +406,9 @@ void ff_sws_init_swScale_altivec(SwsContext *c)
if (!(av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC))
return;
- c->hScale = hScale_altivec_real;
+ if (c->scalingBpp == 8) {
+ c->hScale = hScale_altivec_real;
+ }
if (!is16BPS(dstFormat) && !is9_OR_10BPS(dstFormat) &&
dstFormat != PIX_FMT_NV12 && dstFormat != PIX_FMT_NV21 &&
!c->alpPixBuf) {
diff --git a/libswscale/swscale.c b/libswscale/swscale.c
index 714ae178ae..9d17868019 100644
--- a/libswscale/swscale.c
+++ b/libswscale/swscale.c
@@ -182,6 +182,18 @@ DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={
{ 77, 23, 60, 15, 72, 21, 56, 14, },
};
#endif
+DECLARE_ALIGNED(8, const uint8_t, dither_8x8_128)[8][8] = {
+{ 36, 68, 60, 92, 34, 66, 58, 90,},
+{ 100, 4,124, 28, 98, 2,122, 26,},
+{ 52, 84, 44, 76, 50, 82, 42, 74,},
+{ 116, 20,108, 12,114, 18,106, 10,},
+{ 32, 64, 56, 88, 38, 70, 62, 94,},
+{ 96, 0,120, 24,102, 6,126, 30,},
+{ 48, 80, 40, 72, 54, 86, 46, 78,},
+{ 112, 16,104, 8,118, 22,110, 14,},
+};
+DECLARE_ALIGNED(8, const uint8_t, ff_sws_pb_64)[8] =
+{ 64, 64, 64, 64, 64, 64, 64, 64 };
DECLARE_ALIGNED(8, const uint8_t, dithers)[8][8][8]={
{
@@ -279,18 +291,19 @@ const uint16_t dither_scale[15][16]={
};
static av_always_inline void
-yuv2yuvX16_c_template(const int16_t *lumFilter, const int16_t **lumSrc,
+yuv2yuvX16_c_template(const int16_t *lumFilter, const int32_t **lumSrc,
int lumFilterSize, const int16_t *chrFilter,
- const int16_t **chrUSrc, const int16_t **chrVSrc,
- int chrFilterSize, const int16_t **alpSrc,
+ const int32_t **chrUSrc, const int32_t **chrVSrc,
+ int chrFilterSize, const int32_t **alpSrc,
uint16_t *dest[4], int dstW, int chrDstW,
int big_endian, int output_bits)
{
//FIXME Optimize (just quickly written not optimized..)
int i;
- int shift = 11 + 16 - output_bits;
+ int dword= output_bits == 16;
uint16_t *yDest = dest[0], *uDest = dest[1], *vDest = dest[2],
*aDest = CONFIG_SWSCALE_ALPHA ? dest[3] : NULL;
+ int shift = 11 + 4*dword + 16 - output_bits - 1;
#define output_pixel(pos, val) \
if (big_endian) { \
@@ -307,24 +320,24 @@ yuv2yuvX16_c_template(const int16_t *lumFilter, const int16_t **lumSrc,
} \
}
for (i = 0; i < dstW; i++) {
- int val = 1 << (26-output_bits);
+ int val = 1 << (26-output_bits + 4*dword - 1);
int j;
for (j = 0; j < lumFilterSize; j++)
- val += lumSrc[j][i] * lumFilter[j];
+ val += ((dword ? lumSrc[j][i] : ((int16_t**)lumSrc)[j][i]) * lumFilter[j])>>1;
output_pixel(&yDest[i], val);
}
if (uDest) {
for (i = 0; i < chrDstW; i++) {
- int u = 1 << (26-output_bits);
- int v = 1 << (26-output_bits);
+ int u = 1 << (26-output_bits + 4*dword - 1);
+ int v = 1 << (26-output_bits + 4*dword - 1);
int j;
for (j = 0; j < chrFilterSize; j++) {
- u += chrUSrc[j][i] * chrFilter[j];
- v += chrVSrc[j][i] * chrFilter[j];
+ u += ((dword ? chrUSrc[j][i] : ((int16_t**)chrUSrc)[j][i]) * chrFilter[j]) >> 1;
+ v += ((dword ? chrVSrc[j][i] : ((int16_t**)chrVSrc)[j][i]) * chrFilter[j]) >> 1;
}
output_pixel(&uDest[i], u);
@@ -334,11 +347,11 @@ yuv2yuvX16_c_template(const int16_t *lumFilter, const int16_t **lumSrc,
if (CONFIG_SWSCALE_ALPHA && aDest) {
for (i = 0; i < dstW; i++) {
- int val = 1 << (26-output_bits);
+ int val = 1 << (26-output_bits + 4*dword - 1);
int j;
for (j = 0; j < lumFilterSize; j++)
- val += alpSrc[j][i] * lumFilter[j];
+ val += ((dword ? alpSrc[j][i] : ((int16_t**)alpSrc)[j][i]) * lumFilter[j]) >> 1;
output_pixel(&aDest[i], val);
}
@@ -348,12 +361,16 @@ yuv2yuvX16_c_template(const int16_t *lumFilter, const int16_t **lumSrc,
#define yuv2NBPS(bits, BE_LE, is_be) \
static void yuv2yuvX ## bits ## BE_LE ## _c(SwsContext *c, const int16_t *lumFilter, \
- const int16_t **lumSrc, int lumFilterSize, \
- const int16_t *chrFilter, const int16_t **chrUSrc, \
- const int16_t **chrVSrc, \
- int chrFilterSize, const int16_t **alpSrc, \
+ const int16_t **_lumSrc, int lumFilterSize, \
+ const int16_t *chrFilter, const int16_t **_chrUSrc, \
+ const int16_t **_chrVSrc, \
+ int chrFilterSize, const int16_t **_alpSrc, \
uint8_t *_dest[4], int dstW, int chrDstW) \
{ \
+ const int32_t **lumSrc = (const int32_t **) _lumSrc, \
+ **chrUSrc = (const int32_t **) _chrUSrc, \
+ **chrVSrc = (const int32_t **) _chrVSrc, \
+ **alpSrc = (const int32_t **) _alpSrc; \
yuv2yuvX16_c_template(lumFilter, lumSrc, lumFilterSize, \
chrFilter, chrUSrc, chrVSrc, chrFilterSize, \
alpSrc, (uint16_t **) _dest, \
@@ -371,16 +388,16 @@ static void yuv2yuvX_c(SwsContext *c, const int16_t *lumFilter,
const int16_t *chrFilter, const int16_t **chrUSrc,
const int16_t **chrVSrc,
int chrFilterSize, const int16_t **alpSrc,
- uint8_t *dest[4], int dstW, int chrDstW,
- const uint8_t *lumDither, const uint8_t *chrDither)
+ uint8_t *dest[4], int dstW, int chrDstW)
{
uint8_t *yDest = dest[0], *uDest = dest[1], *vDest = dest[2],
*aDest = CONFIG_SWSCALE_ALPHA ? dest[3] : NULL;
int i;
+ const uint8_t *lumDither = c->lumDither8, *chrDither = c->chrDither8;
//FIXME Optimize (just quickly written not optimized..)
for (i=0; i<dstW; i++) {
- int val = lumDither[i&7] << 12;
+ int val = lumDither[i & 7] << 12;
int j;
for (j=0; j<lumFilterSize; j++)
val += lumSrc[j][i] * lumFilter[j];
@@ -390,8 +407,8 @@ static void yuv2yuvX_c(SwsContext *c, const int16_t *lumFilter,
if (uDest)
for (i=0; i<chrDstW; i++) {
- int u = chrDither[i&7] << 12;
- int v = chrDither[(i+3)&7] << 12;
+ int u = chrDither[i & 7] << 12;
+ int v = chrDither[(i + 3) & 7] << 12;
int j;
for (j=0; j<chrFilterSize; j++) {
u += chrUSrc[j][i] * chrFilter[j];
@@ -404,7 +421,7 @@ static void yuv2yuvX_c(SwsContext *c, const int16_t *lumFilter,
if (CONFIG_SWSCALE_ALPHA && aDest)
for (i=0; i<dstW; i++) {
- int val = lumDither[i&7] << 12;
+ int val = lumDither[i & 7] << 12;
int j;
for (j=0; j<lumFilterSize; j++)
val += alpSrc[j][i] * lumFilter[j];
@@ -416,29 +433,29 @@ static void yuv2yuvX_c(SwsContext *c, const int16_t *lumFilter,
static void yuv2yuv1_c(SwsContext *c, const int16_t *lumSrc,
const int16_t *chrUSrc, const int16_t *chrVSrc,
const int16_t *alpSrc,
- uint8_t *dest[4], int dstW, int chrDstW,
- const uint8_t *lumDither, const uint8_t *chrDither)
+ uint8_t *dest[4], int dstW, int chrDstW)
{
uint8_t *yDest = dest[0], *uDest = dest[1], *vDest = dest[2],
*aDest = CONFIG_SWSCALE_ALPHA ? dest[3] : NULL;
int i;
+ const uint8_t *lumDither = c->lumDither8, *chrDither = c->chrDither8;
for (i=0; i<dstW; i++) {
- int val= (lumSrc[i]+lumDither[i&7])>>7;
+ int val = (lumSrc[i]+ lumDither[i & 7]) >> 7;
yDest[i]= av_clip_uint8(val);
}
if (uDest)
for (i=0; i<chrDstW; i++) {
- int u=(chrUSrc[i]+chrDither[i&7])>>7;
- int v=(chrVSrc[i]+chrDither[(i+3)&7])>>7;
+ int u = (chrUSrc[i] + chrDither[i & 7]) >> 7;
+ int v = (chrVSrc[i] + chrDither[(i + 3) & 7]) >> 7;
uDest[i]= av_clip_uint8(u);
vDest[i]= av_clip_uint8(v);
}
if (CONFIG_SWSCALE_ALPHA && aDest)
for (i=0; i<dstW; i++) {
- int val= (alpSrc[i]+lumDither[i&7])>>7;
+ int val = (alpSrc[i] + lumDither[i & 7]) >> 7;
aDest[i]= av_clip_uint8(val);
}
}
@@ -448,16 +465,16 @@ static void yuv2nv12X_c(SwsContext *c, const int16_t *lumFilter,
const int16_t *chrFilter, const int16_t **chrUSrc,
const int16_t **chrVSrc, int chrFilterSize,
const int16_t **alpSrc, uint8_t *dest[4],
- int dstW, int chrDstW,
- const uint8_t *lumDither, const uint8_t *chrDither)
+ int dstW, int chrDstW)
{
uint8_t *yDest = dest[0], *uDest = dest[1];
enum PixelFormat dstFormat = c->dstFormat;
+ const uint8_t *lumDither = c->lumDither8, *chrDither = c->chrDither8;
//FIXME Optimize (just quickly written not optimized..)
int i;
for (i=0; i<dstW; i++) {
- int val = lumDither[i&7]<<12;
+ int val = lumDither[i & 7] << 12;
int j;
for (j=0; j<lumFilterSize; j++)
val += lumSrc[j][i] * lumFilter[j];
@@ -470,8 +487,8 @@ static void yuv2nv12X_c(SwsContext *c, const int16_t *lumFilter,
if (dstFormat == PIX_FMT_NV12)
for (i=0; i<chrDstW; i++) {
- int u = chrDither[i&7]<<12;
- int v = chrDither[(i+3)&7]<<12;
+ int u = chrDither[i & 7] << 12;
+ int v = chrDither[(i + 3) & 7] << 12;
int j;
for (j=0; j<chrFilterSize; j++) {
u += chrUSrc[j][i] * chrFilter[j];
@@ -483,8 +500,8 @@ static void yuv2nv12X_c(SwsContext *c, const int16_t *lumFilter,
}
else
for (i=0; i<chrDstW; i++) {
- int u = chrDither[i&7]<<12;
- int v = chrDither[(i+3)&7]<<12;
+ int u = chrDither[i & 7] << 12;
+ int v = chrDither[(i + 3) & 7] << 12;
int j;
for (j=0; j<chrFilterSize; j++) {
u += chrUSrc[j][i] * chrFilter[j];
@@ -505,109 +522,121 @@ static void yuv2nv12X_c(SwsContext *c, const int16_t *lumFilter,
static av_always_inline void
yuv2gray16_X_c_template(SwsContext *c, const int16_t *lumFilter,
- const int16_t **lumSrc, int lumFilterSize,
- const int16_t *chrFilter, const int16_t **chrUSrc,
- const int16_t **chrVSrc, int chrFilterSize,
- const int16_t **alpSrc, uint8_t *dest, int dstW,
+ const int32_t **lumSrc, int lumFilterSize,
+ const int16_t *chrFilter, const int32_t **chrUSrc,
+ const int32_t **chrVSrc, int chrFilterSize,
+ const int32_t **alpSrc, uint16_t *dest, int dstW,
int y, enum PixelFormat target)
{
int i;
for (i = 0; i < (dstW >> 1); i++) {
int j;
- int Y1 = 1 << 18;
- int Y2 = 1 << 18;
- const int i2 = 2 * i;
+ int Y1 = 1 << 14;
+ int Y2 = 1 << 14;
for (j = 0; j < lumFilterSize; j++) {
- Y1 += lumSrc[j][i2] * lumFilter[j];
- Y2 += lumSrc[j][i2+1] * lumFilter[j];
+ Y1 += lumSrc[j][i * 2] * lumFilter[j];
+ Y2 += lumSrc[j][i * 2 + 1] * lumFilter[j];
}
- Y1 >>= 11;
- Y2 >>= 11;
+ Y1 >>= 15;
+ Y2 >>= 15;
if ((Y1 | Y2) & 0x10000) {
Y1 = av_clip_uint16(Y1);
Y2 = av_clip_uint16(Y2);
}
- output_pixel(&dest[2 * i2 + 0], Y1);
- output_pixel(&dest[2 * i2 + 2], Y2);
+ output_pixel(&dest[i * 2 + 0], Y1);
+ output_pixel(&dest[i * 2 + 1], Y2);
}
}
static av_always_inline void
-yuv2gray16_2_c_template(SwsContext *c, const int16_t *buf[2],
- const int16_t *ubuf[2], const int16_t *vbuf[2],
- const int16_t *abuf[2], uint8_t *dest, int dstW,
+yuv2gray16_2_c_template(SwsContext *c, const int32_t *buf[2],
+ const int32_t *ubuf[2], const int32_t *vbuf[2],
+ const int32_t *abuf[2], uint16_t *dest, int dstW,
int yalpha, int uvalpha, int y,
enum PixelFormat target)
{
int yalpha1 = 4095 - yalpha;
int i;
- const int16_t *buf0 = buf[0], *buf1 = buf[1];
+ const int32_t *buf0 = buf[0], *buf1 = buf[1];
for (i = 0; i < (dstW >> 1); i++) {
- const int i2 = 2 * i;
- int Y1 = (buf0[i2 ] * yalpha1 + buf1[i2 ] * yalpha) >> 11;
- int Y2 = (buf0[i2+1] * yalpha1 + buf1[i2+1] * yalpha) >> 11;
+ int Y1 = (buf0[i * 2 ] * yalpha1 + buf1[i * 2 ] * yalpha) >> 15;
+ int Y2 = (buf0[i * 2 + 1] * yalpha1 + buf1[i * 2 + 1] * yalpha) >> 15;
- output_pixel(&dest[2 * i2 + 0], Y1);
- output_pixel(&dest[2 * i2 + 2], Y2);
+ output_pixel(&dest[i * 2 + 0], Y1);
+ output_pixel(&dest[i * 2 + 1], Y2);
}
}
static av_always_inline void
-yuv2gray16_1_c_template(SwsContext *c, const int16_t *buf0,
- const int16_t *ubuf[2], const int16_t *vbuf[2],
- const int16_t *abuf0, uint8_t *dest, int dstW,
+yuv2gray16_1_c_template(SwsContext *c, const int32_t *buf0,
+ const int32_t *ubuf[2], const int32_t *vbuf[2],
+ const int32_t *abuf0, uint16_t *dest, int dstW,
int uvalpha, int y, enum PixelFormat target)
{
int i;
for (i = 0; i < (dstW >> 1); i++) {
- const int i2 = 2 * i;
- int Y1 = buf0[i2 ] << 1;
- int Y2 = buf0[i2+1] << 1;
+ int Y1 = (buf0[i * 2 ]+4)>>3;
+ int Y2 = (buf0[i * 2 + 1]+4)>>3;
- output_pixel(&dest[2 * i2 + 0], Y1);
- output_pixel(&dest[2 * i2 + 2], Y2);
+ output_pixel(&dest[i * 2 + 0], Y1);
+ output_pixel(&dest[i * 2 + 1], Y2);
}
}
#undef output_pixel
-#define YUV2PACKEDWRAPPER(name, base, ext, fmt) \
+#define YUV2PACKED16WRAPPER(name, base, ext, fmt) \
static void name ## ext ## _X_c(SwsContext *c, const int16_t *lumFilter, \
- const int16_t **lumSrc, int lumFilterSize, \
- const int16_t *chrFilter, const int16_t **chrUSrc, \
- const int16_t **chrVSrc, int chrFilterSize, \
- const int16_t **alpSrc, uint8_t *dest, int dstW, \
+ const int16_t **_lumSrc, int lumFilterSize, \
+ const int16_t *chrFilter, const int16_t **_chrUSrc, \
+ const int16_t **_chrVSrc, int chrFilterSize, \
+ const int16_t **_alpSrc, uint8_t *_dest, int dstW, \
int y) \
{ \
+ const int32_t **lumSrc = (const int32_t **) _lumSrc, \
+ **chrUSrc = (const int32_t **) _chrUSrc, \
+ **chrVSrc = (const int32_t **) _chrVSrc, \
+ **alpSrc = (const int32_t **) _alpSrc; \
+ uint16_t *dest = (uint16_t *) _dest; \
name ## base ## _X_c_template(c, lumFilter, lumSrc, lumFilterSize, \
chrFilter, chrUSrc, chrVSrc, chrFilterSize, \
alpSrc, dest, dstW, y, fmt); \
} \
\
-static void name ## ext ## _2_c(SwsContext *c, const int16_t *buf[2], \
- const int16_t *ubuf[2], const int16_t *vbuf[2], \
- const int16_t *abuf[2], uint8_t *dest, int dstW, \
+static void name ## ext ## _2_c(SwsContext *c, const int16_t *_buf[2], \
+ const int16_t *_ubuf[2], const int16_t *_vbuf[2], \
+ const int16_t *_abuf[2], uint8_t *_dest, int dstW, \
int yalpha, int uvalpha, int y) \
{ \
+ const int32_t **buf = (const int32_t **) _buf, \
+ **ubuf = (const int32_t **) _ubuf, \
+ **vbuf = (const int32_t **) _vbuf, \
+ **abuf = (const int32_t **) _abuf; \
+ uint16_t *dest = (uint16_t *) _dest; \
name ## base ## _2_c_template(c, buf, ubuf, vbuf, abuf, \
dest, dstW, yalpha, uvalpha, y, fmt); \
} \
\
-static void name ## ext ## _1_c(SwsContext *c, const int16_t *buf0, \
- const int16_t *ubuf[2], const int16_t *vbuf[2], \
- const int16_t *abuf0, uint8_t *dest, int dstW, \
+static void name ## ext ## _1_c(SwsContext *c, const int16_t *_buf0, \
+ const int16_t *_ubuf[2], const int16_t *_vbuf[2], \
+ const int16_t *_abuf0, uint8_t *_dest, int dstW, \
int uvalpha, int y) \
{ \
+ const int32_t *buf0 = (const int32_t *) _buf0, \
+ **ubuf = (const int32_t **) _ubuf, \
+ **vbuf = (const int32_t **) _vbuf, \
+ *abuf0 = (const int32_t *) _abuf0; \
+ uint16_t *dest = (uint16_t *) _dest; \
name ## base ## _1_c_template(c, buf0, ubuf, vbuf, abuf0, dest, \
dstW, uvalpha, y, fmt); \
}
-YUV2PACKEDWRAPPER(yuv2gray16,, LE, PIX_FMT_GRAY16LE);
-YUV2PACKEDWRAPPER(yuv2gray16,, BE, PIX_FMT_GRAY16BE);
+YUV2PACKED16WRAPPER(yuv2gray16,, LE, PIX_FMT_GRAY16LE);
+YUV2PACKED16WRAPPER(yuv2gray16,, BE, PIX_FMT_GRAY16BE);
#define output_pixel(pos, acc) \
if (target == PIX_FMT_MONOBLACK) { \
@@ -703,6 +732,38 @@ yuv2mono_1_c_template(SwsContext *c, const int16_t *buf0,
#undef output_pixel
+#define YUV2PACKEDWRAPPER(name, base, ext, fmt) \
+static void name ## ext ## _X_c(SwsContext *c, const int16_t *lumFilter, \
+ const int16_t **lumSrc, int lumFilterSize, \
+ const int16_t *chrFilter, const int16_t **chrUSrc, \
+ const int16_t **chrVSrc, int chrFilterSize, \
+ const int16_t **alpSrc, uint8_t *dest, int dstW, \
+ int y) \
+{ \
+ name ## base ## _X_c_template(c, lumFilter, lumSrc, lumFilterSize, \
+ chrFilter, chrUSrc, chrVSrc, chrFilterSize, \
+ alpSrc, dest, dstW, y, fmt); \
+} \
+ \
+static void name ## ext ## _2_c(SwsContext *c, const int16_t *buf[2], \
+ const int16_t *ubuf[2], const int16_t *vbuf[2], \
+ const int16_t *abuf[2], uint8_t *dest, int dstW, \
+ int yalpha, int uvalpha, int y) \
+{ \
+ name ## base ## _2_c_template(c, buf, ubuf, vbuf, abuf, \
+ dest, dstW, yalpha, uvalpha, y, fmt); \
+} \
+ \
+static void name ## ext ## _1_c(SwsContext *c, const int16_t *buf0, \
+ const int16_t *ubuf[2], const int16_t *vbuf[2], \
+ const int16_t *abuf0, uint8_t *dest, int dstW, \
+ int uvalpha, int y) \
+{ \
+ name ## base ## _1_c_template(c, buf0, ubuf, vbuf, \
+ abuf0, dest, dstW, uvalpha, \
+ y, fmt); \
+}
+
YUV2PACKEDWRAPPER(yuv2mono,, white, PIX_FMT_MONOWHITE);
YUV2PACKEDWRAPPER(yuv2mono,, black, PIX_FMT_MONOBLACK);
@@ -818,26 +879,32 @@ yuv2422_1_c_template(SwsContext *c, const int16_t *buf0,
YUV2PACKEDWRAPPER(yuv2, 422, yuyv422, PIX_FMT_YUYV422);
YUV2PACKEDWRAPPER(yuv2, 422, uyvy422, PIX_FMT_UYVY422);
-#define r_b ((target == PIX_FMT_RGB48LE || target == PIX_FMT_RGB48BE) ? r : b)
-#define b_r ((target == PIX_FMT_RGB48LE || target == PIX_FMT_RGB48BE) ? b : r)
+#define R_B ((target == PIX_FMT_RGB48LE || target == PIX_FMT_RGB48BE) ? R : B)
+#define B_R ((target == PIX_FMT_RGB48LE || target == PIX_FMT_RGB48BE) ? B : R)
+#define output_pixel(pos, val) \
+ if (isBE(target)) { \
+ AV_WB16(pos, val); \
+ } else { \
+ AV_WL16(pos, val); \
+ }
static av_always_inline void
yuv2rgb48_X_c_template(SwsContext *c, const int16_t *lumFilter,
- const int16_t **lumSrc, int lumFilterSize,
- const int16_t *chrFilter, const int16_t **chrUSrc,
- const int16_t **chrVSrc, int chrFilterSize,
- const int16_t **alpSrc, uint8_t *dest, int dstW,
+ const int32_t **lumSrc, int lumFilterSize,
+ const int16_t *chrFilter, const int32_t **chrUSrc,
+ const int32_t **chrVSrc, int chrFilterSize,
+ const int32_t **alpSrc, uint16_t *dest, int dstW,
int y, enum PixelFormat target)
{
int i;
for (i = 0; i < (dstW >> 1); i++) {
int j;
- int Y1 = 1 << 18;
- int Y2 = 1 << 18;
- int U = 1 << 18;
- int V = 1 << 18;
- const uint8_t *r, *g, *b;
+ int Y1 = 0;
+ int Y2 = 0;
+ int U = -128 << 23; // 19
+ int V = -128 << 23;
+ int R, G, B;
for (j = 0; j < lumFilterSize; j++) {
Y1 += lumSrc[j][i * 2] * lumFilter[j];
@@ -847,40 +914,45 @@ yuv2rgb48_X_c_template(SwsContext *c, const int16_t *lumFilter,
U += chrUSrc[j][i] * chrFilter[j];
V += chrVSrc[j][i] * chrFilter[j];
}
- Y1 >>= 19;
- Y2 >>= 19;
- U >>= 19;
- V >>= 19;
- if ((Y1 | Y2 | U | V) & 0x100) {
- Y1 = av_clip_uint8(Y1);
- Y2 = av_clip_uint8(Y2);
- U = av_clip_uint8(U);
- V = av_clip_uint8(V);
- }
- /* FIXME fix tables so that clipping is not needed and then use _NOCLIP*/
- r = (const uint8_t *) c->table_rV[V];
- g = (const uint8_t *)(c->table_gU[U] + c->table_gV[V]);
- b = (const uint8_t *) c->table_bU[U];
+ // 8bit: 12+15=27; 16-bit: 12+19=31
+ Y1 >>= 14; // 10
+ Y2 >>= 14;
+ U >>= 14;
+ V >>= 14;
+
+ // 8bit: 27 -> 17bit, 16bit: 31 - 14 = 17bit
+ Y1 -= c->yuv2rgb_y_offset;
+ Y2 -= c->yuv2rgb_y_offset;
+ Y1 *= c->yuv2rgb_y_coeff;
+ Y2 *= c->yuv2rgb_y_coeff;
+ Y1 += 1 << 13; // 21
+ Y2 += 1 << 13;
+ // 8bit: 17 + 13bit = 30bit, 16bit: 17 + 13bit = 30bit
+
+ R = V * c->yuv2rgb_v2r_coeff;
+ G = V * c->yuv2rgb_v2g_coeff + U * c->yuv2rgb_u2g_coeff;
+ B = U * c->yuv2rgb_u2b_coeff;
- dest[ 0] = dest[ 1] = r_b[Y1];
- dest[ 2] = dest[ 3] = g[Y1];
- dest[ 4] = dest[ 5] = b_r[Y1];
- dest[ 6] = dest[ 7] = r_b[Y2];
- dest[ 8] = dest[ 9] = g[Y2];
- dest[10] = dest[11] = b_r[Y2];
- dest += 12;
+ // 8bit: 30 - 22 = 8bit, 16bit: 30bit - 14 = 16bit
+ output_pixel(&dest[0], av_clip_uintp2(R_B + Y1, 30) >> 14);
+ output_pixel(&dest[1], av_clip_uintp2( G + Y1, 30) >> 14);
+ output_pixel(&dest[2], av_clip_uintp2(B_R + Y1, 30) >> 14);
+ output_pixel(&dest[3], av_clip_uintp2(R_B + Y2, 30) >> 14);
+ output_pixel(&dest[4], av_clip_uintp2( G + Y2, 30) >> 14);
+ output_pixel(&dest[5], av_clip_uintp2(B_R + Y2, 30) >> 14);
+ dest += 6;
}
}
static av_always_inline void
-yuv2rgb48_2_c_template(SwsContext *c, const int16_t *buf[2],
- const int16_t *ubuf[2], const int16_t *vbuf[2],
- const int16_t *abuf[2], uint8_t *dest, int dstW,
+yuv2rgb48_2_c_template(SwsContext *c, const int32_t *buf[2],
+ const int32_t *ubuf[2], const int32_t *vbuf[2],
+ const int32_t *abuf[2], uint16_t *dest, int dstW,
int yalpha, int uvalpha, int y,
enum PixelFormat target)
{
- const int16_t *buf0 = buf[0], *buf1 = buf[1],
+ const int32_t *buf0 = buf[0], *buf1 = buf[1],
*ubuf0 = ubuf[0], *ubuf1 = ubuf[1],
*vbuf0 = vbuf[0], *vbuf1 = vbuf[1];
int yalpha1 = 4095 - yalpha;
@@ -888,80 +960,108 @@ yuv2rgb48_2_c_template(SwsContext *c, const int16_t *buf[2],
int i;
for (i = 0; i < (dstW >> 1); i++) {
- int Y1 = (buf0[i * 2] * yalpha1 + buf1[i * 2] * yalpha) >> 19;
- int Y2 = (buf0[i * 2 + 1] * yalpha1 + buf1[i * 2 + 1] * yalpha) >> 19;
- int U = (ubuf0[i] * uvalpha1 + ubuf1[i] * uvalpha) >> 19;
- int V = (vbuf0[i] * uvalpha1 + vbuf1[i] * uvalpha) >> 19;
- const uint8_t *r = (const uint8_t *) c->table_rV[V],
- *g = (const uint8_t *)(c->table_gU[U] + c->table_gV[V]),
- *b = (const uint8_t *) c->table_bU[U];
+ int Y1 = (buf0[i * 2] * yalpha1 + buf1[i * 2] * yalpha) >> 14;
+ int Y2 = (buf0[i * 2 + 1] * yalpha1 + buf1[i * 2 + 1] * yalpha) >> 14;
+ int U = (ubuf0[i] * uvalpha1 + ubuf1[i] * uvalpha + (-128 << 23)) >> 14;
+ int V = (vbuf0[i] * uvalpha1 + vbuf1[i] * uvalpha + (-128 << 23)) >> 14;
+ int R, G, B;
+
+ Y1 -= c->yuv2rgb_y_offset;
+ Y2 -= c->yuv2rgb_y_offset;
+ Y1 *= c->yuv2rgb_y_coeff;
+ Y2 *= c->yuv2rgb_y_coeff;
+ Y1 += 1 << 13;
+ Y2 += 1 << 13;
+
+ R = V * c->yuv2rgb_v2r_coeff;
+ G = V * c->yuv2rgb_v2g_coeff + U * c->yuv2rgb_u2g_coeff;
+ B = U * c->yuv2rgb_u2b_coeff;
- dest[ 0] = dest[ 1] = r_b[Y1];
- dest[ 2] = dest[ 3] = g[Y1];
- dest[ 4] = dest[ 5] = b_r[Y1];
- dest[ 6] = dest[ 7] = r_b[Y2];
- dest[ 8] = dest[ 9] = g[Y2];
- dest[10] = dest[11] = b_r[Y2];
- dest += 12;
+ output_pixel(&dest[0], av_clip_uintp2(R_B + Y1, 30) >> 14);
+ output_pixel(&dest[1], av_clip_uintp2( G + Y1, 30) >> 14);
+ output_pixel(&dest[2], av_clip_uintp2(B_R + Y1, 30) >> 14);
+ output_pixel(&dest[3], av_clip_uintp2(R_B + Y2, 30) >> 14);
+ output_pixel(&dest[4], av_clip_uintp2( G + Y2, 30) >> 14);
+ output_pixel(&dest[5], av_clip_uintp2(B_R + Y2, 30) >> 14);
+ dest += 6;
}
}
static av_always_inline void
-yuv2rgb48_1_c_template(SwsContext *c, const int16_t *buf0,
- const int16_t *ubuf[2], const int16_t *vbuf[2],
- const int16_t *abuf0, uint8_t *dest, int dstW,
+yuv2rgb48_1_c_template(SwsContext *c, const int32_t *buf0,
+ const int32_t *ubuf[2], const int32_t *vbuf[2],
+ const int32_t *abuf0, uint16_t *dest, int dstW,
int uvalpha, int y, enum PixelFormat target)
{
- const int16_t *ubuf0 = ubuf[0], *ubuf1 = ubuf[1],
+ const int32_t *ubuf0 = ubuf[0], *ubuf1 = ubuf[1],
*vbuf0 = vbuf[0], *vbuf1 = vbuf[1];
int i;
if (uvalpha < 2048) {
for (i = 0; i < (dstW >> 1); i++) {
- int Y1 = buf0[i * 2] >> 7;
- int Y2 = buf0[i * 2 + 1] >> 7;
- int U = ubuf1[i] >> 7;
- int V = vbuf1[i] >> 7;
- const uint8_t *r = (const uint8_t *) c->table_rV[V],
- *g = (const uint8_t *)(c->table_gU[U] + c->table_gV[V]),
- *b = (const uint8_t *) c->table_bU[U];
-
- dest[ 0] = dest[ 1] = r_b[Y1];
- dest[ 2] = dest[ 3] = g[Y1];
- dest[ 4] = dest[ 5] = b_r[Y1];
- dest[ 6] = dest[ 7] = r_b[Y2];
- dest[ 8] = dest[ 9] = g[Y2];
- dest[10] = dest[11] = b_r[Y2];
- dest += 12;
+ int Y1 = (buf0[i * 2] ) >> 2;
+ int Y2 = (buf0[i * 2 + 1]) >> 2;
+ int U = (ubuf0[i] + (-128 << 11)) >> 2;
+ int V = (vbuf0[i] + (-128 << 11)) >> 2;
+ int R, G, B;
+
+ Y1 -= c->yuv2rgb_y_offset;
+ Y2 -= c->yuv2rgb_y_offset;
+ Y1 *= c->yuv2rgb_y_coeff;
+ Y2 *= c->yuv2rgb_y_coeff;
+ Y1 += 1 << 13;
+ Y2 += 1 << 13;
+
+ R = V * c->yuv2rgb_v2r_coeff;
+ G = V * c->yuv2rgb_v2g_coeff + U * c->yuv2rgb_u2g_coeff;
+ B = U * c->yuv2rgb_u2b_coeff;
+
+ output_pixel(&dest[0], av_clip_uintp2(R_B + Y1, 30) >> 14);
+ output_pixel(&dest[1], av_clip_uintp2( G + Y1, 30) >> 14);
+ output_pixel(&dest[2], av_clip_uintp2(B_R + Y1, 30) >> 14);
+ output_pixel(&dest[3], av_clip_uintp2(R_B + Y2, 30) >> 14);
+ output_pixel(&dest[4], av_clip_uintp2( G + Y2, 30) >> 14);
+ output_pixel(&dest[5], av_clip_uintp2(B_R + Y2, 30) >> 14);
+ dest += 6;
}
} else {
for (i = 0; i < (dstW >> 1); i++) {
- int Y1 = buf0[i * 2] >> 7;
- int Y2 = buf0[i * 2 + 1] >> 7;
- int U = (ubuf0[i] + ubuf1[i]) >> 8;
- int V = (vbuf0[i] + vbuf1[i]) >> 8;
- const uint8_t *r = (const uint8_t *) c->table_rV[V],
- *g = (const uint8_t *)(c->table_gU[U] + c->table_gV[V]),
- *b = (const uint8_t *) c->table_bU[U];
-
- dest[ 0] = dest[ 1] = r_b[Y1];
- dest[ 2] = dest[ 3] = g[Y1];
- dest[ 4] = dest[ 5] = b_r[Y1];
- dest[ 6] = dest[ 7] = r_b[Y2];
- dest[ 8] = dest[ 9] = g[Y2];
- dest[10] = dest[11] = b_r[Y2];
- dest += 12;
+ int Y1 = (buf0[i * 2] ) >> 2;
+ int Y2 = (buf0[i * 2 + 1]) >> 2;
+ int U = (ubuf0[i] + ubuf1[i] + (-128 << 12)) >> 3;
+ int V = (vbuf0[i] + vbuf1[i] + (-128 << 12)) >> 3;
+ int R, G, B;
+
+ Y1 -= c->yuv2rgb_y_offset;
+ Y2 -= c->yuv2rgb_y_offset;
+ Y1 *= c->yuv2rgb_y_coeff;
+ Y2 *= c->yuv2rgb_y_coeff;
+ Y1 += 1 << 13;
+ Y2 += 1 << 13;
+
+ R = V * c->yuv2rgb_v2r_coeff;
+ G = V * c->yuv2rgb_v2g_coeff + U * c->yuv2rgb_u2g_coeff;
+ B = U * c->yuv2rgb_u2b_coeff;
+
+ output_pixel(&dest[0], av_clip_uintp2(R_B + Y1, 30) >> 14);
+ output_pixel(&dest[1], av_clip_uintp2( G + Y1, 30) >> 14);
+ output_pixel(&dest[2], av_clip_uintp2(B_R + Y1, 30) >> 14);
+ output_pixel(&dest[3], av_clip_uintp2(R_B + Y2, 30) >> 14);
+ output_pixel(&dest[4], av_clip_uintp2( G + Y2, 30) >> 14);
+ output_pixel(&dest[5], av_clip_uintp2(B_R + Y2, 30) >> 14);
+ dest += 6;
}
}
}
+#undef output_pixel
#undef r_b
#undef b_r
-YUV2PACKEDWRAPPER(yuv2, rgb48, rgb48be, PIX_FMT_RGB48BE);
-//YUV2PACKEDWRAPPER(yuv2, rgb48, rgb48le, PIX_FMT_RGB48LE);
-YUV2PACKEDWRAPPER(yuv2, rgb48, bgr48be, PIX_FMT_BGR48BE);
-//YUV2PACKEDWRAPPER(yuv2, rgb48, bgr48le, PIX_FMT_BGR48LE);
+YUV2PACKED16WRAPPER(yuv2, rgb48, rgb48be, PIX_FMT_RGB48BE);
+YUV2PACKED16WRAPPER(yuv2, rgb48, rgb48le, PIX_FMT_RGB48LE);
+YUV2PACKED16WRAPPER(yuv2, rgb48, bgr48be, PIX_FMT_BGR48BE);
+YUV2PACKED16WRAPPER(yuv2, rgb48, bgr48le, PIX_FMT_BGR48LE);
static av_always_inline void
yuv2rgb_write(uint8_t *_dest, int i, int Y1, int Y2,
@@ -1000,6 +1100,7 @@ yuv2rgb_write(uint8_t *_dest, int i, int Y1, int Y2,
#define r_b ((target == PIX_FMT_RGB24) ? r : b)
#define b_r ((target == PIX_FMT_RGB24) ? b : r)
+
dest[i * 6 + 0] = r_b[Y1];
dest[i * 6 + 1] = g[Y1];
dest[i * 6 + 2] = b_r[Y1];
@@ -1112,7 +1213,7 @@ yuv2rgb_X_c_template(SwsContext *c, const int16_t *lumFilter,
U = av_clip_uint8(U);
V = av_clip_uint8(V);
}
- if (hasAlpha) {\
+ if (hasAlpha) {
A1 = 1 << 18;
A2 = 1 << 18;
for (j = 0; j < lumFilterSize; j++) {
@@ -1147,7 +1248,8 @@ yuv2rgb_2_c_template(SwsContext *c, const int16_t *buf[2],
const int16_t *buf0 = buf[0], *buf1 = buf[1],
*ubuf0 = ubuf[0], *ubuf1 = ubuf[1],
*vbuf0 = vbuf[0], *vbuf1 = vbuf[1],
- *abuf0 = abuf[0], *abuf1 = abuf[1];
+ *abuf0 = hasAlpha ? abuf[0] : NULL,
+ *abuf1 = hasAlpha ? abuf[1] : NULL;
int yalpha1 = 4095 - yalpha;
int uvalpha1 = 4095 - uvalpha;
int i;
@@ -1404,21 +1506,21 @@ static av_always_inline void fillPlane(uint8_t* plane, int stride,
#define b ((origin == PIX_FMT_BGR48BE || origin == PIX_FMT_BGR48LE) ? r_b : b_r)
static av_always_inline void
-rgb48ToY_c_template(int16_t *dst, const uint16_t *src, int width,
+rgb48ToY_c_template(uint16_t *dst, const uint16_t *src, int width,
enum PixelFormat origin)
{
int i;
for (i = 0; i < width; i++) {
- int r_b = input_pixel(&src[i*3+0]);
- int g = input_pixel(&src[i*3+1]);
- int b_r = input_pixel(&src[i*3+2]);
+ unsigned int r_b = input_pixel(&src[i*3+0]);
+ unsigned int g = input_pixel(&src[i*3+1]);
+ unsigned int b_r = input_pixel(&src[i*3+2]);
- dst[i] = (RY*r + GY*g + BY*b + (32<<(RGB2YUV_SHIFT-1+8)) + (1<<(RGB2YUV_SHIFT-7+8))) >> (RGB2YUV_SHIFT-6+8);
+ dst[i] = (RY*r + GY*g + BY*b + (0x2001<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT;
}
}
static av_always_inline void
-rgb48ToUV_c_template(int16_t *dstU, int16_t *dstV,
+rgb48ToUV_c_template(uint16_t *dstU, uint16_t *dstV,
const uint16_t *src1, const uint16_t *src2,
int width, enum PixelFormat origin)
{
@@ -1429,25 +1531,25 @@ rgb48ToUV_c_template(int16_t *dstU, int16_t *dstV,
int g = input_pixel(&src1[i*3+1]);
int b_r = input_pixel(&src1[i*3+2]);
- dstU[i] = (RU*r + GU*g + BU*b + (256<<(RGB2YUV_SHIFT-1+8)) + (1<<(RGB2YUV_SHIFT-7+8))) >> (RGB2YUV_SHIFT-6+8);
- dstV[i] = (RV*r + GV*g + BV*b + (256<<(RGB2YUV_SHIFT-1+8)) + (1<<(RGB2YUV_SHIFT-7+8))) >> (RGB2YUV_SHIFT-6+8);
+ dstU[i] = (RU*r + GU*g + BU*b + (0x10001<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT;
+ dstV[i] = (RV*r + GV*g + BV*b + (0x10001<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT;
}
}
static av_always_inline void
-rgb48ToUV_half_c_template(int16_t *dstU, int16_t *dstV,
+rgb48ToUV_half_c_template(uint16_t *dstU, uint16_t *dstV,
const uint16_t *src1, const uint16_t *src2,
int width, enum PixelFormat origin)
{
int i;
assert(src1==src2);
for (i = 0; i < width; i++) {
- int r_b = (input_pixel(&src1[6*i + 0])) + (input_pixel(&src1[6*i + 3]));
- int g = (input_pixel(&src1[6*i + 1])) + (input_pixel(&src1[6*i + 4]));
- int b_r = (input_pixel(&src1[6*i + 2])) + (input_pixel(&src1[6*i + 5]));
+ int r_b = (input_pixel(&src1[6 * i + 0]) + input_pixel(&src1[6 * i + 3]) + 1) >> 1;
+ int g = (input_pixel(&src1[6 * i + 1]) + input_pixel(&src1[6 * i + 4]) + 1) >> 1;
+ int b_r = (input_pixel(&src1[6 * i + 2]) + input_pixel(&src1[6 * i + 5]) + 1) >> 1;
- dstU[i]= (RU*r + GU*g + BU*b + (256U<<(RGB2YUV_SHIFT+8)) + (1<<(RGB2YUV_SHIFT-6+8))) >> (RGB2YUV_SHIFT-5+8);
- dstV[i]= (RV*r + GV*g + BV*b + (256U<<(RGB2YUV_SHIFT+8)) + (1<<(RGB2YUV_SHIFT-6+8))) >> (RGB2YUV_SHIFT-5+8);
+ dstU[i]= (RU*r + GU*g + BU*b + (0x10001<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT;
+ dstV[i]= (RV*r + GV*g + BV*b + (0x10001<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT;
}
}
@@ -1456,23 +1558,31 @@ rgb48ToUV_half_c_template(int16_t *dstU, int16_t *dstV,
#undef input_pixel
#define rgb48funcs(pattern, BE_LE, origin) \
-static void pattern ## 48 ## BE_LE ## ToY_c(uint8_t *dst, const uint8_t *src, \
+static void pattern ## 48 ## BE_LE ## ToY_c(uint8_t *_dst, const uint8_t *_src, \
int width, uint32_t *unused) \
{ \
+ const uint16_t *src = (const uint16_t *) _src; \
+ uint16_t *dst = (uint16_t *) _dst; \
rgb48ToY_c_template(dst, src, width, origin); \
} \
\
-static void pattern ## 48 ## BE_LE ## ToUV_c(uint8_t *dstU, uint8_t *dstV, \
- const uint8_t *src1, const uint8_t *src2, \
+static void pattern ## 48 ## BE_LE ## ToUV_c(uint8_t *_dstU, uint8_t *_dstV, \
+ const uint8_t *_src1, const uint8_t *_src2, \
int width, uint32_t *unused) \
{ \
+ const uint16_t *src1 = (const uint16_t *) _src1, \
+ *src2 = (const uint16_t *) _src2; \
+ uint16_t *dstU = (uint16_t *) _dstU, *dstV = (uint16_t *) _dstV; \
rgb48ToUV_c_template(dstU, dstV, src1, src2, width, origin); \
} \
\
-static void pattern ## 48 ## BE_LE ## ToUV_half_c(uint8_t *dstU, uint8_t *dstV, \
- const uint8_t *src1, const uint8_t *src2, \
+static void pattern ## 48 ## BE_LE ## ToUV_half_c(uint8_t *_dstU, uint8_t *_dstV, \
+ const uint8_t *_src1, const uint8_t *_src2, \
int width, uint32_t *unused) \
{ \
+ const uint16_t *src1 = (const uint16_t *) _src1, \
+ *src2 = (const uint16_t *) _src2; \
+ uint16_t *dstU = (uint16_t *) _dstU, *dstV = (uint16_t *) _dstV; \
rgb48ToUV_half_c_template(dstU, dstV, src1, src2, width, origin); \
}
@@ -1705,13 +1815,26 @@ static void yuy2ToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
assert(src1 == src2);
}
-static void LEToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
- const uint8_t *src2, int width, uint32_t *unused)
+static void bswap16Y_c(uint8_t *_dst, const uint8_t *_src, int width, uint32_t *unused)
{
int i;
+ const uint16_t *src = (const uint16_t *) _src;
+ uint16_t *dst = (uint16_t *) _dst;
for (i=0; i<width; i++) {
- dstU[i]= src1[2*i + 1];
- dstV[i]= src2[2*i + 1];
+ dst[i] = av_bswap16(src[i]);
+ }
+}
+
+static void bswap16UV_c(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *_src1,
+ const uint8_t *_src2, int width, uint32_t *unused)
+{
+ int i;
+ const uint16_t *src1 = (const uint16_t *) _src1,
+ *src2 = (const uint16_t *) _src2;
+ uint16_t *dstU = (uint16_t *) _dstU, *dstV = (uint16_t *) _dstV;
+ for (i=0; i<width; i++) {
+ dstU[i] = av_bswap16(src1[i]);
+ dstV[i] = av_bswap16(src2[i]);
}
}
@@ -1736,16 +1859,6 @@ static void uyvyToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
assert(src1 == src2);
}
-static void BEToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
- const uint8_t *src2, int width, uint32_t *unused)
-{
- int i;
- for (i=0; i<width; i++) {
- dstU[i]= src1[2*i];
- dstV[i]= src2[2*i];
- }
-}
-
static av_always_inline void nvXXtoUV_c(uint8_t *dst1, uint8_t *dst2,
const uint8_t *src, int width)
{
@@ -1858,8 +1971,34 @@ static void rgb24ToUV_half_c(int16_t *dstU, int16_t *dstV, const uint8_t *src1,
}
}
+static void hScale16_c(SwsContext *c, int16_t *_dst, int dstW, const uint8_t *_src,
+ const int16_t *filter,
+ const int16_t *filterPos, int filterSize)
+{
+ int i;
+ int32_t *dst = (int32_t *) _dst;
+ const uint16_t *src = (const uint16_t *) _src;
+ int bits = av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1;
+ int sh = (bits <= 7) ? 11 : (bits - 4);
+
+ if((isAnyRGB(c->srcFormat) || c->srcFormat==PIX_FMT_PAL8) && av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1<15)
+ sh= 9;
+
+ for (i = 0; i < dstW; i++) {
+ int j;
+ int srcPos = filterPos[i];
+ int val = 0;
+
+ for (j = 0; j < filterSize; j++) {
+ val += src[srcPos + j] * filter[filterSize * i + j];
+ }
+ // filter=14 bit, input=16 bit, output=30 bit, >> 11 makes 19 bit
+ dst[i] = FFMIN(val >> sh, (1 << 19) - 1);
+ }
+}
+
// bilinear / bicubic scaling
-static void hScale_c(int16_t *dst, int dstW, const uint8_t *src,
+static void hScale_c(SwsContext *c, int16_t *dst, int dstW, const uint8_t *src,
const int16_t *filter, const int16_t *filterPos,
int filterSize)
{
@@ -1877,7 +2016,7 @@ static void hScale_c(int16_t *dst, int dstW, const uint8_t *src,
}
}
-static inline void hScale16_c(int16_t *dst, int dstW, const uint16_t *src, int srcW, int xInc,
+static inline void hScale16N_c(int16_t *dst, int dstW, const uint16_t *src, int srcW, int xInc,
const int16_t *filter, const int16_t *filterPos, long filterSize, int shift)
{
int i, j;
@@ -1892,7 +2031,7 @@ static inline void hScale16_c(int16_t *dst, int dstW, const uint16_t *src, int s
}
}
-static inline void hScale16X_c(int16_t *dst, int dstW, const uint16_t *src, int srcW, int xInc,
+static inline void hScale16NX_c(int16_t *dst, int dstW, const uint16_t *src, int srcW, int xInc,
const int16_t *filter, const int16_t *filterPos, long filterSize, int shift)
{
int i, j;
@@ -1937,6 +2076,41 @@ static void lumRangeFromJpeg_c(int16_t *dst, int width)
dst[i] = (dst[i]*14071 + 33561947)>>14;
}
+static void chrRangeToJpeg16_c(int16_t *_dstU, int16_t *_dstV, int width)
+{
+ int i;
+ int32_t *dstU = (int32_t *) _dstU;
+ int32_t *dstV = (int32_t *) _dstV;
+ for (i = 0; i < width; i++) {
+ dstU[i] = (FFMIN(dstU[i],30775<<4)*4663 - (9289992<<4))>>12; //-264
+ dstV[i] = (FFMIN(dstV[i],30775<<4)*4663 - (9289992<<4))>>12; //-264
+ }
+}
+static void chrRangeFromJpeg16_c(int16_t *_dstU, int16_t *_dstV, int width)
+{
+ int i;
+ int32_t *dstU = (int32_t *) _dstU;
+ int32_t *dstV = (int32_t *) _dstV;
+ for (i = 0; i < width; i++) {
+ dstU[i] = (dstU[i]*1799 + (4081085<<4))>>11; //1469
+ dstV[i] = (dstV[i]*1799 + (4081085<<4))>>11; //1469
+ }
+}
+static void lumRangeToJpeg16_c(int16_t *_dst, int width)
+{
+ int i;
+ int32_t *dst = (int32_t *) _dst;
+ for (i = 0; i < width; i++)
+ dst[i] = (FFMIN(dst[i],30189<<4)*4769 - (39057361<<2))>>12;
+}
+static void lumRangeFromJpeg16_c(int16_t *_dst, int width)
+{
+ int i;
+ int32_t *dst = (int32_t *) _dst;
+ for (i = 0; i < width; i++)
+ dst[i] = (dst[i]*(14071/4) + (33561947<<4)/4)>>12;
+}
+
static void hyscale_fast_c(SwsContext *c, int16_t *dst, int dstWidth,
const uint8_t *src, int srcW, int xInc)
{
@@ -1952,8 +2126,25 @@ static void hyscale_fast_c(SwsContext *c, int16_t *dst, int dstWidth,
dst[i] = src[srcW-1]*128;
}
+static void scale8To16Rv_c(uint16_t *_dst, const uint8_t *src, int len)
+{
+ int i;
+ uint8_t *dst = (uint8_t *) _dst;
+ for (i = len - 1; i >= 0; i--) {
+ dst[i * 2] = dst[i * 2 + 1] = src[i];
+ }
+}
+
+static void scale19To15Fw_c(int16_t *dst, const int32_t *src, int len)
+{
+ int i;
+ for (i = 0; i < len; i++) {
+ dst[i] = src[i] >> 4;
+ }
+}
+
// *** horizontal scale Y line to temp buffer
-static av_always_inline void hyscale(SwsContext *c, uint16_t *dst, int dstWidth,
+static av_always_inline void hyscale(SwsContext *c, int16_t *dst, int dstWidth,
const uint8_t *src, int srcW, int xInc,
const int16_t *hLumFilter,
const int16_t *hLumFilterPos, int hLumFilterSize,
@@ -1968,17 +2159,26 @@ static av_always_inline void hyscale(SwsContext *c, uint16_t *dst, int dstWidth,
src= formatConvBuffer;
}
+ if (av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1 < 8 && c->scalingBpp == 16 && !isAnyRGB(c->srcFormat)) {
+ c->scale8To16Rv((uint16_t *) formatConvBuffer, src, srcW);
+ src = formatConvBuffer;
+ }
+
if (c->hScale16) {
int shift= isAnyRGB(c->srcFormat) || c->srcFormat==PIX_FMT_PAL8 ? 13 : av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1;
c->hScale16(dst, dstWidth, (const uint16_t*)src, srcW, xInc, hLumFilter, hLumFilterPos, hLumFilterSize, shift);
} else if (!c->hyscale_fast) {
- c->hScale(dst, dstWidth, src, hLumFilter, hLumFilterPos, hLumFilterSize);
+ c->hScale(c, dst, dstWidth, src, hLumFilter, hLumFilterPos, hLumFilterSize);
} else { // fast bilinear upscale / crap downscale
c->hyscale_fast(c, dst, dstWidth, src, srcW, xInc);
}
if (convertRange)
convertRange(dst, dstWidth);
+
+ if (av_pix_fmt_descriptors[c->dstFormat].comp[0].depth_minus1 < 15 && c->scalingBpp == 16) {
+ c->scale19To15Fw(dst, (int32_t *) dst, dstWidth);
+ }
}
static void hcscale_fast_c(SwsContext *c, int16_t *dst1, int16_t *dst2,
@@ -2000,7 +2200,7 @@ static void hcscale_fast_c(SwsContext *c, int16_t *dst1, int16_t *dst2,
}
}
-static av_always_inline void hcscale(SwsContext *c, uint16_t *dst1, uint16_t *dst2, int dstWidth,
+static av_always_inline void hcscale(SwsContext *c, int16_t *dst1, int16_t *dst2, int dstWidth,
const uint8_t *src1, const uint8_t *src2,
int srcW, int xInc, const int16_t *hChrFilter,
const int16_t *hChrFilterPos, int hChrFilterSize,
@@ -2013,19 +2213,32 @@ static av_always_inline void hcscale(SwsContext *c, uint16_t *dst1, uint16_t *ds
src2= buf2;
}
+ if (av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1 < 8 && c->scalingBpp == 16 && !isAnyRGB(c->srcFormat)) {
+ uint8_t *buf2 = (formatConvBuffer + FFALIGN(srcW * 2+78, 16));
+ c->scale8To16Rv((uint16_t *) formatConvBuffer, src1, srcW);
+ c->scale8To16Rv((uint16_t *) buf2, src2, srcW);
+ src1 = formatConvBuffer;
+ src2 = buf2;
+ }
+
if (c->hScale16) {
int shift= isAnyRGB(c->srcFormat) || c->srcFormat==PIX_FMT_PAL8 ? 13 : av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1;
c->hScale16(dst1, dstWidth, (const uint16_t*)src1, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize, shift);
c->hScale16(dst2, dstWidth, (const uint16_t*)src2, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize, shift);
} else if (!c->hcscale_fast) {
- c->hScale(dst1, dstWidth, src1, hChrFilter, hChrFilterPos, hChrFilterSize);
- c->hScale(dst2, dstWidth, src2, hChrFilter, hChrFilterPos, hChrFilterSize);
+ c->hScale(c, dst1, dstWidth, src1, hChrFilter, hChrFilterPos, hChrFilterSize);
+ c->hScale(c, dst2, dstWidth, src2, hChrFilter, hChrFilterPos, hChrFilterSize);
} else { // fast bilinear upscale / crap downscale
c->hcscale_fast(c, dst1, dst2, dstWidth, src1, src2, srcW, xInc);
}
if (c->chrConvertRange)
c->chrConvertRange(dst1, dst2, dstWidth);
+
+ if (av_pix_fmt_descriptors[c->dstFormat].comp[0].depth_minus1 < 15 && c->scalingBpp == 16) {
+ c->scale19To15Fw(dst1, (int32_t *) dst1, dstWidth);
+ c->scale19To15Fw(dst2, (int32_t *) dst2, dstWidth);
+ }
}
static av_always_inline void
@@ -2151,20 +2364,20 @@ find_c_packed_planar_out_funcs(SwsContext *c,
*yuv2packedX = yuv2uyvy422_X_c;
break;
case PIX_FMT_RGB48LE:
- //*yuv2packed1 = yuv2rgb48le_1_c;
- //*yuv2packed2 = yuv2rgb48le_2_c;
- //*yuv2packedX = yuv2rgb48le_X_c;
- //break;
+ *yuv2packed1 = yuv2rgb48le_1_c;
+ *yuv2packed2 = yuv2rgb48le_2_c;
+ *yuv2packedX = yuv2rgb48le_X_c;
+ break;
case PIX_FMT_RGB48BE:
*yuv2packed1 = yuv2rgb48be_1_c;
*yuv2packed2 = yuv2rgb48be_2_c;
*yuv2packedX = yuv2rgb48be_X_c;
break;
case PIX_FMT_BGR48LE:
- //*yuv2packed1 = yuv2bgr48le_1_c;
- //*yuv2packed2 = yuv2bgr48le_2_c;
- //*yuv2packedX = yuv2bgr48le_X_c;
- //break;
+ *yuv2packed1 = yuv2bgr48le_1_c;
+ *yuv2packed2 = yuv2bgr48le_2_c;
+ *yuv2packedX = yuv2bgr48le_X_c;
+ break;
case PIX_FMT_BGR48BE:
*yuv2packed1 = yuv2bgr48be_1_c;
*yuv2packed2 = yuv2bgr48be_2_c;
@@ -2311,6 +2524,7 @@ static int swScale(SwsContext *c, const uint8_t* src[],
const int chrSrcSliceH= -((-srcSliceH) >> c->chrSrcVSubSample);
int lastDstY;
uint32_t *pal=c->pal_yuv;
+
int should_dither= isNBPS(c->srcFormat) || is16BPS(c->srcFormat);
yuv2planar1_fn yuv2yuv1 = c->yuv2yuv1;
yuv2planarX_fn yuv2yuvX = c->yuv2yuvX;
@@ -2366,6 +2580,9 @@ static int swScale(SwsContext *c, const uint8_t* src[],
lastInChrBuf= -1;
}
+ if (!should_dither) {
+ c->chrDither8 = c->lumDither8 = ff_sws_pb_64;
+ }
lastDstY= dstY;
for (;dstY < dstH; dstY++) {
@@ -2376,8 +2593,6 @@ static int swScale(SwsContext *c, const uint8_t* src[],
dst[2] + dstStride[2] * chrDstY,
(CONFIG_SWSCALE_ALPHA && alpPixBuf) ? dst[3] + dstStride[3] * dstY : NULL,
};
- const uint8_t *lumDither= should_dither ? dithers[7][dstY &7] : flat64;
- const uint8_t *chrDither= should_dither ? dithers[7][chrDstY&7] : flat64;
const int firstLumSrcY= vLumFilterPos[dstY]; //First line needed as input
const int firstLumSrcY2= vLumFilterPos[FFMIN(dstY | ((1<<c->chrDstVSubSample) - 1), dstH-1)];
@@ -2457,6 +2672,10 @@ static int swScale(SwsContext *c, const uint8_t* src[],
#if HAVE_MMX
updateMMXDitherTables(c, dstY, lumBufIndex, chrBufIndex, lastInLumBuf, lastInChrBuf);
#endif
+ if (should_dither) {
+ c->chrDither8 = dither_8x8_128[chrDstY & 7];
+ c->lumDither8 = dither_8x8_128[dstY & 7];
+ }
if (dstY >= dstH-2) {
// hmm looks like we can't use MMX here without overwriting this array's tail
find_c_packed_planar_out_funcs(c, &yuv2yuv1, &yuv2yuvX,
@@ -2477,13 +2696,13 @@ static int swScale(SwsContext *c, const uint8_t* src[],
if (c->yuv2yuv1 && vLumFilterSize == 1 && vChrFilterSize == 1) { // unscaled YV12
const int16_t *alpBuf= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? alpSrcPtr[0] : NULL;
yuv2yuv1(c, lumSrcPtr[0], chrUSrcPtr[0], chrVSrcPtr[0], alpBuf,
- dest, dstW, chrDstW, lumDither, chrDither);
+ dest, dstW, chrDstW);
} else { //General YV12
yuv2yuvX(c, vLumFilter + dstY * vLumFilterSize,
lumSrcPtr, vLumFilterSize,
vChrFilter + chrDstY * vChrFilterSize,
chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
- alpSrcPtr, dest, dstW, chrDstW, lumDither, chrDither);
+ alpSrcPtr, dest, dstW, chrDstW);
}
} else {
assert(lumSrcPtr + vLumFilterSize - 1 < lumPixBuf + vLumBufSize*2);
@@ -2541,13 +2760,6 @@ static av_cold void sws_init_swScale_c(SwsContext *c)
&c->yuv2packed1, &c->yuv2packed2,
&c->yuv2packedX);
- c->hScale = hScale_c;
-
- if (c->flags & SWS_FAST_BILINEAR) {
- c->hyscale_fast = hyscale_fast_c;
- c->hcscale_fast = hcscale_fast_c;
- }
-
c->chrToYV12 = NULL;
switch(srcFormat) {
case PIX_FMT_YUYV422 : c->chrToYV12 = yuy2ToUV_c; break;
@@ -2559,24 +2771,25 @@ 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_GRAY16BE :
case PIX_FMT_YUV444P9BE:
case PIX_FMT_YUV420P9BE:
case PIX_FMT_YUV444P10BE:
case PIX_FMT_YUV422P10BE:
- case PIX_FMT_YUV420P10BE:
- case PIX_FMT_YUV420P16BE:
- case PIX_FMT_YUV422P16BE:
- case PIX_FMT_YUV444P16BE: c->hScale16= HAVE_BIGENDIAN ? hScale16_c : hScale16X_c; break;
- case PIX_FMT_GRAY16LE :
+ case PIX_FMT_YUV420P10BE: c->hScale16= HAVE_BIGENDIAN ? hScale16N_c : hScale16NX_c; break;
case PIX_FMT_YUV444P9LE:
case PIX_FMT_YUV420P9LE:
case PIX_FMT_YUV422P10LE:
case PIX_FMT_YUV420P10LE:
- case PIX_FMT_YUV444P10LE:
+ case PIX_FMT_YUV444P10LE: c->hScale16= HAVE_BIGENDIAN ? hScale16NX_c : hScale16N_c; break;
+#if HAVE_BIGENDIAN
case PIX_FMT_YUV420P16LE:
case PIX_FMT_YUV422P16LE:
- case PIX_FMT_YUV444P16LE: c->hScale16= HAVE_BIGENDIAN ? hScale16X_c : hScale16_c; break;
+ case PIX_FMT_YUV444P16LE: c->chrToYV12 = bswap16UV_c; break;
+#else
+ case PIX_FMT_YUV420P16BE:
+ case PIX_FMT_YUV422P16BE:
+ case PIX_FMT_YUV444P16BE: c->chrToYV12 = bswap16UV_c; break;
+#endif
}
if (c->chrSrcHSubSample) {
switch(srcFormat) {
@@ -2625,11 +2838,20 @@ static av_cold void sws_init_swScale_c(SwsContext *c)
c->lumToYV12 = NULL;
c->alpToYV12 = NULL;
switch (srcFormat) {
+#if HAVE_BIGENDIAN
+ case PIX_FMT_YUV420P16LE:
+ case PIX_FMT_YUV422P16LE:
+ case PIX_FMT_YUV444P16LE:
+ case PIX_FMT_GRAY16LE: c->lumToYV12 = bswap16Y_c; break;
+#else
+ case PIX_FMT_YUV420P16BE:
+ case PIX_FMT_YUV422P16BE:
+ case PIX_FMT_YUV444P16BE:
+ case PIX_FMT_GRAY16BE: c->lumToYV12 = bswap16Y_c; break;
+#endif
case PIX_FMT_YUYV422 :
- case PIX_FMT_GRAY8A :
- c->lumToYV12 = yuy2ToY_c; break;
- case PIX_FMT_UYVY422 :
- c->lumToYV12 = uyvyToY_c; break;
+ case PIX_FMT_Y400A : c->lumToYV12 = yuy2ToY_c; break;
+ case PIX_FMT_UYVY422 : c->lumToYV12 = uyvyToY_c; break;
case PIX_FMT_BGR24 : c->lumToYV12 = bgr24ToY_c; break;
case PIX_FMT_BGR565LE : c->lumToYV12 = bgr16leToY_c; break;
case PIX_FMT_BGR565BE : c->lumToYV12 = bgr16beToY_c; break;
@@ -2667,8 +2889,16 @@ static av_cold void sws_init_swScale_c(SwsContext *c)
}
}
- if(isAnyRGB(c->srcFormat) || c->srcFormat == PIX_FMT_PAL8)
- c->hScale16= hScale16_c;
+ if((isAnyRGB(c->srcFormat) && av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1<15)
+ || c->srcFormat == PIX_FMT_PAL8)
+ c->hScale16= hScale16N_c;
+
+ if (c->scalingBpp == 8) {
+ c->hScale = hScale_c;
+ if (c->flags & SWS_FAST_BILINEAR) {
+ c->hyscale_fast = hyscale_fast_c;
+ c->hcscale_fast = hcscale_fast_c;
+ }
if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) {
if (c->srcRange) {
@@ -2679,6 +2909,26 @@ static av_cold void sws_init_swScale_c(SwsContext *c)
c->chrConvertRange = chrRangeToJpeg_c;
}
}
+ } else {
+ if(c->hScale16 == hScale16NX_c && !isAnyRGB(c->srcFormat)){
+ c->chrToYV12 = bswap16UV_c;
+ c->lumToYV12 = bswap16Y_c;
+ }
+ c->hScale16 = NULL;
+ c->hScale = hScale16_c;
+ c->scale19To15Fw = scale19To15Fw_c;
+ c->scale8To16Rv = scale8To16Rv_c;
+
+ if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) {
+ if (c->srcRange) {
+ c->lumConvertRange = lumRangeFromJpeg16_c;
+ c->chrConvertRange = chrRangeFromJpeg16_c;
+ } else {
+ c->lumConvertRange = lumRangeToJpeg16_c;
+ c->chrConvertRange = chrRangeToJpeg16_c;
+ }
+ }
+ }
if (!(isGray(srcFormat) || isGray(c->dstFormat) ||
srcFormat == PIX_FMT_MONOBLACK || srcFormat == PIX_FMT_MONOWHITE))
diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h
index 73dc25d547..2ffd44d071 100644
--- a/libswscale/swscale_internal.h
+++ b/libswscale/swscale_internal.h
@@ -77,8 +77,7 @@ typedef int (*SwsFunc)(struct SwsContext *context, const uint8_t* src[],
typedef void (*yuv2planar1_fn) (struct SwsContext *c,
const int16_t *lumSrc, const int16_t *chrUSrc,
const int16_t *chrVSrc, const int16_t *alpSrc,
- uint8_t *dest[4], int dstW, int chrDstW,
- const uint8_t *lumDither, const uint8_t *chrDither);
+ uint8_t *dest[4], int dstW, int chrDstW);
/**
* Write one line of horizontally scaled Y/U/V/A to planar output
* with multi-point vertical scaling between input pixels.
@@ -101,7 +100,7 @@ typedef void (*yuv2planarX_fn) (struct SwsContext *c, const int16_t *lumFilter,
const int16_t *chrFilter, const int16_t **chrUSrc,
const int16_t **chrVSrc, int chrFilterSize,
const int16_t **alpSrc, uint8_t *dest[4],
- int dstW, int chrDstW, const uint8_t *lumDither, const uint8_t *chrDither);
+ int dstW, int chrDstW);
/**
* Write one line of horizontally scaled Y/U/V/A to packed-pixel YUV/RGB
* output without any additional vertical scaling (or point-scaling). Note
@@ -210,6 +209,7 @@ typedef struct SwsContext {
enum PixelFormat srcFormat; ///< Source pixel format.
int dstFormatBpp; ///< Number of bits per pixel of the destination pixel format.
int srcFormatBpp; ///< Number of bits per pixel of the source pixel format.
+ int scalingBpp;
int chrSrcHSubSample; ///< Binary logarithm of horizontal subsampling factor between luma/alpha and chroma planes in source image.
int chrSrcVSubSample; ///< Binary logarithm of vertical subsampling factor between luma/alpha and chroma planes in source image.
int chrDstHSubSample; ///< Binary logarithm of horizontal subsampling factor between luma/alpha and chroma planes in destination image.
@@ -324,7 +324,7 @@ typedef struct SwsContext {
#define UV_OFF "11*8+4*4*256*3+48"
#define UV_OFFx2 "11*8+4*4*256*3+56"
#define DITHER16 "11*8+4*4*256*3+64"
-#define DITHER32 "11*8+4*4*256*3+64+16"
+#define DITHER32 "11*8+4*4*256*3+80"
DECLARE_ALIGNED(8, uint64_t, redDither);
DECLARE_ALIGNED(8, uint64_t, greenDither);
@@ -352,6 +352,8 @@ typedef struct SwsContext {
uint16_t dither16[8];
uint32_t dither32[8];
+ const uint8_t *chrDither8, *lumDither8;
+
#if HAVE_ALTIVEC
vector signed short CY;
vector signed short CRV;
@@ -451,7 +453,7 @@ typedef struct SwsContext {
* (and input coefficients thus padded with zeroes)
* to simplify creating SIMD code.
*/
- void (*hScale)(int16_t *dst, int dstW, const uint8_t *src,
+ void (*hScale)(struct SwsContext *c, int16_t *dst, int dstW, const uint8_t *src,
const int16_t *filter, const int16_t *filterPos,
int filterSize);
@@ -462,6 +464,15 @@ typedef struct SwsContext {
void (*lumConvertRange)(int16_t *dst, int width); ///< Color range conversion function for luma plane if needed.
void (*chrConvertRange)(int16_t *dst1, int16_t *dst2, int width); ///< Color range conversion function for chroma planes if needed.
+ /**
+ * dst[..] = (src[..] << 8) | src[..];
+ */
+ void (*scale8To16Rv)(uint16_t *dst, const uint8_t *src, int len);
+ /**
+ * dst[..] = src[..] >> 4;
+ */
+ void (*scale19To15Fw)(int16_t *dst, const int32_t *src, int len);
+
int needs_hcscale; ///< Set if there are chroma planes to be converted.
} SwsContext;
diff --git a/libswscale/utils.c b/libswscale/utils.c
index bff9f4d3c6..62839ee8e5 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -46,6 +46,7 @@
#include "libavutil/bswap.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
+#include "libavutil/avassert.h"
unsigned swscale_version(void)
{
@@ -777,7 +778,7 @@ SwsContext *sws_alloc_context(void)
int sws_init_context(SwsContext *c, SwsFilter *srcFilter, SwsFilter *dstFilter)
{
- int i;
+ int i, j;
int usesVFilter, usesHFilter;
int unscaled;
SwsFilter dummyFilter= {NULL, NULL, NULL, NULL};
@@ -785,7 +786,7 @@ int sws_init_context(SwsContext *c, SwsFilter *srcFilter, SwsFilter *dstFilter)
int srcH= c->srcH;
int dstW= c->dstW;
int dstH= c->dstH;
- int dst_stride = FFALIGN(dstW * sizeof(int16_t)+66, 16), dst_stride_px = dst_stride >> 1;
+ int dst_stride = FFALIGN(dstW * sizeof(int16_t)+66, 16);
int flags, cpu_flags;
enum PixelFormat srcFormat= c->srcFormat;
enum PixelFormat dstFormat= c->dstFormat;
@@ -882,8 +883,14 @@ int sws_init_context(SwsContext *c, SwsFilter *srcFilter, SwsFilter *dstFilter)
}
}
+ c->scalingBpp = FFMAX(av_pix_fmt_descriptors[srcFormat].comp[0].depth_minus1,
+ av_pix_fmt_descriptors[dstFormat].comp[0].depth_minus1) >= 15 ? 16 : 8;
+
+ if (c->scalingBpp == 16)
+ dst_stride <<= 1;
+ av_assert0(c->scalingBpp<=16);
FF_ALLOC_OR_GOTO(c, c->formatConvBuffer, FFALIGN(srcW*2+78, 16) * 2, fail);
- if (HAVE_MMX2 && cpu_flags & AV_CPU_FLAG_MMX2) {
+ if (HAVE_MMX2 && cpu_flags & AV_CPU_FLAG_MMX2 && c->scalingBpp == 8) {
c->canMMX2BeUsed= (dstW >=srcW && (dstW&31)==0 && (srcW&15)==0) ? 1 : 0;
if (!c->canMMX2BeUsed && dstW >=srcW && (srcW&15)==0 && (flags&SWS_FAST_BILINEAR)) {
if (flags&SWS_PRINT_INFO)
@@ -909,7 +916,7 @@ int sws_init_context(SwsContext *c, SwsFilter *srcFilter, SwsFilter *dstFilter)
c->chrXInc+= 20;
}
//we don't use the x86 asm scaler if MMX is available
- else if (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) {
+ else if (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX && c->scalingBpp == 8) {
c->lumXInc = ((srcW-2)<<16)/(dstW-2) - 20;
c->chrXInc = ((c->chrSrcW-2)<<16)/(c->chrDstW-2) - 20;
}
@@ -1040,12 +1047,12 @@ int sws_init_context(SwsContext *c, SwsFilter *srcFilter, SwsFilter *dstFilter)
FF_ALLOCZ_OR_GOTO(c, c->lumPixBuf[i+c->vLumBufSize], dst_stride+1, fail);
c->lumPixBuf[i] = c->lumPixBuf[i+c->vLumBufSize];
}
- c->uv_off = dst_stride_px;
+ c->uv_off = dst_stride>>1;
c->uv_offx2 = dst_stride;
for (i=0; i<c->vChrBufSize; i++) {
FF_ALLOC_OR_GOTO(c, c->chrUPixBuf[i+c->vChrBufSize], dst_stride*2+1, fail);
c->chrUPixBuf[i] = c->chrUPixBuf[i+c->vChrBufSize];
- c->chrVPixBuf[i] = c->chrVPixBuf[i+c->vChrBufSize] = c->chrUPixBuf[i] + dst_stride_px;
+ c->chrVPixBuf[i] = c->chrVPixBuf[i+c->vChrBufSize] = c->chrUPixBuf[i] + (dst_stride >> 1);
}
if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
for (i=0; i<c->vLumBufSize; i++) {
@@ -1055,7 +1062,13 @@ int sws_init_context(SwsContext *c, SwsFilter *srcFilter, SwsFilter *dstFilter)
//try to avoid drawing green stuff between the right end and the stride end
for (i=0; i<c->vChrBufSize; i++)
- memset(c->chrUPixBuf[i], 64, dst_stride*2+1);
+ if(av_pix_fmt_descriptors[c->dstFormat].comp[0].depth_minus1 == 15){
+ av_assert0(c->scalingBpp == 16);
+ for(j=0; j<dst_stride/2+1; j++)
+ ((int32_t*)(c->chrUPixBuf[i]))[j] = 1<<18;
+ } else
+ for(j=0; j<dst_stride+1; j++)
+ ((int16_t*)(c->chrUPixBuf[i]))[j] = 1<<14;
assert(c->chrDstH <= dstH);
diff --git a/libswscale/x86/swscale_template.c b/libswscale/x86/swscale_template.c
index ae0d394078..87248e76fa 100644
--- a/libswscale/x86/swscale_template.c
+++ b/libswscale/x86/swscale_template.c
@@ -70,26 +70,62 @@
: "%"REG_d, "%"REG_S\
);
+#if !COMPILE_TEMPLATE_MMX2
+static av_always_inline void
+dither_8to16(SwsContext *c, const uint8_t *srcDither, int rot)
+{
+ if (rot) {
+ __asm__ volatile("pxor %%mm0, %%mm0\n\t"
+ "movq (%0), %%mm3\n\t"
+ "movq %%mm3, %%mm4\n\t"
+ "psrlq $24, %%mm3\n\t"
+ "psllq $40, %%mm4\n\t"
+ "por %%mm4, %%mm3\n\t"
+ "movq %%mm3, %%mm4\n\t"
+ "punpcklbw %%mm0, %%mm3\n\t"
+ "punpckhbw %%mm0, %%mm4\n\t"
+ "psraw $4, %%mm3\n\t"
+ "psraw $4, %%mm4\n\t"
+ "movq %%mm3, "DITHER16"+0(%1)\n\t"
+ "movq %%mm4, "DITHER16"+8(%1)\n\t"
+ :: "r"(srcDither), "r"(&c->redDither)
+ );
+ } else {
+ __asm__ volatile("pxor %%mm0, %%mm0\n\t"
+ "movq (%0), %%mm3\n\t"
+ "movq %%mm3, %%mm4\n\t"
+ "punpcklbw %%mm0, %%mm3\n\t"
+ "punpckhbw %%mm0, %%mm4\n\t"
+ "psraw $4, %%mm3\n\t"
+ "psraw $4, %%mm4\n\t"
+ "movq %%mm3, "DITHER16"+0(%1)\n\t"
+ "movq %%mm4, "DITHER16"+8(%1)\n\t"
+ :: "r"(srcDither), "r"(&c->redDither)
+ );
+ }
+}
+#endif
+
static void RENAME(yuv2yuvX)(SwsContext *c, const int16_t *lumFilter,
const int16_t **lumSrc, int lumFilterSize,
const int16_t *chrFilter, const int16_t **chrUSrc,
const int16_t **chrVSrc,
int chrFilterSize, const int16_t **alpSrc,
- uint8_t *dest[4], int dstW, int chrDstW,
- const uint8_t *lumDither, const uint8_t *chrDither)
+ uint8_t *dest[4], int dstW, int chrDstW)
{
int i;
uint8_t *yDest = dest[0], *uDest = dest[1], *vDest = dest[2],
*aDest = CONFIG_SWSCALE_ALPHA ? dest[3] : NULL;
+ const uint8_t *lumDither = c->lumDither8, *chrDither = c->chrDither8;
if (uDest) {
- x86_reg uv_off = c->uv_off;
- for(i=0; i<8; i++) c->dither16[i] = chrDither[i]>>4;
+ x86_reg uv_off = c->uv_offx2 >> 1;
+ dither_8to16(c, chrDither, 0);
YSCALEYUV2YV12X(CHR_MMX_FILTER_OFFSET, uDest, chrDstW, 0)
- for(i=0; i<8; i++) c->dither16[i] = chrDither[(i+3)&7]>>4;
+ dither_8to16(c, chrDither, 1);
YSCALEYUV2YV12X(CHR_MMX_FILTER_OFFSET, vDest - uv_off, chrDstW + uv_off, uv_off)
}
- for(i=0; i<8; i++) c->dither16[i] = lumDither[i]>>4;
+ dither_8to16(c, lumDither, 0);
if (CONFIG_SWSCALE_ALPHA && aDest) {
YSCALEYUV2YV12X(ALP_MMX_FILTER_OFFSET, aDest, dstW, 0)
}
@@ -104,10 +140,6 @@ static void RENAME(yuv2yuvX)(SwsContext *c, const int16_t *lumFilter,
"movq "DITHER32"+8(%0), %%mm5 \n\t"\
"movq "DITHER32"+16(%0), %%mm6 \n\t"\
"movq "DITHER32"+24(%0), %%mm7 \n\t"\
- "pxor %%mm4, %%mm4 \n\t"\
- "pxor %%mm5, %%mm5 \n\t"\
- "pxor %%mm6, %%mm6 \n\t"\
- "pxor %%mm7, %%mm7 \n\t"\
"mov (%%"REG_d"), %%"REG_S" \n\t"\
".p2align 4 \n\t"\
"1: \n\t"\
@@ -157,26 +189,87 @@ static void RENAME(yuv2yuvX)(SwsContext *c, const int16_t *lumFilter,
: "%"REG_a, "%"REG_d, "%"REG_S\
);
+#if !COMPILE_TEMPLATE_MMX2
+static av_always_inline void
+dither_8to32(SwsContext *c, const uint8_t *srcDither, int rot)
+{
+int i;
+if(rot) for(i=0; i<8; i++) c->dither32[i] = srcDither[(i+3)&7]<<12;
+else for(i=0; i<8; i++) c->dither32[i] = srcDither[i&7]<<12;
+return;
+
+ if (rot) {
+ __asm__ volatile("pxor %%mm0, %%mm0\n\t"
+ "movq (%0), %%mm4\n\t"
+ "movq %%mm4, %%mm5\n\t"
+ "psrlq $24, %%mm4\n\t"
+ "psllq $40, %%mm5\n\t"
+ "por %%mm5, %%mm4\n\t"
+ "movq %%mm4, %%mm6\n\t"
+ "punpcklbw %%mm0, %%mm4\n\t"
+ "punpckhbw %%mm0, %%mm6\n\t"
+ "movq %%mm4, %%mm5\n\t"
+ "movq %%mm6, %%mm7\n\t"
+ "punpcklwd %%mm0, %%mm4\n\t"
+ "punpckhwd %%mm0, %%mm5\n\t"
+ "punpcklwd %%mm0, %%mm6\n\t"
+ "punpckhwd %%mm0, %%mm7\n\t"
+ "psllw $12, %%mm4\n\t"
+ "psllw $12, %%mm5\n\t"
+ "psllw $12, %%mm6\n\t"
+ "psllw $12, %%mm7\n\t"
+ "movq %%mm4, "DITHER32"+0(%1)\n\t"
+ "movq %%mm5, "DITHER32"+8(%1)\n\t"
+ "movq %%mm6, "DITHER32"+16(%1)\n\t"
+ "movq %%mm7, "DITHER32"+24(%1)\n\t"
+ :: "r"(srcDither), "r"(&c->redDither)
+ );
+ } else {
+ __asm__ volatile("pxor %%mm0, %%mm0\n\t"
+ "movq (%0), %%mm4\n\t"
+ "movq %%mm4, %%mm6\n\t"
+ "punpcklbw %%mm0, %%mm4\n\t"
+ "punpckhbw %%mm0, %%mm6\n\t"
+ "movq %%mm4, %%mm5\n\t"
+ "movq %%mm6, %%mm7\n\t"
+ "punpcklwd %%mm0, %%mm4\n\t"
+ "punpckhwd %%mm0, %%mm5\n\t"
+ "punpcklwd %%mm0, %%mm6\n\t"
+ "punpckhwd %%mm0, %%mm7\n\t"
+ "psllw $12, %%mm4\n\t"
+ "psllw $12, %%mm5\n\t"
+ "psllw $12, %%mm6\n\t"
+ "psllw $12, %%mm7\n\t"
+ "movq %%mm4, "DITHER32"+0(%1)\n\t"
+ "movq %%mm5, "DITHER32"+8(%1)\n\t"
+ "movq %%mm6, "DITHER32"+16(%1)\n\t"
+ "movq %%mm7, "DITHER32"+24(%1)\n\t"
+ :: "r"(srcDither), "r"(&c->redDither)
+ );
+ }
+}
+#endif
+
static void RENAME(yuv2yuvX_ar)(SwsContext *c, const int16_t *lumFilter,
const int16_t **lumSrc, int lumFilterSize,
const int16_t *chrFilter, const int16_t **chrUSrc,
const int16_t **chrVSrc,
int chrFilterSize, const int16_t **alpSrc,
- uint8_t *dest[4], int dstW, int chrDstW,
- const uint8_t *lumDither, const uint8_t *chrDither)
+ uint8_t *dest[4], int dstW, int chrDstW)
{
int i;
uint8_t *yDest = dest[0], *uDest = dest[1], *vDest = dest[2],
*aDest = CONFIG_SWSCALE_ALPHA ? dest[3] : NULL;
+ const uint8_t *lumDither = c->lumDither8, *chrDither = c->chrDither8;
if (uDest) {
- x86_reg uv_off = c->uv_off;
- for(i=0; i<8; i++) c->dither32[i] = chrDither[i]<<12;
+ x86_reg uv_off = c->uv_offx2 >> 1;
+ dither_8to32(c, chrDither, 0);
YSCALEYUV2YV12X_ACCURATE(CHR_MMX_FILTER_OFFSET, uDest, chrDstW, 0)
- for(i=0; i<8; i++) c->dither32[i] = chrDither[(i+3)&7]<<12;
+ dither_8to32(c, chrDither, 1);
YSCALEYUV2YV12X_ACCURATE(CHR_MMX_FILTER_OFFSET, vDest - uv_off, chrDstW + uv_off, uv_off)
}
- for(i=0; i<8; i++) c->dither32[i] = lumDither[i]<<12;
+ dither_8to32(c, lumDither, 0);
if (CONFIG_SWSCALE_ALPHA && aDest) {
YSCALEYUV2YV12X_ACCURATE(ALP_MMX_FILTER_OFFSET, aDest, dstW, 0)
}
@@ -187,8 +280,7 @@ static void RENAME(yuv2yuvX_ar)(SwsContext *c, const int16_t *lumFilter,
static void RENAME(yuv2yuv1)(SwsContext *c, const int16_t *lumSrc,
const int16_t *chrUSrc, const int16_t *chrVSrc,
const int16_t *alpSrc,
- uint8_t *dst[4], int dstW, int chrDstW,
- const uint8_t *lumDither, const uint8_t *chrDither)
+ uint8_t *dst[4], int dstW, int chrDstW)
{
int p= 4;
const int16_t *src[4]= {
@@ -222,8 +314,7 @@ static void RENAME(yuv2yuv1)(SwsContext *c, const int16_t *lumSrc,
static void RENAME(yuv2yuv1_ar)(SwsContext *c, const int16_t *lumSrc,
const int16_t *chrUSrc, const int16_t *chrVSrc,
const int16_t *alpSrc,
- uint8_t *dst[4], int dstW, int chrDstW,
- const uint8_t *lumDither, const uint8_t *chrDither)
+ uint8_t *dst[4], int dstW, int chrDstW)
{
int p= 4;
const int16_t *src[4]= {
@@ -231,15 +322,16 @@ static void RENAME(yuv2yuv1_ar)(SwsContext *c, const int16_t *lumSrc,
chrVSrc + chrDstW, alpSrc + dstW
};
x86_reg counter[4]= { dstW, chrDstW, chrDstW, dstW };
+ const uint8_t *lumDither = c->lumDither8, *chrDither = c->chrDither8;
while (p--) {
if (dst[p]) {
int i;
- for(i=0; i<8; i++) c->dither16[i] = i<2 ? lumDither[i] : chrDither[i];
+ for(i=0; i<8; i++) c->dither16[i] = (p == 2 || p == 3) ? lumDither[i] : chrDither[i];
__asm__ volatile(
"mov %2, %%"REG_a" \n\t"
- "movq 0(%3), %%mm6 \n\t"
- "movq 8(%3), %%mm7 \n\t"
+ "movq "DITHER16"+0(%3), %%mm6 \n\t"
+ "movq "DITHER16"+8(%3), %%mm7 \n\t"
".p2align 4 \n\t" /* FIXME Unroll? */
"1: \n\t"
"movq (%0, %%"REG_a", 2), %%mm0 \n\t"
@@ -253,7 +345,7 @@ static void RENAME(yuv2yuv1_ar)(SwsContext *c, const int16_t *lumSrc,
"add $8, %%"REG_a" \n\t"
"jnc 1b \n\t"
:: "r" (src[p]), "r" (dst[p] + counter[p]),
- "g" (-counter[p]), "r"(c->dither16)
+ "g" (-counter[p]), "r"(&c->redDither)
: "%"REG_a
);
}
@@ -485,7 +577,7 @@ static void RENAME(yuv2rgb32_X_ar)(SwsContext *c, const int16_t *lumFilter,
{
x86_reg dummy=0;
x86_reg dstW_reg = dstW;
- x86_reg uv_off = c->uv_off << 1;
+ x86_reg uv_off = c->uv_offx2;
if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) {
YSCALEYUV2PACKEDX_ACCURATE
@@ -518,7 +610,7 @@ static void RENAME(yuv2rgb32_X)(SwsContext *c, const int16_t *lumFilter,
{
x86_reg dummy=0;
x86_reg dstW_reg = dstW;
- x86_reg uv_off = c->uv_off << 1;
+ x86_reg uv_off = c->uv_offx2;
if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) {
YSCALEYUV2PACKEDX
@@ -575,7 +667,7 @@ static void RENAME(yuv2rgb565_X_ar)(SwsContext *c, const int16_t *lumFilter,
{
x86_reg dummy=0;
x86_reg dstW_reg = dstW;
- x86_reg uv_off = c->uv_off << 1;
+ x86_reg uv_off = c->uv_offx2;
YSCALEYUV2PACKEDX_ACCURATE
YSCALEYUV2RGBX
@@ -599,7 +691,7 @@ static void RENAME(yuv2rgb565_X)(SwsContext *c, const int16_t *lumFilter,
{
x86_reg dummy=0;
x86_reg dstW_reg = dstW;
- x86_reg uv_off = c->uv_off << 1;
+ x86_reg uv_off = c->uv_offx2;
YSCALEYUV2PACKEDX
YSCALEYUV2RGBX
@@ -652,7 +744,7 @@ static void RENAME(yuv2rgb555_X_ar)(SwsContext *c, const int16_t *lumFilter,
{
x86_reg dummy=0;
x86_reg dstW_reg = dstW;
- x86_reg uv_off = c->uv_off << 1;
+ x86_reg uv_off = c->uv_offx2;
YSCALEYUV2PACKEDX_ACCURATE
YSCALEYUV2RGBX
@@ -676,7 +768,7 @@ static void RENAME(yuv2rgb555_X)(SwsContext *c, const int16_t *lumFilter,
{
x86_reg dummy=0;
x86_reg dstW_reg = dstW;
- x86_reg uv_off = c->uv_off << 1;
+ x86_reg uv_off = c->uv_offx2;
YSCALEYUV2PACKEDX
YSCALEYUV2RGBX
@@ -809,7 +901,7 @@ static void RENAME(yuv2bgr24_X_ar)(SwsContext *c, const int16_t *lumFilter,
{
x86_reg dummy=0;
x86_reg dstW_reg = dstW;
- x86_reg uv_off = c->uv_off << 1;
+ x86_reg uv_off = c->uv_offx2;
YSCALEYUV2PACKEDX_ACCURATE
YSCALEYUV2RGBX
@@ -833,7 +925,7 @@ static void RENAME(yuv2bgr24_X)(SwsContext *c, const int16_t *lumFilter,
{
x86_reg dummy=0;
x86_reg dstW_reg = dstW;
- x86_reg uv_off = c->uv_off << 1;
+ x86_reg uv_off = c->uv_offx2;
YSCALEYUV2PACKEDX
YSCALEYUV2RGBX
@@ -874,7 +966,7 @@ static void RENAME(yuv2yuyv422_X_ar)(SwsContext *c, const int16_t *lumFilter,
{
x86_reg dummy=0;
x86_reg dstW_reg = dstW;
- x86_reg uv_off = c->uv_off << 1;
+ x86_reg uv_off = c->uv_offx2;
YSCALEYUV2PACKEDX_ACCURATE
/* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */
@@ -895,7 +987,7 @@ static void RENAME(yuv2yuyv422_X)(SwsContext *c, const int16_t *lumFilter,
{
x86_reg dummy=0;
x86_reg dstW_reg = dstW;
- x86_reg uv_off = c->uv_off << 1;
+ x86_reg uv_off = c->uv_offx2;
YSCALEYUV2PACKEDX
/* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */
@@ -1637,32 +1729,6 @@ static void RENAME(yuy2ToUV)(uint8_t *dstU, uint8_t *dstV,
assert(src1 == src2);
}
-static void RENAME(LEToUV)(uint8_t *dstU, uint8_t *dstV,
- const uint8_t *src1, const uint8_t *src2,
- int width, uint32_t *unused)
-{
- __asm__ volatile(
- "mov %0, %%"REG_a" \n\t"
- "1: \n\t"
- "movq (%1, %%"REG_a",2), %%mm0 \n\t"
- "movq 8(%1, %%"REG_a",2), %%mm1 \n\t"
- "movq (%2, %%"REG_a",2), %%mm2 \n\t"
- "movq 8(%2, %%"REG_a",2), %%mm3 \n\t"
- "psrlw $8, %%mm0 \n\t"
- "psrlw $8, %%mm1 \n\t"
- "psrlw $8, %%mm2 \n\t"
- "psrlw $8, %%mm3 \n\t"
- "packuswb %%mm1, %%mm0 \n\t"
- "packuswb %%mm3, %%mm2 \n\t"
- "movq %%mm0, (%3, %%"REG_a") \n\t"
- "movq %%mm2, (%4, %%"REG_a") \n\t"
- "add $8, %%"REG_a" \n\t"
- " js 1b \n\t"
- : : "g" ((x86_reg)-width), "r" (src1+width*2), "r" (src2+width*2), "r" (dstU+width), "r" (dstV+width)
- : "%"REG_a
- );
-}
-
/* This is almost identical to the previous, end exists only because
* yuy2ToY/UV)(dst, src+1, ...) would have 100% unaligned accesses. */
static void RENAME(uyvyToY)(uint8_t *dst, const uint8_t *src,
@@ -1712,33 +1778,6 @@ static void RENAME(uyvyToUV)(uint8_t *dstU, uint8_t *dstV,
assert(src1 == src2);
}
-static void RENAME(BEToUV)(uint8_t *dstU, uint8_t *dstV,
- const uint8_t *src1, const uint8_t *src2,
- int width, uint32_t *unused)
-{
- __asm__ volatile(
- "movq "MANGLE(bm01010101)", %%mm4 \n\t"
- "mov %0, %%"REG_a" \n\t"
- "1: \n\t"
- "movq (%1, %%"REG_a",2), %%mm0 \n\t"
- "movq 8(%1, %%"REG_a",2), %%mm1 \n\t"
- "movq (%2, %%"REG_a",2), %%mm2 \n\t"
- "movq 8(%2, %%"REG_a",2), %%mm3 \n\t"
- "pand %%mm4, %%mm0 \n\t"
- "pand %%mm4, %%mm1 \n\t"
- "pand %%mm4, %%mm2 \n\t"
- "pand %%mm4, %%mm3 \n\t"
- "packuswb %%mm1, %%mm0 \n\t"
- "packuswb %%mm3, %%mm2 \n\t"
- "movq %%mm0, (%3, %%"REG_a") \n\t"
- "movq %%mm2, (%4, %%"REG_a") \n\t"
- "add $8, %%"REG_a" \n\t"
- " js 1b \n\t"
- : : "g" ((x86_reg)-width), "r" (src1+width*2), "r" (src2+width*2), "r" (dstU+width), "r" (dstV+width)
- : "%"REG_a
- );
-}
-
static av_always_inline void RENAME(nvXXtoUV)(uint8_t *dst1, uint8_t *dst2,
const uint8_t *src, int width)
{
@@ -1921,7 +1960,7 @@ static void RENAME(rgb24ToUV)(int16_t *dstU, int16_t *dstV,
#if !COMPILE_TEMPLATE_MMX2
// bilinear / bicubic scaling
-static void RENAME(hScale)(int16_t *dst, int dstW,
+static void RENAME(hScale)(SwsContext *c, int16_t *dst, int dstW,
const uint8_t *src, const int16_t *filter,
const int16_t *filterPos, int filterSize)
{
@@ -2433,6 +2472,7 @@ static av_cold void RENAME(sws_init_swScale)(SwsContext *c)
}
}
+ if (c->scalingBpp == 8) {
#if !COMPILE_TEMPLATE_MMX2
c->hScale = RENAME(hScale );
#endif /* !COMPILE_TEMPLATE_MMX2 */
@@ -2450,6 +2490,7 @@ static av_cold void RENAME(sws_init_swScale)(SwsContext *c)
#if COMPILE_TEMPLATE_MMX2
}
#endif /* COMPILE_TEMPLATE_MMX2 */
+ }
#if !COMPILE_TEMPLATE_MMX2
switch(srcFormat) {
@@ -2457,13 +2498,10 @@ static av_cold void RENAME(sws_init_swScale)(SwsContext *c)
case PIX_FMT_UYVY422 : c->chrToYV12 = RENAME(uyvyToUV); break;
case PIX_FMT_NV12 : c->chrToYV12 = RENAME(nv12ToUV); break;
case PIX_FMT_NV21 : c->chrToYV12 = RENAME(nv21ToUV); break;
- case PIX_FMT_GRAY16LE :
case PIX_FMT_YUV420P9LE:
case PIX_FMT_YUV422P10LE:
- case PIX_FMT_YUV420P10LE:
- case PIX_FMT_YUV420P16LE:
- case PIX_FMT_YUV422P16LE:
- case PIX_FMT_YUV444P16LE: c->hScale16= RENAME(hScale16); break;
+ case PIX_FMT_YUV420P10LE: c->hScale16= RENAME(hScale16); break;
+ default: break;
}
#endif /* !COMPILE_TEMPLATE_MMX2 */
if (!c->chrSrcHSubSample) {
@@ -2477,10 +2515,8 @@ static av_cold void RENAME(sws_init_swScale)(SwsContext *c)
switch (srcFormat) {
#if !COMPILE_TEMPLATE_MMX2
case PIX_FMT_YUYV422 :
- case PIX_FMT_Y400A :
- c->lumToYV12 = RENAME(yuy2ToY); break;
- case PIX_FMT_UYVY422 :
- c->lumToYV12 = RENAME(uyvyToY); break;
+ case PIX_FMT_Y400A : c->lumToYV12 = RENAME(yuy2ToY); break;
+ case PIX_FMT_UYVY422 : c->lumToYV12 = RENAME(uyvyToY); break;
#endif /* !COMPILE_TEMPLATE_MMX2 */
case PIX_FMT_BGR24 : c->lumToYV12 = RENAME(bgr24ToY); break;
case PIX_FMT_RGB24 : c->lumToYV12 = RENAME(rgb24ToY); break;
@@ -2494,6 +2530,8 @@ static av_cold void RENAME(sws_init_swScale)(SwsContext *c)
}
}
#endif /* !COMPILE_TEMPLATE_MMX2 */
- if(isAnyRGB(c->srcFormat))
+ if(isAnyRGB(c->srcFormat) && av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1<15)
c->hScale16= RENAME(hScale16);
+ if(c->scalingBpp != 8)
+ c->hScale16 = NULL;
}