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 DECLARE_ALIGNED(8, const uint8_t, dithers)[8][8][8]={
00038 {
00039 { 0, 1, 0, 1, 0, 1, 0, 1,},
00040 { 1, 0, 1, 0, 1, 0, 1, 0,},
00041 { 0, 1, 0, 1, 0, 1, 0, 1,},
00042 { 1, 0, 1, 0, 1, 0, 1, 0,},
00043 { 0, 1, 0, 1, 0, 1, 0, 1,},
00044 { 1, 0, 1, 0, 1, 0, 1, 0,},
00045 { 0, 1, 0, 1, 0, 1, 0, 1,},
00046 { 1, 0, 1, 0, 1, 0, 1, 0,},
00047 },{
00048 { 1, 2, 1, 2, 1, 2, 1, 2,},
00049 { 3, 0, 3, 0, 3, 0, 3, 0,},
00050 { 1, 2, 1, 2, 1, 2, 1, 2,},
00051 { 3, 0, 3, 0, 3, 0, 3, 0,},
00052 { 1, 2, 1, 2, 1, 2, 1, 2,},
00053 { 3, 0, 3, 0, 3, 0, 3, 0,},
00054 { 1, 2, 1, 2, 1, 2, 1, 2,},
00055 { 3, 0, 3, 0, 3, 0, 3, 0,},
00056 },{
00057 { 2, 4, 3, 5, 2, 4, 3, 5,},
00058 { 6, 0, 7, 1, 6, 0, 7, 1,},
00059 { 3, 5, 2, 4, 3, 5, 2, 4,},
00060 { 7, 1, 6, 0, 7, 1, 6, 0,},
00061 { 2, 4, 3, 5, 2, 4, 3, 5,},
00062 { 6, 0, 7, 1, 6, 0, 7, 1,},
00063 { 3, 5, 2, 4, 3, 5, 2, 4,},
00064 { 7, 1, 6, 0, 7, 1, 6, 0,},
00065 },{
00066 { 4, 8, 7, 11, 4, 8, 7, 11,},
00067 { 12, 0, 15, 3, 12, 0, 15, 3,},
00068 { 6, 10, 5, 9, 6, 10, 5, 9,},
00069 { 14, 2, 13, 1, 14, 2, 13, 1,},
00070 { 4, 8, 7, 11, 4, 8, 7, 11,},
00071 { 12, 0, 15, 3, 12, 0, 15, 3,},
00072 { 6, 10, 5, 9, 6, 10, 5, 9,},
00073 { 14, 2, 13, 1, 14, 2, 13, 1,},
00074 },{
00075 { 9, 17, 15, 23, 8, 16, 14, 22,},
00076 { 25, 1, 31, 7, 24, 0, 30, 6,},
00077 { 13, 21, 11, 19, 12, 20, 10, 18,},
00078 { 29, 5, 27, 3, 28, 4, 26, 2,},
00079 { 8, 16, 14, 22, 9, 17, 15, 23,},
00080 { 24, 0, 30, 6, 25, 1, 31, 7,},
00081 { 12, 20, 10, 18, 13, 21, 11, 19,},
00082 { 28, 4, 26, 2, 29, 5, 27, 3,},
00083 },{
00084 { 18, 34, 30, 46, 17, 33, 29, 45,},
00085 { 50, 2, 62, 14, 49, 1, 61, 13,},
00086 { 26, 42, 22, 38, 25, 41, 21, 37,},
00087 { 58, 10, 54, 6, 57, 9, 53, 5,},
00088 { 16, 32, 28, 44, 19, 35, 31, 47,},
00089 { 48, 0, 60, 12, 51, 3, 63, 15,},
00090 { 24, 40, 20, 36, 27, 43, 23, 39,},
00091 { 56, 8, 52, 4, 59, 11, 55, 7,},
00092 },{
00093 { 18, 34, 30, 46, 17, 33, 29, 45,},
00094 { 50, 2, 62, 14, 49, 1, 61, 13,},
00095 { 26, 42, 22, 38, 25, 41, 21, 37,},
00096 { 58, 10, 54, 6, 57, 9, 53, 5,},
00097 { 16, 32, 28, 44, 19, 35, 31, 47,},
00098 { 48, 0, 60, 12, 51, 3, 63, 15,},
00099 { 24, 40, 20, 36, 27, 43, 23, 39,},
00100 { 56, 8, 52, 4, 59, 11, 55, 7,},
00101 },{
00102 { 36, 68, 60, 92, 34, 66, 58, 90,},
00103 { 100, 4,124, 28, 98, 2,122, 26,},
00104 { 52, 84, 44, 76, 50, 82, 42, 74,},
00105 { 116, 20,108, 12,114, 18,106, 10,},
00106 { 32, 64, 56, 88, 38, 70, 62, 94,},
00107 { 96, 0,120, 24,102, 6,126, 30,},
00108 { 48, 80, 40, 72, 54, 86, 46, 78,},
00109 { 112, 16,104, 8,118, 22,110, 14,},
00110 }};
00111
00112 const uint16_t dither_scale[15][16]={
00113 { 2, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,},
00114 { 2, 3, 7, 7, 13, 13, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,},
00115 { 3, 3, 4, 15, 15, 29, 57, 57, 57, 113, 113, 113, 113, 113, 113, 113,},
00116 { 3, 4, 4, 5, 31, 31, 61, 121, 241, 241, 241, 241, 481, 481, 481, 481,},
00117 { 3, 4, 5, 5, 6, 63, 63, 125, 249, 497, 993, 993, 993, 993, 993, 1985,},
00118 { 3, 5, 6, 6, 6, 7, 127, 127, 253, 505, 1009, 2017, 4033, 4033, 4033, 4033,},
00119 { 3, 5, 6, 7, 7, 7, 8, 255, 255, 509, 1017, 2033, 4065, 8129,16257,16257,},
00120 { 3, 5, 6, 8, 8, 8, 8, 9, 511, 511, 1021, 2041, 4081, 8161,16321,32641,},
00121 { 3, 5, 7, 8, 9, 9, 9, 9, 10, 1023, 1023, 2045, 4089, 8177,16353,32705,},
00122 { 3, 5, 7, 8, 10, 10, 10, 10, 10, 11, 2047, 2047, 4093, 8185,16369,32737,},
00123 { 3, 5, 7, 8, 10, 11, 11, 11, 11, 11, 12, 4095, 4095, 8189,16377,32753,},
00124 { 3, 5, 7, 9, 10, 12, 12, 12, 12, 12, 12, 13, 8191, 8191,16381,32761,},
00125 { 3, 5, 7, 9, 10, 12, 13, 13, 13, 13, 13, 13, 14,16383,16383,32765,},
00126 { 3, 5, 7, 9, 10, 12, 14, 14, 14, 14, 14, 14, 14, 15,32767,32767,},
00127 { 3, 5, 7, 9, 11, 12, 14, 15, 15, 15, 15, 15, 15, 15, 16,65535,},
00128 };
00129
00130
00131 static void fillPlane(uint8_t *plane, int stride, int width, int height, int y,
00132 uint8_t val)
00133 {
00134 int i;
00135 uint8_t *ptr = plane + stride * y;
00136 for (i = 0; i < height; i++) {
00137 memset(ptr, val, width);
00138 ptr += stride;
00139 }
00140 }
00141
00142 static void copyPlane(const uint8_t *src, int srcStride,
00143 int srcSliceY, int srcSliceH, int width,
00144 uint8_t *dst, int dstStride)
00145 {
00146 dst += dstStride * srcSliceY;
00147 if (dstStride == srcStride && srcStride > 0) {
00148 memcpy(dst, src, srcSliceH * dstStride);
00149 } else {
00150 int i;
00151 for (i = 0; i < srcSliceH; i++) {
00152 memcpy(dst, src, width);
00153 src += srcStride;
00154 dst += dstStride;
00155 }
00156 }
00157 }
00158
00159 static int planarToNv12Wrapper(SwsContext *c, const uint8_t *src[],
00160 int srcStride[], int srcSliceY,
00161 int srcSliceH, uint8_t *dstParam[],
00162 int dstStride[])
00163 {
00164 uint8_t *dst = dstParam[1] + dstStride[1] * srcSliceY / 2;
00165
00166 copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
00167 dstParam[0], dstStride[0]);
00168
00169 if (c->dstFormat == AV_PIX_FMT_NV12)
00170 interleaveBytes(src[1], src[2], dst, c->srcW / 2, srcSliceH / 2,
00171 srcStride[1], srcStride[2], dstStride[0]);
00172 else
00173 interleaveBytes(src[2], src[1], dst, c->srcW / 2, srcSliceH / 2,
00174 srcStride[2], srcStride[1], dstStride[0]);
00175
00176 return srcSliceH;
00177 }
00178
00179 static int planarToYuy2Wrapper(SwsContext *c, const uint8_t *src[],
00180 int srcStride[], int srcSliceY, int srcSliceH,
00181 uint8_t *dstParam[], int dstStride[])
00182 {
00183 uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
00184
00185 yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
00186 srcStride[1], dstStride[0]);
00187
00188 return srcSliceH;
00189 }
00190
00191 static int planarToUyvyWrapper(SwsContext *c, const uint8_t *src[],
00192 int srcStride[], int srcSliceY, int srcSliceH,
00193 uint8_t *dstParam[], int dstStride[])
00194 {
00195 uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
00196
00197 yv12touyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
00198 srcStride[1], dstStride[0]);
00199
00200 return srcSliceH;
00201 }
00202
00203 static int yuv422pToYuy2Wrapper(SwsContext *c, const uint8_t *src[],
00204 int srcStride[], int srcSliceY, int srcSliceH,
00205 uint8_t *dstParam[], int dstStride[])
00206 {
00207 uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
00208
00209 yuv422ptoyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
00210 srcStride[1], dstStride[0]);
00211
00212 return srcSliceH;
00213 }
00214
00215 static int yuv422pToUyvyWrapper(SwsContext *c, const uint8_t *src[],
00216 int srcStride[], int srcSliceY, int srcSliceH,
00217 uint8_t *dstParam[], int dstStride[])
00218 {
00219 uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
00220
00221 yuv422ptouyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
00222 srcStride[1], dstStride[0]);
00223
00224 return srcSliceH;
00225 }
00226
00227 static int yuyvToYuv420Wrapper(SwsContext *c, const uint8_t *src[],
00228 int srcStride[], int srcSliceY, int srcSliceH,
00229 uint8_t *dstParam[], int dstStride[])
00230 {
00231 uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY;
00232 uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY / 2;
00233 uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY / 2;
00234
00235 yuyvtoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
00236 dstStride[1], srcStride[0]);
00237
00238 if (dstParam[3])
00239 fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
00240
00241 return srcSliceH;
00242 }
00243
00244 static int yuyvToYuv422Wrapper(SwsContext *c, const uint8_t *src[],
00245 int srcStride[], int srcSliceY, int srcSliceH,
00246 uint8_t *dstParam[], int dstStride[])
00247 {
00248 uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY;
00249 uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY;
00250 uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY;
00251
00252 yuyvtoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
00253 dstStride[1], srcStride[0]);
00254
00255 return srcSliceH;
00256 }
00257
00258 static int uyvyToYuv420Wrapper(SwsContext *c, const uint8_t *src[],
00259 int srcStride[], int srcSliceY, int srcSliceH,
00260 uint8_t *dstParam[], int dstStride[])
00261 {
00262 uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY;
00263 uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY / 2;
00264 uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY / 2;
00265
00266 uyvytoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
00267 dstStride[1], srcStride[0]);
00268
00269 if (dstParam[3])
00270 fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
00271
00272 return srcSliceH;
00273 }
00274
00275 static int uyvyToYuv422Wrapper(SwsContext *c, const uint8_t *src[],
00276 int srcStride[], int srcSliceY, int srcSliceH,
00277 uint8_t *dstParam[], int dstStride[])
00278 {
00279 uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY;
00280 uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY;
00281 uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY;
00282
00283 uyvytoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
00284 dstStride[1], srcStride[0]);
00285
00286 return srcSliceH;
00287 }
00288
00289 static void gray8aToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels,
00290 const uint8_t *palette)
00291 {
00292 int i;
00293 for (i = 0; i < num_pixels; i++)
00294 ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i << 1]] | (src[(i << 1) + 1] << 24);
00295 }
00296
00297 static void gray8aToPacked32_1(const uint8_t *src, uint8_t *dst, int num_pixels,
00298 const uint8_t *palette)
00299 {
00300 int i;
00301
00302 for (i = 0; i < num_pixels; i++)
00303 ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i << 1]] | src[(i << 1) + 1];
00304 }
00305
00306 static void gray8aToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels,
00307 const uint8_t *palette)
00308 {
00309 int i;
00310
00311 for (i = 0; i < num_pixels; i++) {
00312
00313 dst[0] = palette[src[i << 1] * 4 + 0];
00314 dst[1] = palette[src[i << 1] * 4 + 1];
00315 dst[2] = palette[src[i << 1] * 4 + 2];
00316 dst += 3;
00317 }
00318 }
00319
00320 static int packed_16bpc_bswap(SwsContext *c, const uint8_t *src[],
00321 int srcStride[], int srcSliceY, int srcSliceH,
00322 uint8_t *dst[], int dstStride[])
00323 {
00324 int i, j;
00325 int srcstr = srcStride[0] >> 1;
00326 int dststr = dstStride[0] >> 1;
00327 uint16_t *dstPtr = (uint16_t *) dst[0];
00328 const uint16_t *srcPtr = (const uint16_t *) src[0];
00329 int min_stride = FFMIN(srcstr, dststr);
00330
00331 for (i = 0; i < srcSliceH; i++) {
00332 for (j = 0; j < min_stride; j++) {
00333 dstPtr[j] = av_bswap16(srcPtr[j]);
00334 }
00335 srcPtr += srcstr;
00336 dstPtr += dststr;
00337 }
00338
00339 return srcSliceH;
00340 }
00341
00342 static int palToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[],
00343 int srcSliceY, int srcSliceH, uint8_t *dst[],
00344 int dstStride[])
00345 {
00346 const enum AVPixelFormat srcFormat = c->srcFormat;
00347 const enum AVPixelFormat dstFormat = c->dstFormat;
00348 void (*conv)(const uint8_t *src, uint8_t *dst, int num_pixels,
00349 const uint8_t *palette) = NULL;
00350 int i;
00351 uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY;
00352 const uint8_t *srcPtr = src[0];
00353
00354 if (srcFormat == AV_PIX_FMT_GRAY8A) {
00355 switch (dstFormat) {
00356 case AV_PIX_FMT_RGB32 : conv = gray8aToPacked32; break;
00357 case AV_PIX_FMT_BGR32 : conv = gray8aToPacked32; break;
00358 case AV_PIX_FMT_BGR32_1: conv = gray8aToPacked32_1; break;
00359 case AV_PIX_FMT_RGB32_1: conv = gray8aToPacked32_1; break;
00360 case AV_PIX_FMT_RGB24 : conv = gray8aToPacked24; break;
00361 case AV_PIX_FMT_BGR24 : conv = gray8aToPacked24; break;
00362 }
00363 } else if (usePal(srcFormat)) {
00364 switch (dstFormat) {
00365 case AV_PIX_FMT_RGB32 : conv = sws_convertPalette8ToPacked32; break;
00366 case AV_PIX_FMT_BGR32 : conv = sws_convertPalette8ToPacked32; break;
00367 case AV_PIX_FMT_BGR32_1: conv = sws_convertPalette8ToPacked32; break;
00368 case AV_PIX_FMT_RGB32_1: conv = sws_convertPalette8ToPacked32; break;
00369 case AV_PIX_FMT_RGB24 : conv = sws_convertPalette8ToPacked24; break;
00370 case AV_PIX_FMT_BGR24 : conv = sws_convertPalette8ToPacked24; break;
00371 }
00372 }
00373
00374 if (!conv)
00375 av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
00376 av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
00377 else {
00378 for (i = 0; i < srcSliceH; i++) {
00379 conv(srcPtr, dstPtr, c->srcW, (uint8_t *) c->pal_rgb);
00380 srcPtr += srcStride[0];
00381 dstPtr += dstStride[0];
00382 }
00383 }
00384
00385 return srcSliceH;
00386 }
00387
00388 static void gbr24ptopacked24(const uint8_t *src[], int srcStride[],
00389 uint8_t *dst, int dstStride, int srcSliceH,
00390 int width)
00391 {
00392 int x, h, i;
00393 for (h = 0; h < srcSliceH; h++) {
00394 uint8_t *dest = dst + dstStride * h;
00395 for (x = 0; x < width; x++) {
00396 *dest++ = src[0][x];
00397 *dest++ = src[1][x];
00398 *dest++ = src[2][x];
00399 }
00400
00401 for (i = 0; i < 3; i++)
00402 src[i] += srcStride[i];
00403 }
00404 }
00405
00406 static void gbr24ptopacked32(const uint8_t *src[], int srcStride[],
00407 uint8_t *dst, int dstStride, int srcSliceH,
00408 int alpha_first, int width)
00409 {
00410 int x, h, i;
00411 for (h = 0; h < srcSliceH; h++) {
00412 uint8_t *dest = dst + dstStride * h;
00413
00414 if (alpha_first) {
00415 for (x = 0; x < width; x++) {
00416 *dest++ = 0xff;
00417 *dest++ = src[0][x];
00418 *dest++ = src[1][x];
00419 *dest++ = src[2][x];
00420 }
00421 } else {
00422 for (x = 0; x < width; x++) {
00423 *dest++ = src[0][x];
00424 *dest++ = src[1][x];
00425 *dest++ = src[2][x];
00426 *dest++ = 0xff;
00427 }
00428 }
00429
00430 for (i = 0; i < 3; i++)
00431 src[i] += srcStride[i];
00432 }
00433 }
00434
00435 static int planarRgbToRgbWrapper(SwsContext *c, const uint8_t *src[],
00436 int srcStride[], int srcSliceY, int srcSliceH,
00437 uint8_t *dst[], int dstStride[])
00438 {
00439 int alpha_first = 0;
00440 const uint8_t *src102[] = { src[1], src[0], src[2] };
00441 const uint8_t *src201[] = { src[2], src[0], src[1] };
00442 int stride102[] = { srcStride[1], srcStride[0], srcStride[2] };
00443 int stride201[] = { srcStride[2], srcStride[0], srcStride[1] };
00444
00445 if (c->srcFormat != AV_PIX_FMT_GBRP) {
00446 av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n",
00447 av_get_pix_fmt_name(c->srcFormat),
00448 av_get_pix_fmt_name(c->dstFormat));
00449 return srcSliceH;
00450 }
00451
00452 switch (c->dstFormat) {
00453 case AV_PIX_FMT_BGR24:
00454 gbr24ptopacked24(src102, stride102,
00455 dst[0] + srcSliceY * dstStride[0], dstStride[0],
00456 srcSliceH, c->srcW);
00457 break;
00458
00459 case AV_PIX_FMT_RGB24:
00460 gbr24ptopacked24(src201, stride201,
00461 dst[0] + srcSliceY * dstStride[0], dstStride[0],
00462 srcSliceH, c->srcW);
00463 break;
00464
00465 case AV_PIX_FMT_ARGB:
00466 alpha_first = 1;
00467 case AV_PIX_FMT_RGBA:
00468 gbr24ptopacked32(src201, stride201,
00469 dst[0] + srcSliceY * dstStride[0], dstStride[0],
00470 srcSliceH, alpha_first, c->srcW);
00471 break;
00472
00473 case AV_PIX_FMT_ABGR:
00474 alpha_first = 1;
00475 case AV_PIX_FMT_BGRA:
00476 gbr24ptopacked32(src102, stride102,
00477 dst[0] + srcSliceY * dstStride[0], dstStride[0],
00478 srcSliceH, alpha_first, c->srcW);
00479 break;
00480
00481 default:
00482 av_log(c, AV_LOG_ERROR,
00483 "unsupported planar RGB conversion %s -> %s\n",
00484 av_get_pix_fmt_name(c->srcFormat),
00485 av_get_pix_fmt_name(c->dstFormat));
00486 }
00487
00488 return srcSliceH;
00489 }
00490
00491 #define isRGBA32(x) ( \
00492 (x) == AV_PIX_FMT_ARGB \
00493 || (x) == AV_PIX_FMT_RGBA \
00494 || (x) == AV_PIX_FMT_BGRA \
00495 || (x) == AV_PIX_FMT_ABGR \
00496 )
00497
00498 #define isRGBA64(x) ( \
00499 (x) == AV_PIX_FMT_RGBA64LE \
00500 || (x) == AV_PIX_FMT_RGBA64BE \
00501 || (x) == AV_PIX_FMT_BGRA64LE \
00502 || (x) == AV_PIX_FMT_BGRA64BE \
00503 )
00504
00505 #define isRGB48(x) ( \
00506 (x) == AV_PIX_FMT_RGB48LE \
00507 || (x) == AV_PIX_FMT_RGB48BE \
00508 || (x) == AV_PIX_FMT_BGR48LE \
00509 || (x) == AV_PIX_FMT_BGR48BE \
00510 )
00511
00512
00513 typedef void (* rgbConvFn) (const uint8_t *, uint8_t *, int);
00514 static rgbConvFn findRgbConvFn(SwsContext *c)
00515 {
00516 const enum AVPixelFormat srcFormat = c->srcFormat;
00517 const enum AVPixelFormat dstFormat = c->dstFormat;
00518 const int srcId = c->srcFormatBpp;
00519 const int dstId = c->dstFormatBpp;
00520 rgbConvFn conv = NULL;
00521
00522 #define IS_NOT_NE(bpp, desc) \
00523 (((bpp + 7) >> 3) == 2 && \
00524 (!(desc->flags & PIX_FMT_BE) != !HAVE_BIGENDIAN))
00525
00526 #define CONV_IS(src, dst) (srcFormat == AV_PIX_FMT_##src && dstFormat == AV_PIX_FMT_##dst)
00527
00528 if (isRGBA32(srcFormat) && isRGBA32(dstFormat)) {
00529 if ( CONV_IS(ABGR, RGBA)
00530 || CONV_IS(ARGB, BGRA)
00531 || CONV_IS(BGRA, ARGB)
00532 || CONV_IS(RGBA, ABGR)) conv = shuffle_bytes_3210;
00533 else if (CONV_IS(ABGR, ARGB)
00534 || CONV_IS(ARGB, ABGR)) conv = shuffle_bytes_0321;
00535 else if (CONV_IS(ABGR, BGRA)
00536 || CONV_IS(ARGB, RGBA)) conv = shuffle_bytes_1230;
00537 else if (CONV_IS(BGRA, RGBA)
00538 || CONV_IS(RGBA, BGRA)) conv = shuffle_bytes_2103;
00539 else if (CONV_IS(BGRA, ABGR)
00540 || CONV_IS(RGBA, ARGB)) conv = shuffle_bytes_3012;
00541 } else if (isRGB48(srcFormat) && isRGB48(dstFormat)) {
00542 if (CONV_IS(RGB48LE, BGR48LE)
00543 || CONV_IS(BGR48LE, RGB48LE)
00544 || CONV_IS(RGB48BE, BGR48BE)
00545 || CONV_IS(BGR48BE, RGB48BE)) conv = rgb48tobgr48_nobswap;
00546 else if (CONV_IS(RGB48LE, BGR48BE)
00547 || CONV_IS(BGR48LE, RGB48BE)
00548 || CONV_IS(RGB48BE, BGR48LE)
00549 || CONV_IS(BGR48BE, RGB48LE)) conv = rgb48tobgr48_bswap;
00550 } else if (isRGBA64(srcFormat) && isRGB48(dstFormat)) {
00551 if (CONV_IS(RGBA64LE, BGR48LE)
00552 || CONV_IS(BGRA64LE, RGB48LE)
00553 || CONV_IS(RGBA64BE, BGR48BE)
00554 || CONV_IS(BGRA64BE, RGB48BE)) conv = rgb64tobgr48_nobswap;
00555 else if (CONV_IS(RGBA64LE, BGR48BE)
00556 || CONV_IS(BGRA64LE, RGB48BE)
00557 || CONV_IS(RGBA64BE, BGR48LE)
00558 || CONV_IS(BGRA64BE, RGB48LE)) conv = rgb64tobgr48_bswap;
00559 else if (CONV_IS(RGBA64LE, RGB48LE)
00560 || CONV_IS(BGRA64LE, BGR48LE)
00561 || CONV_IS(RGBA64BE, RGB48BE)
00562 || CONV_IS(BGRA64BE, BGR48BE)) conv = rgb64to48_nobswap;
00563 else if (CONV_IS(RGBA64LE, RGB48BE)
00564 || CONV_IS(BGRA64LE, BGR48BE)
00565 || CONV_IS(RGBA64BE, RGB48LE)
00566 || CONV_IS(BGRA64BE, BGR48LE)) conv = rgb64to48_bswap;
00567 } else
00568
00569 if ((isBGRinInt(srcFormat) && isBGRinInt(dstFormat)) ||
00570 (isRGBinInt(srcFormat) && isRGBinInt(dstFormat))) {
00571 switch (srcId | (dstId << 16)) {
00572 case 0x000F000C: conv = rgb12to15; break;
00573 case 0x000F0010: conv = rgb16to15; break;
00574 case 0x000F0018: conv = rgb24to15; break;
00575 case 0x000F0020: conv = rgb32to15; break;
00576 case 0x0010000F: conv = rgb15to16; break;
00577 case 0x00100018: conv = rgb24to16; break;
00578 case 0x00100020: conv = rgb32to16; break;
00579 case 0x0018000F: conv = rgb15to24; break;
00580 case 0x00180010: conv = rgb16to24; break;
00581 case 0x00180020: conv = rgb32to24; break;
00582 case 0x0020000F: conv = rgb15to32; break;
00583 case 0x00200010: conv = rgb16to32; break;
00584 case 0x00200018: conv = rgb24to32; break;
00585 }
00586 } else if ((isBGRinInt(srcFormat) && isRGBinInt(dstFormat)) ||
00587 (isRGBinInt(srcFormat) && isBGRinInt(dstFormat))) {
00588 switch (srcId | (dstId << 16)) {
00589 case 0x000C000C: conv = rgb12tobgr12; break;
00590 case 0x000F000F: conv = rgb15tobgr15; break;
00591 case 0x000F0010: conv = rgb16tobgr15; break;
00592 case 0x000F0018: conv = rgb24tobgr15; break;
00593 case 0x000F0020: conv = rgb32tobgr15; break;
00594 case 0x0010000F: conv = rgb15tobgr16; break;
00595 case 0x00100010: conv = rgb16tobgr16; break;
00596 case 0x00100018: conv = rgb24tobgr16; break;
00597 case 0x00100020: conv = rgb32tobgr16; break;
00598 case 0x0018000F: conv = rgb15tobgr24; break;
00599 case 0x00180010: conv = rgb16tobgr24; break;
00600 case 0x00180018: conv = rgb24tobgr24; break;
00601 case 0x00180020: conv = rgb32tobgr24; break;
00602 case 0x0020000F: conv = rgb15tobgr32; break;
00603 case 0x00200010: conv = rgb16tobgr32; break;
00604 case 0x00200018: conv = rgb24tobgr32; break;
00605 }
00606 }
00607
00608 return conv;
00609 }
00610
00611
00612 static int rgbToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[],
00613 int srcSliceY, int srcSliceH, uint8_t *dst[],
00614 int dstStride[])
00615
00616 {
00617 const enum AVPixelFormat srcFormat = c->srcFormat;
00618 const enum AVPixelFormat dstFormat = c->dstFormat;
00619 const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->srcFormat);
00620 const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat);
00621 const int srcBpp = (c->srcFormatBpp + 7) >> 3;
00622 const int dstBpp = (c->dstFormatBpp + 7) >> 3;
00623 rgbConvFn conv = findRgbConvFn(c);
00624
00625 if (!conv) {
00626 av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
00627 av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
00628 } else {
00629 const uint8_t *srcPtr = src[0];
00630 uint8_t *dstPtr = dst[0];
00631 int src_bswap = IS_NOT_NE(c->srcFormatBpp, desc_src);
00632 int dst_bswap = IS_NOT_NE(c->dstFormatBpp, desc_dst);
00633
00634 if ((srcFormat == AV_PIX_FMT_RGB32_1 || srcFormat == AV_PIX_FMT_BGR32_1) &&
00635 !isRGBA32(dstFormat))
00636 srcPtr += ALT32_CORR;
00637
00638 if ((dstFormat == AV_PIX_FMT_RGB32_1 || dstFormat == AV_PIX_FMT_BGR32_1) &&
00639 !isRGBA32(srcFormat))
00640 dstPtr += ALT32_CORR;
00641
00642 if (dstStride[0] * srcBpp == srcStride[0] * dstBpp && srcStride[0] > 0 &&
00643 !(srcStride[0] % srcBpp) && !dst_bswap && !src_bswap)
00644 conv(srcPtr, dstPtr + dstStride[0] * srcSliceY,
00645 srcSliceH * srcStride[0]);
00646 else {
00647 int i, j;
00648 dstPtr += dstStride[0] * srcSliceY;
00649
00650 for (i = 0; i < srcSliceH; i++) {
00651 if(src_bswap) {
00652 for(j=0; j<c->srcW; j++)
00653 ((uint16_t*)c->formatConvBuffer)[j] = av_bswap16(((uint16_t*)srcPtr)[j]);
00654 conv(c->formatConvBuffer, dstPtr, c->srcW * srcBpp);
00655 }else
00656 conv(srcPtr, dstPtr, c->srcW * srcBpp);
00657 if(dst_bswap)
00658 for(j=0; j<c->srcW; j++)
00659 ((uint16_t*)dstPtr)[j] = av_bswap16(((uint16_t*)dstPtr)[j]);
00660 srcPtr += srcStride[0];
00661 dstPtr += dstStride[0];
00662 }
00663 }
00664 }
00665 return srcSliceH;
00666 }
00667
00668 static int bgr24ToYv12Wrapper(SwsContext *c, const uint8_t *src[],
00669 int srcStride[], int srcSliceY, int srcSliceH,
00670 uint8_t *dst[], int dstStride[])
00671 {
00672 rgb24toyv12(
00673 src[0],
00674 dst[0] + srcSliceY * dstStride[0],
00675 dst[1] + (srcSliceY >> 1) * dstStride[1],
00676 dst[2] + (srcSliceY >> 1) * dstStride[2],
00677 c->srcW, srcSliceH,
00678 dstStride[0], dstStride[1], srcStride[0]);
00679 if (dst[3])
00680 fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
00681 return srcSliceH;
00682 }
00683
00684 static int yvu9ToYv12Wrapper(SwsContext *c, const uint8_t *src[],
00685 int srcStride[], int srcSliceY, int srcSliceH,
00686 uint8_t *dst[], int dstStride[])
00687 {
00688 copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
00689 dst[0], dstStride[0]);
00690
00691 planar2x(src[1], dst[1] + dstStride[1] * (srcSliceY >> 1), c->chrSrcW,
00692 srcSliceH >> 2, srcStride[1], dstStride[1]);
00693 planar2x(src[2], dst[2] + dstStride[2] * (srcSliceY >> 1), c->chrSrcW,
00694 srcSliceH >> 2, srcStride[2], dstStride[2]);
00695 if (dst[3])
00696 fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
00697 return srcSliceH;
00698 }
00699
00700
00701 static int packedCopyWrapper(SwsContext *c, const uint8_t *src[],
00702 int srcStride[], int srcSliceY, int srcSliceH,
00703 uint8_t *dst[], int dstStride[])
00704 {
00705 if (dstStride[0] == srcStride[0] && srcStride[0] > 0)
00706 memcpy(dst[0] + dstStride[0] * srcSliceY, src[0], srcSliceH * dstStride[0]);
00707 else {
00708 int i;
00709 const uint8_t *srcPtr = src[0];
00710 uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY;
00711 int length = 0;
00712
00713
00714 while (length + c->srcW <= FFABS(dstStride[0]) &&
00715 length + c->srcW <= FFABS(srcStride[0]))
00716 length += c->srcW;
00717 av_assert1(length != 0);
00718
00719 for (i = 0; i < srcSliceH; i++) {
00720 memcpy(dstPtr, srcPtr, length);
00721 srcPtr += srcStride[0];
00722 dstPtr += dstStride[0];
00723 }
00724 }
00725 return srcSliceH;
00726 }
00727
00728 #define DITHER_COPY(dst, dstStride, src, srcStride, bswap, dbswap)\
00729 uint16_t scale= dither_scale[dst_depth-1][src_depth-1];\
00730 int shift= src_depth-dst_depth + dither_scale[src_depth-2][dst_depth-1];\
00731 for (i = 0; i < height; i++) {\
00732 const uint8_t *dither= dithers[src_depth-9][i&7];\
00733 for (j = 0; j < length-7; j+=8){\
00734 dst[j+0] = dbswap((bswap(src[j+0]) + dither[0])*scale>>shift);\
00735 dst[j+1] = dbswap((bswap(src[j+1]) + dither[1])*scale>>shift);\
00736 dst[j+2] = dbswap((bswap(src[j+2]) + dither[2])*scale>>shift);\
00737 dst[j+3] = dbswap((bswap(src[j+3]) + dither[3])*scale>>shift);\
00738 dst[j+4] = dbswap((bswap(src[j+4]) + dither[4])*scale>>shift);\
00739 dst[j+5] = dbswap((bswap(src[j+5]) + dither[5])*scale>>shift);\
00740 dst[j+6] = dbswap((bswap(src[j+6]) + dither[6])*scale>>shift);\
00741 dst[j+7] = dbswap((bswap(src[j+7]) + dither[7])*scale>>shift);\
00742 }\
00743 for (; j < length; j++)\
00744 dst[j] = dbswap((bswap(src[j]) + dither[j&7])*scale>>shift);\
00745 dst += dstStride;\
00746 src += srcStride;\
00747 }
00748
00749 static int planarCopyWrapper(SwsContext *c, const uint8_t *src[],
00750 int srcStride[], int srcSliceY, int srcSliceH,
00751 uint8_t *dst[], int dstStride[])
00752 {
00753 const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->srcFormat);
00754 const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat);
00755 int plane, i, j;
00756 for (plane = 0; plane < 4; plane++) {
00757 int length = (plane == 0 || plane == 3) ? c->srcW : -((-c->srcW ) >> c->chrDstHSubSample);
00758 int y = (plane == 0 || plane == 3) ? srcSliceY: -((-srcSliceY) >> c->chrDstVSubSample);
00759 int height = (plane == 0 || plane == 3) ? srcSliceH: -((-srcSliceH) >> c->chrDstVSubSample);
00760 const uint8_t *srcPtr = src[plane];
00761 uint8_t *dstPtr = dst[plane] + dstStride[plane] * y;
00762 int shiftonly= plane==1 || plane==2 || (!c->srcRange && plane==0);
00763
00764 if (!dst[plane])
00765 continue;
00766
00767 if (plane == 1 && !dst[2]) continue;
00768 if (!src[plane] || (plane == 1 && !src[2])) {
00769 if (is16BPS(c->dstFormat) || isNBPS(c->dstFormat)) {
00770 fillPlane16(dst[plane], dstStride[plane], length, height, y,
00771 plane == 3, desc_dst->comp[plane].depth_minus1,
00772 isBE(c->dstFormat));
00773 } else {
00774 fillPlane(dst[plane], dstStride[plane], length, height, y,
00775 (plane == 3) ? 255 : 128);
00776 }
00777 } else {
00778 if(isNBPS(c->srcFormat) || isNBPS(c->dstFormat)
00779 || (is16BPS(c->srcFormat) != is16BPS(c->dstFormat))
00780 ) {
00781 const int src_depth = desc_src->comp[plane].depth_minus1 + 1;
00782 const int dst_depth = desc_dst->comp[plane].depth_minus1 + 1;
00783 const uint16_t *srcPtr2 = (const uint16_t *) srcPtr;
00784 uint16_t *dstPtr2 = (uint16_t*)dstPtr;
00785
00786 if (dst_depth == 8) {
00787 if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
00788 DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, , )
00789 } else {
00790 DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, av_bswap16, )
00791 }
00792 } else if (src_depth == 8) {
00793 for (i = 0; i < height; i++) {
00794 #define COPY816(w)\
00795 if(shiftonly){\
00796 for (j = 0; j < length; j++)\
00797 w(&dstPtr2[j], srcPtr[j]<<(dst_depth-8));\
00798 }else{\
00799 for (j = 0; j < length; j++)\
00800 w(&dstPtr2[j], (srcPtr[j]<<(dst_depth-8)) |\
00801 (srcPtr[j]>>(2*8-dst_depth)));\
00802 }
00803 if(isBE(c->dstFormat)){
00804 COPY816(AV_WB16)
00805 } else {
00806 COPY816(AV_WL16)
00807 }
00808 dstPtr2 += dstStride[plane]/2;
00809 srcPtr += srcStride[plane];
00810 }
00811 } else if (src_depth <= dst_depth) {
00812 int orig_length = length;
00813 for (i = 0; i < height; i++) {
00814 if(isBE(c->srcFormat) == HAVE_BIGENDIAN &&
00815 isBE(c->dstFormat) == HAVE_BIGENDIAN &&
00816 shiftonly) {
00817 unsigned shift = dst_depth - src_depth;
00818 length = orig_length;
00819 #if HAVE_FAST_64BIT
00820 #define FAST_COPY_UP(shift) \
00821 for (j = 0; j < length - 3; j += 4) { \
00822 uint64_t v = AV_RN64A(srcPtr2 + j); \
00823 AV_WN64A(dstPtr2 + j, v << shift); \
00824 } \
00825 length &= 3;
00826 #else
00827 #define FAST_COPY_UP(shift) \
00828 for (j = 0; j < length - 1; j += 2) { \
00829 uint32_t v = AV_RN32A(srcPtr2 + j); \
00830 AV_WN32A(dstPtr2 + j, v << shift); \
00831 } \
00832 length &= 1;
00833 #endif
00834 switch (shift)
00835 {
00836 case 6: FAST_COPY_UP(6); break;
00837 case 7: FAST_COPY_UP(7); break;
00838 }
00839 }
00840 #define COPY_UP(r,w) \
00841 if(shiftonly){\
00842 for (j = 0; j < length; j++){ \
00843 unsigned int v= r(&srcPtr2[j]);\
00844 w(&dstPtr2[j], v<<(dst_depth-src_depth));\
00845 }\
00846 }else{\
00847 for (j = 0; j < length; j++){ \
00848 unsigned int v= r(&srcPtr2[j]);\
00849 w(&dstPtr2[j], (v<<(dst_depth-src_depth)) | \
00850 (v>>(2*src_depth-dst_depth)));\
00851 }\
00852 }
00853 if(isBE(c->srcFormat)){
00854 if(isBE(c->dstFormat)){
00855 COPY_UP(AV_RB16, AV_WB16)
00856 } else {
00857 COPY_UP(AV_RB16, AV_WL16)
00858 }
00859 } else {
00860 if(isBE(c->dstFormat)){
00861 COPY_UP(AV_RL16, AV_WB16)
00862 } else {
00863 COPY_UP(AV_RL16, AV_WL16)
00864 }
00865 }
00866 dstPtr2 += dstStride[plane]/2;
00867 srcPtr2 += srcStride[plane]/2;
00868 }
00869 } else {
00870 if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
00871 if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
00872 DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , )
00873 } else {
00874 DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , av_bswap16)
00875 }
00876 }else{
00877 if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
00878 DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, )
00879 } else {
00880 DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, av_bswap16)
00881 }
00882 }
00883 }
00884 } else if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat) &&
00885 isBE(c->srcFormat) != isBE(c->dstFormat)) {
00886
00887 for (i = 0; i < height; i++) {
00888 for (j = 0; j < length; j++)
00889 ((uint16_t *) dstPtr)[j] = av_bswap16(((const uint16_t *) srcPtr)[j]);
00890 srcPtr += srcStride[plane];
00891 dstPtr += dstStride[plane];
00892 }
00893 } else if (dstStride[plane] == srcStride[plane] &&
00894 srcStride[plane] > 0 && srcStride[plane] == length) {
00895 memcpy(dst[plane] + dstStride[plane] * y, src[plane],
00896 height * dstStride[plane]);
00897 } else {
00898 if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat))
00899 length *= 2;
00900 else if (!desc_src->comp[0].depth_minus1)
00901 length >>= 3;
00902 for (i = 0; i < height; i++) {
00903 memcpy(dstPtr, srcPtr, length);
00904 srcPtr += srcStride[plane];
00905 dstPtr += dstStride[plane];
00906 }
00907 }
00908 }
00909 }
00910 return srcSliceH;
00911 }
00912
00913
00914 #define IS_DIFFERENT_ENDIANESS(src_fmt, dst_fmt, pix_fmt) \
00915 ((src_fmt == pix_fmt ## BE && dst_fmt == pix_fmt ## LE) || \
00916 (src_fmt == pix_fmt ## LE && dst_fmt == pix_fmt ## BE))
00917
00918
00919 void ff_get_unscaled_swscale(SwsContext *c)
00920 {
00921 const enum AVPixelFormat srcFormat = c->srcFormat;
00922 const enum AVPixelFormat dstFormat = c->dstFormat;
00923 const int flags = c->flags;
00924 const int dstH = c->dstH;
00925 int needsDither;
00926
00927 needsDither = isAnyRGB(dstFormat) &&
00928 c->dstFormatBpp < 24 &&
00929 (c->dstFormatBpp < c->srcFormatBpp || (!isAnyRGB(srcFormat)));
00930
00931
00932 if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUVA420P) &&
00933 (dstFormat == AV_PIX_FMT_NV12 || dstFormat == AV_PIX_FMT_NV21)) {
00934 c->swScale = planarToNv12Wrapper;
00935 }
00936
00937 if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUV422P ||
00938 srcFormat == AV_PIX_FMT_YUVA420P) && isAnyRGB(dstFormat) &&
00939 !(flags & SWS_ACCURATE_RND) && !(dstH & 1)) {
00940 c->swScale = ff_yuv2rgb_get_func_ptr(c);
00941 }
00942
00943 if (srcFormat == AV_PIX_FMT_YUV410P &&
00944 (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P) &&
00945 !(flags & SWS_BITEXACT)) {
00946 c->swScale = yvu9ToYv12Wrapper;
00947 }
00948
00949
00950 if (srcFormat == AV_PIX_FMT_BGR24 &&
00951 (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P) &&
00952 !(flags & SWS_ACCURATE_RND))
00953 c->swScale = bgr24ToYv12Wrapper;
00954
00955
00956 if (isAnyRGB(srcFormat) && isAnyRGB(dstFormat) && findRgbConvFn(c)
00957 && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT))))
00958 c->swScale= rgbToRgbWrapper;
00959
00960 #define isByteRGB(f) (\
00961 f == AV_PIX_FMT_RGB32 ||\
00962 f == AV_PIX_FMT_RGB32_1 ||\
00963 f == AV_PIX_FMT_RGB24 ||\
00964 f == AV_PIX_FMT_BGR32 ||\
00965 f == AV_PIX_FMT_BGR32_1 ||\
00966 f == AV_PIX_FMT_BGR24)
00967
00968 if (isAnyRGB(srcFormat) && isPlanar(srcFormat) && isByteRGB(dstFormat))
00969 c->swScale = planarRgbToRgbWrapper;
00970
00971
00972 if (IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR444) ||
00973 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR48) ||
00974 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGRA64) ||
00975 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR555) ||
00976 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR565) ||
00977 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GRAY16) ||
00978 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB444) ||
00979 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB48) ||
00980 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGBA64) ||
00981 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB555) ||
00982 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB565))
00983 c->swScale = packed_16bpc_bswap;
00984
00985 if (usePal(srcFormat) && isByteRGB(dstFormat))
00986 c->swScale = palToRgbWrapper;
00987
00988 if (srcFormat == AV_PIX_FMT_YUV422P) {
00989 if (dstFormat == AV_PIX_FMT_YUYV422)
00990 c->swScale = yuv422pToYuy2Wrapper;
00991 else if (dstFormat == AV_PIX_FMT_UYVY422)
00992 c->swScale = yuv422pToUyvyWrapper;
00993 }
00994
00995
00996 if (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)) {
00997
00998 if (srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUVA420P) {
00999 if (dstFormat == AV_PIX_FMT_YUYV422)
01000 c->swScale = planarToYuy2Wrapper;
01001 else if (dstFormat == AV_PIX_FMT_UYVY422)
01002 c->swScale = planarToUyvyWrapper;
01003 }
01004 }
01005 if (srcFormat == AV_PIX_FMT_YUYV422 &&
01006 (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P))
01007 c->swScale = yuyvToYuv420Wrapper;
01008 if (srcFormat == AV_PIX_FMT_UYVY422 &&
01009 (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P))
01010 c->swScale = uyvyToYuv420Wrapper;
01011 if (srcFormat == AV_PIX_FMT_YUYV422 && dstFormat == AV_PIX_FMT_YUV422P)
01012 c->swScale = yuyvToYuv422Wrapper;
01013 if (srcFormat == AV_PIX_FMT_UYVY422 && dstFormat == AV_PIX_FMT_YUV422P)
01014 c->swScale = uyvyToYuv422Wrapper;
01015
01016 #define isPlanarGray(x) (isGray(x) && (x) != AV_PIX_FMT_GRAY8A)
01017
01018 if ( srcFormat == dstFormat ||
01019 (srcFormat == AV_PIX_FMT_YUVA420P && dstFormat == AV_PIX_FMT_YUV420P) ||
01020 (srcFormat == AV_PIX_FMT_YUV420P && dstFormat == AV_PIX_FMT_YUVA420P) ||
01021 (isPlanarYUV(srcFormat) && isPlanarGray(dstFormat)) ||
01022 (isPlanarYUV(dstFormat) && isPlanarGray(srcFormat)) ||
01023 (isPlanarGray(dstFormat) && isPlanarGray(srcFormat)) ||
01024 (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat) &&
01025 c->chrDstHSubSample == c->chrSrcHSubSample &&
01026 c->chrDstVSubSample == c->chrSrcVSubSample &&
01027 dstFormat != AV_PIX_FMT_NV12 && dstFormat != AV_PIX_FMT_NV21 &&
01028 srcFormat != AV_PIX_FMT_NV12 && srcFormat != AV_PIX_FMT_NV21))
01029 {
01030 if (isPacked(c->srcFormat))
01031 c->swScale = packedCopyWrapper;
01032 else
01033 c->swScale = planarCopyWrapper;
01034 }
01035
01036 if (ARCH_BFIN)
01037 ff_bfin_get_unscaled_swscale(c);
01038 if (HAVE_ALTIVEC)
01039 ff_swscale_get_unscaled_altivec(c);
01040 }
01041
01042
01043 void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst,
01044 int num_pixels, const uint8_t *palette)
01045 {
01046 int i;
01047
01048 for (i = 0; i < num_pixels; i++)
01049 ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i]];
01050 }
01051
01052
01053 void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst,
01054 int num_pixels, const uint8_t *palette)
01055 {
01056 int i;
01057
01058 for (i = 0; i < num_pixels; i++) {
01059
01060 dst[0] = palette[src[i] * 4 + 0];
01061 dst[1] = palette[src[i] * 4 + 1];
01062 dst[2] = palette[src[i] * 4 + 2];
01063 dst += 3;
01064 }
01065 }