/*
* Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
*
- * This file is part of FFmpeg.
+ * This file is part of Libav.
*
- * FFmpeg is free software; you can redistribute it and/or
+ * Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * FFmpeg is distributed in the hope that it will be useful,
+ * Libav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
//#undef ARCH_X86
#define DITHER1XBPP
-#define FAST_BGR2YV12 // use 7 bit coefficients instead of 15 bit
-
#define isPacked(x) ( \
(x)==PIX_FMT_PAL8 \
|| (x)==PIX_FMT_YUYV422 \
|| (x)==PIX_FMT_UYVY422 \
+ || (x)==PIX_FMT_Y400A \
|| isAnyRGB(x) \
)
#define RU (-(int)(0.169*224/255*(1<<RGB2YUV_SHIFT)+0.5))
static const double rgb2yuv_table[8][9]={
- {0.7152, 0.0722, 0.2126, -0.386, 0.5, -0.115, -0.454, -0.046, 0.5},
- {0.7152, 0.0722, 0.2126, -0.386, 0.5, -0.115, -0.454, -0.046, 0.5},
- {0.587 , 0.114 , 0.299 , -0.331, 0.5, -0.169, -0.419, -0.081, 0.5},
- {0.587 , 0.114 , 0.299 , -0.331, 0.5, -0.169, -0.419, -0.081, 0.5},
+ {0.7152, 0.0722, 0.2126, -0.386, 0.5, -0.115, -0.454, -0.046, 0.5}, //ITU709
+ {0.7152, 0.0722, 0.2126, -0.386, 0.5, -0.115, -0.454, -0.046, 0.5}, //ITU709
+ {0.587 , 0.114 , 0.299 , -0.331, 0.5, -0.169, -0.419, -0.081, 0.5}, //DEFAULT / ITU601 / ITU624 / SMPTE 170M
+ {0.587 , 0.114 , 0.299 , -0.331, 0.5, -0.169, -0.419, -0.081, 0.5}, //DEFAULT / ITU601 / ITU624 / SMPTE 170M
{0.59 , 0.11 , 0.30 , -0.331, 0.5, -0.169, -0.421, -0.079, 0.5}, //FCC
- {0.587 , 0.114 , 0.299 , -0.331, 0.5, -0.169, -0.419, -0.081, 0.5},
- {0.587 , 0.114 , 0.299 , -0.331, 0.5, -0.169, -0.419, -0.081, 0.5}, //SMPTE 170M
- {0.701 , 0.087 , 0.212 , -0.384, 0.5 -0.116, -0.445, -0.055, 0.5}, //SMPTE 240M
+ {0.587 , 0.114 , 0.299 , -0.331, 0.5, -0.169, -0.419, -0.081, 0.5}, //DEFAULT / ITU601 / ITU624 / SMPTE 170M
+ {0.587 , 0.114 , 0.299 , -0.331, 0.5, -0.169, -0.419, -0.081, 0.5}, //DEFAULT / ITU601 / ITU624 / SMPTE 170M
+ {0.701 , 0.087 , 0.212 , -0.384, 0.5, -0.116, -0.445, -0.055, 0.5}, //SMPTE 240M
};
/*
}
BGR2Y(uint32_t, bgr32ToY,16, 0, 0, 0x00FF, 0xFF00, 0x00FF, RY<< 8, GY , BY<< 8, RGB2YUV_SHIFT+8)
+BGR2Y(uint32_t,bgr321ToY,16,16, 0, 0xFF00, 0x00FF, 0xFF00, RY , GY<<8, BY , RGB2YUV_SHIFT+8)
BGR2Y(uint32_t, rgb32ToY, 0, 0,16, 0x00FF, 0xFF00, 0x00FF, RY<< 8, GY , BY<< 8, RGB2YUV_SHIFT+8)
+BGR2Y(uint32_t,rgb321ToY, 0,16,16, 0xFF00, 0x00FF, 0xFF00, RY , GY<<8, BY , RGB2YUV_SHIFT+8)
BGR2Y(uint16_t, bgr16ToY, 0, 0, 0, 0x001F, 0x07E0, 0xF800, RY<<11, GY<<5, BY , RGB2YUV_SHIFT+8)
BGR2Y(uint16_t, bgr15ToY, 0, 0, 0, 0x001F, 0x03E0, 0x7C00, RY<<10, GY<<5, BY , RGB2YUV_SHIFT+7)
BGR2Y(uint16_t, rgb16ToY, 0, 0, 0, 0xF800, 0x07E0, 0x001F, RY , GY<<5, BY<<11, RGB2YUV_SHIFT+8)
}
}
-#define BGR2UV(type, name, shr, shg, shb, maska, maskr, maskg, maskb, RU, GU, BU, RV, GV, BV, S)\
+#define BGR2UV(type, name, shr, shg, shb, shp, maskr, maskg, maskb, RU, GU, BU, RV, GV, BV, S) \
static inline void name(uint8_t *dstU, uint8_t *dstV, const uint8_t *src, const uint8_t *dummy, long width, uint32_t *unused)\
{\
int i;\
for (i=0; i<width; i++) {\
- int b= (((const type*)src)[i]&maskb)>>shb;\
- int g= (((const type*)src)[i]&maskg)>>shg;\
- int r= (((const type*)src)[i]&maskr)>>shr;\
+ int b= ((((const type*)src)[i]>>shp)&maskb)>>shb;\
+ int g= ((((const type*)src)[i]>>shp)&maskg)>>shg;\
+ int r= ((((const type*)src)[i]>>shp)&maskr)>>shr;\
\
dstU[i]= ((RU)*r + (GU)*g + (BU)*b + (257<<((S)-1)))>>(S);\
dstV[i]= ((RV)*r + (GV)*g + (BV)*b + (257<<((S)-1)))>>(S);\
{\
int i;\
for (i=0; i<width; i++) {\
- int pix0= ((const type*)src)[2*i+0];\
- int pix1= ((const type*)src)[2*i+1];\
+ int pix0= ((const type*)src)[2*i+0]>>shp;\
+ int pix1= ((const type*)src)[2*i+1]>>shp;\
int g= (pix0&~(maskr|maskb))+(pix1&~(maskr|maskb));\
int b= ((pix0+pix1-g)&(maskb|(2*maskb)))>>shb;\
int r= ((pix0+pix1-g)&(maskr|(2*maskr)))>>shr;\
}\
}
-BGR2UV(uint32_t, bgr32ToUV,16, 0, 0, 0xFF000000, 0xFF0000, 0xFF00, 0x00FF, RU<< 8, GU , BU<< 8, RV<< 8, GV , BV<< 8, RGB2YUV_SHIFT+8)
-BGR2UV(uint32_t, rgb32ToUV, 0, 0,16, 0xFF000000, 0x00FF, 0xFF00, 0xFF0000, RU<< 8, GU , BU<< 8, RV<< 8, GV , BV<< 8, RGB2YUV_SHIFT+8)
-BGR2UV(uint16_t, bgr16ToUV, 0, 0, 0, 0, 0x001F, 0x07E0, 0xF800, RU<<11, GU<<5, BU , RV<<11, GV<<5, BV , RGB2YUV_SHIFT+8)
-BGR2UV(uint16_t, bgr15ToUV, 0, 0, 0, 0, 0x001F, 0x03E0, 0x7C00, RU<<10, GU<<5, BU , RV<<10, GV<<5, BV , RGB2YUV_SHIFT+7)
-BGR2UV(uint16_t, rgb16ToUV, 0, 0, 0, 0, 0xF800, 0x07E0, 0x001F, RU , GU<<5, BU<<11, RV , GV<<5, BV<<11, RGB2YUV_SHIFT+8)
-BGR2UV(uint16_t, rgb15ToUV, 0, 0, 0, 0, 0x7C00, 0x03E0, 0x001F, RU , GU<<5, BU<<10, RV , GV<<5, BV<<10, RGB2YUV_SHIFT+7)
+BGR2UV(uint32_t, bgr32ToUV,16, 0, 0, 0, 0xFF0000, 0xFF00, 0x00FF, RU<< 8, GU , BU<< 8, RV<< 8, GV , BV<< 8, RGB2YUV_SHIFT+8)
+BGR2UV(uint32_t,bgr321ToUV,16, 0, 0, 8, 0xFF0000, 0xFF00, 0x00FF, RU<< 8, GU , BU<< 8, RV<< 8, GV , BV<< 8, RGB2YUV_SHIFT+8)
+BGR2UV(uint32_t, rgb32ToUV, 0, 0,16, 0, 0x00FF, 0xFF00, 0xFF0000, RU<< 8, GU , BU<< 8, RV<< 8, GV , BV<< 8, RGB2YUV_SHIFT+8)
+BGR2UV(uint32_t,rgb321ToUV, 0, 0,16, 8, 0x00FF, 0xFF00, 0xFF0000, RU<< 8, GU , BU<< 8, RV<< 8, GV , BV<< 8, RGB2YUV_SHIFT+8)
+BGR2UV(uint16_t, bgr16ToUV, 0, 0, 0, 0, 0x001F, 0x07E0, 0xF800, RU<<11, GU<<5, BU , RV<<11, GV<<5, BV , RGB2YUV_SHIFT+8)
+BGR2UV(uint16_t, bgr15ToUV, 0, 0, 0, 0, 0x001F, 0x03E0, 0x7C00, RU<<10, GU<<5, BU , RV<<10, GV<<5, BV , RGB2YUV_SHIFT+7)
+BGR2UV(uint16_t, rgb16ToUV, 0, 0, 0, 0, 0xF800, 0x07E0, 0x001F, RU , GU<<5, BU<<11, RV , GV<<5, BV<<11, RGB2YUV_SHIFT+8)
+BGR2UV(uint16_t, rgb15ToUV, 0, 0, 0, 0, 0x7C00, 0x03E0, 0x001F, RU , GU<<5, BU<<10, RV , GV<<5, BV<<10, RGB2YUV_SHIFT+7)
static inline void palToY(uint8_t *dst, const uint8_t *src, long width, uint32_t *pal)
{
//Note: we have C, MMX, MMX2, 3DNOW versions, there is no 3DNOW+MMX2 one
//Plain C versions
-#if (!HAVE_MMX && !HAVE_ALTIVEC) || CONFIG_RUNTIME_CPUDETECT
-#define COMPILE_C
+#if CONFIG_RUNTIME_CPUDETECT
+# define COMPILE_C 1
+# if ARCH_X86
+# define COMPILE_MMX HAVE_MMX
+# define COMPILE_MMX2 HAVE_MMX2
+# define COMPILE_3DNOW HAVE_AMD3DNOW
+# elif ARCH_PPC
+# define COMPILE_ALTIVEC HAVE_ALTIVEC
+# endif
+#else /* CONFIG_RUNTIME_CPUDETECT */
+# if ARCH_X86
+# if HAVE_MMX2
+# define COMPILE_MMX2 1
+# elif HAVE_AMD3DNOW
+# define COMPILE_3DNOW 1
+# elif HAVE_MMX
+# define COMPILE_MMX 1
+# else
+# define COMPILE_C 1
+# endif
+# elif ARCH_PPC && HAVE_ALTIVEC
+# define COMPILE_ALTIVEC 1
+# else
+# define COMPILE_C 1
+# endif
#endif
-#if ARCH_PPC
-#if HAVE_ALTIVEC
-#define COMPILE_ALTIVEC
+#ifndef COMPILE_C
+# define COMPILE_C 0
#endif
-#endif //ARCH_PPC
-
-#if ARCH_X86
-
-#if (HAVE_MMX && !HAVE_AMD3DNOW && !HAVE_MMX2) || CONFIG_RUNTIME_CPUDETECT
-#define COMPILE_MMX
+#ifndef COMPILE_MMX
+# define COMPILE_MMX 0
#endif
-
-#if HAVE_MMX2 || CONFIG_RUNTIME_CPUDETECT
-#define COMPILE_MMX2
+#ifndef COMPILE_MMX2
+# define COMPILE_MMX2 0
#endif
-
-#if (HAVE_AMD3DNOW && !HAVE_MMX2) || CONFIG_RUNTIME_CPUDETECT
-#define COMPILE_3DNOW
+#ifndef COMPILE_3DNOW
+# define COMPILE_3DNOW 0
+#endif
+#ifndef COMPILE_ALTIVEC
+# define COMPILE_ALTIVEC 0
#endif
-#endif //ARCH_X86
#define COMPILE_TEMPLATE_MMX 0
#define COMPILE_TEMPLATE_MMX2 0
#define COMPILE_TEMPLATE_AMD3DNOW 0
#define COMPILE_TEMPLATE_ALTIVEC 0
-#ifdef COMPILE_C
+#if COMPILE_C
#define RENAME(a) a ## _C
#include "swscale_template.c"
#endif
-#ifdef COMPILE_ALTIVEC
+#if COMPILE_ALTIVEC
#undef RENAME
#undef COMPILE_TEMPLATE_ALTIVEC
#define COMPILE_TEMPLATE_ALTIVEC 1
#if ARCH_X86
//MMX versions
-#ifdef COMPILE_MMX
+#if COMPILE_MMX
#undef RENAME
#undef COMPILE_TEMPLATE_MMX
#undef COMPILE_TEMPLATE_MMX2
#endif
//MMX2 versions
-#ifdef COMPILE_MMX2
+#if COMPILE_MMX2
#undef RENAME
#undef COMPILE_TEMPLATE_MMX
#undef COMPILE_TEMPLATE_MMX2
#endif
//3DNOW versions
-#ifdef COMPILE_3DNOW
+#if COMPILE_3DNOW
#undef RENAME
#undef COMPILE_TEMPLATE_MMX
#undef COMPILE_TEMPLATE_MMX2
}
#else
-#ifdef COMPILE_ALTIVEC
+#if COMPILE_ALTIVEC
if (flags & SWS_CPU_CAPS_ALTIVEC) {
sws_init_swScale_altivec(c);
return swScale_altivec;
#endif //!CONFIG_RUNTIME_CPUDETECT
}
-static int planarToNv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
- int srcSliceH, uint8_t* dstParam[], int dstStride[])
+static void copyPlane(const uint8_t *src, int srcStride,
+ int srcSliceY, int srcSliceH, int width,
+ uint8_t *dst, int dstStride)
{
- uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
- /* Copy Y plane */
- if (dstStride[0]==srcStride[0] && srcStride[0] > 0)
- memcpy(dst, src[0], srcSliceH*dstStride[0]);
- else {
+ dst += dstStride * srcSliceY;
+ if (dstStride == srcStride && srcStride > 0) {
+ memcpy(dst, src, srcSliceH * dstStride);
+ } else {
int i;
- const uint8_t *srcPtr= src[0];
- uint8_t *dstPtr= dst;
for (i=0; i<srcSliceH; i++) {
- memcpy(dstPtr, srcPtr, c->srcW);
- srcPtr+= srcStride[0];
- dstPtr+= dstStride[0];
+ memcpy(dst, src, width);
+ src += srcStride;
+ dst += dstStride;
}
}
- dst = dstParam[1] + dstStride[1]*srcSliceY/2;
+}
+
+static int planarToNv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dstParam[], int dstStride[])
+{
+ uint8_t *dst = dstParam[1] + dstStride[1]*srcSliceY/2;
+
+ copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
+ dstParam[0], dstStride[0]);
+
if (c->dstFormat == PIX_FMT_NV12)
interleaveBytes(src[1], src[2], dst, c->srcW/2, srcSliceH/2, srcStride[1], srcStride[2], dstStride[0]);
else
return srcSliceH;
}
+static void gray8aToPacked32(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette)
+{
+ long i;
+ for (i=0; i<num_pixels; i++)
+ ((uint32_t *) dst)[i] = ((const uint32_t *)palette)[src[i<<1]] | (src[(i<<1)+1] << 24);
+}
+
+static void gray8aToPacked32_1(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette)
+{
+ long i;
+
+ for (i=0; i<num_pixels; i++)
+ ((uint32_t *) dst)[i] = ((const uint32_t *)palette)[src[i<<1]] | src[(i<<1)+1];
+}
+
+static void gray8aToPacked24(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette)
+{
+ long i;
+
+ for (i=0; i<num_pixels; i++) {
+ //FIXME slow?
+ dst[0]= palette[src[i<<1]*4+0];
+ dst[1]= palette[src[i<<1]*4+1];
+ dst[2]= palette[src[i<<1]*4+2];
+ dst+= 3;
+ }
+}
+
static int palToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
int srcSliceH, uint8_t* dst[], int dstStride[])
{
uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
const uint8_t *srcPtr= src[0];
- if (usePal(srcFormat)) {
+ if (srcFormat == PIX_FMT_Y400A) {
+ switch (dstFormat) {
+ case PIX_FMT_RGB32 : conv = gray8aToPacked32; break;
+ case PIX_FMT_BGR32 : conv = gray8aToPacked32; break;
+ case PIX_FMT_BGR32_1: conv = gray8aToPacked32_1; break;
+ case PIX_FMT_RGB32_1: conv = gray8aToPacked32_1; break;
+ case PIX_FMT_RGB24 : conv = gray8aToPacked24; break;
+ case PIX_FMT_BGR24 : conv = gray8aToPacked24; break;
+ }
+ } else if (usePal(srcFormat)) {
switch (dstFormat) {
case PIX_FMT_RGB32 : conv = sws_convertPalette8ToPacked32; break;
case PIX_FMT_BGR32 : conv = sws_convertPalette8ToPacked32; break;
static int yvu9ToYv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
int srcSliceH, uint8_t* dst[], int dstStride[])
{
- int i;
-
- /* copy Y */
- if (srcStride[0]==dstStride[0] && srcStride[0] > 0)
- memcpy(dst[0]+ srcSliceY*dstStride[0], src[0], srcStride[0]*srcSliceH);
- else {
- const uint8_t *srcPtr= src[0];
- uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
-
- for (i=0; i<srcSliceH; i++) {
- memcpy(dstPtr, srcPtr, c->srcW);
- srcPtr+= srcStride[0];
- dstPtr+= dstStride[0];
- }
- }
+ copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
+ dst[0], dstStride[0]);
- if (c->dstFormat==PIX_FMT_YUV420P || c->dstFormat==PIX_FMT_YUVA420P) {
- planar2x(src[1], dst[1] + dstStride[1]*(srcSliceY >> 1), c->chrSrcW,
- srcSliceH >> 2, srcStride[1], dstStride[1]);
- planar2x(src[2], dst[2] + dstStride[2]*(srcSliceY >> 1), c->chrSrcW,
- srcSliceH >> 2, srcStride[2], dstStride[2]);
- } else {
- planar2x(src[1], dst[2] + dstStride[2]*(srcSliceY >> 1), c->chrSrcW,
- srcSliceH >> 2, srcStride[1], dstStride[2]);
- planar2x(src[2], dst[1] + dstStride[1]*(srcSliceY >> 1), c->chrSrcW,
- srcSliceH >> 2, srcStride[2], dstStride[1]);
- }
+ planar2x(src[1], dst[1] + dstStride[1]*(srcSliceY >> 1), c->chrSrcW,
+ srcSliceH >> 2, srcStride[1], dstStride[1]);
+ planar2x(src[2], dst[2] + dstStride[2]*(srcSliceY >> 1), c->chrSrcW,
+ srcSliceH >> 2, srcStride[2], dstStride[2]);
if (dst[3])
fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
return srcSliceH;
for (i=0; i<height; i++) {
for (j=0; j<length; j++)
- ((uint16_t*)dstPtr)[j] = bswap_16(((const uint16_t*)srcPtr)[j]);
+ ((uint16_t*)dstPtr)[j] = av_bswap16(((const uint16_t*)srcPtr)[j]);
srcPtr+= srcStride[plane];
dstPtr+= dstStride[plane];
}
- } else if (dstStride[plane]==srcStride[plane] && srcStride[plane] > 0)
- memcpy(dst[plane] + dstStride[plane]*y, src[plane], height*dstStride[plane]);
- else {
+ } else if (dstStride[plane] == srcStride[plane] &&
+ srcStride[plane] > 0 && srcStride[plane] == length) {
+ memcpy(dst[plane] + dstStride[plane]*y, src[plane],
+ height*dstStride[plane]);
+ } else {
if(is16BPS(c->srcFormat) && is16BPS(c->dstFormat))
length*=2;
for (i=0; i<height; i++) {
if(srcFormat == PIX_FMT_UYVY422 && dstFormat == PIX_FMT_YUV422P)
c->swScale= uyvyToYuv422Wrapper;
-#ifdef COMPILE_ALTIVEC
+#if COMPILE_ALTIVEC
if ((c->flags & SWS_CPU_CAPS_ALTIVEC) &&
!(c->flags & SWS_BITEXACT) &&
srcFormat == PIX_FMT_YUV420P) {
}
}
+static int check_image_pointers(uint8_t *data[4], enum PixelFormat pix_fmt,
+ const int linesizes[4])
+{
+ const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ int plane = desc->comp[i].plane;
+ if (!data[plane] || !linesizes[plane])
+ return 0;
+ }
+
+ return 1;
+}
+
/**
* swscale wrapper, so we don't need to export the SwsContext.
* Assumes planar YUV to be in YUV order instead of YVU.
if (srcSliceH == 0)
return 0;
+ if (!check_image_pointers(src, c->srcFormat, srcStride)) {
+ av_log(c, AV_LOG_ERROR, "bad src image pointers\n");
+ return 0;
+ }
+ if (!check_image_pointers(dst, c->dstFormat, dstStride)) {
+ av_log(c, AV_LOG_ERROR, "bad dst image pointers\n");
+ return 0;
+ }
+
if (c->sliceDir == 0 && srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) {
av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n");
return 0;
r= (i>>3 )*255;
g= ((i>>1)&3)*85;
b= (i&1 )*255;
- } else if(c->srcFormat == PIX_FMT_GRAY8) {
+ } else if(c->srcFormat == PIX_FMT_GRAY8 || c->srcFormat == PIX_FMT_Y400A) {
r = g = b = i;
} else {
assert(c->srcFormat == PIX_FMT_BGR4_BYTE);