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, static 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, static 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, static 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. DECLARE_ALIGNED(8, static const uint8_t, dither_8x8_256)[8][8] = {
  66. { 72, 136, 120, 184, 68, 132, 116, 180,},
  67. { 200, 8, 248, 56, 196, 4, 244, 52,},
  68. { 104, 168, 88, 152, 100, 164, 84, 148,},
  69. { 232, 40, 216, 24, 228, 36, 212, 20,},
  70. { 64, 128, 102, 176, 76, 140, 124, 188,},
  71. { 192, 0, 240, 48, 204, 12, 252, 60,},
  72. { 96, 160, 80, 144, 108, 172, 92, 156,},
  73. { 224, 32, 208, 16, 236, 44, 220, 28,},
  74. };
  75. #define RGB2YUV_SHIFT 15
  76. #define BY ( (int) (0.114 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
  77. #define BV (-(int) (0.081 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
  78. #define BU ( (int) (0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
  79. #define GY ( (int) (0.587 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
  80. #define GV (-(int) (0.419 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
  81. #define GU (-(int) (0.331 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
  82. #define RY ( (int) (0.299 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
  83. #define RV ( (int) (0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
  84. #define RU (-(int) (0.169 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
  85. static void fillPlane(uint8_t *plane, int stride, int width, int height, int y,
  86. uint8_t val)
  87. {
  88. int i;
  89. uint8_t *ptr = plane + stride * y;
  90. for (i = 0; i < height; i++) {
  91. memset(ptr, val, width);
  92. ptr += stride;
  93. }
  94. }
  95. static void fill_plane9or10(uint8_t *plane, int stride, int width,
  96. int height, int y, uint8_t val,
  97. const int dst_depth, const int big_endian)
  98. {
  99. int i, j;
  100. uint16_t *dst = (uint16_t *) (plane + stride * y);
  101. #define FILL8TO9_OR_10(wfunc) \
  102. for (i = 0; i < height; i++) { \
  103. for (j = 0; j < width; j++) { \
  104. wfunc(&dst[j], (val << (dst_depth - 8)) | \
  105. (val >> (16 - dst_depth))); \
  106. } \
  107. dst += stride / 2; \
  108. }
  109. if (big_endian) {
  110. FILL8TO9_OR_10(AV_WB16);
  111. } else {
  112. FILL8TO9_OR_10(AV_WL16);
  113. }
  114. }
  115. static void copyPlane(const uint8_t *src, int srcStride,
  116. int srcSliceY, int srcSliceH, int width,
  117. uint8_t *dst, int dstStride)
  118. {
  119. dst += dstStride * srcSliceY;
  120. if (dstStride == srcStride && srcStride > 0) {
  121. memcpy(dst, src, srcSliceH * dstStride);
  122. } else {
  123. int i;
  124. for (i = 0; i < srcSliceH; i++) {
  125. memcpy(dst, src, width);
  126. src += srcStride;
  127. dst += dstStride;
  128. }
  129. }
  130. }
  131. static int planarToNv12Wrapper(SwsContext *c, const uint8_t *src[],
  132. int srcStride[], int srcSliceY,
  133. int srcSliceH, uint8_t *dstParam[],
  134. int dstStride[])
  135. {
  136. uint8_t *dst = dstParam[1] + dstStride[1] * srcSliceY / 2;
  137. copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
  138. dstParam[0], dstStride[0]);
  139. if (c->dstFormat == AV_PIX_FMT_NV12)
  140. interleaveBytes(src[1], src[2], dst, c->srcW / 2, srcSliceH / 2,
  141. srcStride[1], srcStride[2], dstStride[0]);
  142. else
  143. interleaveBytes(src[2], src[1], dst, c->srcW / 2, srcSliceH / 2,
  144. srcStride[2], srcStride[1], dstStride[0]);
  145. return srcSliceH;
  146. }
  147. static int planarToYuy2Wrapper(SwsContext *c, const uint8_t *src[],
  148. int srcStride[], int srcSliceY, int srcSliceH,
  149. uint8_t *dstParam[], int dstStride[])
  150. {
  151. uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
  152. yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
  153. srcStride[1], dstStride[0]);
  154. return srcSliceH;
  155. }
  156. static int planarToUyvyWrapper(SwsContext *c, const uint8_t *src[],
  157. int srcStride[], int srcSliceY, int srcSliceH,
  158. uint8_t *dstParam[], int dstStride[])
  159. {
  160. uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
  161. yv12touyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
  162. srcStride[1], dstStride[0]);
  163. return srcSliceH;
  164. }
  165. static int yuv422pToYuy2Wrapper(SwsContext *c, const uint8_t *src[],
  166. int srcStride[], int srcSliceY, int srcSliceH,
  167. uint8_t *dstParam[], int dstStride[])
  168. {
  169. uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
  170. yuv422ptoyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
  171. srcStride[1], dstStride[0]);
  172. return srcSliceH;
  173. }
  174. static 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. yuv422ptouyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
  180. srcStride[1], dstStride[0]);
  181. return srcSliceH;
  182. }
  183. static int yuyvToYuv420Wrapper(SwsContext *c, const uint8_t *src[],
  184. int srcStride[], int srcSliceY, int srcSliceH,
  185. uint8_t *dstParam[], int dstStride[])
  186. {
  187. uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY;
  188. uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY / 2;
  189. uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY / 2;
  190. yuyvtoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
  191. dstStride[1], srcStride[0]);
  192. if (dstParam[3])
  193. fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
  194. return srcSliceH;
  195. }
  196. static int yuyvToYuv422Wrapper(SwsContext *c, const uint8_t *src[],
  197. int srcStride[], int srcSliceY, int srcSliceH,
  198. uint8_t *dstParam[], int dstStride[])
  199. {
  200. uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY;
  201. uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY;
  202. uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY;
  203. yuyvtoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
  204. dstStride[1], srcStride[0]);
  205. return srcSliceH;
  206. }
  207. static int uyvyToYuv420Wrapper(SwsContext *c, const uint8_t *src[],
  208. int srcStride[], int srcSliceY, int srcSliceH,
  209. uint8_t *dstParam[], int dstStride[])
  210. {
  211. uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY;
  212. uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY / 2;
  213. uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY / 2;
  214. uyvytoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
  215. dstStride[1], srcStride[0]);
  216. if (dstParam[3])
  217. fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
  218. return srcSliceH;
  219. }
  220. static int uyvyToYuv422Wrapper(SwsContext *c, const uint8_t *src[],
  221. int srcStride[], int srcSliceY, int srcSliceH,
  222. uint8_t *dstParam[], int dstStride[])
  223. {
  224. uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY;
  225. uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY;
  226. uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY;
  227. uyvytoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
  228. dstStride[1], srcStride[0]);
  229. return srcSliceH;
  230. }
  231. static void gray8aToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels,
  232. const uint8_t *palette)
  233. {
  234. int i;
  235. for (i = 0; i < num_pixels; i++)
  236. ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i << 1]] | (src[(i << 1) + 1] << 24);
  237. }
  238. static void gray8aToPacked32_1(const uint8_t *src, uint8_t *dst, int num_pixels,
  239. const uint8_t *palette)
  240. {
  241. int i;
  242. for (i = 0; i < num_pixels; i++)
  243. ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i << 1]] | src[(i << 1) + 1];
  244. }
  245. static void gray8aToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels,
  246. const uint8_t *palette)
  247. {
  248. int i;
  249. for (i = 0; i < num_pixels; i++) {
  250. //FIXME slow?
  251. dst[0] = palette[src[i << 1] * 4 + 0];
  252. dst[1] = palette[src[i << 1] * 4 + 1];
  253. dst[2] = palette[src[i << 1] * 4 + 2];
  254. dst += 3;
  255. }
  256. }
  257. static int packed_16bpc_bswap(SwsContext *c, const uint8_t *src[],
  258. int srcStride[], int srcSliceY, int srcSliceH,
  259. uint8_t *dst[], int dstStride[])
  260. {
  261. int i, j;
  262. int srcstr = srcStride[0] >> 1;
  263. int dststr = dstStride[0] >> 1;
  264. uint16_t *dstPtr = (uint16_t *) dst[0];
  265. const uint16_t *srcPtr = (const uint16_t *) src[0];
  266. int min_stride = FFMIN(srcstr, dststr);
  267. for (i = 0; i < srcSliceH; i++) {
  268. for (j = 0; j < min_stride; j++) {
  269. dstPtr[j] = av_bswap16(srcPtr[j]);
  270. }
  271. srcPtr += srcstr;
  272. dstPtr += dststr;
  273. }
  274. return srcSliceH;
  275. }
  276. static int palToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[],
  277. int srcSliceY, int srcSliceH, uint8_t *dst[],
  278. int dstStride[])
  279. {
  280. const enum AVPixelFormat srcFormat = c->srcFormat;
  281. const enum AVPixelFormat dstFormat = c->dstFormat;
  282. void (*conv)(const uint8_t *src, uint8_t *dst, int num_pixels,
  283. const uint8_t *palette) = NULL;
  284. int i;
  285. uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY;
  286. const uint8_t *srcPtr = src[0];
  287. if (srcFormat == AV_PIX_FMT_Y400A) {
  288. switch (dstFormat) {
  289. case AV_PIX_FMT_RGB32 : conv = gray8aToPacked32; break;
  290. case AV_PIX_FMT_BGR32 : conv = gray8aToPacked32; break;
  291. case AV_PIX_FMT_BGR32_1: conv = gray8aToPacked32_1; break;
  292. case AV_PIX_FMT_RGB32_1: conv = gray8aToPacked32_1; break;
  293. case AV_PIX_FMT_RGB24 : conv = gray8aToPacked24; break;
  294. case AV_PIX_FMT_BGR24 : conv = gray8aToPacked24; break;
  295. }
  296. } else if (usePal(srcFormat)) {
  297. switch (dstFormat) {
  298. case AV_PIX_FMT_RGB32 : conv = sws_convertPalette8ToPacked32; break;
  299. case AV_PIX_FMT_BGR32 : conv = sws_convertPalette8ToPacked32; break;
  300. case AV_PIX_FMT_BGR32_1: conv = sws_convertPalette8ToPacked32; break;
  301. case AV_PIX_FMT_RGB32_1: conv = sws_convertPalette8ToPacked32; break;
  302. case AV_PIX_FMT_RGB24 : conv = sws_convertPalette8ToPacked24; break;
  303. case AV_PIX_FMT_BGR24 : conv = sws_convertPalette8ToPacked24; break;
  304. }
  305. }
  306. if (!conv)
  307. av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
  308. sws_format_name(srcFormat), sws_format_name(dstFormat));
  309. else {
  310. for (i = 0; i < srcSliceH; i++) {
  311. conv(srcPtr, dstPtr, c->srcW, (uint8_t *) c->pal_rgb);
  312. srcPtr += srcStride[0];
  313. dstPtr += dstStride[0];
  314. }
  315. }
  316. return srcSliceH;
  317. }
  318. static void gbr24ptopacked24(const uint8_t *src[], int srcStride[],
  319. uint8_t *dst, int dstStride, int srcSliceH,
  320. int width)
  321. {
  322. int x, h, i;
  323. for (h = 0; h < srcSliceH; h++) {
  324. uint8_t *dest = dst + dstStride * h;
  325. for (x = 0; x < width; x++) {
  326. *dest++ = src[0][x];
  327. *dest++ = src[1][x];
  328. *dest++ = src[2][x];
  329. }
  330. for (i = 0; i < 3; i++)
  331. src[i] += srcStride[i];
  332. }
  333. }
  334. static void gbr24ptopacked32(const uint8_t *src[], int srcStride[],
  335. uint8_t *dst, int dstStride, int srcSliceH,
  336. int alpha_first, int width)
  337. {
  338. int x, h, i;
  339. for (h = 0; h < srcSliceH; h++) {
  340. uint8_t *dest = dst + dstStride * h;
  341. if (alpha_first) {
  342. for (x = 0; x < width; x++) {
  343. *dest++ = 0xff;
  344. *dest++ = src[0][x];
  345. *dest++ = src[1][x];
  346. *dest++ = src[2][x];
  347. }
  348. } else {
  349. for (x = 0; x < width; x++) {
  350. *dest++ = src[0][x];
  351. *dest++ = src[1][x];
  352. *dest++ = src[2][x];
  353. *dest++ = 0xff;
  354. }
  355. }
  356. for (i = 0; i < 3; i++)
  357. src[i] += srcStride[i];
  358. }
  359. }
  360. static int planarRgbToRgbWrapper(SwsContext *c, const uint8_t *src[],
  361. int srcStride[], int srcSliceY, int srcSliceH,
  362. uint8_t *dst[], int dstStride[])
  363. {
  364. int alpha_first = 0;
  365. const uint8_t *src102[] = { src[1], src[0], src[2] };
  366. const uint8_t *src201[] = { src[2], src[0], src[1] };
  367. int stride102[] = { srcStride[1], srcStride[0], srcStride[2] };
  368. int stride201[] = { srcStride[2], srcStride[0], srcStride[1] };
  369. if (c->srcFormat != AV_PIX_FMT_GBRP) {
  370. av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n",
  371. av_get_pix_fmt_name(c->srcFormat),
  372. av_get_pix_fmt_name(c->dstFormat));
  373. return srcSliceH;
  374. }
  375. switch (c->dstFormat) {
  376. case AV_PIX_FMT_BGR24:
  377. gbr24ptopacked24(src102, stride102,
  378. dst[0] + srcSliceY * dstStride[0], dstStride[0],
  379. srcSliceH, c->srcW);
  380. break;
  381. case AV_PIX_FMT_RGB24:
  382. gbr24ptopacked24(src201, stride201,
  383. dst[0] + srcSliceY * dstStride[0], dstStride[0],
  384. srcSliceH, c->srcW);
  385. break;
  386. case AV_PIX_FMT_ARGB:
  387. alpha_first = 1;
  388. case AV_PIX_FMT_RGBA:
  389. gbr24ptopacked32(src201, stride201,
  390. dst[0] + srcSliceY * dstStride[0], dstStride[0],
  391. srcSliceH, alpha_first, c->srcW);
  392. break;
  393. case AV_PIX_FMT_ABGR:
  394. alpha_first = 1;
  395. case AV_PIX_FMT_BGRA:
  396. gbr24ptopacked32(src102, stride102,
  397. dst[0] + srcSliceY * dstStride[0], dstStride[0],
  398. srcSliceH, alpha_first, c->srcW);
  399. break;
  400. default:
  401. av_log(c, AV_LOG_ERROR,
  402. "unsupported planar RGB conversion %s -> %s\n",
  403. av_get_pix_fmt_name(c->srcFormat),
  404. av_get_pix_fmt_name(c->dstFormat));
  405. }
  406. return srcSliceH;
  407. }
  408. static void packedtogbr24p(const uint8_t *src, int srcStride,
  409. uint8_t *dst[], int dstStride[], int srcSliceH,
  410. int alpha_first, int inc_size, int width)
  411. {
  412. uint8_t *dest[3];
  413. int x, h;
  414. dest[0] = dst[0];
  415. dest[1] = dst[1];
  416. dest[2] = dst[2];
  417. if (alpha_first)
  418. src++;
  419. for (h = 0; h < srcSliceH; h++) {
  420. for (x = 0; x < width; x++) {
  421. dest[0][x] = src[0];
  422. dest[1][x] = src[1];
  423. dest[2][x] = src[2];
  424. src += inc_size;
  425. }
  426. src += srcStride - width * inc_size;
  427. dest[0] += dstStride[0];
  428. dest[1] += dstStride[1];
  429. dest[2] += dstStride[2];
  430. }
  431. }
  432. static int rgbToPlanarRgbWrapper(SwsContext *c, const uint8_t *src[],
  433. int srcStride[], int srcSliceY, int srcSliceH,
  434. uint8_t *dst[], int dstStride[])
  435. {
  436. int alpha_first = 0;
  437. int stride102[] = { dstStride[1], dstStride[0], dstStride[2] };
  438. int stride201[] = { dstStride[2], dstStride[0], dstStride[1] };
  439. uint8_t *dst102[] = { dst[1] + srcSliceY * dstStride[1],
  440. dst[0] + srcSliceY * dstStride[0],
  441. dst[2] + srcSliceY * dstStride[2] };
  442. uint8_t *dst201[] = { dst[2] + srcSliceY * dstStride[2],
  443. dst[0] + srcSliceY * dstStride[0],
  444. dst[1] + srcSliceY * dstStride[1] };
  445. switch (c->srcFormat) {
  446. case AV_PIX_FMT_RGB24:
  447. packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst201,
  448. stride201, srcSliceH, alpha_first, 3, c->srcW);
  449. break;
  450. case AV_PIX_FMT_BGR24:
  451. packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst102,
  452. stride102, srcSliceH, alpha_first, 3, c->srcW);
  453. break;
  454. case AV_PIX_FMT_ARGB:
  455. alpha_first = 1;
  456. case AV_PIX_FMT_RGBA:
  457. packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst201,
  458. stride201, srcSliceH, alpha_first, 4, c->srcW);
  459. break;
  460. case AV_PIX_FMT_ABGR:
  461. alpha_first = 1;
  462. case AV_PIX_FMT_BGRA:
  463. packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst102,
  464. stride102, srcSliceH, alpha_first, 4, c->srcW);
  465. break;
  466. default:
  467. av_log(c, AV_LOG_ERROR,
  468. "unsupported planar RGB conversion %s -> %s\n",
  469. av_get_pix_fmt_name(c->srcFormat),
  470. av_get_pix_fmt_name(c->dstFormat));
  471. }
  472. return srcSliceH;
  473. }
  474. #define isRGBA32(x) ( \
  475. (x) == AV_PIX_FMT_ARGB \
  476. || (x) == AV_PIX_FMT_RGBA \
  477. || (x) == AV_PIX_FMT_BGRA \
  478. || (x) == AV_PIX_FMT_ABGR \
  479. )
  480. /* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */
  481. typedef void (* rgbConvFn) (const uint8_t *, uint8_t *, int);
  482. static rgbConvFn findRgbConvFn(SwsContext *c)
  483. {
  484. const enum AVPixelFormat srcFormat = c->srcFormat;
  485. const enum AVPixelFormat dstFormat = c->dstFormat;
  486. const int srcId = c->srcFormatBpp;
  487. const int dstId = c->dstFormatBpp;
  488. rgbConvFn conv = NULL;
  489. const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(srcFormat);
  490. const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(dstFormat);
  491. #define IS_NOT_NE(bpp, desc) \
  492. (((bpp + 7) >> 3) == 2 && \
  493. (!(desc->flags & AV_PIX_FMT_FLAG_BE) != !HAVE_BIGENDIAN))
  494. /* if this is non-native rgb444/555/565, don't handle it here. */
  495. if (IS_NOT_NE(srcId, desc_src) || IS_NOT_NE(dstId, desc_dst))
  496. return NULL;
  497. #define CONV_IS(src, dst) (srcFormat == AV_PIX_FMT_##src && dstFormat == AV_PIX_FMT_##dst)
  498. if (isRGBA32(srcFormat) && isRGBA32(dstFormat)) {
  499. if ( CONV_IS(ABGR, RGBA)
  500. || CONV_IS(ARGB, BGRA)
  501. || CONV_IS(BGRA, ARGB)
  502. || CONV_IS(RGBA, ABGR)) conv = shuffle_bytes_3210;
  503. else if (CONV_IS(ABGR, ARGB)
  504. || CONV_IS(ARGB, ABGR)) conv = shuffle_bytes_0321;
  505. else if (CONV_IS(ABGR, BGRA)
  506. || CONV_IS(ARGB, RGBA)) conv = shuffle_bytes_1230;
  507. else if (CONV_IS(BGRA, RGBA)
  508. || CONV_IS(RGBA, BGRA)) conv = shuffle_bytes_2103;
  509. else if (CONV_IS(BGRA, ABGR)
  510. || CONV_IS(RGBA, ARGB)) conv = shuffle_bytes_3012;
  511. } else
  512. /* BGR -> BGR */
  513. if ((isBGRinInt(srcFormat) && isBGRinInt(dstFormat)) ||
  514. (isRGBinInt(srcFormat) && isRGBinInt(dstFormat))) {
  515. switch (srcId | (dstId << 16)) {
  516. case 0x000F000C: conv = rgb12to15; break;
  517. case 0x000F0010: conv = rgb16to15; break;
  518. case 0x000F0018: conv = rgb24to15; break;
  519. case 0x000F0020: conv = rgb32to15; break;
  520. case 0x0010000F: conv = rgb15to16; break;
  521. case 0x00100018: conv = rgb24to16; break;
  522. case 0x00100020: conv = rgb32to16; break;
  523. case 0x0018000F: conv = rgb15to24; break;
  524. case 0x00180010: conv = rgb16to24; break;
  525. case 0x00180020: conv = rgb32to24; break;
  526. case 0x0020000F: conv = rgb15to32; break;
  527. case 0x00200010: conv = rgb16to32; break;
  528. case 0x00200018: conv = rgb24to32; break;
  529. }
  530. } else if ((isBGRinInt(srcFormat) && isRGBinInt(dstFormat)) ||
  531. (isRGBinInt(srcFormat) && isBGRinInt(dstFormat))) {
  532. switch (srcId | (dstId << 16)) {
  533. case 0x000C000C: conv = rgb12tobgr12; break;
  534. case 0x000F000F: conv = rgb15tobgr15; break;
  535. case 0x000F0010: conv = rgb16tobgr15; break;
  536. case 0x000F0018: conv = rgb24tobgr15; break;
  537. case 0x000F0020: conv = rgb32tobgr15; break;
  538. case 0x0010000F: conv = rgb15tobgr16; break;
  539. case 0x00100010: conv = rgb16tobgr16; break;
  540. case 0x00100018: conv = rgb24tobgr16; break;
  541. case 0x00100020: conv = rgb32tobgr16; break;
  542. case 0x0018000F: conv = rgb15tobgr24; break;
  543. case 0x00180010: conv = rgb16tobgr24; break;
  544. case 0x00180018: conv = rgb24tobgr24; break;
  545. case 0x00180020: conv = rgb32tobgr24; break;
  546. case 0x0020000F: conv = rgb15tobgr32; break;
  547. case 0x00200010: conv = rgb16tobgr32; break;
  548. case 0x00200018: conv = rgb24tobgr32; break;
  549. }
  550. }
  551. return conv;
  552. }
  553. /* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */
  554. static int rgbToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[],
  555. int srcSliceY, int srcSliceH, uint8_t *dst[],
  556. int dstStride[])
  557. {
  558. const enum AVPixelFormat srcFormat = c->srcFormat;
  559. const enum AVPixelFormat dstFormat = c->dstFormat;
  560. const int srcBpp = (c->srcFormatBpp + 7) >> 3;
  561. const int dstBpp = (c->dstFormatBpp + 7) >> 3;
  562. rgbConvFn conv = findRgbConvFn(c);
  563. if (!conv) {
  564. av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
  565. sws_format_name(srcFormat), sws_format_name(dstFormat));
  566. } else {
  567. const uint8_t *srcPtr = src[0];
  568. uint8_t *dstPtr = dst[0];
  569. if ((srcFormat == AV_PIX_FMT_RGB32_1 || srcFormat == AV_PIX_FMT_BGR32_1) &&
  570. !isRGBA32(dstFormat))
  571. srcPtr += ALT32_CORR;
  572. if ((dstFormat == AV_PIX_FMT_RGB32_1 || dstFormat == AV_PIX_FMT_BGR32_1) &&
  573. !isRGBA32(srcFormat))
  574. dstPtr += ALT32_CORR;
  575. if (dstStride[0] * srcBpp == srcStride[0] * dstBpp && srcStride[0] > 0 &&
  576. !(srcStride[0] % srcBpp))
  577. conv(srcPtr, dstPtr + dstStride[0] * srcSliceY,
  578. srcSliceH * srcStride[0]);
  579. else {
  580. int i;
  581. dstPtr += dstStride[0] * srcSliceY;
  582. for (i = 0; i < srcSliceH; i++) {
  583. conv(srcPtr, dstPtr, c->srcW * srcBpp);
  584. srcPtr += srcStride[0];
  585. dstPtr += dstStride[0];
  586. }
  587. }
  588. }
  589. return srcSliceH;
  590. }
  591. static int bgr24ToYv12Wrapper(SwsContext *c, const uint8_t *src[],
  592. int srcStride[], int srcSliceY, int srcSliceH,
  593. uint8_t *dst[], int dstStride[])
  594. {
  595. rgb24toyv12(
  596. src[0],
  597. dst[0] + srcSliceY * dstStride[0],
  598. dst[1] + (srcSliceY >> 1) * dstStride[1],
  599. dst[2] + (srcSliceY >> 1) * dstStride[2],
  600. c->srcW, srcSliceH,
  601. dstStride[0], dstStride[1], srcStride[0]);
  602. if (dst[3])
  603. fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
  604. return srcSliceH;
  605. }
  606. static int yvu9ToYv12Wrapper(SwsContext *c, const uint8_t *src[],
  607. int srcStride[], int srcSliceY, int srcSliceH,
  608. uint8_t *dst[], int dstStride[])
  609. {
  610. copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
  611. dst[0], dstStride[0]);
  612. planar2x(src[1], dst[1] + dstStride[1] * (srcSliceY >> 1), c->chrSrcW,
  613. srcSliceH >> 2, srcStride[1], dstStride[1]);
  614. planar2x(src[2], dst[2] + dstStride[2] * (srcSliceY >> 1), c->chrSrcW,
  615. srcSliceH >> 2, srcStride[2], dstStride[2]);
  616. if (dst[3])
  617. fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
  618. return srcSliceH;
  619. }
  620. /* unscaled copy like stuff (assumes nearly identical formats) */
  621. static int packedCopyWrapper(SwsContext *c, const uint8_t *src[],
  622. int srcStride[], int srcSliceY, int srcSliceH,
  623. uint8_t *dst[], int dstStride[])
  624. {
  625. if (dstStride[0] == srcStride[0] && srcStride[0] > 0)
  626. memcpy(dst[0] + dstStride[0] * srcSliceY, src[0], srcSliceH * dstStride[0]);
  627. else {
  628. int i;
  629. const uint8_t *srcPtr = src[0];
  630. uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY;
  631. int length = 0;
  632. /* universal length finder */
  633. while (length + c->srcW <= FFABS(dstStride[0]) &&
  634. length + c->srcW <= FFABS(srcStride[0]))
  635. length += c->srcW;
  636. assert(length != 0);
  637. for (i = 0; i < srcSliceH; i++) {
  638. memcpy(dstPtr, srcPtr, length);
  639. srcPtr += srcStride[0];
  640. dstPtr += dstStride[0];
  641. }
  642. }
  643. return srcSliceH;
  644. }
  645. #define clip9(x) av_clip_uintp2(x, 9)
  646. #define clip10(x) av_clip_uintp2(x, 10)
  647. #define DITHER_COPY(dst, dstStride, wfunc, src, srcStride, rfunc, dithers, shift, clip) \
  648. for (i = 0; i < height; i++) { \
  649. const uint8_t *dither = dithers[i & 7]; \
  650. for (j = 0; j < length - 7; j += 8) { \
  651. wfunc(&dst[j + 0], clip((rfunc(&src[j + 0]) + dither[0]) >> shift)); \
  652. wfunc(&dst[j + 1], clip((rfunc(&src[j + 1]) + dither[1]) >> shift)); \
  653. wfunc(&dst[j + 2], clip((rfunc(&src[j + 2]) + dither[2]) >> shift)); \
  654. wfunc(&dst[j + 3], clip((rfunc(&src[j + 3]) + dither[3]) >> shift)); \
  655. wfunc(&dst[j + 4], clip((rfunc(&src[j + 4]) + dither[4]) >> shift)); \
  656. wfunc(&dst[j + 5], clip((rfunc(&src[j + 5]) + dither[5]) >> shift)); \
  657. wfunc(&dst[j + 6], clip((rfunc(&src[j + 6]) + dither[6]) >> shift)); \
  658. wfunc(&dst[j + 7], clip((rfunc(&src[j + 7]) + dither[7]) >> shift)); \
  659. } \
  660. for (; j < length; j++) \
  661. wfunc(&dst[j], (rfunc(&src[j]) + dither[j & 7]) >> shift); \
  662. dst += dstStride; \
  663. src += srcStride; \
  664. }
  665. static int planarCopyWrapper(SwsContext *c, const uint8_t *src[],
  666. int srcStride[], int srcSliceY, int srcSliceH,
  667. uint8_t *dst[], int dstStride[])
  668. {
  669. const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->srcFormat);
  670. const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat);
  671. int plane, i, j;
  672. for (plane = 0; plane < 4; plane++) {
  673. int length = (plane == 0 || plane == 3) ? c->srcW : -((-c->srcW ) >> c->chrDstHSubSample);
  674. int y = (plane == 0 || plane == 3) ? srcSliceY: -((-srcSliceY) >> c->chrDstVSubSample);
  675. int height = (plane == 0 || plane == 3) ? srcSliceH: -((-srcSliceH) >> c->chrDstVSubSample);
  676. const uint8_t *srcPtr = src[plane];
  677. uint8_t *dstPtr = dst[plane] + dstStride[plane] * y;
  678. if (!dst[plane])
  679. continue;
  680. // ignore palette for GRAY8
  681. if (plane == 1 && !dst[2]) continue;
  682. if (!src[plane] || (plane == 1 && !src[2])) {
  683. int val = (plane == 3) ? 255 : 128;
  684. if (is16BPS(c->dstFormat))
  685. length *= 2;
  686. if (is9_OR_10BPS(c->dstFormat)) {
  687. fill_plane9or10(dst[plane], dstStride[plane],
  688. length, height, y, val,
  689. desc_dst->comp[plane].depth_minus1 + 1,
  690. isBE(c->dstFormat));
  691. } else
  692. fillPlane(dst[plane], dstStride[plane], length, height, y,
  693. val);
  694. } else {
  695. if (is9_OR_10BPS(c->srcFormat)) {
  696. const int src_depth = desc_src->comp[plane].depth_minus1 + 1;
  697. const int dst_depth = desc_dst->comp[plane].depth_minus1 + 1;
  698. const uint16_t *srcPtr2 = (const uint16_t *) srcPtr;
  699. if (is16BPS(c->dstFormat)) {
  700. uint16_t *dstPtr2 = (uint16_t *) dstPtr;
  701. #define COPY9_OR_10TO16(rfunc, wfunc) \
  702. for (i = 0; i < height; i++) { \
  703. for (j = 0; j < length; j++) { \
  704. int srcpx = rfunc(&srcPtr2[j]); \
  705. wfunc(&dstPtr2[j], (srcpx << (16 - src_depth)) | (srcpx >> (2 * src_depth - 16))); \
  706. } \
  707. dstPtr2 += dstStride[plane] / 2; \
  708. srcPtr2 += srcStride[plane] / 2; \
  709. }
  710. if (isBE(c->dstFormat)) {
  711. if (isBE(c->srcFormat)) {
  712. COPY9_OR_10TO16(AV_RB16, AV_WB16);
  713. } else {
  714. COPY9_OR_10TO16(AV_RL16, AV_WB16);
  715. }
  716. } else {
  717. if (isBE(c->srcFormat)) {
  718. COPY9_OR_10TO16(AV_RB16, AV_WL16);
  719. } else {
  720. COPY9_OR_10TO16(AV_RL16, AV_WL16);
  721. }
  722. }
  723. } else if (is9_OR_10BPS(c->dstFormat)) {
  724. uint16_t *dstPtr2 = (uint16_t *) dstPtr;
  725. #define COPY9_OR_10TO9_OR_10(loop) \
  726. for (i = 0; i < height; i++) { \
  727. for (j = 0; j < length; j++) { \
  728. loop; \
  729. } \
  730. dstPtr2 += dstStride[plane] / 2; \
  731. srcPtr2 += srcStride[plane] / 2; \
  732. }
  733. #define COPY9_OR_10TO9_OR_10_2(rfunc, wfunc) \
  734. if (dst_depth > src_depth) { \
  735. COPY9_OR_10TO9_OR_10(int srcpx = rfunc(&srcPtr2[j]); \
  736. wfunc(&dstPtr2[j], (srcpx << 1) | (srcpx >> 9))); \
  737. } else if (dst_depth < src_depth) { \
  738. DITHER_COPY(dstPtr2, dstStride[plane] / 2, wfunc, \
  739. srcPtr2, srcStride[plane] / 2, rfunc, \
  740. dither_8x8_1, 1, clip9); \
  741. } else { \
  742. COPY9_OR_10TO9_OR_10(wfunc(&dstPtr2[j], rfunc(&srcPtr2[j]))); \
  743. }
  744. if (isBE(c->dstFormat)) {
  745. if (isBE(c->srcFormat)) {
  746. COPY9_OR_10TO9_OR_10_2(AV_RB16, AV_WB16);
  747. } else {
  748. COPY9_OR_10TO9_OR_10_2(AV_RL16, AV_WB16);
  749. }
  750. } else {
  751. if (isBE(c->srcFormat)) {
  752. COPY9_OR_10TO9_OR_10_2(AV_RB16, AV_WL16);
  753. } else {
  754. COPY9_OR_10TO9_OR_10_2(AV_RL16, AV_WL16);
  755. }
  756. }
  757. } else {
  758. #define W8(a, b) { *(a) = (b); }
  759. #define COPY9_OR_10TO8(rfunc) \
  760. if (src_depth == 9) { \
  761. DITHER_COPY(dstPtr, dstStride[plane], W8, \
  762. srcPtr2, srcStride[plane] / 2, rfunc, \
  763. dither_8x8_1, 1, av_clip_uint8); \
  764. } else { \
  765. DITHER_COPY(dstPtr, dstStride[plane], W8, \
  766. srcPtr2, srcStride[plane] / 2, rfunc, \
  767. dither_8x8_3, 2, av_clip_uint8); \
  768. }
  769. if (isBE(c->srcFormat)) {
  770. COPY9_OR_10TO8(AV_RB16);
  771. } else {
  772. COPY9_OR_10TO8(AV_RL16);
  773. }
  774. }
  775. } else if (is9_OR_10BPS(c->dstFormat)) {
  776. const int dst_depth = desc_dst->comp[plane].depth_minus1 + 1;
  777. uint16_t *dstPtr2 = (uint16_t *) dstPtr;
  778. if (is16BPS(c->srcFormat)) {
  779. const uint16_t *srcPtr2 = (const uint16_t *) srcPtr;
  780. #define COPY16TO9_OR_10(rfunc, wfunc) \
  781. if (dst_depth == 9) { \
  782. DITHER_COPY(dstPtr2, dstStride[plane] / 2, wfunc, \
  783. srcPtr2, srcStride[plane] / 2, rfunc, \
  784. ff_dither_8x8_128, 7, clip9); \
  785. } else { \
  786. DITHER_COPY(dstPtr2, dstStride[plane] / 2, wfunc, \
  787. srcPtr2, srcStride[plane] / 2, rfunc, \
  788. dither_8x8_64, 6, clip10); \
  789. }
  790. if (isBE(c->dstFormat)) {
  791. if (isBE(c->srcFormat)) {
  792. COPY16TO9_OR_10(AV_RB16, AV_WB16);
  793. } else {
  794. COPY16TO9_OR_10(AV_RL16, AV_WB16);
  795. }
  796. } else {
  797. if (isBE(c->srcFormat)) {
  798. COPY16TO9_OR_10(AV_RB16, AV_WL16);
  799. } else {
  800. COPY16TO9_OR_10(AV_RL16, AV_WL16);
  801. }
  802. }
  803. } else /* 8bit */ {
  804. #define COPY8TO9_OR_10(wfunc) \
  805. for (i = 0; i < height; i++) { \
  806. for (j = 0; j < length; j++) { \
  807. const int srcpx = srcPtr[j]; \
  808. wfunc(&dstPtr2[j], (srcpx << (dst_depth - 8)) | (srcpx >> (16 - dst_depth))); \
  809. } \
  810. dstPtr2 += dstStride[plane] / 2; \
  811. srcPtr += srcStride[plane]; \
  812. }
  813. if (isBE(c->dstFormat)) {
  814. COPY8TO9_OR_10(AV_WB16);
  815. } else {
  816. COPY8TO9_OR_10(AV_WL16);
  817. }
  818. }
  819. } else if (is16BPS(c->srcFormat) && !is16BPS(c->dstFormat)) {
  820. const uint16_t *srcPtr2 = (const uint16_t *) srcPtr;
  821. #define COPY16TO8(rfunc) \
  822. DITHER_COPY(dstPtr, dstStride[plane], W8, \
  823. srcPtr2, srcStride[plane] / 2, rfunc, \
  824. dither_8x8_256, 8, av_clip_uint8);
  825. if (isBE(c->srcFormat)) {
  826. COPY16TO8(AV_RB16);
  827. } else {
  828. COPY16TO8(AV_RL16);
  829. }
  830. } else if (!is16BPS(c->srcFormat) && is16BPS(c->dstFormat)) {
  831. for (i = 0; i < height; i++) {
  832. for (j = 0; j < length; j++) {
  833. dstPtr[ j << 1 ] = srcPtr[j];
  834. dstPtr[(j << 1) + 1] = srcPtr[j];
  835. }
  836. srcPtr += srcStride[plane];
  837. dstPtr += dstStride[plane];
  838. }
  839. } else if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat) &&
  840. isBE(c->srcFormat) != isBE(c->dstFormat)) {
  841. for (i = 0; i < height; i++) {
  842. for (j = 0; j < length; j++)
  843. ((uint16_t *) dstPtr)[j] = av_bswap16(((const uint16_t *) srcPtr)[j]);
  844. srcPtr += srcStride[plane];
  845. dstPtr += dstStride[plane];
  846. }
  847. } else if (dstStride[plane] == srcStride[plane] &&
  848. srcStride[plane] > 0 && srcStride[plane] == length) {
  849. memcpy(dst[plane] + dstStride[plane] * y, src[plane],
  850. height * dstStride[plane]);
  851. } else {
  852. if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat))
  853. length *= 2;
  854. else if (!desc_src->comp[0].depth_minus1)
  855. length >>= 3; // monowhite/black
  856. for (i = 0; i < height; i++) {
  857. memcpy(dstPtr, srcPtr, length);
  858. srcPtr += srcStride[plane];
  859. dstPtr += dstStride[plane];
  860. }
  861. }
  862. }
  863. }
  864. return srcSliceH;
  865. }
  866. #define IS_DIFFERENT_ENDIANESS(src_fmt, dst_fmt, pix_fmt) \
  867. ((src_fmt == pix_fmt ## BE && dst_fmt == pix_fmt ## LE) || \
  868. (src_fmt == pix_fmt ## LE && dst_fmt == pix_fmt ## BE))
  869. void ff_get_unscaled_swscale(SwsContext *c)
  870. {
  871. const enum AVPixelFormat srcFormat = c->srcFormat;
  872. const enum AVPixelFormat dstFormat = c->dstFormat;
  873. const int flags = c->flags;
  874. const int dstH = c->dstH;
  875. int needsDither;
  876. needsDither = isAnyRGB(dstFormat) &&
  877. c->dstFormatBpp < 24 &&
  878. (c->dstFormatBpp < c->srcFormatBpp || (!isAnyRGB(srcFormat)));
  879. /* yv12_to_nv12 */
  880. if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUVA420P) &&
  881. (dstFormat == AV_PIX_FMT_NV12 || dstFormat == AV_PIX_FMT_NV21)) {
  882. c->swscale = planarToNv12Wrapper;
  883. }
  884. /* yuv2bgr */
  885. if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUV422P ||
  886. srcFormat == AV_PIX_FMT_YUVA420P) && isAnyRGB(dstFormat) &&
  887. !(flags & SWS_ACCURATE_RND) && !(dstH & 1)) {
  888. c->swscale = ff_yuv2rgb_get_func_ptr(c);
  889. }
  890. if (srcFormat == AV_PIX_FMT_YUV410P &&
  891. (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P) &&
  892. !(flags & SWS_BITEXACT)) {
  893. c->swscale = yvu9ToYv12Wrapper;
  894. }
  895. /* bgr24toYV12 */
  896. if (srcFormat == AV_PIX_FMT_BGR24 &&
  897. (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P) &&
  898. !(flags & SWS_ACCURATE_RND))
  899. c->swscale = bgr24ToYv12Wrapper;
  900. /* RGB/BGR -> RGB/BGR (no dither needed forms) */
  901. if (isAnyRGB(srcFormat) && isAnyRGB(dstFormat) && findRgbConvFn(c)
  902. && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT))))
  903. c->swscale = rgbToRgbWrapper;
  904. #define isByteRGB(f) ( \
  905. f == AV_PIX_FMT_RGB32 || \
  906. f == AV_PIX_FMT_RGB32_1 || \
  907. f == AV_PIX_FMT_RGB24 || \
  908. f == AV_PIX_FMT_BGR32 || \
  909. f == AV_PIX_FMT_BGR32_1 || \
  910. f == AV_PIX_FMT_BGR24)
  911. if (srcFormat == AV_PIX_FMT_GBRP && isPlanar(srcFormat) && isByteRGB(dstFormat))
  912. c->swscale = planarRgbToRgbWrapper;
  913. if (av_pix_fmt_desc_get(srcFormat)->comp[0].depth_minus1 == 7 &&
  914. isPackedRGB(srcFormat) && dstFormat == AV_PIX_FMT_GBRP)
  915. c->swscale = rgbToPlanarRgbWrapper;
  916. /* bswap 16 bits per pixel/component packed formats */
  917. if (IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR444) ||
  918. IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR48) ||
  919. IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR555) ||
  920. IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR565) ||
  921. IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GRAY16) ||
  922. IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB444) ||
  923. IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB48) ||
  924. IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB555) ||
  925. IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB565) ||
  926. IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_XYZ12))
  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_get_unscaled_swscale_bfin(c);
  982. if (ARCH_PPC)
  983. ff_get_unscaled_swscale_ppc(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. }