00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <inttypes.h>
00022 #include <string.h>
00023 #include <math.h>
00024 #include <stdio.h>
00025 #include "config.h"
00026 #include "swscale.h"
00027 #include "swscale_internal.h"
00028 #include "rgb2rgb.h"
00029 #include "libavutil/intreadwrite.h"
00030 #include "libavutil/cpu.h"
00031 #include "libavutil/avutil.h"
00032 #include "libavutil/mathematics.h"
00033 #include "libavutil/bswap.h"
00034 #include "libavutil/pixdesc.h"
00035 #include "libavutil/avassert.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 DECLARE_ALIGNED(8, const uint8_t, dithers)[8][8][8]={
00049 {
00050 { 0, 1, 0, 1, 0, 1, 0, 1,},
00051 { 1, 0, 1, 0, 1, 0, 1, 0,},
00052 { 0, 1, 0, 1, 0, 1, 0, 1,},
00053 { 1, 0, 1, 0, 1, 0, 1, 0,},
00054 { 0, 1, 0, 1, 0, 1, 0, 1,},
00055 { 1, 0, 1, 0, 1, 0, 1, 0,},
00056 { 0, 1, 0, 1, 0, 1, 0, 1,},
00057 { 1, 0, 1, 0, 1, 0, 1, 0,},
00058 },{
00059 { 1, 2, 1, 2, 1, 2, 1, 2,},
00060 { 3, 0, 3, 0, 3, 0, 3, 0,},
00061 { 1, 2, 1, 2, 1, 2, 1, 2,},
00062 { 3, 0, 3, 0, 3, 0, 3, 0,},
00063 { 1, 2, 1, 2, 1, 2, 1, 2,},
00064 { 3, 0, 3, 0, 3, 0, 3, 0,},
00065 { 1, 2, 1, 2, 1, 2, 1, 2,},
00066 { 3, 0, 3, 0, 3, 0, 3, 0,},
00067 },{
00068 { 2, 4, 3, 5, 2, 4, 3, 5,},
00069 { 6, 0, 7, 1, 6, 0, 7, 1,},
00070 { 3, 5, 2, 4, 3, 5, 2, 4,},
00071 { 7, 1, 6, 0, 7, 1, 6, 0,},
00072 { 2, 4, 3, 5, 2, 4, 3, 5,},
00073 { 6, 0, 7, 1, 6, 0, 7, 1,},
00074 { 3, 5, 2, 4, 3, 5, 2, 4,},
00075 { 7, 1, 6, 0, 7, 1, 6, 0,},
00076 },{
00077 { 4, 8, 7, 11, 4, 8, 7, 11,},
00078 { 12, 0, 15, 3, 12, 0, 15, 3,},
00079 { 6, 10, 5, 9, 6, 10, 5, 9,},
00080 { 14, 2, 13, 1, 14, 2, 13, 1,},
00081 { 4, 8, 7, 11, 4, 8, 7, 11,},
00082 { 12, 0, 15, 3, 12, 0, 15, 3,},
00083 { 6, 10, 5, 9, 6, 10, 5, 9,},
00084 { 14, 2, 13, 1, 14, 2, 13, 1,},
00085 },{
00086 { 9, 17, 15, 23, 8, 16, 14, 22,},
00087 { 25, 1, 31, 7, 24, 0, 30, 6,},
00088 { 13, 21, 11, 19, 12, 20, 10, 18,},
00089 { 29, 5, 27, 3, 28, 4, 26, 2,},
00090 { 8, 16, 14, 22, 9, 17, 15, 23,},
00091 { 24, 0, 30, 6, 25, 1, 31, 7,},
00092 { 12, 20, 10, 18, 13, 21, 11, 19,},
00093 { 28, 4, 26, 2, 29, 5, 27, 3,},
00094 },{
00095 { 18, 34, 30, 46, 17, 33, 29, 45,},
00096 { 50, 2, 62, 14, 49, 1, 61, 13,},
00097 { 26, 42, 22, 38, 25, 41, 21, 37,},
00098 { 58, 10, 54, 6, 57, 9, 53, 5,},
00099 { 16, 32, 28, 44, 19, 35, 31, 47,},
00100 { 48, 0, 60, 12, 51, 3, 63, 15,},
00101 { 24, 40, 20, 36, 27, 43, 23, 39,},
00102 { 56, 8, 52, 4, 59, 11, 55, 7,},
00103 },{
00104 { 18, 34, 30, 46, 17, 33, 29, 45,},
00105 { 50, 2, 62, 14, 49, 1, 61, 13,},
00106 { 26, 42, 22, 38, 25, 41, 21, 37,},
00107 { 58, 10, 54, 6, 57, 9, 53, 5,},
00108 { 16, 32, 28, 44, 19, 35, 31, 47,},
00109 { 48, 0, 60, 12, 51, 3, 63, 15,},
00110 { 24, 40, 20, 36, 27, 43, 23, 39,},
00111 { 56, 8, 52, 4, 59, 11, 55, 7,},
00112 },{
00113 { 36, 68, 60, 92, 34, 66, 58, 90,},
00114 { 100, 4,124, 28, 98, 2,122, 26,},
00115 { 52, 84, 44, 76, 50, 82, 42, 74,},
00116 { 116, 20,108, 12,114, 18,106, 10,},
00117 { 32, 64, 56, 88, 38, 70, 62, 94,},
00118 { 96, 0,120, 24,102, 6,126, 30,},
00119 { 48, 80, 40, 72, 54, 86, 46, 78,},
00120 { 112, 16,104, 8,118, 22,110, 14,},
00121 }};
00122
00123 static const uint8_t flat64[8]={64,64,64,64,64,64,64,64};
00124
00125 const uint16_t dither_scale[15][16]={
00126 { 2, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,},
00127 { 2, 3, 7, 7, 13, 13, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,},
00128 { 3, 3, 4, 15, 15, 29, 57, 57, 57, 113, 113, 113, 113, 113, 113, 113,},
00129 { 3, 4, 4, 5, 31, 31, 61, 121, 241, 241, 241, 241, 481, 481, 481, 481,},
00130 { 3, 4, 5, 5, 6, 63, 63, 125, 249, 497, 993, 993, 993, 993, 993, 1985,},
00131 { 3, 5, 6, 6, 6, 7, 127, 127, 253, 505, 1009, 2017, 4033, 4033, 4033, 4033,},
00132 { 3, 5, 6, 7, 7, 7, 8, 255, 255, 509, 1017, 2033, 4065, 8129,16257,16257,},
00133 { 3, 5, 6, 8, 8, 8, 8, 9, 511, 511, 1021, 2041, 4081, 8161,16321,32641,},
00134 { 3, 5, 7, 8, 9, 9, 9, 9, 10, 1023, 1023, 2045, 4089, 8177,16353,32705,},
00135 { 3, 5, 7, 8, 10, 10, 10, 10, 10, 11, 2047, 2047, 4093, 8185,16369,32737,},
00136 { 3, 5, 7, 8, 10, 11, 11, 11, 11, 11, 12, 4095, 4095, 8189,16377,32753,},
00137 { 3, 5, 7, 9, 10, 12, 12, 12, 12, 12, 12, 13, 8191, 8191,16381,32761,},
00138 { 3, 5, 7, 9, 10, 12, 13, 13, 13, 13, 13, 13, 14,16383,16383,32765,},
00139 { 3, 5, 7, 9, 10, 12, 14, 14, 14, 14, 14, 14, 14, 15,32767,32767,},
00140 { 3, 5, 7, 9, 11, 12, 14, 15, 15, 15, 15, 15, 15, 15, 16,65535,},
00141 };
00142
00143
00144 static void fillPlane(uint8_t *plane, int stride, int width, int height, int y,
00145 uint8_t val)
00146 {
00147 int i;
00148 uint8_t *ptr = plane + stride * y;
00149 for (i = 0; i < height; i++) {
00150 memset(ptr, val, width);
00151 ptr += stride;
00152 }
00153 }
00154
00155 static void fillPlane16(uint8_t *plane, int stride, int width, int height, int y,
00156 int alpha, int bits)
00157 {
00158 int i, j;
00159 uint8_t *ptr = plane + stride * y;
00160 int v = alpha ? -1 : (1<<bits);
00161 for (i = 0; i < height; i++) {
00162 for (j = 0; j < width; j++) {
00163 AV_WN16(ptr+2*j, v);
00164 }
00165 ptr += stride;
00166 }
00167 }
00168
00169 static void copyPlane(const uint8_t *src, int srcStride,
00170 int srcSliceY, int srcSliceH, int width,
00171 uint8_t *dst, int dstStride)
00172 {
00173 dst += dstStride * srcSliceY;
00174 if (dstStride == srcStride && srcStride > 0) {
00175 memcpy(dst, src, srcSliceH * dstStride);
00176 } else {
00177 int i;
00178 for (i = 0; i < srcSliceH; i++) {
00179 memcpy(dst, src, width);
00180 src += srcStride;
00181 dst += dstStride;
00182 }
00183 }
00184 }
00185
00186 static int planarToNv12Wrapper(SwsContext *c, const uint8_t *src[],
00187 int srcStride[], int srcSliceY,
00188 int srcSliceH, uint8_t *dstParam[],
00189 int dstStride[])
00190 {
00191 uint8_t *dst = dstParam[1] + dstStride[1] * srcSliceY / 2;
00192
00193 copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
00194 dstParam[0], dstStride[0]);
00195
00196 if (c->dstFormat == PIX_FMT_NV12)
00197 interleaveBytes(src[1], src[2], dst, c->srcW / 2, srcSliceH / 2,
00198 srcStride[1], srcStride[2], dstStride[0]);
00199 else
00200 interleaveBytes(src[2], src[1], dst, c->srcW / 2, srcSliceH / 2,
00201 srcStride[2], srcStride[1], dstStride[0]);
00202
00203 return srcSliceH;
00204 }
00205
00206 static int planarToYuy2Wrapper(SwsContext *c, const uint8_t *src[],
00207 int srcStride[], int srcSliceY, int srcSliceH,
00208 uint8_t *dstParam[], int dstStride[])
00209 {
00210 uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
00211
00212 yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
00213 srcStride[1], dstStride[0]);
00214
00215 return srcSliceH;
00216 }
00217
00218 static int planarToUyvyWrapper(SwsContext *c, const uint8_t *src[],
00219 int srcStride[], int srcSliceY, int srcSliceH,
00220 uint8_t *dstParam[], int dstStride[])
00221 {
00222 uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
00223
00224 yv12touyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
00225 srcStride[1], dstStride[0]);
00226
00227 return srcSliceH;
00228 }
00229
00230 static int yuv422pToYuy2Wrapper(SwsContext *c, const uint8_t *src[],
00231 int srcStride[], int srcSliceY, int srcSliceH,
00232 uint8_t *dstParam[], int dstStride[])
00233 {
00234 uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
00235
00236 yuv422ptoyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
00237 srcStride[1], dstStride[0]);
00238
00239 return srcSliceH;
00240 }
00241
00242 static int yuv422pToUyvyWrapper(SwsContext *c, const uint8_t *src[],
00243 int srcStride[], int srcSliceY, int srcSliceH,
00244 uint8_t *dstParam[], int dstStride[])
00245 {
00246 uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
00247
00248 yuv422ptouyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
00249 srcStride[1], dstStride[0]);
00250
00251 return srcSliceH;
00252 }
00253
00254 static int yuyvToYuv420Wrapper(SwsContext *c, const uint8_t *src[],
00255 int srcStride[], int srcSliceY, int srcSliceH,
00256 uint8_t *dstParam[], int dstStride[])
00257 {
00258 uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY;
00259 uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY / 2;
00260 uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY / 2;
00261
00262 yuyvtoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
00263 dstStride[1], srcStride[0]);
00264
00265 if (dstParam[3])
00266 fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
00267
00268 return srcSliceH;
00269 }
00270
00271 static int yuyvToYuv422Wrapper(SwsContext *c, const uint8_t *src[],
00272 int srcStride[], int srcSliceY, int srcSliceH,
00273 uint8_t *dstParam[], int dstStride[])
00274 {
00275 uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY;
00276 uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY;
00277 uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY;
00278
00279 yuyvtoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
00280 dstStride[1], srcStride[0]);
00281
00282 return srcSliceH;
00283 }
00284
00285 static int uyvyToYuv420Wrapper(SwsContext *c, const uint8_t *src[],
00286 int srcStride[], int srcSliceY, int srcSliceH,
00287 uint8_t *dstParam[], int dstStride[])
00288 {
00289 uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY;
00290 uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY / 2;
00291 uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY / 2;
00292
00293 uyvytoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
00294 dstStride[1], srcStride[0]);
00295
00296 if (dstParam[3])
00297 fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
00298
00299 return srcSliceH;
00300 }
00301
00302 static int uyvyToYuv422Wrapper(SwsContext *c, const uint8_t *src[],
00303 int srcStride[], int srcSliceY, int srcSliceH,
00304 uint8_t *dstParam[], int dstStride[])
00305 {
00306 uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY;
00307 uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY;
00308 uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY;
00309
00310 uyvytoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
00311 dstStride[1], srcStride[0]);
00312
00313 return srcSliceH;
00314 }
00315
00316 static void gray8aToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels,
00317 const uint8_t *palette)
00318 {
00319 int i;
00320 for (i = 0; i < num_pixels; i++)
00321 ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i << 1]] | (src[(i << 1) + 1] << 24);
00322 }
00323
00324 static void gray8aToPacked32_1(const uint8_t *src, uint8_t *dst, int num_pixels,
00325 const uint8_t *palette)
00326 {
00327 int i;
00328
00329 for (i = 0; i < num_pixels; i++)
00330 ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i << 1]] | src[(i << 1) + 1];
00331 }
00332
00333 static void gray8aToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels,
00334 const uint8_t *palette)
00335 {
00336 int i;
00337
00338 for (i = 0; i < num_pixels; i++) {
00339
00340 dst[0] = palette[src[i << 1] * 4 + 0];
00341 dst[1] = palette[src[i << 1] * 4 + 1];
00342 dst[2] = palette[src[i << 1] * 4 + 2];
00343 dst += 3;
00344 }
00345 }
00346
00347 static int packed_16bpc_bswap(SwsContext *c, const uint8_t *src[],
00348 int srcStride[], int srcSliceY, int srcSliceH,
00349 uint8_t *dst[], int dstStride[])
00350 {
00351 int i, j;
00352 int srcstr = srcStride[0] >> 1;
00353 int dststr = dstStride[0] >> 1;
00354 uint16_t *dstPtr = (uint16_t *) dst[0];
00355 const uint16_t *srcPtr = (const uint16_t *) src[0];
00356 int min_stride = FFMIN(srcstr, dststr);
00357
00358 for (i = 0; i < srcSliceH; i++) {
00359 for (j = 0; j < min_stride; j++) {
00360 dstPtr[j] = av_bswap16(srcPtr[j]);
00361 }
00362 srcPtr += srcstr;
00363 dstPtr += dststr;
00364 }
00365
00366 return srcSliceH;
00367 }
00368
00369 static int palToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[],
00370 int srcSliceY, int srcSliceH, uint8_t *dst[],
00371 int dstStride[])
00372 {
00373 const enum PixelFormat srcFormat = c->srcFormat;
00374 const enum PixelFormat dstFormat = c->dstFormat;
00375 void (*conv)(const uint8_t *src, uint8_t *dst, int num_pixels,
00376 const uint8_t *palette) = NULL;
00377 int i;
00378 uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY;
00379 const uint8_t *srcPtr = src[0];
00380
00381 if (srcFormat == PIX_FMT_GRAY8A) {
00382 switch (dstFormat) {
00383 case PIX_FMT_RGB32 : conv = gray8aToPacked32; break;
00384 case PIX_FMT_BGR32 : conv = gray8aToPacked32; break;
00385 case PIX_FMT_BGR32_1: conv = gray8aToPacked32_1; break;
00386 case PIX_FMT_RGB32_1: conv = gray8aToPacked32_1; break;
00387 case PIX_FMT_RGB24 : conv = gray8aToPacked24; break;
00388 case PIX_FMT_BGR24 : conv = gray8aToPacked24; break;
00389 }
00390 } else if (usePal(srcFormat)) {
00391 switch (dstFormat) {
00392 case PIX_FMT_RGB32 : conv = sws_convertPalette8ToPacked32; break;
00393 case PIX_FMT_BGR32 : conv = sws_convertPalette8ToPacked32; break;
00394 case PIX_FMT_BGR32_1: conv = sws_convertPalette8ToPacked32; break;
00395 case PIX_FMT_RGB32_1: conv = sws_convertPalette8ToPacked32; break;
00396 case PIX_FMT_RGB24 : conv = sws_convertPalette8ToPacked24; break;
00397 case PIX_FMT_BGR24 : conv = sws_convertPalette8ToPacked24; break;
00398 }
00399 }
00400
00401 if (!conv)
00402 av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
00403 av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
00404 else {
00405 for (i = 0; i < srcSliceH; i++) {
00406 conv(srcPtr, dstPtr, c->srcW, (uint8_t *) c->pal_rgb);
00407 srcPtr += srcStride[0];
00408 dstPtr += dstStride[0];
00409 }
00410 }
00411
00412 return srcSliceH;
00413 }
00414
00415 static void gbr24ptopacked24(const uint8_t *src[], int srcStride[],
00416 uint8_t *dst, int dstStride, int srcSliceH,
00417 int width)
00418 {
00419 int x, h, i;
00420 for (h = 0; h < srcSliceH; h++) {
00421 uint8_t *dest = dst + dstStride * h;
00422 for (x = 0; x < width; x++) {
00423 *dest++ = src[0][x];
00424 *dest++ = src[1][x];
00425 *dest++ = src[2][x];
00426 }
00427
00428 for (i = 0; i < 3; i++)
00429 src[i] += srcStride[i];
00430 }
00431 }
00432
00433 static void gbr24ptopacked32(const uint8_t *src[], int srcStride[],
00434 uint8_t *dst, int dstStride, int srcSliceH,
00435 int alpha_first, int width)
00436 {
00437 int x, h, i;
00438 for (h = 0; h < srcSliceH; h++) {
00439 uint8_t *dest = dst + dstStride * h;
00440
00441 if (alpha_first) {
00442 for (x = 0; x < width; x++) {
00443 *dest++ = 0xff;
00444 *dest++ = src[0][x];
00445 *dest++ = src[1][x];
00446 *dest++ = src[2][x];
00447 }
00448 } else {
00449 for (x = 0; x < width; x++) {
00450 *dest++ = src[0][x];
00451 *dest++ = src[1][x];
00452 *dest++ = src[2][x];
00453 *dest++ = 0xff;
00454 }
00455 }
00456
00457 for (i = 0; i < 3; i++)
00458 src[i] += srcStride[i];
00459 }
00460 }
00461
00462 static int planarRgbToRgbWrapper(SwsContext *c, const uint8_t *src[],
00463 int srcStride[], int srcSliceY, int srcSliceH,
00464 uint8_t *dst[], int dstStride[])
00465 {
00466 int alpha_first = 0;
00467 if (c->srcFormat != PIX_FMT_GBRP) {
00468 av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n",
00469 av_get_pix_fmt_name(c->srcFormat),
00470 av_get_pix_fmt_name(c->dstFormat));
00471 return srcSliceH;
00472 }
00473
00474 switch (c->dstFormat) {
00475 case PIX_FMT_BGR24:
00476 gbr24ptopacked24((const uint8_t *[]) { src[1], src[0], src[2] },
00477 (int []) { srcStride[1], srcStride[0], srcStride[2] },
00478 dst[0] + srcSliceY * dstStride[0], dstStride[0],
00479 srcSliceH, c->srcW);
00480 break;
00481
00482 case PIX_FMT_RGB24:
00483 gbr24ptopacked24((const uint8_t *[]) { src[2], src[0], src[1] },
00484 (int []) { srcStride[2], srcStride[0], srcStride[1] },
00485 dst[0] + srcSliceY * dstStride[0], dstStride[0],
00486 srcSliceH, c->srcW);
00487 break;
00488
00489 case PIX_FMT_ARGB:
00490 alpha_first = 1;
00491 case PIX_FMT_RGBA:
00492 gbr24ptopacked32((const uint8_t *[]) { src[2], src[0], src[1] },
00493 (int []) { srcStride[2], srcStride[0], srcStride[1] },
00494 dst[0] + srcSliceY * dstStride[0], dstStride[0],
00495 srcSliceH, alpha_first, c->srcW);
00496 break;
00497
00498 case PIX_FMT_ABGR:
00499 alpha_first = 1;
00500 case PIX_FMT_BGRA:
00501 gbr24ptopacked32((const uint8_t *[]) { src[1], src[0], src[2] },
00502 (int []) { srcStride[1], srcStride[0], srcStride[2] },
00503 dst[0] + srcSliceY * dstStride[0], dstStride[0],
00504 srcSliceH, alpha_first, c->srcW);
00505 break;
00506
00507 default:
00508 av_log(c, AV_LOG_ERROR,
00509 "unsupported planar RGB conversion %s -> %s\n",
00510 av_get_pix_fmt_name(c->srcFormat),
00511 av_get_pix_fmt_name(c->dstFormat));
00512 }
00513
00514 return srcSliceH;
00515 }
00516
00517 #define isRGBA32(x) ( \
00518 (x) == PIX_FMT_ARGB \
00519 || (x) == PIX_FMT_RGBA \
00520 || (x) == PIX_FMT_BGRA \
00521 || (x) == PIX_FMT_ABGR \
00522 )
00523
00524 #define isRGBA64(x) ( \
00525 (x) == PIX_FMT_RGBA64LE \
00526 || (x) == PIX_FMT_RGBA64BE \
00527 || (x) == PIX_FMT_BGRA64LE \
00528 || (x) == PIX_FMT_BGRA64BE \
00529 )
00530
00531 #define isRGB48(x) ( \
00532 (x) == PIX_FMT_RGB48LE \
00533 || (x) == PIX_FMT_RGB48BE \
00534 || (x) == PIX_FMT_BGR48LE \
00535 || (x) == PIX_FMT_BGR48BE \
00536 )
00537
00538
00539 typedef void (* rgbConvFn) (const uint8_t *, uint8_t *, int);
00540 static rgbConvFn findRgbConvFn(SwsContext *c)
00541 {
00542 const enum PixelFormat srcFormat = c->srcFormat;
00543 const enum PixelFormat dstFormat = c->dstFormat;
00544 const int srcId = c->srcFormatBpp;
00545 const int dstId = c->dstFormatBpp;
00546 rgbConvFn conv = NULL;
00547
00548 #define IS_NOT_NE(bpp, fmt) \
00549 (((bpp + 7) >> 3) == 2 && \
00550 (!(av_pix_fmt_descriptors[fmt].flags & PIX_FMT_BE) != !HAVE_BIGENDIAN))
00551
00552 #define CONV_IS(src, dst) (srcFormat == PIX_FMT_##src && dstFormat == PIX_FMT_##dst)
00553
00554 if (isRGBA32(srcFormat) && isRGBA32(dstFormat)) {
00555 if ( CONV_IS(ABGR, RGBA)
00556 || CONV_IS(ARGB, BGRA)
00557 || CONV_IS(BGRA, ARGB)
00558 || CONV_IS(RGBA, ABGR)) conv = shuffle_bytes_3210;
00559 else if (CONV_IS(ABGR, ARGB)
00560 || CONV_IS(ARGB, ABGR)) conv = shuffle_bytes_0321;
00561 else if (CONV_IS(ABGR, BGRA)
00562 || CONV_IS(ARGB, RGBA)) conv = shuffle_bytes_1230;
00563 else if (CONV_IS(BGRA, RGBA)
00564 || CONV_IS(RGBA, BGRA)) conv = shuffle_bytes_2103;
00565 else if (CONV_IS(BGRA, ABGR)
00566 || CONV_IS(RGBA, ARGB)) conv = shuffle_bytes_3012;
00567 } else if (isRGB48(srcFormat) && isRGB48(dstFormat)) {
00568 if (CONV_IS(RGB48LE, BGR48LE)
00569 || CONV_IS(BGR48LE, RGB48LE)
00570 || CONV_IS(RGB48BE, BGR48BE)
00571 || CONV_IS(BGR48BE, RGB48BE)) conv = rgb48tobgr48_nobswap;
00572 else if (CONV_IS(RGB48LE, BGR48BE)
00573 || CONV_IS(BGR48LE, RGB48BE)
00574 || CONV_IS(RGB48BE, BGR48LE)
00575 || CONV_IS(BGR48BE, RGB48LE)) conv = rgb48tobgr48_bswap;
00576 } else if (isRGBA64(srcFormat) && isRGB48(dstFormat)) {
00577 if (CONV_IS(RGBA64LE, BGR48LE)
00578 || CONV_IS(BGRA64LE, RGB48LE)
00579 || CONV_IS(RGBA64BE, BGR48BE)
00580 || CONV_IS(BGRA64BE, RGB48BE)) conv = rgb64tobgr48_nobswap;
00581 else if (CONV_IS(RGBA64LE, BGR48BE)
00582 || CONV_IS(BGRA64LE, RGB48BE)
00583 || CONV_IS(RGBA64BE, BGR48LE)
00584 || CONV_IS(BGRA64BE, RGB48LE)) conv = rgb64tobgr48_bswap;
00585 else if (CONV_IS(RGBA64LE, RGB48LE)
00586 || CONV_IS(BGRA64LE, BGR48LE)
00587 || CONV_IS(RGBA64BE, RGB48BE)
00588 || CONV_IS(BGRA64BE, BGR48BE)) conv = rgb64to48_nobswap;
00589 else if (CONV_IS(RGBA64LE, RGB48BE)
00590 || CONV_IS(BGRA64LE, BGR48BE)
00591 || CONV_IS(RGBA64BE, RGB48LE)
00592 || CONV_IS(BGRA64BE, BGR48LE)) conv = rgb64to48_bswap;
00593 } else
00594
00595 if ((isBGRinInt(srcFormat) && isBGRinInt(dstFormat)) ||
00596 (isRGBinInt(srcFormat) && isRGBinInt(dstFormat))) {
00597 switch (srcId | (dstId << 16)) {
00598 case 0x000F000C: conv = rgb12to15; break;
00599 case 0x000F0010: conv = rgb16to15; break;
00600 case 0x000F0018: conv = rgb24to15; break;
00601 case 0x000F0020: conv = rgb32to15; break;
00602 case 0x0010000F: conv = rgb15to16; break;
00603 case 0x00100018: conv = rgb24to16; break;
00604 case 0x00100020: conv = rgb32to16; break;
00605 case 0x0018000F: conv = rgb15to24; break;
00606 case 0x00180010: conv = rgb16to24; break;
00607 case 0x00180020: conv = rgb32to24; break;
00608 case 0x0020000F: conv = rgb15to32; break;
00609 case 0x00200010: conv = rgb16to32; break;
00610 case 0x00200018: conv = rgb24to32; break;
00611 }
00612 } else if ((isBGRinInt(srcFormat) && isRGBinInt(dstFormat)) ||
00613 (isRGBinInt(srcFormat) && isBGRinInt(dstFormat))) {
00614 switch (srcId | (dstId << 16)) {
00615 case 0x000C000C: conv = rgb12tobgr12; break;
00616 case 0x000F000F: conv = rgb15tobgr15; break;
00617 case 0x000F0010: conv = rgb16tobgr15; break;
00618 case 0x000F0018: conv = rgb24tobgr15; break;
00619 case 0x000F0020: conv = rgb32tobgr15; break;
00620 case 0x0010000F: conv = rgb15tobgr16; break;
00621 case 0x00100010: conv = rgb16tobgr16; break;
00622 case 0x00100018: conv = rgb24tobgr16; break;
00623 case 0x00100020: conv = rgb32tobgr16; break;
00624 case 0x0018000F: conv = rgb15tobgr24; break;
00625 case 0x00180010: conv = rgb16tobgr24; break;
00626 case 0x00180018: conv = rgb24tobgr24; break;
00627 case 0x00180020: conv = rgb32tobgr24; break;
00628 case 0x0020000F: conv = rgb15tobgr32; break;
00629 case 0x00200010: conv = rgb16tobgr32; break;
00630 case 0x00200018: conv = rgb24tobgr32; break;
00631 }
00632 }
00633
00634 return conv;
00635 }
00636
00637
00638 static int rgbToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[],
00639 int srcSliceY, int srcSliceH, uint8_t *dst[],
00640 int dstStride[])
00641
00642 {
00643 const enum PixelFormat srcFormat = c->srcFormat;
00644 const enum PixelFormat dstFormat = c->dstFormat;
00645 const int srcBpp = (c->srcFormatBpp + 7) >> 3;
00646 const int dstBpp = (c->dstFormatBpp + 7) >> 3;
00647 rgbConvFn conv = findRgbConvFn(c);
00648
00649 if (!conv) {
00650 av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
00651 av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
00652 } else {
00653 const uint8_t *srcPtr = src[0];
00654 uint8_t *dstPtr = dst[0];
00655 int src_bswap = IS_NOT_NE(c->srcFormatBpp, srcFormat);
00656 int dst_bswap = IS_NOT_NE(c->dstFormatBpp, dstFormat);
00657
00658 if ((srcFormat == PIX_FMT_RGB32_1 || srcFormat == PIX_FMT_BGR32_1) &&
00659 !isRGBA32(dstFormat))
00660 srcPtr += ALT32_CORR;
00661
00662 if ((dstFormat == PIX_FMT_RGB32_1 || dstFormat == PIX_FMT_BGR32_1) &&
00663 !isRGBA32(srcFormat))
00664 dstPtr += ALT32_CORR;
00665
00666 if (dstStride[0] * srcBpp == srcStride[0] * dstBpp && srcStride[0] > 0 &&
00667 !(srcStride[0] % srcBpp) && !dst_bswap && !src_bswap)
00668 conv(srcPtr, dstPtr + dstStride[0] * srcSliceY,
00669 srcSliceH * srcStride[0]);
00670 else {
00671 int i, j;
00672 dstPtr += dstStride[0] * srcSliceY;
00673
00674 for (i = 0; i < srcSliceH; i++) {
00675 if(src_bswap) {
00676 for(j=0; j<c->srcW; j++)
00677 ((uint16_t*)c->formatConvBuffer)[j] = av_bswap16(((uint16_t*)srcPtr)[j]);
00678 conv(c->formatConvBuffer, dstPtr, c->srcW * srcBpp);
00679 }else
00680 conv(srcPtr, dstPtr, c->srcW * srcBpp);
00681 if(dst_bswap)
00682 for(j=0; j<c->srcW; j++)
00683 ((uint16_t*)dstPtr)[j] = av_bswap16(((uint16_t*)dstPtr)[j]);
00684 srcPtr += srcStride[0];
00685 dstPtr += dstStride[0];
00686 }
00687 }
00688 }
00689 return srcSliceH;
00690 }
00691
00692 static int bgr24ToYv12Wrapper(SwsContext *c, const uint8_t *src[],
00693 int srcStride[], int srcSliceY, int srcSliceH,
00694 uint8_t *dst[], int dstStride[])
00695 {
00696 rgb24toyv12(
00697 src[0],
00698 dst[0] + srcSliceY * dstStride[0],
00699 dst[1] + (srcSliceY >> 1) * dstStride[1],
00700 dst[2] + (srcSliceY >> 1) * dstStride[2],
00701 c->srcW, srcSliceH,
00702 dstStride[0], dstStride[1], srcStride[0]);
00703 if (dst[3])
00704 fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
00705 return srcSliceH;
00706 }
00707
00708 static int yvu9ToYv12Wrapper(SwsContext *c, const uint8_t *src[],
00709 int srcStride[], int srcSliceY, int srcSliceH,
00710 uint8_t *dst[], int dstStride[])
00711 {
00712 copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
00713 dst[0], dstStride[0]);
00714
00715 planar2x(src[1], dst[1] + dstStride[1] * (srcSliceY >> 1), c->chrSrcW,
00716 srcSliceH >> 2, srcStride[1], dstStride[1]);
00717 planar2x(src[2], dst[2] + dstStride[2] * (srcSliceY >> 1), c->chrSrcW,
00718 srcSliceH >> 2, srcStride[2], dstStride[2]);
00719 if (dst[3])
00720 fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
00721 return srcSliceH;
00722 }
00723
00724
00725 static int packedCopyWrapper(SwsContext *c, const uint8_t *src[],
00726 int srcStride[], int srcSliceY, int srcSliceH,
00727 uint8_t *dst[], int dstStride[])
00728 {
00729 if (dstStride[0] == srcStride[0] && srcStride[0] > 0)
00730 memcpy(dst[0] + dstStride[0] * srcSliceY, src[0], srcSliceH * dstStride[0]);
00731 else {
00732 int i;
00733 const uint8_t *srcPtr = src[0];
00734 uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY;
00735 int length = 0;
00736
00737
00738 while (length + c->srcW <= FFABS(dstStride[0]) &&
00739 length + c->srcW <= FFABS(srcStride[0]))
00740 length += c->srcW;
00741 av_assert1(length != 0);
00742
00743 for (i = 0; i < srcSliceH; i++) {
00744 memcpy(dstPtr, srcPtr, length);
00745 srcPtr += srcStride[0];
00746 dstPtr += dstStride[0];
00747 }
00748 }
00749 return srcSliceH;
00750 }
00751
00752 #define DITHER_COPY(dst, dstStride, src, srcStride, bswap, dbswap)\
00753 uint16_t scale= dither_scale[dst_depth-1][src_depth-1];\
00754 int shift= src_depth-dst_depth + dither_scale[src_depth-2][dst_depth-1];\
00755 for (i = 0; i < height; i++) {\
00756 const uint8_t *dither= dithers[src_depth-9][i&7];\
00757 for (j = 0; j < length-7; j+=8){\
00758 dst[j+0] = dbswap((bswap(src[j+0]) + dither[0])*scale>>shift);\
00759 dst[j+1] = dbswap((bswap(src[j+1]) + dither[1])*scale>>shift);\
00760 dst[j+2] = dbswap((bswap(src[j+2]) + dither[2])*scale>>shift);\
00761 dst[j+3] = dbswap((bswap(src[j+3]) + dither[3])*scale>>shift);\
00762 dst[j+4] = dbswap((bswap(src[j+4]) + dither[4])*scale>>shift);\
00763 dst[j+5] = dbswap((bswap(src[j+5]) + dither[5])*scale>>shift);\
00764 dst[j+6] = dbswap((bswap(src[j+6]) + dither[6])*scale>>shift);\
00765 dst[j+7] = dbswap((bswap(src[j+7]) + dither[7])*scale>>shift);\
00766 }\
00767 for (; j < length; j++)\
00768 dst[j] = dbswap((bswap(src[j]) + dither[j&7])*scale>>shift);\
00769 dst += dstStride;\
00770 src += srcStride;\
00771 }
00772
00773 static int planarCopyWrapper(SwsContext *c, const uint8_t *src[],
00774 int srcStride[], int srcSliceY, int srcSliceH,
00775 uint8_t *dst[], int dstStride[])
00776 {
00777 int plane, i, j;
00778 for (plane = 0; plane < 4; plane++) {
00779 int length = (plane == 0 || plane == 3) ? c->srcW : -((-c->srcW ) >> c->chrDstHSubSample);
00780 int y = (plane == 0 || plane == 3) ? srcSliceY: -((-srcSliceY) >> c->chrDstVSubSample);
00781 int height = (plane == 0 || plane == 3) ? srcSliceH: -((-srcSliceH) >> c->chrDstVSubSample);
00782 const uint8_t *srcPtr = src[plane];
00783 uint8_t *dstPtr = dst[plane] + dstStride[plane] * y;
00784 int shiftonly= plane==1 || plane==2 || (!c->srcRange && plane==0);
00785
00786 if (!dst[plane])
00787 continue;
00788
00789 if (plane == 1 && !dst[2]) continue;
00790 if (!src[plane] || (plane == 1 && !src[2])) {
00791 if (is16BPS(c->dstFormat) || isNBPS(c->dstFormat)) {
00792 fillPlane16(dst[plane], dstStride[plane], length, height, y,
00793 plane == 3, av_pix_fmt_descriptors[c->dstFormat].comp[plane].depth_minus1);
00794 } else {
00795 fillPlane(dst[plane], dstStride[plane], length, height, y,
00796 (plane == 3) ? 255 : 128);
00797 }
00798 } else {
00799 if(isNBPS(c->srcFormat) || isNBPS(c->dstFormat)
00800 || (is16BPS(c->srcFormat) != is16BPS(c->dstFormat))
00801 ) {
00802 const int src_depth = av_pix_fmt_descriptors[c->srcFormat].comp[plane].depth_minus1 + 1;
00803 const int dst_depth = av_pix_fmt_descriptors[c->dstFormat].comp[plane].depth_minus1 + 1;
00804 const uint16_t *srcPtr2 = (const uint16_t *) srcPtr;
00805 uint16_t *dstPtr2 = (uint16_t*)dstPtr;
00806
00807 if (dst_depth == 8) {
00808 if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
00809 DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, , )
00810 } else {
00811 DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, av_bswap16, )
00812 }
00813 } else if (src_depth == 8) {
00814 for (i = 0; i < height; i++) {
00815 #define COPY816(w)\
00816 if(shiftonly){\
00817 for (j = 0; j < length; j++)\
00818 w(&dstPtr2[j], srcPtr[j]<<(dst_depth-8));\
00819 }else{\
00820 for (j = 0; j < length; j++)\
00821 w(&dstPtr2[j], (srcPtr[j]<<(dst_depth-8)) |\
00822 (srcPtr[j]>>(2*8-dst_depth)));\
00823 }
00824 if(isBE(c->dstFormat)){
00825 COPY816(AV_WB16)
00826 } else {
00827 COPY816(AV_WL16)
00828 }
00829 dstPtr2 += dstStride[plane]/2;
00830 srcPtr += srcStride[plane];
00831 }
00832 } else if (src_depth <= dst_depth) {
00833 int orig_length = length;
00834 for (i = 0; i < height; i++) {
00835 if(isBE(c->srcFormat) == HAVE_BIGENDIAN &&
00836 isBE(c->dstFormat) == HAVE_BIGENDIAN &&
00837 shiftonly) {
00838 unsigned shift = dst_depth - src_depth;
00839 length = orig_length;
00840 #if HAVE_FAST_64BIT
00841 #define FAST_COPY_UP(shift) \
00842 for (j = 0; j < length - 3; j += 4) { \
00843 uint64_t v = AV_RN64A(srcPtr2 + j); \
00844 AV_WN64A(dstPtr2 + j, v << shift); \
00845 } \
00846 length &= 3;
00847 #else
00848 #define FAST_COPY_UP(shift) \
00849 for (j = 0; j < length - 1; j += 2) { \
00850 uint32_t v = AV_RN32A(srcPtr2 + j); \
00851 AV_WN32A(dstPtr2 + j, v << shift); \
00852 } \
00853 length &= 1;
00854 #endif
00855 switch (shift)
00856 {
00857 case 6: FAST_COPY_UP(6); break;
00858 case 7: FAST_COPY_UP(7); break;
00859 }
00860 }
00861 #define COPY_UP(r,w) \
00862 if(shiftonly){\
00863 for (j = 0; j < length; j++){ \
00864 unsigned int v= r(&srcPtr2[j]);\
00865 w(&dstPtr2[j], v<<(dst_depth-src_depth));\
00866 }\
00867 }else{\
00868 for (j = 0; j < length; j++){ \
00869 unsigned int v= r(&srcPtr2[j]);\
00870 w(&dstPtr2[j], (v<<(dst_depth-src_depth)) | \
00871 (v>>(2*src_depth-dst_depth)));\
00872 }\
00873 }
00874 if(isBE(c->srcFormat)){
00875 if(isBE(c->dstFormat)){
00876 COPY_UP(AV_RB16, AV_WB16)
00877 } else {
00878 COPY_UP(AV_RB16, AV_WL16)
00879 }
00880 } else {
00881 if(isBE(c->dstFormat)){
00882 COPY_UP(AV_RL16, AV_WB16)
00883 } else {
00884 COPY_UP(AV_RL16, AV_WL16)
00885 }
00886 }
00887 dstPtr2 += dstStride[plane]/2;
00888 srcPtr2 += srcStride[plane]/2;
00889 }
00890 } else {
00891 if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
00892 if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
00893 DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , )
00894 } else {
00895 DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , av_bswap16)
00896 }
00897 }else{
00898 if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
00899 DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, )
00900 } else {
00901 DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, av_bswap16)
00902 }
00903 }
00904 }
00905 } else if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat) &&
00906 isBE(c->srcFormat) != isBE(c->dstFormat)) {
00907
00908 for (i = 0; i < height; i++) {
00909 for (j = 0; j < length; j++)
00910 ((uint16_t *) dstPtr)[j] = av_bswap16(((const uint16_t *) srcPtr)[j]);
00911 srcPtr += srcStride[plane];
00912 dstPtr += dstStride[plane];
00913 }
00914 } else if (dstStride[plane] == srcStride[plane] &&
00915 srcStride[plane] > 0 && srcStride[plane] == length) {
00916 memcpy(dst[plane] + dstStride[plane] * y, src[plane],
00917 height * dstStride[plane]);
00918 } else {
00919 if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat))
00920 length *= 2;
00921 else if (!av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1)
00922 length >>= 3;
00923 for (i = 0; i < height; i++) {
00924 memcpy(dstPtr, srcPtr, length);
00925 srcPtr += srcStride[plane];
00926 dstPtr += dstStride[plane];
00927 }
00928 }
00929 }
00930 }
00931 return srcSliceH;
00932 }
00933
00934
00935 #define IS_DIFFERENT_ENDIANESS(src_fmt, dst_fmt, pix_fmt) \
00936 ((src_fmt == pix_fmt ## BE && dst_fmt == pix_fmt ## LE) || \
00937 (src_fmt == pix_fmt ## LE && dst_fmt == pix_fmt ## BE))
00938
00939
00940 void ff_get_unscaled_swscale(SwsContext *c)
00941 {
00942 const enum PixelFormat srcFormat = c->srcFormat;
00943 const enum PixelFormat dstFormat = c->dstFormat;
00944 const int flags = c->flags;
00945 const int dstH = c->dstH;
00946 int needsDither;
00947
00948 needsDither = isAnyRGB(dstFormat) &&
00949 c->dstFormatBpp < 24 &&
00950 (c->dstFormatBpp < c->srcFormatBpp || (!isAnyRGB(srcFormat)));
00951
00952
00953 if ((srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) &&
00954 (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21)) {
00955 c->swScale = planarToNv12Wrapper;
00956 }
00957
00958 if ((srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUV422P ||
00959 srcFormat == PIX_FMT_YUVA420P) && isAnyRGB(dstFormat) &&
00960 !(flags & SWS_ACCURATE_RND) && !(dstH & 1)) {
00961 c->swScale = ff_yuv2rgb_get_func_ptr(c);
00962 }
00963
00964 if (srcFormat == PIX_FMT_YUV410P &&
00965 (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P) &&
00966 !(flags & SWS_BITEXACT)) {
00967 c->swScale = yvu9ToYv12Wrapper;
00968 }
00969
00970
00971 if (srcFormat == PIX_FMT_BGR24 &&
00972 (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P) &&
00973 !(flags & SWS_ACCURATE_RND))
00974 c->swScale = bgr24ToYv12Wrapper;
00975
00976
00977 if (isAnyRGB(srcFormat) && isAnyRGB(dstFormat) && findRgbConvFn(c)
00978 && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT))))
00979 c->swScale= rgbToRgbWrapper;
00980
00981 #define isByteRGB(f) (\
00982 f == PIX_FMT_RGB32 ||\
00983 f == PIX_FMT_RGB32_1 ||\
00984 f == PIX_FMT_RGB24 ||\
00985 f == PIX_FMT_BGR32 ||\
00986 f == PIX_FMT_BGR32_1 ||\
00987 f == PIX_FMT_BGR24)
00988
00989 if (isAnyRGB(srcFormat) && isPlanar(srcFormat) && isByteRGB(dstFormat))
00990 c->swScale = planarRgbToRgbWrapper;
00991
00992
00993 if (IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR444) ||
00994 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR48) ||
00995 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGRA64) ||
00996 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR555) ||
00997 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR565) ||
00998 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_GRAY16) ||
00999 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB444) ||
01000 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB48) ||
01001 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGBA64) ||
01002 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB555) ||
01003 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB565))
01004 c->swScale = packed_16bpc_bswap;
01005
01006 if (usePal(srcFormat) && isByteRGB(dstFormat))
01007 c->swScale = palToRgbWrapper;
01008
01009 if (srcFormat == PIX_FMT_YUV422P) {
01010 if (dstFormat == PIX_FMT_YUYV422)
01011 c->swScale = yuv422pToYuy2Wrapper;
01012 else if (dstFormat == PIX_FMT_UYVY422)
01013 c->swScale = yuv422pToUyvyWrapper;
01014 }
01015
01016
01017 if (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)) {
01018
01019 if (srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) {
01020 if (dstFormat == PIX_FMT_YUYV422)
01021 c->swScale = planarToYuy2Wrapper;
01022 else if (dstFormat == PIX_FMT_UYVY422)
01023 c->swScale = planarToUyvyWrapper;
01024 }
01025 }
01026 if (srcFormat == PIX_FMT_YUYV422 &&
01027 (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P))
01028 c->swScale = yuyvToYuv420Wrapper;
01029 if (srcFormat == PIX_FMT_UYVY422 &&
01030 (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P))
01031 c->swScale = uyvyToYuv420Wrapper;
01032 if (srcFormat == PIX_FMT_YUYV422 && dstFormat == PIX_FMT_YUV422P)
01033 c->swScale = yuyvToYuv422Wrapper;
01034 if (srcFormat == PIX_FMT_UYVY422 && dstFormat == PIX_FMT_YUV422P)
01035 c->swScale = uyvyToYuv422Wrapper;
01036
01037 #define isPlanarGray(x) (isGray(x) && (x) != PIX_FMT_GRAY8A)
01038
01039 if ( srcFormat == dstFormat ||
01040 (srcFormat == PIX_FMT_YUVA420P && dstFormat == PIX_FMT_YUV420P) ||
01041 (srcFormat == PIX_FMT_YUV420P && dstFormat == PIX_FMT_YUVA420P) ||
01042 (isPlanarYUV(srcFormat) && isPlanarGray(dstFormat)) ||
01043 (isPlanarYUV(dstFormat) && isPlanarGray(srcFormat)) ||
01044 (isPlanarGray(dstFormat) && isPlanarGray(srcFormat)) ||
01045 (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat) &&
01046 c->chrDstHSubSample == c->chrSrcHSubSample &&
01047 c->chrDstVSubSample == c->chrSrcVSubSample &&
01048 dstFormat != PIX_FMT_NV12 && dstFormat != PIX_FMT_NV21 &&
01049 srcFormat != PIX_FMT_NV12 && srcFormat != PIX_FMT_NV21))
01050 {
01051 if (isPacked(c->srcFormat))
01052 c->swScale = packedCopyWrapper;
01053 else
01054 c->swScale = planarCopyWrapper;
01055 }
01056
01057 if (ARCH_BFIN)
01058 ff_bfin_get_unscaled_swscale(c);
01059 if (HAVE_ALTIVEC)
01060 ff_swscale_get_unscaled_altivec(c);
01061 }
01062
01063 static void reset_ptr(const uint8_t *src[], int format)
01064 {
01065 if (!isALPHA(format))
01066 src[3] = NULL;
01067 if (!isPlanar(format)) {
01068 src[3] = src[2] = NULL;
01069
01070 if (!usePal(format))
01071 src[1] = NULL;
01072 }
01073 }
01074
01075 static int check_image_pointers(const uint8_t * const data[4], enum PixelFormat pix_fmt,
01076 const int linesizes[4])
01077 {
01078 const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
01079 int i;
01080
01081 for (i = 0; i < 4; i++) {
01082 int plane = desc->comp[i].plane;
01083 if (!data[plane] || !linesizes[plane])
01084 return 0;
01085 }
01086
01087 return 1;
01088 }
01089
01094 int attribute_align_arg sws_scale(struct SwsContext *c,
01095 const uint8_t * const srcSlice[],
01096 const int srcStride[], int srcSliceY,
01097 int srcSliceH, uint8_t *const dst[],
01098 const int dstStride[])
01099 {
01100 int i, ret;
01101 const uint8_t *src2[4] = { srcSlice[0], srcSlice[1], srcSlice[2], srcSlice[3] };
01102 uint8_t *dst2[4] = { dst[0], dst[1], dst[2], dst[3] };
01103 uint8_t *rgb0_tmp = NULL;
01104
01105
01106 if (srcSliceH == 0)
01107 return 0;
01108
01109 if (!check_image_pointers(srcSlice, c->srcFormat, srcStride)) {
01110 av_log(c, AV_LOG_ERROR, "bad src image pointers\n");
01111 return 0;
01112 }
01113 if (!check_image_pointers((const uint8_t* const*)dst, c->dstFormat, dstStride)) {
01114 av_log(c, AV_LOG_ERROR, "bad dst image pointers\n");
01115 return 0;
01116 }
01117
01118 if (c->sliceDir == 0 && srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) {
01119 av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n");
01120 return 0;
01121 }
01122 if (c->sliceDir == 0) {
01123 if (srcSliceY == 0) c->sliceDir = 1; else c->sliceDir = -1;
01124 }
01125
01126 if (usePal(c->srcFormat)) {
01127 for (i = 0; i < 256; i++) {
01128 int p, r, g, b, y, u, v, a = 0xff;
01129 if (c->srcFormat == PIX_FMT_PAL8) {
01130 p = ((const uint32_t *)(srcSlice[1]))[i];
01131 a = (p >> 24) & 0xFF;
01132 r = (p >> 16) & 0xFF;
01133 g = (p >> 8) & 0xFF;
01134 b = p & 0xFF;
01135 } else if (c->srcFormat == PIX_FMT_RGB8) {
01136 r = ( i >> 5 ) * 36;
01137 g = ((i >> 2) & 7) * 36;
01138 b = ( i & 3) * 85;
01139 } else if (c->srcFormat == PIX_FMT_BGR8) {
01140 b = ( i >> 6 ) * 85;
01141 g = ((i >> 3) & 7) * 36;
01142 r = ( i & 7) * 36;
01143 } else if (c->srcFormat == PIX_FMT_RGB4_BYTE) {
01144 r = ( i >> 3 ) * 255;
01145 g = ((i >> 1) & 3) * 85;
01146 b = ( i & 1) * 255;
01147 } else if (c->srcFormat == PIX_FMT_GRAY8 || c->srcFormat == PIX_FMT_GRAY8A) {
01148 r = g = b = i;
01149 } else {
01150 av_assert1(c->srcFormat == PIX_FMT_BGR4_BYTE);
01151 b = ( i >> 3 ) * 255;
01152 g = ((i >> 1) & 3) * 85;
01153 r = ( i & 1) * 255;
01154 }
01155 y = av_clip_uint8((RY * r + GY * g + BY * b + ( 33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
01156 u = av_clip_uint8((RU * r + GU * g + BU * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
01157 v = av_clip_uint8((RV * r + GV * g + BV * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
01158 c->pal_yuv[i]= y + (u<<8) + (v<<16) + (a<<24);
01159
01160 switch (c->dstFormat) {
01161 case PIX_FMT_BGR32:
01162 #if !HAVE_BIGENDIAN
01163 case PIX_FMT_RGB24:
01164 #endif
01165 c->pal_rgb[i]= r + (g<<8) + (b<<16) + (a<<24);
01166 break;
01167 case PIX_FMT_BGR32_1:
01168 #if HAVE_BIGENDIAN
01169 case PIX_FMT_BGR24:
01170 #endif
01171 c->pal_rgb[i]= a + (r<<8) + (g<<16) + (b<<24);
01172 break;
01173 case PIX_FMT_RGB32_1:
01174 #if HAVE_BIGENDIAN
01175 case PIX_FMT_RGB24:
01176 #endif
01177 c->pal_rgb[i]= a + (b<<8) + (g<<16) + (r<<24);
01178 break;
01179 case PIX_FMT_RGB32:
01180 #if !HAVE_BIGENDIAN
01181 case PIX_FMT_BGR24:
01182 #endif
01183 default:
01184 c->pal_rgb[i]= b + (g<<8) + (r<<16) + (a<<24);
01185 }
01186 }
01187 }
01188
01189 if (c->src0Alpha && !c->dst0Alpha && isALPHA(c->dstFormat)) {
01190 uint8_t *base;
01191 int x,y;
01192 rgb0_tmp = av_malloc(FFABS(srcStride[0]) * srcSliceH + 32);
01193 base = srcStride[0] < 0 ? rgb0_tmp - srcStride[0] * (srcSliceH-1) : rgb0_tmp;
01194 for (y=0; y<srcSliceH; y++){
01195 memcpy(base + srcStride[0]*y, src2[0] + srcStride[0]*y, 4*c->srcW);
01196 for (x=c->src0Alpha-1; x<4*c->srcW; x+=4) {
01197 base[ srcStride[0]*y + x] = 0xFF;
01198 }
01199 }
01200 src2[0] = base;
01201 }
01202
01203
01204 if (c->sliceDir == 1) {
01205
01206 int srcStride2[4] = { srcStride[0], srcStride[1], srcStride[2],
01207 srcStride[3] };
01208 int dstStride2[4] = { dstStride[0], dstStride[1], dstStride[2],
01209 dstStride[3] };
01210
01211 reset_ptr(src2, c->srcFormat);
01212 reset_ptr((void*)dst2, c->dstFormat);
01213
01214
01215 if (srcSliceY + srcSliceH == c->srcH)
01216 c->sliceDir = 0;
01217
01218 ret = c->swScale(c, src2, srcStride2, srcSliceY, srcSliceH, dst2,
01219 dstStride2);
01220 } else {
01221
01222 int srcStride2[4] = { -srcStride[0], -srcStride[1], -srcStride[2],
01223 -srcStride[3] };
01224 int dstStride2[4] = { -dstStride[0], -dstStride[1], -dstStride[2],
01225 -dstStride[3] };
01226
01227 src2[0] += (srcSliceH - 1) * srcStride[0];
01228 if (!usePal(c->srcFormat))
01229 src2[1] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[1];
01230 src2[2] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[2];
01231 src2[3] += (srcSliceH - 1) * srcStride[3];
01232 dst2[0] += ( c->dstH - 1) * dstStride[0];
01233 dst2[1] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[1];
01234 dst2[2] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[2];
01235 dst2[3] += ( c->dstH - 1) * dstStride[3];
01236
01237 reset_ptr(src2, c->srcFormat);
01238 reset_ptr((void*)dst2, c->dstFormat);
01239
01240
01241 if (!srcSliceY)
01242 c->sliceDir = 0;
01243
01244 ret = c->swScale(c, src2, srcStride2, c->srcH-srcSliceY-srcSliceH,
01245 srcSliceH, dst2, dstStride2);
01246 }
01247
01248 av_free(rgb0_tmp);
01249 return ret;
01250 }
01251
01252
01253 void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst,
01254 int num_pixels, const uint8_t *palette)
01255 {
01256 int i;
01257
01258 for (i = 0; i < num_pixels; i++)
01259 ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i]];
01260 }
01261
01262
01263 void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst,
01264 int num_pixels, const uint8_t *palette)
01265 {
01266 int i;
01267
01268 for (i = 0; i < num_pixels; i++) {
01269
01270 dst[0] = palette[src[i] * 4 + 0];
01271 dst[1] = palette[src[i] * 4 + 1];
01272 dst[2] = palette[src[i] * 4 + 2];
01273 dst += 3;
01274 }
01275 }