1/* 2 * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at> 3 * 4 * This file is part of Libav. 5 * 6 * Libav is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * Libav is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with Libav; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21#include <inttypes.h> 22#include <string.h> 23#include <math.h> 24#include <stdio.h> 25#include "config.h" 26#include <assert.h> 27#include "swscale.h" 28#include "swscale_internal.h" 29#include "rgb2rgb.h" 30#include "libavutil/intreadwrite.h" 31#include "libavutil/cpu.h" 32#include "libavutil/avutil.h" 33#include "libavutil/mathematics.h" 34#include "libavutil/bswap.h" 35#include "libavutil/pixdesc.h" 36 37DECLARE_ALIGNED(8, const uint8_t, dither_8x8_1)[8][8] = { 38 { 0, 1, 0, 1, 0, 1, 0, 1,}, 39 { 1, 0, 1, 0, 1, 0, 1, 0,}, 40 { 0, 1, 0, 1, 0, 1, 0, 1,}, 41 { 1, 0, 1, 0, 1, 0, 1, 0,}, 42 { 0, 1, 0, 1, 0, 1, 0, 1,}, 43 { 1, 0, 1, 0, 1, 0, 1, 0,}, 44 { 0, 1, 0, 1, 0, 1, 0, 1,}, 45 { 1, 0, 1, 0, 1, 0, 1, 0,}, 46}; 47DECLARE_ALIGNED(8, const uint8_t, dither_8x8_3)[8][8] = { 48 { 1, 2, 1, 2, 1, 2, 1, 2,}, 49 { 3, 0, 3, 0, 3, 0, 3, 0,}, 50 { 1, 2, 1, 2, 1, 2, 1, 2,}, 51 { 3, 0, 3, 0, 3, 0, 3, 0,}, 52 { 1, 2, 1, 2, 1, 2, 1, 2,}, 53 { 3, 0, 3, 0, 3, 0, 3, 0,}, 54 { 1, 2, 1, 2, 1, 2, 1, 2,}, 55 { 3, 0, 3, 0, 3, 0, 3, 0,}, 56}; 57DECLARE_ALIGNED(8, const uint8_t, dither_8x8_64)[8][8] = { 58 { 18, 34, 30, 46, 17, 33, 29, 45,}, 59 { 50, 2, 62, 14, 49, 1, 61, 13,}, 60 { 26, 42, 22, 38, 25, 41, 21, 37,}, 61 { 58, 10, 54, 6, 57, 9, 53, 5,}, 62 { 16, 32, 28, 44, 19, 35, 31, 47,}, 63 { 48, 0, 60, 12, 51, 3, 63, 15,}, 64 { 24, 40, 20, 36, 27, 43, 23, 39,}, 65 { 56, 8, 52, 4, 59, 11, 55, 7,}, 66}; 67extern const uint8_t dither_8x8_128[8][8]; 68DECLARE_ALIGNED(8, const uint8_t, dither_8x8_256)[8][8] = { 69 { 72, 136, 120, 184, 68, 132, 116, 180,}, 70 { 200, 8, 248, 56, 196, 4, 244, 52,}, 71 { 104, 168, 88, 152, 100, 164, 84, 148,}, 72 { 232, 40, 216, 24, 228, 36, 212, 20,}, 73 { 64, 128, 102, 176, 76, 140, 124, 188,}, 74 { 192, 0, 240, 48, 204, 12, 252, 60,}, 75 { 96, 160, 80, 144, 108, 172, 92, 156,}, 76 { 224, 32, 208, 16, 236, 44, 220, 28,}, 77}; 78 79#define RGB2YUV_SHIFT 15 80#define BY ( (int) (0.114 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5)) 81#define BV (-(int) (0.081 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5)) 82#define BU ( (int) (0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5)) 83#define GY ( (int) (0.587 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5)) 84#define GV (-(int) (0.419 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5)) 85#define GU (-(int) (0.331 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5)) 86#define RY ( (int) (0.299 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5)) 87#define RV ( (int) (0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5)) 88#define RU (-(int) (0.169 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5)) 89 90static void fillPlane(uint8_t *plane, int stride, int width, int height, int y, 91 uint8_t val) 92{ 93 int i; 94 uint8_t *ptr = plane + stride * y; 95 for (i = 0; i < height; i++) { 96 memset(ptr, val, width); 97 ptr += stride; 98 } 99} 100 101static void copyPlane(const uint8_t *src, int srcStride, 102 int srcSliceY, int srcSliceH, int width, 103 uint8_t *dst, int dstStride) 104{ 105 dst += dstStride * srcSliceY; 106 if (dstStride == srcStride && srcStride > 0) { 107 memcpy(dst, src, srcSliceH * dstStride); 108 } else { 109 int i; 110 for (i = 0; i < srcSliceH; i++) { 111 memcpy(dst, src, width); 112 src += srcStride; 113 dst += dstStride; 114 } 115 } 116} 117 118static int planarToNv12Wrapper(SwsContext *c, const uint8_t *src[], 119 int srcStride[], int srcSliceY, 120 int srcSliceH, uint8_t *dstParam[], 121 int dstStride[]) 122{ 123 uint8_t *dst = dstParam[1] + dstStride[1] * srcSliceY / 2; 124 125 copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, 126 dstParam[0], dstStride[0]); 127 128 if (c->dstFormat == PIX_FMT_NV12) 129 interleaveBytes(src[1], src[2], dst, c->srcW / 2, srcSliceH / 2, 130 srcStride[1], srcStride[2], dstStride[0]); 131 else 132 interleaveBytes(src[2], src[1], dst, c->srcW / 2, srcSliceH / 2, 133 srcStride[2], srcStride[1], dstStride[0]); 134 135 return srcSliceH; 136} 137 138static int planarToYuy2Wrapper(SwsContext *c, const uint8_t *src[], 139 int srcStride[], int srcSliceY, int srcSliceH, 140 uint8_t *dstParam[], int dstStride[]) 141{ 142 uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY; 143 144 yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], 145 srcStride[1], dstStride[0]); 146 147 return srcSliceH; 148} 149 150static int planarToUyvyWrapper(SwsContext *c, const uint8_t *src[], 151 int srcStride[], int srcSliceY, int srcSliceH, 152 uint8_t *dstParam[], int dstStride[]) 153{ 154 uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY; 155 156 yv12touyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], 157 srcStride[1], dstStride[0]); 158 159 return srcSliceH; 160} 161 162static int yuv422pToYuy2Wrapper(SwsContext *c, const uint8_t *src[], 163 int srcStride[], int srcSliceY, int srcSliceH, 164 uint8_t *dstParam[], int dstStride[]) 165{ 166 uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY; 167 168 yuv422ptoyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], 169 srcStride[1], dstStride[0]); 170 171 return srcSliceH; 172} 173 174static int yuv422pToUyvyWrapper(SwsContext *c, const uint8_t *src[], 175 int srcStride[], int srcSliceY, int srcSliceH, 176 uint8_t *dstParam[], int dstStride[]) 177{ 178 uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY; 179 180 yuv422ptouyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], 181 srcStride[1], dstStride[0]); 182 183 return srcSliceH; 184} 185 186static int yuyvToYuv420Wrapper(SwsContext *c, const uint8_t *src[], 187 int srcStride[], int srcSliceY, int srcSliceH, 188 uint8_t *dstParam[], int dstStride[]) 189{ 190 uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY; 191 uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY / 2; 192 uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY / 2; 193 194 yuyvtoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], 195 dstStride[1], srcStride[0]); 196 197 if (dstParam[3]) 198 fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); 199 200 return srcSliceH; 201} 202 203static int yuyvToYuv422Wrapper(SwsContext *c, const uint8_t *src[], 204 int srcStride[], int srcSliceY, int srcSliceH, 205 uint8_t *dstParam[], int dstStride[]) 206{ 207 uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY; 208 uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY; 209 uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY; 210 211 yuyvtoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], 212 dstStride[1], srcStride[0]); 213 214 return srcSliceH; 215} 216 217static int uyvyToYuv420Wrapper(SwsContext *c, const uint8_t *src[], 218 int srcStride[], int srcSliceY, int srcSliceH, 219 uint8_t *dstParam[], int dstStride[]) 220{ 221 uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY; 222 uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY / 2; 223 uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY / 2; 224 225 uyvytoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], 226 dstStride[1], srcStride[0]); 227 228 if (dstParam[3]) 229 fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); 230 231 return srcSliceH; 232} 233 234static int uyvyToYuv422Wrapper(SwsContext *c, const uint8_t *src[], 235 int srcStride[], int srcSliceY, int srcSliceH, 236 uint8_t *dstParam[], int dstStride[]) 237{ 238 uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY; 239 uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY; 240 uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY; 241 242 uyvytoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], 243 dstStride[1], srcStride[0]); 244 245 return srcSliceH; 246} 247 248static void gray8aToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, 249 const uint8_t *palette) 250{ 251 int i; 252 for (i = 0; i < num_pixels; i++) 253 ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i << 1]] | (src[(i << 1) + 1] << 24); 254} 255 256static void gray8aToPacked32_1(const uint8_t *src, uint8_t *dst, int num_pixels, 257 const uint8_t *palette) 258{ 259 int i; 260 261 for (i = 0; i < num_pixels; i++) 262 ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i << 1]] | src[(i << 1) + 1]; 263} 264 265static void gray8aToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, 266 const uint8_t *palette) 267{ 268 int i; 269 270 for (i = 0; i < num_pixels; i++) { 271 //FIXME slow? 272 dst[0] = palette[src[i << 1] * 4 + 0]; 273 dst[1] = palette[src[i << 1] * 4 + 1]; 274 dst[2] = palette[src[i << 1] * 4 + 2]; 275 dst += 3; 276 } 277} 278 279static int packed_16bpc_bswap(SwsContext *c, const uint8_t *src[], 280 int srcStride[], int srcSliceY, int srcSliceH, 281 uint8_t *dst[], int dstStride[]) 282{ 283 int i, j; 284 int srcstr = srcStride[0] >> 1; 285 int dststr = dstStride[0] >> 1; 286 uint16_t *dstPtr = (uint16_t *) dst[0]; 287 const uint16_t *srcPtr = (const uint16_t *) src[0]; 288 int min_stride = FFMIN(srcstr, dststr); 289 290 for (i = 0; i < srcSliceH; i++) { 291 for (j = 0; j < min_stride; j++) { 292 dstPtr[j] = av_bswap16(srcPtr[j]); 293 } 294 srcPtr += srcstr; 295 dstPtr += dststr; 296 } 297 298 return srcSliceH; 299} 300 301static int palToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[], 302 int srcSliceY, int srcSliceH, uint8_t *dst[], 303 int dstStride[]) 304{ 305 const enum PixelFormat srcFormat = c->srcFormat; 306 const enum PixelFormat dstFormat = c->dstFormat; 307 void (*conv)(const uint8_t *src, uint8_t *dst, int num_pixels, 308 const uint8_t *palette) = NULL; 309 int i; 310 uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY; 311 const uint8_t *srcPtr = src[0]; 312 313 if (srcFormat == PIX_FMT_Y400A) { 314 switch (dstFormat) { 315 case PIX_FMT_RGB32 : conv = gray8aToPacked32; break; 316 case PIX_FMT_BGR32 : conv = gray8aToPacked32; break; 317 case PIX_FMT_BGR32_1: conv = gray8aToPacked32_1; break; 318 case PIX_FMT_RGB32_1: conv = gray8aToPacked32_1; break; 319 case PIX_FMT_RGB24 : conv = gray8aToPacked24; break; 320 case PIX_FMT_BGR24 : conv = gray8aToPacked24; break; 321 } 322 } else if (usePal(srcFormat)) { 323 switch (dstFormat) { 324 case PIX_FMT_RGB32 : conv = sws_convertPalette8ToPacked32; break; 325 case PIX_FMT_BGR32 : conv = sws_convertPalette8ToPacked32; break; 326 case PIX_FMT_BGR32_1: conv = sws_convertPalette8ToPacked32; break; 327 case PIX_FMT_RGB32_1: conv = sws_convertPalette8ToPacked32; break; 328 case PIX_FMT_RGB24 : conv = sws_convertPalette8ToPacked24; break; 329 case PIX_FMT_BGR24 : conv = sws_convertPalette8ToPacked24; break; 330 } 331 } 332 333 if (!conv) 334 av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n", 335 sws_format_name(srcFormat), sws_format_name(dstFormat)); 336 else { 337 for (i = 0; i < srcSliceH; i++) { 338 conv(srcPtr, dstPtr, c->srcW, (uint8_t *) c->pal_rgb); 339 srcPtr += srcStride[0]; 340 dstPtr += dstStride[0]; 341 } 342 } 343 344 return srcSliceH; 345} 346 347#define isRGBA32(x) ( \ 348 (x) == PIX_FMT_ARGB \ 349 || (x) == PIX_FMT_RGBA \ 350 || (x) == PIX_FMT_BGRA \ 351 || (x) == PIX_FMT_ABGR \ 352 ) 353 354/* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */ 355typedef void (* rgbConvFn) (const uint8_t *, uint8_t *, int); 356static rgbConvFn findRgbConvFn(SwsContext *c) 357{ 358 const enum PixelFormat srcFormat = c->srcFormat; 359 const enum PixelFormat dstFormat = c->dstFormat; 360 const int srcId = c->srcFormatBpp; 361 const int dstId = c->dstFormatBpp; 362 rgbConvFn conv = NULL; 363 364#define IS_NOT_NE(bpp, fmt) \ 365 (((bpp + 7) >> 3) == 2 && \ 366 (!(av_pix_fmt_descriptors[fmt].flags & PIX_FMT_BE) != !HAVE_BIGENDIAN)) 367 368 /* if this is non-native rgb444/555/565, don't handle it here. */ 369 if (IS_NOT_NE(srcId, srcFormat) || IS_NOT_NE(dstId, dstFormat)) 370 return NULL; 371 372#define CONV_IS(src, dst) (srcFormat == PIX_FMT_##src && dstFormat == PIX_FMT_##dst) 373 374 if (isRGBA32(srcFormat) && isRGBA32(dstFormat)) { 375 if ( CONV_IS(ABGR, RGBA) 376 || CONV_IS(ARGB, BGRA) 377 || CONV_IS(BGRA, ARGB) 378 || CONV_IS(RGBA, ABGR)) conv = shuffle_bytes_3210; 379 else if (CONV_IS(ABGR, ARGB) 380 || CONV_IS(ARGB, ABGR)) conv = shuffle_bytes_0321; 381 else if (CONV_IS(ABGR, BGRA) 382 || CONV_IS(ARGB, RGBA)) conv = shuffle_bytes_1230; 383 else if (CONV_IS(BGRA, RGBA) 384 || CONV_IS(RGBA, BGRA)) conv = shuffle_bytes_2103; 385 else if (CONV_IS(BGRA, ABGR) 386 || CONV_IS(RGBA, ARGB)) conv = shuffle_bytes_3012; 387 } else 388 /* BGR -> BGR */ 389 if ((isBGRinInt(srcFormat) && isBGRinInt(dstFormat)) || 390 (isRGBinInt(srcFormat) && isRGBinInt(dstFormat))) { 391 switch (srcId | (dstId << 16)) { 392 case 0x000F000C: conv = rgb12to15; break; 393 case 0x000F0010: conv = rgb16to15; break; 394 case 0x000F0018: conv = rgb24to15; break; 395 case 0x000F0020: conv = rgb32to15; break; 396 case 0x0010000F: conv = rgb15to16; break; 397 case 0x00100018: conv = rgb24to16; break; 398 case 0x00100020: conv = rgb32to16; break; 399 case 0x0018000F: conv = rgb15to24; break; 400 case 0x00180010: conv = rgb16to24; break; 401 case 0x00180020: conv = rgb32to24; break; 402 case 0x0020000F: conv = rgb15to32; break; 403 case 0x00200010: conv = rgb16to32; break; 404 case 0x00200018: conv = rgb24to32; break; 405 } 406 } else if ((isBGRinInt(srcFormat) && isRGBinInt(dstFormat)) || 407 (isRGBinInt(srcFormat) && isBGRinInt(dstFormat))) { 408 switch (srcId | (dstId << 16)) { 409 case 0x000C000C: conv = rgb12tobgr12; break; 410 case 0x000F000F: conv = rgb15tobgr15; break; 411 case 0x000F0010: conv = rgb16tobgr15; break; 412 case 0x000F0018: conv = rgb24tobgr15; break; 413 case 0x000F0020: conv = rgb32tobgr15; break; 414 case 0x0010000F: conv = rgb15tobgr16; break; 415 case 0x00100010: conv = rgb16tobgr16; break; 416 case 0x00100018: conv = rgb24tobgr16; break; 417 case 0x00100020: conv = rgb32tobgr16; break; 418 case 0x0018000F: conv = rgb15tobgr24; break; 419 case 0x00180010: conv = rgb16tobgr24; break; 420 case 0x00180018: conv = rgb24tobgr24; break; 421 case 0x00180020: conv = rgb32tobgr24; break; 422 case 0x0020000F: conv = rgb15tobgr32; break; 423 case 0x00200010: conv = rgb16tobgr32; break; 424 case 0x00200018: conv = rgb24tobgr32; break; 425 } 426 } 427 428 return conv; 429} 430 431/* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */ 432static int rgbToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[], 433 int srcSliceY, int srcSliceH, uint8_t *dst[], 434 int dstStride[]) 435 436{ 437 const enum PixelFormat srcFormat = c->srcFormat; 438 const enum PixelFormat dstFormat = c->dstFormat; 439 const int srcBpp = (c->srcFormatBpp + 7) >> 3; 440 const int dstBpp = (c->dstFormatBpp + 7) >> 3; 441 rgbConvFn conv = findRgbConvFn(c); 442 443 if (!conv) { 444 av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n", 445 sws_format_name(srcFormat), sws_format_name(dstFormat)); 446 } else { 447 const uint8_t *srcPtr = src[0]; 448 uint8_t *dstPtr = dst[0]; 449 if ((srcFormat == PIX_FMT_RGB32_1 || srcFormat == PIX_FMT_BGR32_1) && 450 !isRGBA32(dstFormat)) 451 srcPtr += ALT32_CORR; 452 453 if ((dstFormat == PIX_FMT_RGB32_1 || dstFormat == PIX_FMT_BGR32_1) && 454 !isRGBA32(srcFormat)) 455 dstPtr += ALT32_CORR; 456 457 if (dstStride[0] * srcBpp == srcStride[0] * dstBpp && srcStride[0] > 0 && 458 !(srcStride[0] % srcBpp)) 459 conv(srcPtr, dstPtr + dstStride[0] * srcSliceY, 460 srcSliceH * srcStride[0]); 461 else { 462 int i; 463 dstPtr += dstStride[0] * srcSliceY; 464 465 for (i = 0; i < srcSliceH; i++) { 466 conv(srcPtr, dstPtr, c->srcW * srcBpp); 467 srcPtr += srcStride[0]; 468 dstPtr += dstStride[0]; 469 } 470 } 471 } 472 return srcSliceH; 473} 474 475static int bgr24ToYv12Wrapper(SwsContext *c, const uint8_t *src[], 476 int srcStride[], int srcSliceY, int srcSliceH, 477 uint8_t *dst[], int dstStride[]) 478{ 479 rgb24toyv12( 480 src[0], 481 dst[0] + srcSliceY * dstStride[0], 482 dst[1] + (srcSliceY >> 1) * dstStride[1], 483 dst[2] + (srcSliceY >> 1) * dstStride[2], 484 c->srcW, srcSliceH, 485 dstStride[0], dstStride[1], srcStride[0]); 486 if (dst[3]) 487 fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); 488 return srcSliceH; 489} 490 491static int yvu9ToYv12Wrapper(SwsContext *c, const uint8_t *src[], 492 int srcStride[], int srcSliceY, int srcSliceH, 493 uint8_t *dst[], int dstStride[]) 494{ 495 copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, 496 dst[0], dstStride[0]); 497 498 planar2x(src[1], dst[1] + dstStride[1] * (srcSliceY >> 1), c->chrSrcW, 499 srcSliceH >> 2, srcStride[1], dstStride[1]); 500 planar2x(src[2], dst[2] + dstStride[2] * (srcSliceY >> 1), c->chrSrcW, 501 srcSliceH >> 2, srcStride[2], dstStride[2]); 502 if (dst[3]) 503 fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); 504 return srcSliceH; 505} 506 507/* unscaled copy like stuff (assumes nearly identical formats) */ 508static int packedCopyWrapper(SwsContext *c, const uint8_t *src[], 509 int srcStride[], int srcSliceY, int srcSliceH, 510 uint8_t *dst[], int dstStride[]) 511{ 512 if (dstStride[0] == srcStride[0] && srcStride[0] > 0) 513 memcpy(dst[0] + dstStride[0] * srcSliceY, src[0], srcSliceH * dstStride[0]); 514 else { 515 int i; 516 const uint8_t *srcPtr = src[0]; 517 uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY; 518 int length = 0; 519 520 /* universal length finder */ 521 while (length + c->srcW <= FFABS(dstStride[0]) && 522 length + c->srcW <= FFABS(srcStride[0])) 523 length += c->srcW; 524 assert(length != 0); 525 526 for (i = 0; i < srcSliceH; i++) { 527 memcpy(dstPtr, srcPtr, length); 528 srcPtr += srcStride[0]; 529 dstPtr += dstStride[0]; 530 } 531 } 532 return srcSliceH; 533} 534 535#define clip9(x) av_clip_uintp2(x, 9) 536#define clip10(x) av_clip_uintp2(x, 10) 537#define DITHER_COPY(dst, dstStride, wfunc, src, srcStride, rfunc, dithers, shift, clip) \ 538 for (i = 0; i < height; i++) { \ 539 const uint8_t *dither = dithers[i & 7]; \ 540 for (j = 0; j < length - 7; j += 8) { \ 541 wfunc(&dst[j + 0], clip((rfunc(&src[j + 0]) + dither[0]) >> shift)); \ 542 wfunc(&dst[j + 1], clip((rfunc(&src[j + 1]) + dither[1]) >> shift)); \ 543 wfunc(&dst[j + 2], clip((rfunc(&src[j + 2]) + dither[2]) >> shift)); \ 544 wfunc(&dst[j + 3], clip((rfunc(&src[j + 3]) + dither[3]) >> shift)); \ 545 wfunc(&dst[j + 4], clip((rfunc(&src[j + 4]) + dither[4]) >> shift)); \ 546 wfunc(&dst[j + 5], clip((rfunc(&src[j + 5]) + dither[5]) >> shift)); \ 547 wfunc(&dst[j + 6], clip((rfunc(&src[j + 6]) + dither[6]) >> shift)); \ 548 wfunc(&dst[j + 7], clip((rfunc(&src[j + 7]) + dither[7]) >> shift)); \ 549 } \ 550 for (; j < length; j++) \ 551 wfunc(&dst[j], (rfunc(&src[j]) + dither[j & 7]) >> shift); \ 552 dst += dstStride; \ 553 src += srcStride; \ 554 } 555 556static int planarCopyWrapper(SwsContext *c, const uint8_t *src[], 557 int srcStride[], int srcSliceY, int srcSliceH, 558 uint8_t *dst[], int dstStride[]) 559{ 560 int plane, i, j; 561 for (plane = 0; plane < 4; plane++) { 562 int length = (plane == 0 || plane == 3) ? c->srcW : -((-c->srcW ) >> c->chrDstHSubSample); 563 int y = (plane == 0 || plane == 3) ? srcSliceY: -((-srcSliceY) >> c->chrDstVSubSample); 564 int height = (plane == 0 || plane == 3) ? srcSliceH: -((-srcSliceH) >> c->chrDstVSubSample); 565 const uint8_t *srcPtr = src[plane]; 566 uint8_t *dstPtr = dst[plane] + dstStride[plane] * y; 567 568 if (!dst[plane]) 569 continue; 570 // ignore palette for GRAY8 571 if (plane == 1 && !dst[2]) continue; 572 if (!src[plane] || (plane == 1 && !src[2])) { 573 if (is16BPS(c->dstFormat)) 574 length *= 2; 575 fillPlane(dst[plane], dstStride[plane], length, height, y, 576 (plane == 3) ? 255 : 128); 577 } else { 578 if (is9_OR_10BPS(c->srcFormat)) { 579 const int src_depth = av_pix_fmt_descriptors[c->srcFormat].comp[plane].depth_minus1 + 1; 580 const int dst_depth = av_pix_fmt_descriptors[c->dstFormat].comp[plane].depth_minus1 + 1; 581 const uint16_t *srcPtr2 = (const uint16_t *) srcPtr; 582 583 if (is16BPS(c->dstFormat)) { 584 uint16_t *dstPtr2 = (uint16_t *) dstPtr; 585#define COPY9_OR_10TO16(rfunc, wfunc) \ 586 for (i = 0; i < height; i++) { \ 587 for (j = 0; j < length; j++) { \ 588 int srcpx = rfunc(&srcPtr2[j]); \ 589 wfunc(&dstPtr2[j], (srcpx << (16 - src_depth)) | (srcpx >> (2 * src_depth - 16))); \ 590 } \ 591 dstPtr2 += dstStride[plane] / 2; \ 592 srcPtr2 += srcStride[plane] / 2; \ 593 } 594 if (isBE(c->dstFormat)) { 595 if (isBE(c->srcFormat)) { 596 COPY9_OR_10TO16(AV_RB16, AV_WB16); 597 } else { 598 COPY9_OR_10TO16(AV_RL16, AV_WB16); 599 } 600 } else { 601 if (isBE(c->srcFormat)) { 602 COPY9_OR_10TO16(AV_RB16, AV_WL16); 603 } else { 604 COPY9_OR_10TO16(AV_RL16, AV_WL16); 605 } 606 } 607 } else if (is9_OR_10BPS(c->dstFormat)) { 608 uint16_t *dstPtr2 = (uint16_t *) dstPtr; 609#define COPY9_OR_10TO9_OR_10(loop) \ 610 for (i = 0; i < height; i++) { \ 611 for (j = 0; j < length; j++) { \ 612 loop; \ 613 } \ 614 dstPtr2 += dstStride[plane] / 2; \ 615 srcPtr2 += srcStride[plane] / 2; \ 616 } 617#define COPY9_OR_10TO9_OR_10_2(rfunc, wfunc) \ 618 if (dst_depth > src_depth) { \ 619 COPY9_OR_10TO9_OR_10(int srcpx = rfunc(&srcPtr2[j]); \ 620 wfunc(&dstPtr2[j], (srcpx << 1) | (srcpx >> 9))); \ 621 } else if (dst_depth < src_depth) { \ 622 DITHER_COPY(dstPtr2, dstStride[plane] / 2, wfunc, \ 623 srcPtr2, srcStride[plane] / 2, rfunc, \ 624 dither_8x8_1, 1, clip9); \ 625 } else { \ 626 COPY9_OR_10TO9_OR_10(wfunc(&dstPtr2[j], rfunc(&srcPtr2[j]))); \ 627 } 628 if (isBE(c->dstFormat)) { 629 if (isBE(c->srcFormat)) { 630 COPY9_OR_10TO9_OR_10_2(AV_RB16, AV_WB16); 631 } else { 632 COPY9_OR_10TO9_OR_10_2(AV_RL16, AV_WB16); 633 } 634 } else { 635 if (isBE(c->srcFormat)) { 636 COPY9_OR_10TO9_OR_10_2(AV_RB16, AV_WL16); 637 } else { 638 COPY9_OR_10TO9_OR_10_2(AV_RL16, AV_WL16); 639 } 640 } 641 } else { 642#define W8(a, b) { *(a) = (b); } 643#define COPY9_OR_10TO8(rfunc) \ 644 if (src_depth == 9) { \ 645 DITHER_COPY(dstPtr, dstStride[plane], W8, \ 646 srcPtr2, srcStride[plane] / 2, rfunc, \ 647 dither_8x8_1, 1, av_clip_uint8); \ 648 } else { \ 649 DITHER_COPY(dstPtr, dstStride[plane], W8, \ 650 srcPtr2, srcStride[plane] / 2, rfunc, \ 651 dither_8x8_3, 2, av_clip_uint8); \ 652 } 653 if (isBE(c->srcFormat)) { 654 COPY9_OR_10TO8(AV_RB16); 655 } else { 656 COPY9_OR_10TO8(AV_RL16); 657 } 658 } 659 } else if (is9_OR_10BPS(c->dstFormat)) { 660 const int dst_depth = av_pix_fmt_descriptors[c->dstFormat].comp[plane].depth_minus1 + 1; 661 uint16_t *dstPtr2 = (uint16_t *) dstPtr; 662 663 if (is16BPS(c->srcFormat)) { 664 const uint16_t *srcPtr2 = (const uint16_t *) srcPtr; 665#define COPY16TO9_OR_10(rfunc, wfunc) \ 666 if (dst_depth == 9) { \ 667 DITHER_COPY(dstPtr2, dstStride[plane] / 2, wfunc, \ 668 srcPtr2, srcStride[plane] / 2, rfunc, \ 669 dither_8x8_128, 7, clip9); \ 670 } else { \ 671 DITHER_COPY(dstPtr2, dstStride[plane] / 2, wfunc, \ 672 srcPtr2, srcStride[plane] / 2, rfunc, \ 673 dither_8x8_64, 6, clip10); \ 674 } 675 if (isBE(c->dstFormat)) { 676 if (isBE(c->srcFormat)) { 677 COPY16TO9_OR_10(AV_RB16, AV_WB16); 678 } else { 679 COPY16TO9_OR_10(AV_RL16, AV_WB16); 680 } 681 } else { 682 if (isBE(c->srcFormat)) { 683 COPY16TO9_OR_10(AV_RB16, AV_WL16); 684 } else { 685 COPY16TO9_OR_10(AV_RL16, AV_WL16); 686 } 687 } 688 } else /* 8bit */ { 689#define COPY8TO9_OR_10(wfunc) \ 690 for (i = 0; i < height; i++) { \ 691 for (j = 0; j < length; j++) { \ 692 const int srcpx = srcPtr[j]; \ 693 wfunc(&dstPtr2[j], (srcpx << (dst_depth - 8)) | (srcpx >> (16 - dst_depth))); \ 694 } \ 695 dstPtr2 += dstStride[plane] / 2; \ 696 srcPtr += srcStride[plane]; \ 697 } 698 if (isBE(c->dstFormat)) { 699 COPY8TO9_OR_10(AV_WB16); 700 } else { 701 COPY8TO9_OR_10(AV_WL16); 702 } 703 } 704 } else if (is16BPS(c->srcFormat) && !is16BPS(c->dstFormat)) { 705 const uint16_t *srcPtr2 = (const uint16_t *) srcPtr; 706#define COPY16TO8(rfunc) \ 707 DITHER_COPY(dstPtr, dstStride[plane], W8, \ 708 srcPtr2, srcStride[plane] / 2, rfunc, \ 709 dither_8x8_256, 8, av_clip_uint8); 710 if (isBE(c->srcFormat)) { 711 COPY16TO8(AV_RB16); 712 } else { 713 COPY16TO8(AV_RL16); 714 } 715 } else if (!is16BPS(c->srcFormat) && is16BPS(c->dstFormat)) { 716 for (i = 0; i < height; i++) { 717 for (j = 0; j < length; j++) { 718 dstPtr[ j << 1 ] = srcPtr[j]; 719 dstPtr[(j << 1) + 1] = srcPtr[j]; 720 } 721 srcPtr += srcStride[plane]; 722 dstPtr += dstStride[plane]; 723 } 724 } else if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat) && 725 isBE(c->srcFormat) != isBE(c->dstFormat)) { 726 727 for (i = 0; i < height; i++) { 728 for (j = 0; j < length; j++) 729 ((uint16_t *) dstPtr)[j] = av_bswap16(((const uint16_t *) srcPtr)[j]); 730 srcPtr += srcStride[plane]; 731 dstPtr += dstStride[plane]; 732 } 733 } else if (dstStride[plane] == srcStride[plane] && 734 srcStride[plane] > 0 && srcStride[plane] == length) { 735 memcpy(dst[plane] + dstStride[plane] * y, src[plane], 736 height * dstStride[plane]); 737 } else { 738 if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat)) 739 length *= 2; 740 else if (!av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1) 741 length >>= 3; // monowhite/black 742 for (i = 0; i < height; i++) { 743 memcpy(dstPtr, srcPtr, length); 744 srcPtr += srcStride[plane]; 745 dstPtr += dstStride[plane]; 746 } 747 } 748 } 749 } 750 return srcSliceH; 751} 752 753 754#define IS_DIFFERENT_ENDIANESS(src_fmt, dst_fmt, pix_fmt) \ 755 ((src_fmt == pix_fmt ## BE && dst_fmt == pix_fmt ## LE) || \ 756 (src_fmt == pix_fmt ## LE && dst_fmt == pix_fmt ## BE)) 757 758 759void ff_get_unscaled_swscale(SwsContext *c) 760{ 761 const enum PixelFormat srcFormat = c->srcFormat; 762 const enum PixelFormat dstFormat = c->dstFormat; 763 const int flags = c->flags; 764 const int dstH = c->dstH; 765 int needsDither; 766 767 needsDither = isAnyRGB(dstFormat) && 768 c->dstFormatBpp < 24 && 769 (c->dstFormatBpp < c->srcFormatBpp || (!isAnyRGB(srcFormat))); 770 771 /* yv12_to_nv12 */ 772 if ((srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) && 773 (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21)) { 774 c->swScale = planarToNv12Wrapper; 775 } 776 /* yuv2bgr */ 777 if ((srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUV422P || 778 srcFormat == PIX_FMT_YUVA420P) && isAnyRGB(dstFormat) && 779 !(flags & SWS_ACCURATE_RND) && !(dstH & 1)) { 780 c->swScale = ff_yuv2rgb_get_func_ptr(c); 781 } 782 783 if (srcFormat == PIX_FMT_YUV410P && 784 (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P) && 785 !(flags & SWS_BITEXACT)) { 786 c->swScale = yvu9ToYv12Wrapper; 787 } 788 789 /* bgr24toYV12 */ 790 if (srcFormat == PIX_FMT_BGR24 && 791 (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P) && 792 !(flags & SWS_ACCURATE_RND)) 793 c->swScale = bgr24ToYv12Wrapper; 794 795 /* RGB/BGR -> RGB/BGR (no dither needed forms) */ 796 if (isAnyRGB(srcFormat) && isAnyRGB(dstFormat) && findRgbConvFn(c) 797 && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)))) 798 c->swScale= rgbToRgbWrapper; 799 800 /* bswap 16 bits per pixel/component packed formats */ 801 if (IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR444) || 802 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR48) || 803 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR555) || 804 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR565) || 805 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_GRAY16) || 806 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB444) || 807 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB48) || 808 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB555) || 809 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB565)) 810 c->swScale = packed_16bpc_bswap; 811 812 if ((usePal(srcFormat) && ( 813 dstFormat == PIX_FMT_RGB32 || 814 dstFormat == PIX_FMT_RGB32_1 || 815 dstFormat == PIX_FMT_RGB24 || 816 dstFormat == PIX_FMT_BGR32 || 817 dstFormat == PIX_FMT_BGR32_1 || 818 dstFormat == PIX_FMT_BGR24))) 819 c->swScale = palToRgbWrapper; 820 821 if (srcFormat == PIX_FMT_YUV422P) { 822 if (dstFormat == PIX_FMT_YUYV422) 823 c->swScale = yuv422pToYuy2Wrapper; 824 else if (dstFormat == PIX_FMT_UYVY422) 825 c->swScale = yuv422pToUyvyWrapper; 826 } 827 828 /* LQ converters if -sws 0 or -sws 4*/ 829 if (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)) { 830 /* yv12_to_yuy2 */ 831 if (srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) { 832 if (dstFormat == PIX_FMT_YUYV422) 833 c->swScale = planarToYuy2Wrapper; 834 else if (dstFormat == PIX_FMT_UYVY422) 835 c->swScale = planarToUyvyWrapper; 836 } 837 } 838 if (srcFormat == PIX_FMT_YUYV422 && 839 (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P)) 840 c->swScale = yuyvToYuv420Wrapper; 841 if (srcFormat == PIX_FMT_UYVY422 && 842 (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P)) 843 c->swScale = uyvyToYuv420Wrapper; 844 if (srcFormat == PIX_FMT_YUYV422 && dstFormat == PIX_FMT_YUV422P) 845 c->swScale = yuyvToYuv422Wrapper; 846 if (srcFormat == PIX_FMT_UYVY422 && dstFormat == PIX_FMT_YUV422P) 847 c->swScale = uyvyToYuv422Wrapper; 848 849 /* simple copy */ 850 if ( srcFormat == dstFormat || 851 (srcFormat == PIX_FMT_YUVA420P && dstFormat == PIX_FMT_YUV420P) || 852 (srcFormat == PIX_FMT_YUV420P && dstFormat == PIX_FMT_YUVA420P) || 853 (isPlanarYUV(srcFormat) && isGray(dstFormat)) || 854 (isPlanarYUV(dstFormat) && isGray(srcFormat)) || 855 (isGray(dstFormat) && isGray(srcFormat)) || 856 (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat) && 857 c->chrDstHSubSample == c->chrSrcHSubSample && 858 c->chrDstVSubSample == c->chrSrcVSubSample && 859 dstFormat != PIX_FMT_NV12 && dstFormat != PIX_FMT_NV21 && 860 srcFormat != PIX_FMT_NV12 && srcFormat != PIX_FMT_NV21)) 861 { 862 if (isPacked(c->srcFormat)) 863 c->swScale = packedCopyWrapper; 864 else /* Planar YUV or gray */ 865 c->swScale = planarCopyWrapper; 866 } 867 868 if (ARCH_BFIN) 869 ff_bfin_get_unscaled_swscale(c); 870 if (HAVE_ALTIVEC) 871 ff_swscale_get_unscaled_altivec(c); 872} 873 874static void reset_ptr(const uint8_t *src[], int format) 875{ 876 if (!isALPHA(format)) 877 src[3] = NULL; 878 if (!isPlanar(format)) { 879 src[3] = src[2] = NULL; 880 881 if (!usePal(format)) 882 src[1] = NULL; 883 } 884} 885 886static int check_image_pointers(uint8_t *data[4], enum PixelFormat pix_fmt, 887 const int linesizes[4]) 888{ 889 const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt]; 890 int i; 891 892 for (i = 0; i < 4; i++) { 893 int plane = desc->comp[i].plane; 894 if (!data[plane] || !linesizes[plane]) 895 return 0; 896 } 897 898 return 1; 899} 900 901/** 902 * swscale wrapper, so we don't need to export the SwsContext. 903 * Assumes planar YUV to be in YUV order instead of YVU. 904 */ 905int attribute_align_arg sws_scale(struct SwsContext *c, 906 const uint8_t * const srcSlice[], 907 const int srcStride[], int srcSliceY, 908 int srcSliceH, uint8_t *const dst[], 909 const int dstStride[]) 910{ 911 int i; 912 const uint8_t *src2[4] = { srcSlice[0], srcSlice[1], srcSlice[2], srcSlice[3] }; 913 uint8_t *dst2[4] = { dst[0], dst[1], dst[2], dst[3] }; 914 915 // do not mess up sliceDir if we have a "trailing" 0-size slice 916 if (srcSliceH == 0) 917 return 0; 918 919 if (!check_image_pointers(srcSlice, c->srcFormat, srcStride)) { 920 av_log(c, AV_LOG_ERROR, "bad src image pointers\n"); 921 return 0; 922 } 923 if (!check_image_pointers(dst, c->dstFormat, dstStride)) { 924 av_log(c, AV_LOG_ERROR, "bad dst image pointers\n"); 925 return 0; 926 } 927 928 if (c->sliceDir == 0 && srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) { 929 av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n"); 930 return 0; 931 } 932 if (c->sliceDir == 0) { 933 if (srcSliceY == 0) c->sliceDir = 1; else c->sliceDir = -1; 934 } 935 936 if (usePal(c->srcFormat)) { 937 for (i = 0; i < 256; i++) { 938 int p, r, g, b, y, u, v; 939 if (c->srcFormat == PIX_FMT_PAL8) { 940 p = ((const uint32_t *)(srcSlice[1]))[i]; 941 r = (p >> 16) & 0xFF; 942 g = (p >> 8) & 0xFF; 943 b = p & 0xFF; 944 } else if (c->srcFormat == PIX_FMT_RGB8) { 945 r = ( i >> 5 ) * 36; 946 g = ((i >> 2) & 7) * 36; 947 b = ( i & 3) * 85; 948 } else if (c->srcFormat == PIX_FMT_BGR8) { 949 b = ( i >> 6 ) * 85; 950 g = ((i >> 3) & 7) * 36; 951 r = ( i & 7) * 36; 952 } else if (c->srcFormat == PIX_FMT_RGB4_BYTE) { 953 r = ( i >> 3 ) * 255; 954 g = ((i >> 1) & 3) * 85; 955 b = ( i & 1) * 255; 956 } else if (c->srcFormat == PIX_FMT_GRAY8 || 957 c->srcFormat == PIX_FMT_Y400A) { 958 r = g = b = i; 959 } else { 960 assert(c->srcFormat == PIX_FMT_BGR4_BYTE); 961 b = ( i >> 3 ) * 255; 962 g = ((i >> 1) & 3) * 85; 963 r = ( i & 1) * 255; 964 } 965 y = av_clip_uint8((RY * r + GY * g + BY * b + ( 33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT); 966 u = av_clip_uint8((RU * r + GU * g + BU * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT); 967 v = av_clip_uint8((RV * r + GV * g + BV * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT); 968 c->pal_yuv[i] = y + (u << 8) + (v << 16); 969 970 switch (c->dstFormat) { 971 case PIX_FMT_BGR32: 972#if !HAVE_BIGENDIAN 973 case PIX_FMT_RGB24: 974#endif 975 c->pal_rgb[i] = r + (g << 8) + (b << 16); 976 break; 977 case PIX_FMT_BGR32_1: 978#if HAVE_BIGENDIAN 979 case PIX_FMT_BGR24: 980#endif 981 c->pal_rgb[i] = (r + (g << 8) + (b << 16)) << 8; 982 break; 983 case PIX_FMT_RGB32_1: 984#if HAVE_BIGENDIAN 985 case PIX_FMT_RGB24: 986#endif 987 c->pal_rgb[i] = (b + (g << 8) + (r << 16)) << 8; 988 break; 989 case PIX_FMT_RGB32: 990#if !HAVE_BIGENDIAN 991 case PIX_FMT_BGR24: 992#endif 993 default: 994 c->pal_rgb[i] = b + (g << 8) + (r << 16); 995 } 996 } 997 } 998 999 // copy strides, so they can safely be modified 1000 if (c->sliceDir == 1) { 1001 // slices go from top to bottom 1002 int srcStride2[4] = { srcStride[0], srcStride[1], srcStride[2], 1003 srcStride[3] }; 1004 int dstStride2[4] = { dstStride[0], dstStride[1], dstStride[2], 1005 dstStride[3] }; 1006 1007 reset_ptr(src2, c->srcFormat); 1008 reset_ptr((const uint8_t **) dst2, c->dstFormat); 1009 1010 /* reset slice direction at end of frame */ 1011 if (srcSliceY + srcSliceH == c->srcH) 1012 c->sliceDir = 0; 1013 1014 return c->swScale(c, src2, srcStride2, srcSliceY, srcSliceH, dst2, 1015 dstStride2); 1016 } else { 1017 // slices go from bottom to top => we flip the image internally 1018 int srcStride2[4] = { -srcStride[0], -srcStride[1], -srcStride[2], 1019 -srcStride[3] }; 1020 int dstStride2[4] = { -dstStride[0], -dstStride[1], -dstStride[2], 1021 -dstStride[3] }; 1022 1023 src2[0] += (srcSliceH - 1) * srcStride[0]; 1024 if (!usePal(c->srcFormat)) 1025 src2[1] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[1]; 1026 src2[2] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[2]; 1027 src2[3] += (srcSliceH - 1) * srcStride[3]; 1028 dst2[0] += ( c->dstH - 1) * dstStride[0]; 1029 dst2[1] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[1]; 1030 dst2[2] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[2]; 1031 dst2[3] += ( c->dstH - 1) * dstStride[3]; 1032 1033 reset_ptr(src2, c->srcFormat); 1034 reset_ptr((const uint8_t **) dst2, c->dstFormat); 1035 1036 /* reset slice direction at end of frame */ 1037 if (!srcSliceY) 1038 c->sliceDir = 0; 1039 1040 return c->swScale(c, src2, srcStride2, c->srcH-srcSliceY-srcSliceH, 1041 srcSliceH, dst2, dstStride2); 1042 } 1043} 1044 1045/* Convert the palette to the same packed 32-bit format as the palette */ 1046void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, 1047 int num_pixels, const uint8_t *palette) 1048{ 1049 int i; 1050 1051 for (i = 0; i < num_pixels; i++) 1052 ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i]]; 1053} 1054 1055/* Palette format: ABCD -> dst format: ABC */ 1056void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst, 1057 int num_pixels, const uint8_t *palette) 1058{ 1059 int i; 1060 1061 for (i = 0; i < num_pixels; i++) { 1062 //FIXME slow? 1063 dst[0] = palette[src[i] * 4 + 0]; 1064 dst[1] = palette[src[i] * 4 + 1]; 1065 dst[2] = palette[src[i] * 4 + 2]; 1066 dst += 3; 1067 } 1068} 1069