Libav 0.7.1
|
00001 /* 00002 * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at> 00003 * 00004 * This file is part of Libav. 00005 * 00006 * Libav is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * Libav is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with Libav; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00021 #include <inttypes.h> 00022 #include <string.h> 00023 #include <math.h> 00024 #include <stdio.h> 00025 #include "config.h" 00026 #include <assert.h> 00027 #include "swscale.h" 00028 #include "swscale_internal.h" 00029 #include "rgb2rgb.h" 00030 #include "libavutil/intreadwrite.h" 00031 #include "libavutil/cpu.h" 00032 #include "libavutil/avutil.h" 00033 #include "libavutil/mathematics.h" 00034 #include "libavutil/bswap.h" 00035 #include "libavutil/pixdesc.h" 00036 00037 #define RGB2YUV_SHIFT 15 00038 #define BY ( (int)(0.114*219/255*(1<<RGB2YUV_SHIFT)+0.5)) 00039 #define BV (-(int)(0.081*224/255*(1<<RGB2YUV_SHIFT)+0.5)) 00040 #define BU ( (int)(0.500*224/255*(1<<RGB2YUV_SHIFT)+0.5)) 00041 #define GY ( (int)(0.587*219/255*(1<<RGB2YUV_SHIFT)+0.5)) 00042 #define GV (-(int)(0.419*224/255*(1<<RGB2YUV_SHIFT)+0.5)) 00043 #define GU (-(int)(0.331*224/255*(1<<RGB2YUV_SHIFT)+0.5)) 00044 #define RY ( (int)(0.299*219/255*(1<<RGB2YUV_SHIFT)+0.5)) 00045 #define RV ( (int)(0.500*224/255*(1<<RGB2YUV_SHIFT)+0.5)) 00046 #define RU (-(int)(0.169*224/255*(1<<RGB2YUV_SHIFT)+0.5)) 00047 00048 static void fillPlane(uint8_t* plane, int stride, int width, int height, int y, uint8_t val) 00049 { 00050 int i; 00051 uint8_t *ptr = plane + stride*y; 00052 for (i=0; i<height; i++) { 00053 memset(ptr, val, width); 00054 ptr += stride; 00055 } 00056 } 00057 00058 static void copyPlane(const uint8_t *src, int srcStride, 00059 int srcSliceY, int srcSliceH, int width, 00060 uint8_t *dst, int dstStride) 00061 { 00062 dst += dstStride * srcSliceY; 00063 if (dstStride == srcStride && srcStride > 0) { 00064 memcpy(dst, src, srcSliceH * dstStride); 00065 } else { 00066 int i; 00067 for (i=0; i<srcSliceH; i++) { 00068 memcpy(dst, src, width); 00069 src += srcStride; 00070 dst += dstStride; 00071 } 00072 } 00073 } 00074 00075 static int planarToNv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, 00076 int srcSliceH, uint8_t* dstParam[], int dstStride[]) 00077 { 00078 uint8_t *dst = dstParam[1] + dstStride[1]*srcSliceY/2; 00079 00080 copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, 00081 dstParam[0], dstStride[0]); 00082 00083 if (c->dstFormat == PIX_FMT_NV12) 00084 interleaveBytes(src[1], src[2], dst, c->srcW/2, srcSliceH/2, srcStride[1], srcStride[2], dstStride[0]); 00085 else 00086 interleaveBytes(src[2], src[1], dst, c->srcW/2, srcSliceH/2, srcStride[2], srcStride[1], dstStride[0]); 00087 00088 return srcSliceH; 00089 } 00090 00091 static int planarToYuy2Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, 00092 int srcSliceH, uint8_t* dstParam[], int dstStride[]) 00093 { 00094 uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY; 00095 00096 yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], srcStride[1], dstStride[0]); 00097 00098 return srcSliceH; 00099 } 00100 00101 static int planarToUyvyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, 00102 int srcSliceH, uint8_t* dstParam[], int dstStride[]) 00103 { 00104 uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY; 00105 00106 yv12touyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], srcStride[1], dstStride[0]); 00107 00108 return srcSliceH; 00109 } 00110 00111 static int yuv422pToYuy2Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, 00112 int srcSliceH, uint8_t* dstParam[], int dstStride[]) 00113 { 00114 uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY; 00115 00116 yuv422ptoyuy2(src[0],src[1],src[2],dst,c->srcW,srcSliceH,srcStride[0],srcStride[1],dstStride[0]); 00117 00118 return srcSliceH; 00119 } 00120 00121 static int yuv422pToUyvyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, 00122 int srcSliceH, uint8_t* dstParam[], int dstStride[]) 00123 { 00124 uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY; 00125 00126 yuv422ptouyvy(src[0],src[1],src[2],dst,c->srcW,srcSliceH,srcStride[0],srcStride[1],dstStride[0]); 00127 00128 return srcSliceH; 00129 } 00130 00131 static int yuyvToYuv420Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, 00132 int srcSliceH, uint8_t* dstParam[], int dstStride[]) 00133 { 00134 uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY; 00135 uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY/2; 00136 uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY/2; 00137 00138 yuyvtoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]); 00139 00140 if (dstParam[3]) 00141 fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); 00142 00143 return srcSliceH; 00144 } 00145 00146 static int yuyvToYuv422Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, 00147 int srcSliceH, uint8_t* dstParam[], int dstStride[]) 00148 { 00149 uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY; 00150 uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY; 00151 uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY; 00152 00153 yuyvtoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]); 00154 00155 return srcSliceH; 00156 } 00157 00158 static int uyvyToYuv420Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, 00159 int srcSliceH, uint8_t* dstParam[], int dstStride[]) 00160 { 00161 uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY; 00162 uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY/2; 00163 uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY/2; 00164 00165 uyvytoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]); 00166 00167 if (dstParam[3]) 00168 fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); 00169 00170 return srcSliceH; 00171 } 00172 00173 static int uyvyToYuv422Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, 00174 int srcSliceH, uint8_t* dstParam[], int dstStride[]) 00175 { 00176 uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY; 00177 uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY; 00178 uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY; 00179 00180 uyvytoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]); 00181 00182 return srcSliceH; 00183 } 00184 00185 static void gray8aToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette) 00186 { 00187 int i; 00188 for (i=0; i<num_pixels; i++) 00189 ((uint32_t *) dst)[i] = ((const uint32_t *)palette)[src[i<<1]] | (src[(i<<1)+1] << 24); 00190 } 00191 00192 static void gray8aToPacked32_1(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette) 00193 { 00194 int i; 00195 00196 for (i=0; i<num_pixels; i++) 00197 ((uint32_t *) dst)[i] = ((const uint32_t *)palette)[src[i<<1]] | src[(i<<1)+1]; 00198 } 00199 00200 static void gray8aToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette) 00201 { 00202 int i; 00203 00204 for (i=0; i<num_pixels; i++) { 00205 //FIXME slow? 00206 dst[0]= palette[src[i<<1]*4+0]; 00207 dst[1]= palette[src[i<<1]*4+1]; 00208 dst[2]= palette[src[i<<1]*4+2]; 00209 dst+= 3; 00210 } 00211 } 00212 00213 static int palToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, 00214 int srcSliceH, uint8_t* dst[], int dstStride[]) 00215 { 00216 const enum PixelFormat srcFormat= c->srcFormat; 00217 const enum PixelFormat dstFormat= c->dstFormat; 00218 void (*conv)(const uint8_t *src, uint8_t *dst, int num_pixels, 00219 const uint8_t *palette)=NULL; 00220 int i; 00221 uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY; 00222 const uint8_t *srcPtr= src[0]; 00223 00224 if (srcFormat == PIX_FMT_Y400A) { 00225 switch (dstFormat) { 00226 case PIX_FMT_RGB32 : conv = gray8aToPacked32; break; 00227 case PIX_FMT_BGR32 : conv = gray8aToPacked32; break; 00228 case PIX_FMT_BGR32_1: conv = gray8aToPacked32_1; break; 00229 case PIX_FMT_RGB32_1: conv = gray8aToPacked32_1; break; 00230 case PIX_FMT_RGB24 : conv = gray8aToPacked24; break; 00231 case PIX_FMT_BGR24 : conv = gray8aToPacked24; break; 00232 } 00233 } else if (usePal(srcFormat)) { 00234 switch (dstFormat) { 00235 case PIX_FMT_RGB32 : conv = sws_convertPalette8ToPacked32; break; 00236 case PIX_FMT_BGR32 : conv = sws_convertPalette8ToPacked32; break; 00237 case PIX_FMT_BGR32_1: conv = sws_convertPalette8ToPacked32; break; 00238 case PIX_FMT_RGB32_1: conv = sws_convertPalette8ToPacked32; break; 00239 case PIX_FMT_RGB24 : conv = sws_convertPalette8ToPacked24; break; 00240 case PIX_FMT_BGR24 : conv = sws_convertPalette8ToPacked24; break; 00241 } 00242 } 00243 00244 if (!conv) 00245 av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n", 00246 sws_format_name(srcFormat), sws_format_name(dstFormat)); 00247 else { 00248 for (i=0; i<srcSliceH; i++) { 00249 conv(srcPtr, dstPtr, c->srcW, (uint8_t *) c->pal_rgb); 00250 srcPtr+= srcStride[0]; 00251 dstPtr+= dstStride[0]; 00252 } 00253 } 00254 00255 return srcSliceH; 00256 } 00257 00258 #define isRGBA32(x) ( \ 00259 (x) == PIX_FMT_ARGB \ 00260 || (x) == PIX_FMT_RGBA \ 00261 || (x) == PIX_FMT_BGRA \ 00262 || (x) == PIX_FMT_ABGR \ 00263 ) 00264 00265 /* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */ 00266 static int rgbToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, 00267 int srcSliceH, uint8_t* dst[], int dstStride[]) 00268 { 00269 const enum PixelFormat srcFormat= c->srcFormat; 00270 const enum PixelFormat dstFormat= c->dstFormat; 00271 const int srcBpp= (c->srcFormatBpp + 7) >> 3; 00272 const int dstBpp= (c->dstFormatBpp + 7) >> 3; 00273 const int srcId= c->srcFormatBpp >> 2; /* 1:0, 4:1, 8:2, 15:3, 16:4, 24:6, 32:8 */ 00274 const int dstId= c->dstFormatBpp >> 2; 00275 void (*conv)(const uint8_t *src, uint8_t *dst, int src_size)=NULL; 00276 00277 #define CONV_IS(src, dst) (srcFormat == PIX_FMT_##src && dstFormat == PIX_FMT_##dst) 00278 00279 if (isRGBA32(srcFormat) && isRGBA32(dstFormat)) { 00280 if ( CONV_IS(ABGR, RGBA) 00281 || CONV_IS(ARGB, BGRA) 00282 || CONV_IS(BGRA, ARGB) 00283 || CONV_IS(RGBA, ABGR)) conv = shuffle_bytes_3210; 00284 else if (CONV_IS(ABGR, ARGB) 00285 || CONV_IS(ARGB, ABGR)) conv = shuffle_bytes_0321; 00286 else if (CONV_IS(ABGR, BGRA) 00287 || CONV_IS(ARGB, RGBA)) conv = shuffle_bytes_1230; 00288 else if (CONV_IS(BGRA, RGBA) 00289 || CONV_IS(RGBA, BGRA)) conv = shuffle_bytes_2103; 00290 else if (CONV_IS(BGRA, ABGR) 00291 || CONV_IS(RGBA, ARGB)) conv = shuffle_bytes_3012; 00292 } else 00293 /* BGR -> BGR */ 00294 if ( (isBGRinInt(srcFormat) && isBGRinInt(dstFormat)) 00295 || (isRGBinInt(srcFormat) && isRGBinInt(dstFormat))) { 00296 switch(srcId | (dstId<<4)) { 00297 case 0x34: conv= rgb16to15; break; 00298 case 0x36: conv= rgb24to15; break; 00299 case 0x38: conv= rgb32to15; break; 00300 case 0x43: conv= rgb15to16; break; 00301 case 0x46: conv= rgb24to16; break; 00302 case 0x48: conv= rgb32to16; break; 00303 case 0x63: conv= rgb15to24; break; 00304 case 0x64: conv= rgb16to24; break; 00305 case 0x68: conv= rgb32to24; break; 00306 case 0x83: conv= rgb15to32; break; 00307 case 0x84: conv= rgb16to32; break; 00308 case 0x86: conv= rgb24to32; break; 00309 } 00310 } else if ( (isBGRinInt(srcFormat) && isRGBinInt(dstFormat)) 00311 || (isRGBinInt(srcFormat) && isBGRinInt(dstFormat))) { 00312 switch(srcId | (dstId<<4)) { 00313 case 0x33: conv= rgb15tobgr15; break; 00314 case 0x34: conv= rgb16tobgr15; break; 00315 case 0x36: conv= rgb24tobgr15; break; 00316 case 0x38: conv= rgb32tobgr15; break; 00317 case 0x43: conv= rgb15tobgr16; break; 00318 case 0x44: conv= rgb16tobgr16; break; 00319 case 0x46: conv= rgb24tobgr16; break; 00320 case 0x48: conv= rgb32tobgr16; break; 00321 case 0x63: conv= rgb15tobgr24; break; 00322 case 0x64: conv= rgb16tobgr24; break; 00323 case 0x66: conv= rgb24tobgr24; break; 00324 case 0x68: conv= rgb32tobgr24; break; 00325 case 0x83: conv= rgb15tobgr32; break; 00326 case 0x84: conv= rgb16tobgr32; break; 00327 case 0x86: conv= rgb24tobgr32; break; 00328 } 00329 } 00330 00331 if (!conv) { 00332 av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n", 00333 sws_format_name(srcFormat), sws_format_name(dstFormat)); 00334 } else { 00335 const uint8_t *srcPtr= src[0]; 00336 uint8_t *dstPtr= dst[0]; 00337 if ((srcFormat == PIX_FMT_RGB32_1 || srcFormat == PIX_FMT_BGR32_1) && !isRGBA32(dstFormat)) 00338 srcPtr += ALT32_CORR; 00339 00340 if ((dstFormat == PIX_FMT_RGB32_1 || dstFormat == PIX_FMT_BGR32_1) && !isRGBA32(srcFormat)) 00341 dstPtr += ALT32_CORR; 00342 00343 if (dstStride[0]*srcBpp == srcStride[0]*dstBpp && srcStride[0] > 0) 00344 conv(srcPtr, dstPtr + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]); 00345 else { 00346 int i; 00347 dstPtr += dstStride[0]*srcSliceY; 00348 00349 for (i=0; i<srcSliceH; i++) { 00350 conv(srcPtr, dstPtr, c->srcW*srcBpp); 00351 srcPtr+= srcStride[0]; 00352 dstPtr+= dstStride[0]; 00353 } 00354 } 00355 } 00356 return srcSliceH; 00357 } 00358 00359 static int bgr24ToYv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, 00360 int srcSliceH, uint8_t* dst[], int dstStride[]) 00361 { 00362 rgb24toyv12( 00363 src[0], 00364 dst[0]+ srcSliceY *dstStride[0], 00365 dst[1]+(srcSliceY>>1)*dstStride[1], 00366 dst[2]+(srcSliceY>>1)*dstStride[2], 00367 c->srcW, srcSliceH, 00368 dstStride[0], dstStride[1], srcStride[0]); 00369 if (dst[3]) 00370 fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); 00371 return srcSliceH; 00372 } 00373 00374 static int yvu9ToYv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, 00375 int srcSliceH, uint8_t* dst[], int dstStride[]) 00376 { 00377 copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, 00378 dst[0], dstStride[0]); 00379 00380 planar2x(src[1], dst[1] + dstStride[1]*(srcSliceY >> 1), c->chrSrcW, 00381 srcSliceH >> 2, srcStride[1], dstStride[1]); 00382 planar2x(src[2], dst[2] + dstStride[2]*(srcSliceY >> 1), c->chrSrcW, 00383 srcSliceH >> 2, srcStride[2], dstStride[2]); 00384 if (dst[3]) 00385 fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); 00386 return srcSliceH; 00387 } 00388 00389 /* unscaled copy like stuff (assumes nearly identical formats) */ 00390 static int packedCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, 00391 int srcSliceH, uint8_t* dst[], int dstStride[]) 00392 { 00393 if (dstStride[0]==srcStride[0] && srcStride[0] > 0) 00394 memcpy(dst[0] + dstStride[0]*srcSliceY, src[0], srcSliceH*dstStride[0]); 00395 else { 00396 int i; 00397 const uint8_t *srcPtr= src[0]; 00398 uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY; 00399 int length=0; 00400 00401 /* universal length finder */ 00402 while(length+c->srcW <= FFABS(dstStride[0]) 00403 && length+c->srcW <= FFABS(srcStride[0])) length+= c->srcW; 00404 assert(length!=0); 00405 00406 for (i=0; i<srcSliceH; i++) { 00407 memcpy(dstPtr, srcPtr, length); 00408 srcPtr+= srcStride[0]; 00409 dstPtr+= dstStride[0]; 00410 } 00411 } 00412 return srcSliceH; 00413 } 00414 00415 static int planarCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, 00416 int srcSliceH, uint8_t* dst[], int dstStride[]) 00417 { 00418 int plane, i, j; 00419 for (plane=0; plane<4; plane++) { 00420 int length= (plane==0 || plane==3) ? c->srcW : -((-c->srcW )>>c->chrDstHSubSample); 00421 int y= (plane==0 || plane==3) ? srcSliceY: -((-srcSliceY)>>c->chrDstVSubSample); 00422 int height= (plane==0 || plane==3) ? srcSliceH: -((-srcSliceH)>>c->chrDstVSubSample); 00423 const uint8_t *srcPtr= src[plane]; 00424 uint8_t *dstPtr= dst[plane] + dstStride[plane]*y; 00425 00426 if (!dst[plane]) continue; 00427 // ignore palette for GRAY8 00428 if (plane == 1 && !dst[2]) continue; 00429 if (!src[plane] || (plane == 1 && !src[2])) { 00430 if(is16BPS(c->dstFormat)) 00431 length*=2; 00432 fillPlane(dst[plane], dstStride[plane], length, height, y, (plane==3) ? 255 : 128); 00433 } else { 00434 if(is9_OR_10BPS(c->srcFormat)) { 00435 const int src_depth = av_pix_fmt_descriptors[c->srcFormat].comp[plane].depth_minus1+1; 00436 const int dst_depth = av_pix_fmt_descriptors[c->dstFormat].comp[plane].depth_minus1+1; 00437 const uint16_t *srcPtr2 = (const uint16_t*)srcPtr; 00438 00439 if (is16BPS(c->dstFormat)) { 00440 uint16_t *dstPtr2 = (uint16_t*)dstPtr; 00441 #define COPY9_OR_10TO16(rfunc, wfunc) \ 00442 for (i = 0; i < height; i++) { \ 00443 for (j = 0; j < length; j++) { \ 00444 int srcpx = rfunc(&srcPtr2[j]); \ 00445 wfunc(&dstPtr2[j], (srcpx<<(16-src_depth)) | (srcpx>>(2*src_depth-16))); \ 00446 } \ 00447 dstPtr2 += dstStride[plane]/2; \ 00448 srcPtr2 += srcStride[plane]/2; \ 00449 } 00450 if (isBE(c->dstFormat)) { 00451 if (isBE(c->srcFormat)) { 00452 COPY9_OR_10TO16(AV_RB16, AV_WB16); 00453 } else { 00454 COPY9_OR_10TO16(AV_RL16, AV_WB16); 00455 } 00456 } else { 00457 if (isBE(c->srcFormat)) { 00458 COPY9_OR_10TO16(AV_RB16, AV_WL16); 00459 } else { 00460 COPY9_OR_10TO16(AV_RL16, AV_WL16); 00461 } 00462 } 00463 } else if (is9_OR_10BPS(c->dstFormat)) { 00464 uint16_t *dstPtr2 = (uint16_t*)dstPtr; 00465 #define COPY9_OR_10TO9_OR_10(loop) \ 00466 for (i = 0; i < height; i++) { \ 00467 for (j = 0; j < length; j++) { \ 00468 loop; \ 00469 } \ 00470 dstPtr2 += dstStride[plane]/2; \ 00471 srcPtr2 += srcStride[plane]/2; \ 00472 } 00473 #define COPY9_OR_10TO9_OR_10_2(rfunc, wfunc) \ 00474 if (dst_depth > src_depth) { \ 00475 COPY9_OR_10TO9_OR_10(int srcpx = rfunc(&srcPtr2[j]); \ 00476 wfunc(&dstPtr2[j], (srcpx << 1) | (srcpx >> 9))); \ 00477 } else if (dst_depth < src_depth) { \ 00478 COPY9_OR_10TO9_OR_10(wfunc(&dstPtr2[j], rfunc(&srcPtr2[j]) >> 1)); \ 00479 } else { \ 00480 COPY9_OR_10TO9_OR_10(wfunc(&dstPtr2[j], rfunc(&srcPtr2[j]))); \ 00481 } 00482 if (isBE(c->dstFormat)) { 00483 if (isBE(c->srcFormat)) { 00484 COPY9_OR_10TO9_OR_10_2(AV_RB16, AV_WB16); 00485 } else { 00486 COPY9_OR_10TO9_OR_10_2(AV_RL16, AV_WB16); 00487 } 00488 } else { 00489 if (isBE(c->srcFormat)) { 00490 COPY9_OR_10TO9_OR_10_2(AV_RB16, AV_WL16); 00491 } else { 00492 COPY9_OR_10TO9_OR_10_2(AV_RL16, AV_WL16); 00493 } 00494 } 00495 } else { 00496 // FIXME Maybe dither instead. 00497 #define COPY9_OR_10TO8(rfunc) \ 00498 for (i = 0; i < height; i++) { \ 00499 for (j = 0; j < length; j++) { \ 00500 dstPtr[j] = rfunc(&srcPtr2[j])>>(src_depth-8); \ 00501 } \ 00502 dstPtr += dstStride[plane]; \ 00503 srcPtr2 += srcStride[plane]/2; \ 00504 } 00505 if (isBE(c->srcFormat)) { 00506 COPY9_OR_10TO8(AV_RB16); 00507 } else { 00508 COPY9_OR_10TO8(AV_RL16); 00509 } 00510 } 00511 } else if(is9_OR_10BPS(c->dstFormat)) { 00512 const int dst_depth = av_pix_fmt_descriptors[c->dstFormat].comp[plane].depth_minus1+1; 00513 uint16_t *dstPtr2 = (uint16_t*)dstPtr; 00514 00515 if (is16BPS(c->srcFormat)) { 00516 const uint16_t *srcPtr2 = (const uint16_t*)srcPtr; 00517 #define COPY16TO9_OR_10(rfunc, wfunc) \ 00518 for (i = 0; i < height; i++) { \ 00519 for (j = 0; j < length; j++) { \ 00520 wfunc(&dstPtr2[j], rfunc(&srcPtr2[j])>>(16-dst_depth)); \ 00521 } \ 00522 dstPtr2 += dstStride[plane]/2; \ 00523 srcPtr2 += srcStride[plane]/2; \ 00524 } 00525 if (isBE(c->dstFormat)) { 00526 if (isBE(c->srcFormat)) { 00527 COPY16TO9_OR_10(AV_RB16, AV_WB16); 00528 } else { 00529 COPY16TO9_OR_10(AV_RL16, AV_WB16); 00530 } 00531 } else { 00532 if (isBE(c->srcFormat)) { 00533 COPY16TO9_OR_10(AV_RB16, AV_WL16); 00534 } else { 00535 COPY16TO9_OR_10(AV_RL16, AV_WL16); 00536 } 00537 } 00538 } else /* 8bit */ { 00539 #define COPY8TO9_OR_10(wfunc) \ 00540 for (i = 0; i < height; i++) { \ 00541 for (j = 0; j < length; j++) { \ 00542 const int srcpx = srcPtr[j]; \ 00543 wfunc(&dstPtr2[j], (srcpx<<(dst_depth-8)) | (srcpx >> (16-dst_depth))); \ 00544 } \ 00545 dstPtr2 += dstStride[plane]/2; \ 00546 srcPtr += srcStride[plane]; \ 00547 } 00548 if (isBE(c->dstFormat)) { 00549 COPY8TO9_OR_10(AV_WB16); 00550 } else { 00551 COPY8TO9_OR_10(AV_WL16); 00552 } 00553 } 00554 } else if(is16BPS(c->srcFormat) && !is16BPS(c->dstFormat)) { 00555 if (!isBE(c->srcFormat)) srcPtr++; 00556 for (i=0; i<height; i++) { 00557 for (j=0; j<length; j++) dstPtr[j] = srcPtr[j<<1]; 00558 srcPtr+= srcStride[plane]; 00559 dstPtr+= dstStride[plane]; 00560 } 00561 } else if(!is16BPS(c->srcFormat) && is16BPS(c->dstFormat)) { 00562 for (i=0; i<height; i++) { 00563 for (j=0; j<length; j++) { 00564 dstPtr[ j<<1 ] = srcPtr[j]; 00565 dstPtr[(j<<1)+1] = srcPtr[j]; 00566 } 00567 srcPtr+= srcStride[plane]; 00568 dstPtr+= dstStride[plane]; 00569 } 00570 } else if(is16BPS(c->srcFormat) && is16BPS(c->dstFormat) 00571 && isBE(c->srcFormat) != isBE(c->dstFormat)) { 00572 00573 for (i=0; i<height; i++) { 00574 for (j=0; j<length; j++) 00575 ((uint16_t*)dstPtr)[j] = av_bswap16(((const uint16_t*)srcPtr)[j]); 00576 srcPtr+= srcStride[plane]; 00577 dstPtr+= dstStride[plane]; 00578 } 00579 } else if (dstStride[plane] == srcStride[plane] && 00580 srcStride[plane] > 0 && srcStride[plane] == length) { 00581 memcpy(dst[plane] + dstStride[plane]*y, src[plane], 00582 height*dstStride[plane]); 00583 } else { 00584 if(is16BPS(c->srcFormat) && is16BPS(c->dstFormat)) 00585 length*=2; 00586 for (i=0; i<height; i++) { 00587 memcpy(dstPtr, srcPtr, length); 00588 srcPtr+= srcStride[plane]; 00589 dstPtr+= dstStride[plane]; 00590 } 00591 } 00592 } 00593 } 00594 return srcSliceH; 00595 } 00596 00597 void ff_get_unscaled_swscale(SwsContext *c) 00598 { 00599 const enum PixelFormat srcFormat = c->srcFormat; 00600 const enum PixelFormat dstFormat = c->dstFormat; 00601 const int flags = c->flags; 00602 const int dstH = c->dstH; 00603 int needsDither; 00604 00605 needsDither= isAnyRGB(dstFormat) 00606 && c->dstFormatBpp < 24 00607 && (c->dstFormatBpp < c->srcFormatBpp || (!isAnyRGB(srcFormat))); 00608 00609 /* yv12_to_nv12 */ 00610 if ((srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) && (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21)) { 00611 c->swScale= planarToNv12Wrapper; 00612 } 00613 /* yuv2bgr */ 00614 if ((srcFormat==PIX_FMT_YUV420P || srcFormat==PIX_FMT_YUV422P || srcFormat==PIX_FMT_YUVA420P) && isAnyRGB(dstFormat) 00615 && !(flags & SWS_ACCURATE_RND) && !(dstH&1)) { 00616 c->swScale= ff_yuv2rgb_get_func_ptr(c); 00617 } 00618 00619 if (srcFormat==PIX_FMT_YUV410P && (dstFormat==PIX_FMT_YUV420P || dstFormat==PIX_FMT_YUVA420P) && !(flags & SWS_BITEXACT)) { 00620 c->swScale= yvu9ToYv12Wrapper; 00621 } 00622 00623 /* bgr24toYV12 */ 00624 if (srcFormat==PIX_FMT_BGR24 && (dstFormat==PIX_FMT_YUV420P || dstFormat==PIX_FMT_YUVA420P) && !(flags & SWS_ACCURATE_RND)) 00625 c->swScale= bgr24ToYv12Wrapper; 00626 00627 /* RGB/BGR -> RGB/BGR (no dither needed forms) */ 00628 if ( isAnyRGB(srcFormat) 00629 && isAnyRGB(dstFormat) 00630 && srcFormat != PIX_FMT_BGR8 && dstFormat != PIX_FMT_BGR8 00631 && srcFormat != PIX_FMT_RGB8 && dstFormat != PIX_FMT_RGB8 00632 && srcFormat != PIX_FMT_BGR4 && dstFormat != PIX_FMT_BGR4 00633 && srcFormat != PIX_FMT_RGB4 && dstFormat != PIX_FMT_RGB4 00634 && srcFormat != PIX_FMT_BGR4_BYTE && dstFormat != PIX_FMT_BGR4_BYTE 00635 && srcFormat != PIX_FMT_RGB4_BYTE && dstFormat != PIX_FMT_RGB4_BYTE 00636 && srcFormat != PIX_FMT_MONOBLACK && dstFormat != PIX_FMT_MONOBLACK 00637 && srcFormat != PIX_FMT_MONOWHITE && dstFormat != PIX_FMT_MONOWHITE 00638 && srcFormat != PIX_FMT_RGB48LE && dstFormat != PIX_FMT_RGB48LE 00639 && srcFormat != PIX_FMT_RGB48BE && dstFormat != PIX_FMT_RGB48BE 00640 && srcFormat != PIX_FMT_BGR48LE && dstFormat != PIX_FMT_BGR48LE 00641 && srcFormat != PIX_FMT_BGR48BE && dstFormat != PIX_FMT_BGR48BE 00642 && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)))) 00643 c->swScale= rgbToRgbWrapper; 00644 00645 if ((usePal(srcFormat) && ( 00646 dstFormat == PIX_FMT_RGB32 || 00647 dstFormat == PIX_FMT_RGB32_1 || 00648 dstFormat == PIX_FMT_RGB24 || 00649 dstFormat == PIX_FMT_BGR32 || 00650 dstFormat == PIX_FMT_BGR32_1 || 00651 dstFormat == PIX_FMT_BGR24))) 00652 c->swScale= palToRgbWrapper; 00653 00654 if (srcFormat == PIX_FMT_YUV422P) { 00655 if (dstFormat == PIX_FMT_YUYV422) 00656 c->swScale= yuv422pToYuy2Wrapper; 00657 else if (dstFormat == PIX_FMT_UYVY422) 00658 c->swScale= yuv422pToUyvyWrapper; 00659 } 00660 00661 /* LQ converters if -sws 0 or -sws 4*/ 00662 if (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)) { 00663 /* yv12_to_yuy2 */ 00664 if (srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) { 00665 if (dstFormat == PIX_FMT_YUYV422) 00666 c->swScale= planarToYuy2Wrapper; 00667 else if (dstFormat == PIX_FMT_UYVY422) 00668 c->swScale= planarToUyvyWrapper; 00669 } 00670 } 00671 if(srcFormat == PIX_FMT_YUYV422 && (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P)) 00672 c->swScale= yuyvToYuv420Wrapper; 00673 if(srcFormat == PIX_FMT_UYVY422 && (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P)) 00674 c->swScale= uyvyToYuv420Wrapper; 00675 if(srcFormat == PIX_FMT_YUYV422 && dstFormat == PIX_FMT_YUV422P) 00676 c->swScale= yuyvToYuv422Wrapper; 00677 if(srcFormat == PIX_FMT_UYVY422 && dstFormat == PIX_FMT_YUV422P) 00678 c->swScale= uyvyToYuv422Wrapper; 00679 00680 /* simple copy */ 00681 if ( srcFormat == dstFormat 00682 || (srcFormat == PIX_FMT_YUVA420P && dstFormat == PIX_FMT_YUV420P) 00683 || (srcFormat == PIX_FMT_YUV420P && dstFormat == PIX_FMT_YUVA420P) 00684 || (isPlanarYUV(srcFormat) && isGray(dstFormat)) 00685 || (isPlanarYUV(dstFormat) && isGray(srcFormat)) 00686 || (isGray(dstFormat) && isGray(srcFormat)) 00687 || (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat) 00688 && c->chrDstHSubSample == c->chrSrcHSubSample 00689 && c->chrDstVSubSample == c->chrSrcVSubSample 00690 && dstFormat != PIX_FMT_NV12 && dstFormat != PIX_FMT_NV21 00691 && srcFormat != PIX_FMT_NV12 && srcFormat != PIX_FMT_NV21)) 00692 { 00693 if (isPacked(c->srcFormat)) 00694 c->swScale= packedCopyWrapper; 00695 else /* Planar YUV or gray */ 00696 c->swScale= planarCopyWrapper; 00697 } 00698 00699 if (ARCH_BFIN) 00700 ff_bfin_get_unscaled_swscale(c); 00701 if (HAVE_ALTIVEC) 00702 ff_swscale_get_unscaled_altivec(c); 00703 } 00704 00705 static void reset_ptr(const uint8_t* src[], int format) 00706 { 00707 if(!isALPHA(format)) 00708 src[3]=NULL; 00709 if(!isPlanarYUV(format)) { 00710 src[3]=src[2]=NULL; 00711 00712 if (!usePal(format)) 00713 src[1]= NULL; 00714 } 00715 } 00716 00717 static int check_image_pointers(uint8_t *data[4], enum PixelFormat pix_fmt, 00718 const int linesizes[4]) 00719 { 00720 const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt]; 00721 int i; 00722 00723 for (i = 0; i < 4; i++) { 00724 int plane = desc->comp[i].plane; 00725 if (!data[plane] || !linesizes[plane]) 00726 return 0; 00727 } 00728 00729 return 1; 00730 } 00731 00736 int sws_scale(SwsContext *c, const uint8_t* const src[], const int srcStride[], int srcSliceY, 00737 int srcSliceH, uint8_t* const dst[], const int dstStride[]) 00738 { 00739 int i; 00740 const uint8_t* src2[4]= {src[0], src[1], src[2], src[3]}; 00741 uint8_t* dst2[4]= {dst[0], dst[1], dst[2], dst[3]}; 00742 00743 // do not mess up sliceDir if we have a "trailing" 0-size slice 00744 if (srcSliceH == 0) 00745 return 0; 00746 00747 if (!check_image_pointers(src, c->srcFormat, srcStride)) { 00748 av_log(c, AV_LOG_ERROR, "bad src image pointers\n"); 00749 return 0; 00750 } 00751 if (!check_image_pointers(dst, c->dstFormat, dstStride)) { 00752 av_log(c, AV_LOG_ERROR, "bad dst image pointers\n"); 00753 return 0; 00754 } 00755 00756 if (c->sliceDir == 0 && srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) { 00757 av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n"); 00758 return 0; 00759 } 00760 if (c->sliceDir == 0) { 00761 if (srcSliceY == 0) c->sliceDir = 1; else c->sliceDir = -1; 00762 } 00763 00764 if (usePal(c->srcFormat)) { 00765 for (i=0; i<256; i++) { 00766 int p, r, g, b,y,u,v; 00767 if(c->srcFormat == PIX_FMT_PAL8) { 00768 p=((const uint32_t*)(src[1]))[i]; 00769 r= (p>>16)&0xFF; 00770 g= (p>> 8)&0xFF; 00771 b= p &0xFF; 00772 } else if(c->srcFormat == PIX_FMT_RGB8) { 00773 r= (i>>5 )*36; 00774 g= ((i>>2)&7)*36; 00775 b= (i&3 )*85; 00776 } else if(c->srcFormat == PIX_FMT_BGR8) { 00777 b= (i>>6 )*85; 00778 g= ((i>>3)&7)*36; 00779 r= (i&7 )*36; 00780 } else if(c->srcFormat == PIX_FMT_RGB4_BYTE) { 00781 r= (i>>3 )*255; 00782 g= ((i>>1)&3)*85; 00783 b= (i&1 )*255; 00784 } else if(c->srcFormat == PIX_FMT_GRAY8 || c->srcFormat == PIX_FMT_Y400A) { 00785 r = g = b = i; 00786 } else { 00787 assert(c->srcFormat == PIX_FMT_BGR4_BYTE); 00788 b= (i>>3 )*255; 00789 g= ((i>>1)&3)*85; 00790 r= (i&1 )*255; 00791 } 00792 y= av_clip_uint8((RY*r + GY*g + BY*b + ( 33<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT); 00793 u= av_clip_uint8((RU*r + GU*g + BU*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT); 00794 v= av_clip_uint8((RV*r + GV*g + BV*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT); 00795 c->pal_yuv[i]= y + (u<<8) + (v<<16); 00796 00797 switch(c->dstFormat) { 00798 case PIX_FMT_BGR32: 00799 #if !HAVE_BIGENDIAN 00800 case PIX_FMT_RGB24: 00801 #endif 00802 c->pal_rgb[i]= r + (g<<8) + (b<<16); 00803 break; 00804 case PIX_FMT_BGR32_1: 00805 #if HAVE_BIGENDIAN 00806 case PIX_FMT_BGR24: 00807 #endif 00808 c->pal_rgb[i]= (r + (g<<8) + (b<<16)) << 8; 00809 break; 00810 case PIX_FMT_RGB32_1: 00811 #if HAVE_BIGENDIAN 00812 case PIX_FMT_RGB24: 00813 #endif 00814 c->pal_rgb[i]= (b + (g<<8) + (r<<16)) << 8; 00815 break; 00816 case PIX_FMT_RGB32: 00817 #if !HAVE_BIGENDIAN 00818 case PIX_FMT_BGR24: 00819 #endif 00820 default: 00821 c->pal_rgb[i]= b + (g<<8) + (r<<16); 00822 } 00823 } 00824 } 00825 00826 // copy strides, so they can safely be modified 00827 if (c->sliceDir == 1) { 00828 // slices go from top to bottom 00829 int srcStride2[4]= {srcStride[0], srcStride[1], srcStride[2], srcStride[3]}; 00830 int dstStride2[4]= {dstStride[0], dstStride[1], dstStride[2], dstStride[3]}; 00831 00832 reset_ptr(src2, c->srcFormat); 00833 reset_ptr((const uint8_t**)dst2, c->dstFormat); 00834 00835 /* reset slice direction at end of frame */ 00836 if (srcSliceY + srcSliceH == c->srcH) 00837 c->sliceDir = 0; 00838 00839 return c->swScale(c, src2, srcStride2, srcSliceY, srcSliceH, dst2, dstStride2); 00840 } else { 00841 // slices go from bottom to top => we flip the image internally 00842 int srcStride2[4]= {-srcStride[0], -srcStride[1], -srcStride[2], -srcStride[3]}; 00843 int dstStride2[4]= {-dstStride[0], -dstStride[1], -dstStride[2], -dstStride[3]}; 00844 00845 src2[0] += (srcSliceH-1)*srcStride[0]; 00846 if (!usePal(c->srcFormat)) 00847 src2[1] += ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[1]; 00848 src2[2] += ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[2]; 00849 src2[3] += (srcSliceH-1)*srcStride[3]; 00850 dst2[0] += ( c->dstH -1)*dstStride[0]; 00851 dst2[1] += ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[1]; 00852 dst2[2] += ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[2]; 00853 dst2[3] += ( c->dstH -1)*dstStride[3]; 00854 00855 reset_ptr(src2, c->srcFormat); 00856 reset_ptr((const uint8_t**)dst2, c->dstFormat); 00857 00858 /* reset slice direction at end of frame */ 00859 if (!srcSliceY) 00860 c->sliceDir = 0; 00861 00862 return c->swScale(c, src2, srcStride2, c->srcH-srcSliceY-srcSliceH, srcSliceH, dst2, dstStride2); 00863 } 00864 } 00865 00866 /* Convert the palette to the same packed 32-bit format as the palette */ 00867 void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette) 00868 { 00869 int i; 00870 00871 for (i=0; i<num_pixels; i++) 00872 ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i]]; 00873 } 00874 00875 /* Palette format: ABCD -> dst format: ABC */ 00876 void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette) 00877 { 00878 int i; 00879 00880 for (i=0; i<num_pixels; i++) { 00881 //FIXME slow? 00882 dst[0]= palette[src[i]*4+0]; 00883 dst[1]= palette[src[i]*4+1]; 00884 dst[2]= palette[src[i]*4+2]; 00885 dst+= 3; 00886 } 00887 }