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.

1343 lines
52KB

  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 void packedtogbr24p(const uint8_t *src, int srcStride,
  426. uint8_t *dst[], int dstStride[], int srcSliceH,
  427. int alpha_first, int inc_size, int width)
  428. {
  429. uint8_t *dest[3];
  430. int x, h;
  431. dest[0] = dst[0];
  432. dest[1] = dst[1];
  433. dest[2] = dst[2];
  434. if (alpha_first)
  435. src++;
  436. for (h = 0; h < srcSliceH; h++) {
  437. for (x = 0; x < width; x++) {
  438. dest[0][x] = src[0];
  439. dest[1][x] = src[1];
  440. dest[2][x] = src[2];
  441. src += inc_size;
  442. }
  443. src += srcStride - width * inc_size;
  444. dest[0] += dstStride[0];
  445. dest[1] += dstStride[1];
  446. dest[2] += dstStride[2];
  447. }
  448. }
  449. static int rgbToPlanarRgbWrapper(SwsContext *c, const uint8_t *src[],
  450. int srcStride[], int srcSliceY, int srcSliceH,
  451. uint8_t *dst[], int dstStride[])
  452. {
  453. int alpha_first = 0;
  454. int stride102[] = { dstStride[1], dstStride[0], dstStride[2] };
  455. int stride201[] = { dstStride[2], dstStride[0], dstStride[1] };
  456. uint8_t *dst102[] = { dst[1] + srcSliceY * dstStride[1],
  457. dst[0] + srcSliceY * dstStride[0],
  458. dst[2] + srcSliceY * dstStride[2] };
  459. uint8_t *dst201[] = { dst[2] + srcSliceY * dstStride[2],
  460. dst[0] + srcSliceY * dstStride[0],
  461. dst[1] + srcSliceY * dstStride[1] };
  462. switch (c->srcFormat) {
  463. case AV_PIX_FMT_RGB24:
  464. packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst201,
  465. stride201, srcSliceH, alpha_first, 3, c->srcW);
  466. break;
  467. case AV_PIX_FMT_BGR24:
  468. packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst102,
  469. stride102, srcSliceH, alpha_first, 3, c->srcW);
  470. break;
  471. case AV_PIX_FMT_ARGB:
  472. alpha_first = 1;
  473. case AV_PIX_FMT_RGBA:
  474. packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst201,
  475. stride201, srcSliceH, alpha_first, 4, c->srcW);
  476. break;
  477. case AV_PIX_FMT_ABGR:
  478. alpha_first = 1;
  479. case AV_PIX_FMT_BGRA:
  480. packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst102,
  481. stride102, srcSliceH, alpha_first, 4, c->srcW);
  482. break;
  483. default:
  484. av_log(c, AV_LOG_ERROR,
  485. "unsupported planar RGB conversion %s -> %s\n",
  486. av_get_pix_fmt_name(c->srcFormat),
  487. av_get_pix_fmt_name(c->dstFormat));
  488. }
  489. return srcSliceH;
  490. }
  491. #define isRGBA32(x) ( \
  492. (x) == AV_PIX_FMT_ARGB \
  493. || (x) == AV_PIX_FMT_RGBA \
  494. || (x) == AV_PIX_FMT_BGRA \
  495. || (x) == AV_PIX_FMT_ABGR \
  496. )
  497. /* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */
  498. typedef void (* rgbConvFn) (const uint8_t *, uint8_t *, int);
  499. static rgbConvFn findRgbConvFn(SwsContext *c)
  500. {
  501. const enum AVPixelFormat srcFormat = c->srcFormat;
  502. const enum AVPixelFormat dstFormat = c->dstFormat;
  503. const int srcId = c->srcFormatBpp;
  504. const int dstId = c->dstFormatBpp;
  505. rgbConvFn conv = NULL;
  506. const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(srcFormat);
  507. const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(dstFormat);
  508. #define IS_NOT_NE(bpp, desc) \
  509. (((bpp + 7) >> 3) == 2 && \
  510. (!(desc->flags & AV_PIX_FMT_FLAG_BE) != !HAVE_BIGENDIAN))
  511. /* if this is non-native rgb444/555/565, don't handle it here. */
  512. if (IS_NOT_NE(srcId, desc_src) || IS_NOT_NE(dstId, desc_dst))
  513. return NULL;
  514. #define CONV_IS(src, dst) (srcFormat == AV_PIX_FMT_##src && dstFormat == AV_PIX_FMT_##dst)
  515. if (isRGBA32(srcFormat) && isRGBA32(dstFormat)) {
  516. if ( CONV_IS(ABGR, RGBA)
  517. || CONV_IS(ARGB, BGRA)
  518. || CONV_IS(BGRA, ARGB)
  519. || CONV_IS(RGBA, ABGR)) conv = shuffle_bytes_3210;
  520. else if (CONV_IS(ABGR, ARGB)
  521. || CONV_IS(ARGB, ABGR)) conv = shuffle_bytes_0321;
  522. else if (CONV_IS(ABGR, BGRA)
  523. || CONV_IS(ARGB, RGBA)) conv = shuffle_bytes_1230;
  524. else if (CONV_IS(BGRA, RGBA)
  525. || CONV_IS(RGBA, BGRA)) conv = shuffle_bytes_2103;
  526. else if (CONV_IS(BGRA, ABGR)
  527. || CONV_IS(RGBA, ARGB)) conv = shuffle_bytes_3012;
  528. } else
  529. /* BGR -> BGR */
  530. if ((isBGRinInt(srcFormat) && isBGRinInt(dstFormat)) ||
  531. (isRGBinInt(srcFormat) && isRGBinInt(dstFormat))) {
  532. switch (srcId | (dstId << 16)) {
  533. case 0x000F000C: conv = rgb12to15; break;
  534. case 0x000F0010: conv = rgb16to15; break;
  535. case 0x000F0018: conv = rgb24to15; break;
  536. case 0x000F0020: conv = rgb32to15; break;
  537. case 0x0010000F: conv = rgb15to16; break;
  538. case 0x00100018: conv = rgb24to16; break;
  539. case 0x00100020: conv = rgb32to16; break;
  540. case 0x0018000F: conv = rgb15to24; break;
  541. case 0x00180010: conv = rgb16to24; break;
  542. case 0x00180020: conv = rgb32to24; break;
  543. case 0x0020000F: conv = rgb15to32; break;
  544. case 0x00200010: conv = rgb16to32; break;
  545. case 0x00200018: conv = rgb24to32; break;
  546. }
  547. } else if ((isBGRinInt(srcFormat) && isRGBinInt(dstFormat)) ||
  548. (isRGBinInt(srcFormat) && isBGRinInt(dstFormat))) {
  549. switch (srcId | (dstId << 16)) {
  550. case 0x000C000C: conv = rgb12tobgr12; break;
  551. case 0x000F000F: conv = rgb15tobgr15; break;
  552. case 0x000F0010: conv = rgb16tobgr15; break;
  553. case 0x000F0018: conv = rgb24tobgr15; break;
  554. case 0x000F0020: conv = rgb32tobgr15; break;
  555. case 0x0010000F: conv = rgb15tobgr16; break;
  556. case 0x00100010: conv = rgb16tobgr16; break;
  557. case 0x00100018: conv = rgb24tobgr16; break;
  558. case 0x00100020: conv = rgb32tobgr16; break;
  559. case 0x0018000F: conv = rgb15tobgr24; break;
  560. case 0x00180010: conv = rgb16tobgr24; break;
  561. case 0x00180018: conv = rgb24tobgr24; break;
  562. case 0x00180020: conv = rgb32tobgr24; break;
  563. case 0x0020000F: conv = rgb15tobgr32; break;
  564. case 0x00200010: conv = rgb16tobgr32; break;
  565. case 0x00200018: conv = rgb24tobgr32; break;
  566. }
  567. }
  568. return conv;
  569. }
  570. /* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */
  571. static int rgbToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[],
  572. int srcSliceY, int srcSliceH, uint8_t *dst[],
  573. int dstStride[])
  574. {
  575. const enum AVPixelFormat srcFormat = c->srcFormat;
  576. const enum AVPixelFormat dstFormat = c->dstFormat;
  577. const int srcBpp = (c->srcFormatBpp + 7) >> 3;
  578. const int dstBpp = (c->dstFormatBpp + 7) >> 3;
  579. rgbConvFn conv = findRgbConvFn(c);
  580. if (!conv) {
  581. av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
  582. sws_format_name(srcFormat), sws_format_name(dstFormat));
  583. } else {
  584. const uint8_t *srcPtr = src[0];
  585. uint8_t *dstPtr = dst[0];
  586. if ((srcFormat == AV_PIX_FMT_RGB32_1 || srcFormat == AV_PIX_FMT_BGR32_1) &&
  587. !isRGBA32(dstFormat))
  588. srcPtr += ALT32_CORR;
  589. if ((dstFormat == AV_PIX_FMT_RGB32_1 || dstFormat == AV_PIX_FMT_BGR32_1) &&
  590. !isRGBA32(srcFormat))
  591. dstPtr += ALT32_CORR;
  592. if (dstStride[0] * srcBpp == srcStride[0] * dstBpp && srcStride[0] > 0 &&
  593. !(srcStride[0] % srcBpp))
  594. conv(srcPtr, dstPtr + dstStride[0] * srcSliceY,
  595. (srcSliceH - 1) * srcStride[0] + c->srcW * srcBpp);
  596. else {
  597. int i;
  598. dstPtr += dstStride[0] * srcSliceY;
  599. for (i = 0; i < srcSliceH; i++) {
  600. conv(srcPtr, dstPtr, c->srcW * srcBpp);
  601. srcPtr += srcStride[0];
  602. dstPtr += dstStride[0];
  603. }
  604. }
  605. }
  606. return srcSliceH;
  607. }
  608. static int bgr24ToYv12Wrapper(SwsContext *c, const uint8_t *src[],
  609. int srcStride[], int srcSliceY, int srcSliceH,
  610. uint8_t *dst[], int dstStride[])
  611. {
  612. rgb24toyv12(
  613. src[0],
  614. dst[0] + srcSliceY * dstStride[0],
  615. dst[1] + (srcSliceY >> 1) * dstStride[1],
  616. dst[2] + (srcSliceY >> 1) * dstStride[2],
  617. c->srcW, srcSliceH,
  618. dstStride[0], dstStride[1], srcStride[0]);
  619. if (dst[3])
  620. fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
  621. return srcSliceH;
  622. }
  623. static int yvu9ToYv12Wrapper(SwsContext *c, const uint8_t *src[],
  624. int srcStride[], int srcSliceY, int srcSliceH,
  625. uint8_t *dst[], int dstStride[])
  626. {
  627. copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
  628. dst[0], dstStride[0]);
  629. planar2x(src[1], dst[1] + dstStride[1] * (srcSliceY >> 1), c->chrSrcW,
  630. srcSliceH >> 2, srcStride[1], dstStride[1]);
  631. planar2x(src[2], dst[2] + dstStride[2] * (srcSliceY >> 1), c->chrSrcW,
  632. srcSliceH >> 2, srcStride[2], dstStride[2]);
  633. if (dst[3])
  634. fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
  635. return srcSliceH;
  636. }
  637. /* unscaled copy like stuff (assumes nearly identical formats) */
  638. static int packedCopyWrapper(SwsContext *c, const uint8_t *src[],
  639. int srcStride[], int srcSliceY, int srcSliceH,
  640. uint8_t *dst[], int dstStride[])
  641. {
  642. if (dstStride[0] == srcStride[0] && srcStride[0] > 0)
  643. memcpy(dst[0] + dstStride[0] * srcSliceY, src[0], srcSliceH * dstStride[0]);
  644. else {
  645. int i;
  646. const uint8_t *srcPtr = src[0];
  647. uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY;
  648. int length = 0;
  649. /* universal length finder */
  650. while (length + c->srcW <= FFABS(dstStride[0]) &&
  651. length + c->srcW <= FFABS(srcStride[0]))
  652. length += c->srcW;
  653. assert(length != 0);
  654. for (i = 0; i < srcSliceH; i++) {
  655. memcpy(dstPtr, srcPtr, length);
  656. srcPtr += srcStride[0];
  657. dstPtr += dstStride[0];
  658. }
  659. }
  660. return srcSliceH;
  661. }
  662. #define clip9(x) av_clip_uintp2(x, 9)
  663. #define clip10(x) av_clip_uintp2(x, 10)
  664. #define DITHER_COPY(dst, dstStride, wfunc, src, srcStride, rfunc, dithers, shift, clip) \
  665. for (i = 0; i < height; i++) { \
  666. const uint8_t *dither = dithers[i & 7]; \
  667. for (j = 0; j < length - 7; j += 8) { \
  668. wfunc(&dst[j + 0], clip((rfunc(&src[j + 0]) + dither[0]) >> shift)); \
  669. wfunc(&dst[j + 1], clip((rfunc(&src[j + 1]) + dither[1]) >> shift)); \
  670. wfunc(&dst[j + 2], clip((rfunc(&src[j + 2]) + dither[2]) >> shift)); \
  671. wfunc(&dst[j + 3], clip((rfunc(&src[j + 3]) + dither[3]) >> shift)); \
  672. wfunc(&dst[j + 4], clip((rfunc(&src[j + 4]) + dither[4]) >> shift)); \
  673. wfunc(&dst[j + 5], clip((rfunc(&src[j + 5]) + dither[5]) >> shift)); \
  674. wfunc(&dst[j + 6], clip((rfunc(&src[j + 6]) + dither[6]) >> shift)); \
  675. wfunc(&dst[j + 7], clip((rfunc(&src[j + 7]) + dither[7]) >> shift)); \
  676. } \
  677. for (; j < length; j++) \
  678. wfunc(&dst[j], (rfunc(&src[j]) + dither[j & 7]) >> shift); \
  679. dst += dstStride; \
  680. src += srcStride; \
  681. }
  682. static int planarCopyWrapper(SwsContext *c, const uint8_t *src[],
  683. int srcStride[], int srcSliceY, int srcSliceH,
  684. uint8_t *dst[], int dstStride[])
  685. {
  686. const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->srcFormat);
  687. const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat);
  688. int plane, i, j;
  689. for (plane = 0; plane < 4; plane++) {
  690. int length = (plane == 0 || plane == 3) ? c->srcW : -((-c->srcW ) >> c->chrDstHSubSample);
  691. int y = (plane == 0 || plane == 3) ? srcSliceY: -((-srcSliceY) >> c->chrDstVSubSample);
  692. int height = (plane == 0 || plane == 3) ? srcSliceH: -((-srcSliceH) >> c->chrDstVSubSample);
  693. const uint8_t *srcPtr = src[plane];
  694. uint8_t *dstPtr = dst[plane] + dstStride[plane] * y;
  695. int shiftonly = plane == 1 || plane == 2 || (!c->srcRange && plane == 0);
  696. if (!dst[plane])
  697. continue;
  698. // ignore palette for GRAY8
  699. if (plane == 1 && !dst[2]) continue;
  700. if (!src[plane] || (plane == 1 && !src[2])) {
  701. int val = (plane == 3) ? 255 : 128;
  702. if (is16BPS(c->dstFormat))
  703. length *= 2;
  704. if (is9_OR_10BPS(c->dstFormat)) {
  705. fill_plane9or10(dst[plane], dstStride[plane],
  706. length, height, y, val,
  707. desc_dst->comp[plane].depth_minus1 + 1,
  708. isBE(c->dstFormat));
  709. } else
  710. fillPlane(dst[plane], dstStride[plane], length, height, y,
  711. val);
  712. } else {
  713. if (is9_OR_10BPS(c->srcFormat)) {
  714. const int src_depth = desc_src->comp[plane].depth_minus1 + 1;
  715. const int dst_depth = desc_dst->comp[plane].depth_minus1 + 1;
  716. const uint16_t *srcPtr2 = (const uint16_t *) srcPtr;
  717. if (is16BPS(c->dstFormat)) {
  718. uint16_t *dstPtr2 = (uint16_t *) dstPtr;
  719. #define COPY9_OR_10TO16(rfunc, wfunc) \
  720. if (shiftonly) { \
  721. for (i = 0; i < height; i++) { \
  722. for (j = 0; j < length; j++) { \
  723. int srcpx = rfunc(&srcPtr2[j]); \
  724. wfunc(&dstPtr2[j], srcpx << (16 - src_depth)); \
  725. } \
  726. dstPtr2 += dstStride[plane] / 2; \
  727. srcPtr2 += srcStride[plane] / 2; \
  728. } \
  729. } else { \
  730. for (i = 0; i < height; i++) { \
  731. for (j = 0; j < length; j++) { \
  732. int srcpx = rfunc(&srcPtr2[j]); \
  733. wfunc(&dstPtr2[j], (srcpx << (16 - src_depth)) | (srcpx >> (2 * src_depth - 16))); \
  734. } \
  735. dstPtr2 += dstStride[plane] / 2; \
  736. srcPtr2 += srcStride[plane] / 2; \
  737. } \
  738. }
  739. if (isBE(c->dstFormat)) {
  740. if (isBE(c->srcFormat)) {
  741. COPY9_OR_10TO16(AV_RB16, AV_WB16);
  742. } else {
  743. COPY9_OR_10TO16(AV_RL16, AV_WB16);
  744. }
  745. } else {
  746. if (isBE(c->srcFormat)) {
  747. COPY9_OR_10TO16(AV_RB16, AV_WL16);
  748. } else {
  749. COPY9_OR_10TO16(AV_RL16, AV_WL16);
  750. }
  751. }
  752. } else if (is9_OR_10BPS(c->dstFormat)) {
  753. uint16_t *dstPtr2 = (uint16_t *) dstPtr;
  754. #define COPY9_OR_10TO9_OR_10(loop) \
  755. for (i = 0; i < height; i++) { \
  756. for (j = 0; j < length; j++) { \
  757. loop; \
  758. } \
  759. dstPtr2 += dstStride[plane] / 2; \
  760. srcPtr2 += srcStride[plane] / 2; \
  761. }
  762. #define COPY9_OR_10TO9_OR_10_2(rfunc, wfunc) \
  763. if (dst_depth > src_depth) { \
  764. COPY9_OR_10TO9_OR_10(int srcpx = rfunc(&srcPtr2[j]); \
  765. wfunc(&dstPtr2[j], (srcpx << 1) | (srcpx >> 9))); \
  766. } else if (dst_depth < src_depth) { \
  767. DITHER_COPY(dstPtr2, dstStride[plane] / 2, wfunc, \
  768. srcPtr2, srcStride[plane] / 2, rfunc, \
  769. dither_8x8_1, 1, clip9); \
  770. } else { \
  771. COPY9_OR_10TO9_OR_10(wfunc(&dstPtr2[j], rfunc(&srcPtr2[j]))); \
  772. }
  773. if (isBE(c->dstFormat)) {
  774. if (isBE(c->srcFormat)) {
  775. COPY9_OR_10TO9_OR_10_2(AV_RB16, AV_WB16);
  776. } else {
  777. COPY9_OR_10TO9_OR_10_2(AV_RL16, AV_WB16);
  778. }
  779. } else {
  780. if (isBE(c->srcFormat)) {
  781. COPY9_OR_10TO9_OR_10_2(AV_RB16, AV_WL16);
  782. } else {
  783. COPY9_OR_10TO9_OR_10_2(AV_RL16, AV_WL16);
  784. }
  785. }
  786. } else {
  787. #define W8(a, b) { *(a) = (b); }
  788. #define COPY9_OR_10TO8(rfunc) \
  789. if (src_depth == 9) { \
  790. DITHER_COPY(dstPtr, dstStride[plane], W8, \
  791. srcPtr2, srcStride[plane] / 2, rfunc, \
  792. dither_8x8_1, 1, av_clip_uint8); \
  793. } else { \
  794. DITHER_COPY(dstPtr, dstStride[plane], W8, \
  795. srcPtr2, srcStride[plane] / 2, rfunc, \
  796. dither_8x8_3, 2, av_clip_uint8); \
  797. }
  798. if (isBE(c->srcFormat)) {
  799. COPY9_OR_10TO8(AV_RB16);
  800. } else {
  801. COPY9_OR_10TO8(AV_RL16);
  802. }
  803. }
  804. } else if (is9_OR_10BPS(c->dstFormat)) {
  805. const int dst_depth = desc_dst->comp[plane].depth_minus1 + 1;
  806. uint16_t *dstPtr2 = (uint16_t *) dstPtr;
  807. if (is16BPS(c->srcFormat)) {
  808. const uint16_t *srcPtr2 = (const uint16_t *) srcPtr;
  809. #define COPY16TO9_OR_10(rfunc, wfunc) \
  810. if (dst_depth == 9) { \
  811. DITHER_COPY(dstPtr2, dstStride[plane] / 2, wfunc, \
  812. srcPtr2, srcStride[plane] / 2, rfunc, \
  813. ff_dither_8x8_128, 7, clip9); \
  814. } else { \
  815. DITHER_COPY(dstPtr2, dstStride[plane] / 2, wfunc, \
  816. srcPtr2, srcStride[plane] / 2, rfunc, \
  817. dither_8x8_64, 6, clip10); \
  818. }
  819. if (isBE(c->dstFormat)) {
  820. if (isBE(c->srcFormat)) {
  821. COPY16TO9_OR_10(AV_RB16, AV_WB16);
  822. } else {
  823. COPY16TO9_OR_10(AV_RL16, AV_WB16);
  824. }
  825. } else {
  826. if (isBE(c->srcFormat)) {
  827. COPY16TO9_OR_10(AV_RB16, AV_WL16);
  828. } else {
  829. COPY16TO9_OR_10(AV_RL16, AV_WL16);
  830. }
  831. }
  832. } else /* 8bit */ {
  833. #define COPY8TO9_OR_10(wfunc) \
  834. if (shiftonly) { \
  835. for (i = 0; i < height; i++) { \
  836. for (j = 0; j < length; j++) { \
  837. const int srcpx = srcPtr[j]; \
  838. wfunc(&dstPtr2[j], srcpx << (dst_depth - 8)); \
  839. } \
  840. dstPtr2 += dstStride[plane] / 2; \
  841. srcPtr += srcStride[plane]; \
  842. } \
  843. } else { \
  844. for (i = 0; i < height; i++) { \
  845. for (j = 0; j < length; j++) { \
  846. const int srcpx = srcPtr[j]; \
  847. wfunc(&dstPtr2[j], (srcpx << (dst_depth - 8)) | (srcpx >> (16 - dst_depth))); \
  848. } \
  849. dstPtr2 += dstStride[plane] / 2; \
  850. srcPtr += srcStride[plane]; \
  851. } \
  852. }
  853. if (isBE(c->dstFormat)) {
  854. COPY8TO9_OR_10(AV_WB16);
  855. } else {
  856. COPY8TO9_OR_10(AV_WL16);
  857. }
  858. }
  859. } else if (is16BPS(c->srcFormat) && !is16BPS(c->dstFormat)) {
  860. const uint16_t *srcPtr2 = (const uint16_t *) srcPtr;
  861. #define COPY16TO8(rfunc) \
  862. DITHER_COPY(dstPtr, dstStride[plane], W8, \
  863. srcPtr2, srcStride[plane] / 2, rfunc, \
  864. dither_8x8_256, 8, av_clip_uint8);
  865. if (isBE(c->srcFormat)) {
  866. COPY16TO8(AV_RB16);
  867. } else {
  868. COPY16TO8(AV_RL16);
  869. }
  870. } else if (!is16BPS(c->srcFormat) && is16BPS(c->dstFormat)) {
  871. for (i = 0; i < height; i++) {
  872. for (j = 0; j < length; j++) {
  873. dstPtr[ j << 1 ] = srcPtr[j];
  874. dstPtr[(j << 1) + 1] = srcPtr[j];
  875. }
  876. srcPtr += srcStride[plane];
  877. dstPtr += dstStride[plane];
  878. }
  879. } else if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat) &&
  880. isBE(c->srcFormat) != isBE(c->dstFormat)) {
  881. for (i = 0; i < height; i++) {
  882. for (j = 0; j < length; j++)
  883. ((uint16_t *) dstPtr)[j] = av_bswap16(((const uint16_t *) srcPtr)[j]);
  884. srcPtr += srcStride[plane];
  885. dstPtr += dstStride[plane];
  886. }
  887. } else if (dstStride[plane] == srcStride[plane] &&
  888. srcStride[plane] > 0 && srcStride[plane] == length) {
  889. memcpy(dst[plane] + dstStride[plane] * y, src[plane],
  890. height * dstStride[plane]);
  891. } else {
  892. if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat))
  893. length *= 2;
  894. else if (!desc_src->comp[0].depth_minus1)
  895. length >>= 3; // monowhite/black
  896. for (i = 0; i < height; i++) {
  897. memcpy(dstPtr, srcPtr, length);
  898. srcPtr += srcStride[plane];
  899. dstPtr += dstStride[plane];
  900. }
  901. }
  902. }
  903. }
  904. return srcSliceH;
  905. }
  906. #define IS_DIFFERENT_ENDIANESS(src_fmt, dst_fmt, pix_fmt) \
  907. ((src_fmt == pix_fmt ## BE && dst_fmt == pix_fmt ## LE) || \
  908. (src_fmt == pix_fmt ## LE && dst_fmt == pix_fmt ## BE))
  909. void ff_get_unscaled_swscale(SwsContext *c)
  910. {
  911. const enum AVPixelFormat srcFormat = c->srcFormat;
  912. const enum AVPixelFormat dstFormat = c->dstFormat;
  913. const int flags = c->flags;
  914. const int dstH = c->dstH;
  915. int needsDither;
  916. needsDither = isAnyRGB(dstFormat) &&
  917. c->dstFormatBpp < 24 &&
  918. (c->dstFormatBpp < c->srcFormatBpp || (!isAnyRGB(srcFormat)));
  919. /* yv12_to_nv12 */
  920. if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUVA420P) &&
  921. (dstFormat == AV_PIX_FMT_NV12 || dstFormat == AV_PIX_FMT_NV21)) {
  922. c->swscale = planarToNv12Wrapper;
  923. }
  924. /* nv12_to_yv12 */
  925. if (dstFormat == AV_PIX_FMT_YUV420P &&
  926. (srcFormat == AV_PIX_FMT_NV12 || srcFormat == AV_PIX_FMT_NV21)) {
  927. c->swscale = nv12ToPlanarWrapper;
  928. }
  929. /* yuv2bgr */
  930. if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUV422P ||
  931. srcFormat == AV_PIX_FMT_YUVA420P) && isAnyRGB(dstFormat) &&
  932. !(flags & SWS_ACCURATE_RND) && !(dstH & 1)) {
  933. c->swscale = ff_yuv2rgb_get_func_ptr(c);
  934. }
  935. if (srcFormat == AV_PIX_FMT_YUV410P &&
  936. (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P) &&
  937. !(flags & SWS_BITEXACT)) {
  938. c->swscale = yvu9ToYv12Wrapper;
  939. }
  940. /* bgr24toYV12 */
  941. if (srcFormat == AV_PIX_FMT_BGR24 &&
  942. (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P) &&
  943. !(flags & SWS_ACCURATE_RND))
  944. c->swscale = bgr24ToYv12Wrapper;
  945. /* RGB/BGR -> RGB/BGR (no dither needed forms) */
  946. if (isAnyRGB(srcFormat) && isAnyRGB(dstFormat) && findRgbConvFn(c)
  947. && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT))))
  948. c->swscale = rgbToRgbWrapper;
  949. #define isByteRGB(f) ( \
  950. f == AV_PIX_FMT_RGB32 || \
  951. f == AV_PIX_FMT_RGB32_1 || \
  952. f == AV_PIX_FMT_RGB24 || \
  953. f == AV_PIX_FMT_BGR32 || \
  954. f == AV_PIX_FMT_BGR32_1 || \
  955. f == AV_PIX_FMT_BGR24)
  956. if (srcFormat == AV_PIX_FMT_GBRP && isPlanar(srcFormat) && isByteRGB(dstFormat))
  957. c->swscale = planarRgbToRgbWrapper;
  958. if (av_pix_fmt_desc_get(srcFormat)->comp[0].depth_minus1 == 7 &&
  959. isPackedRGB(srcFormat) && dstFormat == AV_PIX_FMT_GBRP)
  960. c->swscale = rgbToPlanarRgbWrapper;
  961. /* bswap 16 bits per pixel/component packed formats */
  962. if (IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR444) ||
  963. IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR48) ||
  964. IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR555) ||
  965. IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR565) ||
  966. IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGRA64) ||
  967. IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GRAY16) ||
  968. IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YA16) ||
  969. IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB444) ||
  970. IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB48) ||
  971. IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB555) ||
  972. IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB565) ||
  973. IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGBA64) ||
  974. IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_XYZ12))
  975. c->swscale = packed_16bpc_bswap;
  976. if ((usePal(srcFormat) && (
  977. dstFormat == AV_PIX_FMT_RGB32 ||
  978. dstFormat == AV_PIX_FMT_RGB32_1 ||
  979. dstFormat == AV_PIX_FMT_RGB24 ||
  980. dstFormat == AV_PIX_FMT_BGR32 ||
  981. dstFormat == AV_PIX_FMT_BGR32_1 ||
  982. dstFormat == AV_PIX_FMT_BGR24)))
  983. c->swscale = palToRgbWrapper;
  984. if (srcFormat == AV_PIX_FMT_YUV422P) {
  985. if (dstFormat == AV_PIX_FMT_YUYV422)
  986. c->swscale = yuv422pToYuy2Wrapper;
  987. else if (dstFormat == AV_PIX_FMT_UYVY422)
  988. c->swscale = yuv422pToUyvyWrapper;
  989. }
  990. /* LQ converters if -sws 0 or -sws 4*/
  991. if (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)) {
  992. /* yv12_to_yuy2 */
  993. if (srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUVA420P) {
  994. if (dstFormat == AV_PIX_FMT_YUYV422)
  995. c->swscale = planarToYuy2Wrapper;
  996. else if (dstFormat == AV_PIX_FMT_UYVY422)
  997. c->swscale = planarToUyvyWrapper;
  998. }
  999. }
  1000. if (srcFormat == AV_PIX_FMT_YUYV422 &&
  1001. (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P))
  1002. c->swscale = yuyvToYuv420Wrapper;
  1003. if (srcFormat == AV_PIX_FMT_UYVY422 &&
  1004. (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P))
  1005. c->swscale = uyvyToYuv420Wrapper;
  1006. if (srcFormat == AV_PIX_FMT_YUYV422 && dstFormat == AV_PIX_FMT_YUV422P)
  1007. c->swscale = yuyvToYuv422Wrapper;
  1008. if (srcFormat == AV_PIX_FMT_UYVY422 && dstFormat == AV_PIX_FMT_YUV422P)
  1009. c->swscale = uyvyToYuv422Wrapper;
  1010. /* simple copy */
  1011. if ( srcFormat == dstFormat ||
  1012. (srcFormat == AV_PIX_FMT_YUVA420P && dstFormat == AV_PIX_FMT_YUV420P) ||
  1013. (srcFormat == AV_PIX_FMT_YUV420P && dstFormat == AV_PIX_FMT_YUVA420P) ||
  1014. (isPlanarYUV(srcFormat) && isGray(dstFormat)) ||
  1015. (isPlanarYUV(dstFormat) && isGray(srcFormat)) ||
  1016. (isGray(dstFormat) && isGray(srcFormat)) ||
  1017. (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat) &&
  1018. c->chrDstHSubSample == c->chrSrcHSubSample &&
  1019. c->chrDstVSubSample == c->chrSrcVSubSample &&
  1020. dstFormat != AV_PIX_FMT_NV12 && dstFormat != AV_PIX_FMT_NV21 &&
  1021. srcFormat != AV_PIX_FMT_NV12 && srcFormat != AV_PIX_FMT_NV21))
  1022. {
  1023. if (isPacked(c->srcFormat))
  1024. c->swscale = packedCopyWrapper;
  1025. else /* Planar YUV or gray */
  1026. c->swscale = planarCopyWrapper;
  1027. }
  1028. if (ARCH_PPC)
  1029. ff_get_unscaled_swscale_ppc(c);
  1030. }
  1031. static void reset_ptr(const uint8_t *src[], int format)
  1032. {
  1033. if (!isALPHA(format))
  1034. src[3] = NULL;
  1035. if (!isPlanar(format)) {
  1036. src[3] = src[2] = NULL;
  1037. if (!usePal(format))
  1038. src[1] = NULL;
  1039. }
  1040. }
  1041. static int check_image_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt,
  1042. const int linesizes[4])
  1043. {
  1044. const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
  1045. int i;
  1046. for (i = 0; i < 4; i++) {
  1047. int plane = desc->comp[i].plane;
  1048. if (!data[plane] || !linesizes[plane])
  1049. return 0;
  1050. }
  1051. return 1;
  1052. }
  1053. /**
  1054. * swscale wrapper, so we don't need to export the SwsContext.
  1055. * Assumes planar YUV to be in YUV order instead of YVU.
  1056. */
  1057. int attribute_align_arg sws_scale(struct SwsContext *c,
  1058. const uint8_t * const srcSlice[],
  1059. const int srcStride[], int srcSliceY,
  1060. int srcSliceH, uint8_t *const dst[],
  1061. const int dstStride[])
  1062. {
  1063. int i;
  1064. const uint8_t *src2[4] = { srcSlice[0], srcSlice[1], srcSlice[2], srcSlice[3] };
  1065. uint8_t *dst2[4] = { dst[0], dst[1], dst[2], dst[3] };
  1066. // do not mess up sliceDir if we have a "trailing" 0-size slice
  1067. if (srcSliceH == 0)
  1068. return 0;
  1069. if (!check_image_pointers(srcSlice, c->srcFormat, srcStride)) {
  1070. av_log(c, AV_LOG_ERROR, "bad src image pointers\n");
  1071. return 0;
  1072. }
  1073. if (!check_image_pointers(dst, c->dstFormat, dstStride)) {
  1074. av_log(c, AV_LOG_ERROR, "bad dst image pointers\n");
  1075. return 0;
  1076. }
  1077. if (c->sliceDir == 0 && srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) {
  1078. av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n");
  1079. return 0;
  1080. }
  1081. if (c->sliceDir == 0) {
  1082. if (srcSliceY == 0) c->sliceDir = 1; else c->sliceDir = -1;
  1083. }
  1084. if (usePal(c->srcFormat)) {
  1085. for (i = 0; i < 256; i++) {
  1086. int r, g, b, y, u, v;
  1087. if (c->srcFormat == AV_PIX_FMT_PAL8) {
  1088. uint32_t p = ((const uint32_t *)(srcSlice[1]))[i];
  1089. r = (p >> 16) & 0xFF;
  1090. g = (p >> 8) & 0xFF;
  1091. b = p & 0xFF;
  1092. } else if (c->srcFormat == AV_PIX_FMT_RGB8) {
  1093. r = ( i >> 5 ) * 36;
  1094. g = ((i >> 2) & 7) * 36;
  1095. b = ( i & 3) * 85;
  1096. } else if (c->srcFormat == AV_PIX_FMT_BGR8) {
  1097. b = ( i >> 6 ) * 85;
  1098. g = ((i >> 3) & 7) * 36;
  1099. r = ( i & 7) * 36;
  1100. } else if (c->srcFormat == AV_PIX_FMT_RGB4_BYTE) {
  1101. r = ( i >> 3 ) * 255;
  1102. g = ((i >> 1) & 3) * 85;
  1103. b = ( i & 1) * 255;
  1104. } else if (c->srcFormat == AV_PIX_FMT_GRAY8 ||
  1105. c->srcFormat == AV_PIX_FMT_YA8) {
  1106. r = g = b = i;
  1107. } else {
  1108. assert(c->srcFormat == AV_PIX_FMT_BGR4_BYTE);
  1109. b = ( i >> 3 ) * 255;
  1110. g = ((i >> 1) & 3) * 85;
  1111. r = ( i & 1) * 255;
  1112. }
  1113. y = av_clip_uint8((RY * r + GY * g + BY * b + ( 33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
  1114. u = av_clip_uint8((RU * r + GU * g + BU * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
  1115. v = av_clip_uint8((RV * r + GV * g + BV * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
  1116. c->pal_yuv[i] = y + (u << 8) + (v << 16) + (0xFFU << 24);
  1117. switch (c->dstFormat) {
  1118. case AV_PIX_FMT_BGR32:
  1119. #if !HAVE_BIGENDIAN
  1120. case AV_PIX_FMT_RGB24:
  1121. #endif
  1122. c->pal_rgb[i] = r + (g << 8) + (b << 16) + (0xFFU << 24);
  1123. break;
  1124. case AV_PIX_FMT_BGR32_1:
  1125. #if HAVE_BIGENDIAN
  1126. case AV_PIX_FMT_BGR24:
  1127. #endif
  1128. c->pal_rgb[i] = 0xFF + (r << 8) + (g << 16) + ((unsigned)b << 24);
  1129. break;
  1130. case AV_PIX_FMT_RGB32_1:
  1131. #if HAVE_BIGENDIAN
  1132. case AV_PIX_FMT_RGB24:
  1133. #endif
  1134. c->pal_rgb[i] = 0xFF + (b << 8) + (g << 16) + ((unsigned)r << 24);
  1135. break;
  1136. case AV_PIX_FMT_RGB32:
  1137. #if !HAVE_BIGENDIAN
  1138. case AV_PIX_FMT_BGR24:
  1139. #endif
  1140. default:
  1141. c->pal_rgb[i] = b + (g << 8) + (r << 16) + (0xFFU << 24);
  1142. }
  1143. }
  1144. }
  1145. // copy strides, so they can safely be modified
  1146. if (c->sliceDir == 1) {
  1147. // slices go from top to bottom
  1148. int srcStride2[4] = { srcStride[0], srcStride[1], srcStride[2],
  1149. srcStride[3] };
  1150. int dstStride2[4] = { dstStride[0], dstStride[1], dstStride[2],
  1151. dstStride[3] };
  1152. reset_ptr(src2, c->srcFormat);
  1153. reset_ptr((const uint8_t **) dst2, c->dstFormat);
  1154. /* reset slice direction at end of frame */
  1155. if (srcSliceY + srcSliceH == c->srcH)
  1156. c->sliceDir = 0;
  1157. return c->swscale(c, src2, srcStride2, srcSliceY, srcSliceH, dst2,
  1158. dstStride2);
  1159. } else {
  1160. // slices go from bottom to top => we flip the image internally
  1161. int srcStride2[4] = { -srcStride[0], -srcStride[1], -srcStride[2],
  1162. -srcStride[3] };
  1163. int dstStride2[4] = { -dstStride[0], -dstStride[1], -dstStride[2],
  1164. -dstStride[3] };
  1165. src2[0] += (srcSliceH - 1) * srcStride[0];
  1166. if (!usePal(c->srcFormat))
  1167. src2[1] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[1];
  1168. src2[2] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[2];
  1169. src2[3] += (srcSliceH - 1) * srcStride[3];
  1170. dst2[0] += ( c->dstH - 1) * dstStride[0];
  1171. dst2[1] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[1];
  1172. dst2[2] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[2];
  1173. dst2[3] += ( c->dstH - 1) * dstStride[3];
  1174. reset_ptr(src2, c->srcFormat);
  1175. reset_ptr((const uint8_t **) dst2, c->dstFormat);
  1176. /* reset slice direction at end of frame */
  1177. if (!srcSliceY)
  1178. c->sliceDir = 0;
  1179. return c->swscale(c, src2, srcStride2, c->srcH-srcSliceY-srcSliceH,
  1180. srcSliceH, dst2, dstStride2);
  1181. }
  1182. }
  1183. /* Convert the palette to the same packed 32-bit format as the palette */
  1184. void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst,
  1185. int num_pixels, const uint8_t *palette)
  1186. {
  1187. int i;
  1188. for (i = 0; i < num_pixels; i++)
  1189. ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i]];
  1190. }
  1191. /* Palette format: ABCD -> dst format: ABC */
  1192. void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst,
  1193. int num_pixels, const uint8_t *palette)
  1194. {
  1195. int i;
  1196. for (i = 0; i < num_pixels; i++) {
  1197. //FIXME slow?
  1198. dst[0] = palette[src[i] * 4 + 0];
  1199. dst[1] = palette[src[i] * 4 + 1];
  1200. dst[2] = palette[src[i] * 4 + 2];
  1201. dst += 3;
  1202. }
  1203. }