You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1293 lines
49KB

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