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.

1369 lines
54KB

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