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.

931 lines
29KB

  1. /*
  2. * software RGB to RGB converter
  3. * pluralize by software PAL8 to RGB converter
  4. * software YUV to YUV converter
  5. * software YUV to RGB converter
  6. * Written by Nick Kurshev.
  7. * palette & YUV & runtime CPU stuff by Michael (michaelni@gmx.at)
  8. * lot of big-endian byte order fixes by Alex Beregszaszi
  9. *
  10. * This file is part of FFmpeg.
  11. *
  12. * FFmpeg is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU Lesser General Public
  14. * License as published by the Free Software Foundation; either
  15. * version 2.1 of the License, or (at your option) any later version.
  16. *
  17. * FFmpeg is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  20. * Lesser General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU Lesser General Public
  23. * License along with FFmpeg; if not, write to the Free Software
  24. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  25. */
  26. #include <stddef.h>
  27. static inline void rgb24tobgr32_c(const uint8_t *src, uint8_t *dst,
  28. int src_size)
  29. {
  30. uint8_t *dest = dst;
  31. const uint8_t *s = src;
  32. const uint8_t *end = s + src_size;
  33. while (s < end) {
  34. #if HAVE_BIGENDIAN
  35. /* RGB24 (= R, G, B) -> RGB32 (= A, B, G, R) */
  36. *dest++ = 255;
  37. *dest++ = s[2];
  38. *dest++ = s[1];
  39. *dest++ = s[0];
  40. s += 3;
  41. #else
  42. *dest++ = *s++;
  43. *dest++ = *s++;
  44. *dest++ = *s++;
  45. *dest++ = 255;
  46. #endif
  47. }
  48. }
  49. static inline void rgb32tobgr24_c(const uint8_t *src, uint8_t *dst,
  50. int src_size)
  51. {
  52. uint8_t *dest = dst;
  53. const uint8_t *s = src;
  54. const uint8_t *end = s + src_size;
  55. while (s < end) {
  56. #if HAVE_BIGENDIAN
  57. /* RGB32 (= A, B, G, R) -> RGB24 (= R, G, B) */
  58. s++;
  59. dest[2] = *s++;
  60. dest[1] = *s++;
  61. dest[0] = *s++;
  62. dest += 3;
  63. #else
  64. *dest++ = *s++;
  65. *dest++ = *s++;
  66. *dest++ = *s++;
  67. s++;
  68. #endif
  69. }
  70. }
  71. /*
  72. * original by Strepto/Astral
  73. * ported to gcc & bugfixed: A'rpi
  74. * MMXEXT, 3DNOW optimization by Nick Kurshev
  75. * 32-bit C version, and and&add trick by Michael Niedermayer
  76. */
  77. static inline void rgb15to16_c(const uint8_t *src, uint8_t *dst, int src_size)
  78. {
  79. register uint8_t *d = dst;
  80. register const uint8_t *s = src;
  81. register const uint8_t *end = s + src_size;
  82. const uint8_t *mm_end = end - 3;
  83. while (s < mm_end) {
  84. register unsigned x = *((const uint32_t *)s);
  85. *((uint32_t *)d) = (x & 0x7FFF7FFF) + (x & 0x7FE07FE0);
  86. d += 4;
  87. s += 4;
  88. }
  89. if (s < end) {
  90. register unsigned short x = *((const uint16_t *)s);
  91. *((uint16_t *)d) = (x & 0x7FFF) + (x & 0x7FE0);
  92. }
  93. }
  94. static inline void rgb16to15_c(const uint8_t *src, uint8_t *dst, int src_size)
  95. {
  96. register uint8_t *d = dst;
  97. register const uint8_t *s = src;
  98. register const uint8_t *end = s + src_size;
  99. const uint8_t *mm_end = end - 3;
  100. while (s < mm_end) {
  101. register uint32_t x = *((const uint32_t *)s);
  102. *((uint32_t *)d) = ((x >> 1) & 0x7FE07FE0) | (x & 0x001F001F);
  103. s += 4;
  104. d += 4;
  105. }
  106. if (s < end) {
  107. register uint16_t x = *((const uint16_t *)s);
  108. *((uint16_t *)d) = ((x >> 1) & 0x7FE0) | (x & 0x001F);
  109. }
  110. }
  111. static inline void rgb32to16_c(const uint8_t *src, uint8_t *dst, int src_size)
  112. {
  113. uint16_t *d = (uint16_t *)dst;
  114. const uint8_t *s = src;
  115. const uint8_t *end = s + src_size;
  116. while (s < end) {
  117. register int rgb = *(const uint32_t *)s;
  118. s += 4;
  119. *d++ = ((rgb & 0xFF) >> 3) +
  120. ((rgb & 0xFC00) >> 5) +
  121. ((rgb & 0xF80000) >> 8);
  122. }
  123. }
  124. static inline void rgb32tobgr16_c(const uint8_t *src, uint8_t *dst,
  125. int src_size)
  126. {
  127. uint16_t *d = (uint16_t *)dst;
  128. const uint8_t *s = src;
  129. const uint8_t *end = s + src_size;
  130. while (s < end) {
  131. register int rgb = *(const uint32_t *)s;
  132. s += 4;
  133. *d++ = ((rgb & 0xF8) << 8) +
  134. ((rgb & 0xFC00) >> 5) +
  135. ((rgb & 0xF80000) >> 19);
  136. }
  137. }
  138. static inline void rgb32to15_c(const uint8_t *src, uint8_t *dst, int src_size)
  139. {
  140. uint16_t *d = (uint16_t *)dst;
  141. const uint8_t *s = src;
  142. const uint8_t *end = s + src_size;
  143. while (s < end) {
  144. register int rgb = *(const uint32_t *)s;
  145. s += 4;
  146. *d++ = ((rgb & 0xFF) >> 3) +
  147. ((rgb & 0xF800) >> 6) +
  148. ((rgb & 0xF80000) >> 9);
  149. }
  150. }
  151. static inline void rgb32tobgr15_c(const uint8_t *src, uint8_t *dst,
  152. int src_size)
  153. {
  154. uint16_t *d = (uint16_t *)dst;
  155. const uint8_t *s = src;
  156. const uint8_t *end = s + src_size;
  157. while (s < end) {
  158. register int rgb = *(const uint32_t *)s;
  159. s += 4;
  160. *d++ = ((rgb & 0xF8) << 7) +
  161. ((rgb & 0xF800) >> 6) +
  162. ((rgb & 0xF80000) >> 19);
  163. }
  164. }
  165. static inline void rgb24tobgr16_c(const uint8_t *src, uint8_t *dst,
  166. int src_size)
  167. {
  168. uint16_t *d = (uint16_t *)dst;
  169. const uint8_t *s = src;
  170. const uint8_t *end = s + src_size;
  171. while (s < end) {
  172. const int b = *s++;
  173. const int g = *s++;
  174. const int r = *s++;
  175. *d++ = (b >> 3) | ((g & 0xFC) << 3) | ((r & 0xF8) << 8);
  176. }
  177. }
  178. static inline void rgb24to16_c(const uint8_t *src, uint8_t *dst, int src_size)
  179. {
  180. uint16_t *d = (uint16_t *)dst;
  181. const uint8_t *s = src;
  182. const uint8_t *end = s + src_size;
  183. while (s < end) {
  184. const int r = *s++;
  185. const int g = *s++;
  186. const int b = *s++;
  187. *d++ = (b >> 3) | ((g & 0xFC) << 3) | ((r & 0xF8) << 8);
  188. }
  189. }
  190. static inline void rgb24tobgr15_c(const uint8_t *src, uint8_t *dst,
  191. int src_size)
  192. {
  193. uint16_t *d = (uint16_t *)dst;
  194. const uint8_t *s = src;
  195. const uint8_t *end = s + src_size;
  196. while (s < end) {
  197. const int b = *s++;
  198. const int g = *s++;
  199. const int r = *s++;
  200. *d++ = (b >> 3) | ((g & 0xF8) << 2) | ((r & 0xF8) << 7);
  201. }
  202. }
  203. static inline void rgb24to15_c(const uint8_t *src, uint8_t *dst, int src_size)
  204. {
  205. uint16_t *d = (uint16_t *)dst;
  206. const uint8_t *s = src;
  207. const uint8_t *end = s + src_size;
  208. while (s < end) {
  209. const int r = *s++;
  210. const int g = *s++;
  211. const int b = *s++;
  212. *d++ = (b >> 3) | ((g & 0xF8) << 2) | ((r & 0xF8) << 7);
  213. }
  214. }
  215. static inline void rgb15tobgr24_c(const uint8_t *src, uint8_t *dst,
  216. int src_size)
  217. {
  218. uint8_t *d = dst;
  219. const uint16_t *s = (const uint16_t *)src;
  220. const uint16_t *end = s + src_size / 2;
  221. while (s < end) {
  222. register uint16_t bgr = *s++;
  223. *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
  224. *d++ = ((bgr&0x03E0)>>2) | ((bgr&0x03E0)>> 7);
  225. *d++ = ((bgr&0x7C00)>>7) | ((bgr&0x7C00)>>12);
  226. }
  227. }
  228. static inline void rgb16tobgr24_c(const uint8_t *src, uint8_t *dst,
  229. int src_size)
  230. {
  231. uint8_t *d = (uint8_t *)dst;
  232. const uint16_t *s = (const uint16_t *)src;
  233. const uint16_t *end = s + src_size / 2;
  234. while (s < end) {
  235. register uint16_t bgr = *s++;
  236. *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
  237. *d++ = ((bgr&0x07E0)>>3) | ((bgr&0x07E0)>> 9);
  238. *d++ = ((bgr&0xF800)>>8) | ((bgr&0xF800)>>13);
  239. }
  240. }
  241. static inline void rgb15to32_c(const uint8_t *src, uint8_t *dst, int src_size)
  242. {
  243. uint8_t *d = dst;
  244. const uint16_t *s = (const uint16_t *)src;
  245. const uint16_t *end = s + src_size / 2;
  246. while (s < end) {
  247. register uint16_t bgr = *s++;
  248. #if HAVE_BIGENDIAN
  249. *d++ = 255;
  250. *d++ = ((bgr&0x7C00)>>7) | ((bgr&0x7C00)>>12);
  251. *d++ = ((bgr&0x03E0)>>2) | ((bgr&0x03E0)>> 7);
  252. *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
  253. #else
  254. *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
  255. *d++ = ((bgr&0x03E0)>>2) | ((bgr&0x03E0)>> 7);
  256. *d++ = ((bgr&0x7C00)>>7) | ((bgr&0x7C00)>>12);
  257. *d++ = 255;
  258. #endif
  259. }
  260. }
  261. static inline void rgb16to32_c(const uint8_t *src, uint8_t *dst, int src_size)
  262. {
  263. uint8_t *d = dst;
  264. const uint16_t *s = (const uint16_t *)src;
  265. const uint16_t *end = s + src_size / 2;
  266. while (s < end) {
  267. register uint16_t bgr = *s++;
  268. #if HAVE_BIGENDIAN
  269. *d++ = 255;
  270. *d++ = ((bgr&0xF800)>>8) | ((bgr&0xF800)>>13);
  271. *d++ = ((bgr&0x07E0)>>3) | ((bgr&0x07E0)>> 9);
  272. *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
  273. #else
  274. *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
  275. *d++ = ((bgr&0x07E0)>>3) | ((bgr&0x07E0)>> 9);
  276. *d++ = ((bgr&0xF800)>>8) | ((bgr&0xF800)>>13);
  277. *d++ = 255;
  278. #endif
  279. }
  280. }
  281. static inline void shuffle_bytes_2103_c(const uint8_t *src, uint8_t *dst,
  282. int src_size)
  283. {
  284. int idx = 15 - src_size;
  285. const uint8_t *s = src - idx;
  286. uint8_t *d = dst - idx;
  287. for (; idx < 15; idx += 4) {
  288. register int v = *(const uint32_t *)&s[idx], g = v & 0xff00ff00;
  289. v &= 0xff00ff;
  290. *(uint32_t *)&d[idx] = (v >> 16) + g + (v << 16);
  291. }
  292. }
  293. static inline void rgb24tobgr24_c(const uint8_t *src, uint8_t *dst, int src_size)
  294. {
  295. unsigned i;
  296. for (i = 0; i < src_size; i += 3) {
  297. register uint8_t x = src[i + 2];
  298. dst[i + 1] = src[i + 1];
  299. dst[i + 2] = src[i + 0];
  300. dst[i + 0] = x;
  301. }
  302. }
  303. static inline void yuvPlanartoyuy2_c(const uint8_t *ysrc, const uint8_t *usrc,
  304. const uint8_t *vsrc, uint8_t *dst,
  305. int width, int height,
  306. int lumStride, int chromStride,
  307. int dstStride, int vertLumPerChroma)
  308. {
  309. int y, i;
  310. const int chromWidth = width >> 1;
  311. for (y = 0; y < height; y++) {
  312. #if HAVE_FAST_64BIT
  313. uint64_t *ldst = (uint64_t *)dst;
  314. const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
  315. for (i = 0; i < chromWidth; i += 2) {
  316. uint64_t k = yc[0] + (uc[0] << 8) +
  317. (yc[1] << 16) + (unsigned)(vc[0] << 24);
  318. uint64_t l = yc[2] + (uc[1] << 8) +
  319. (yc[3] << 16) + (unsigned)(vc[1] << 24);
  320. *ldst++ = k + (l << 32);
  321. yc += 4;
  322. uc += 2;
  323. vc += 2;
  324. }
  325. #else
  326. int *idst = (int32_t *)dst;
  327. const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
  328. for (i = 0; i < chromWidth; i++) {
  329. #if HAVE_BIGENDIAN
  330. *idst++ = (yc[0] << 24) + (uc[0] << 16) +
  331. (yc[1] << 8) + (vc[0] << 0);
  332. #else
  333. *idst++ = yc[0] + (uc[0] << 8) +
  334. (yc[1] << 16) + (vc[0] << 24);
  335. #endif
  336. yc += 2;
  337. uc++;
  338. vc++;
  339. }
  340. #endif
  341. if ((y & (vertLumPerChroma - 1)) == vertLumPerChroma - 1) {
  342. usrc += chromStride;
  343. vsrc += chromStride;
  344. }
  345. ysrc += lumStride;
  346. dst += dstStride;
  347. }
  348. }
  349. /**
  350. * Height should be a multiple of 2 and width should be a multiple of 16.
  351. * (If this is a problem for anyone then tell me, and I will fix it.)
  352. */
  353. static inline void yv12toyuy2_c(const uint8_t *ysrc, const uint8_t *usrc,
  354. const uint8_t *vsrc, uint8_t *dst,
  355. int width, int height, int lumStride,
  356. int chromStride, int dstStride)
  357. {
  358. //FIXME interpolate chroma
  359. yuvPlanartoyuy2_c(ysrc, usrc, vsrc, dst, width, height, lumStride,
  360. chromStride, dstStride, 2);
  361. }
  362. static inline void yuvPlanartouyvy_c(const uint8_t *ysrc, const uint8_t *usrc,
  363. const uint8_t *vsrc, uint8_t *dst,
  364. int width, int height,
  365. int lumStride, int chromStride,
  366. int dstStride, int vertLumPerChroma)
  367. {
  368. int y, i;
  369. const int chromWidth = width >> 1;
  370. for (y = 0; y < height; y++) {
  371. #if HAVE_FAST_64BIT
  372. uint64_t *ldst = (uint64_t *)dst;
  373. const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
  374. for (i = 0; i < chromWidth; i += 2) {
  375. uint64_t k = uc[0] + (yc[0] << 8) +
  376. (vc[0] << 16) + (unsigned)(yc[1] << 24);
  377. uint64_t l = uc[1] + (yc[2] << 8) +
  378. (vc[1] << 16) + (unsigned)(yc[3] << 24);
  379. *ldst++ = k + (l << 32);
  380. yc += 4;
  381. uc += 2;
  382. vc += 2;
  383. }
  384. #else
  385. int *idst = (int32_t *)dst;
  386. const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
  387. for (i = 0; i < chromWidth; i++) {
  388. #if HAVE_BIGENDIAN
  389. *idst++ = (uc[0] << 24) + (yc[0] << 16) +
  390. (vc[0] << 8) + (yc[1] << 0);
  391. #else
  392. *idst++ = uc[0] + (yc[0] << 8) +
  393. (vc[0] << 16) + (yc[1] << 24);
  394. #endif
  395. yc += 2;
  396. uc++;
  397. vc++;
  398. }
  399. #endif
  400. if ((y & (vertLumPerChroma - 1)) == vertLumPerChroma - 1) {
  401. usrc += chromStride;
  402. vsrc += chromStride;
  403. }
  404. ysrc += lumStride;
  405. dst += dstStride;
  406. }
  407. }
  408. /**
  409. * Height should be a multiple of 2 and width should be a multiple of 16
  410. * (If this is a problem for anyone then tell me, and I will fix it.)
  411. */
  412. static inline void yv12touyvy_c(const uint8_t *ysrc, const uint8_t *usrc,
  413. const uint8_t *vsrc, uint8_t *dst,
  414. int width, int height, int lumStride,
  415. int chromStride, int dstStride)
  416. {
  417. //FIXME interpolate chroma
  418. yuvPlanartouyvy_c(ysrc, usrc, vsrc, dst, width, height, lumStride,
  419. chromStride, dstStride, 2);
  420. }
  421. /**
  422. * Width should be a multiple of 16.
  423. */
  424. static inline void yuv422ptouyvy_c(const uint8_t *ysrc, const uint8_t *usrc,
  425. const uint8_t *vsrc, uint8_t *dst,
  426. int width, int height, int lumStride,
  427. int chromStride, int dstStride)
  428. {
  429. yuvPlanartouyvy_c(ysrc, usrc, vsrc, dst, width, height, lumStride,
  430. chromStride, dstStride, 1);
  431. }
  432. /**
  433. * Width should be a multiple of 16.
  434. */
  435. static inline void yuv422ptoyuy2_c(const uint8_t *ysrc, const uint8_t *usrc,
  436. const uint8_t *vsrc, uint8_t *dst,
  437. int width, int height, int lumStride,
  438. int chromStride, int dstStride)
  439. {
  440. yuvPlanartoyuy2_c(ysrc, usrc, vsrc, dst, width, height, lumStride,
  441. chromStride, dstStride, 1);
  442. }
  443. /**
  444. * Height should be a multiple of 2 and width should be a multiple of 16.
  445. * (If this is a problem for anyone then tell me, and I will fix it.)
  446. */
  447. static inline void yuy2toyv12_c(const uint8_t *src, uint8_t *ydst,
  448. uint8_t *udst, uint8_t *vdst,
  449. int width, int height, int lumStride,
  450. int chromStride, int srcStride)
  451. {
  452. int y;
  453. const int chromWidth = width >> 1;
  454. for (y = 0; y < height; y += 2) {
  455. int i;
  456. for (i = 0; i < chromWidth; i++) {
  457. ydst[2 * i + 0] = src[4 * i + 0];
  458. udst[i] = src[4 * i + 1];
  459. ydst[2 * i + 1] = src[4 * i + 2];
  460. vdst[i] = src[4 * i + 3];
  461. }
  462. ydst += lumStride;
  463. src += srcStride;
  464. for (i = 0; i < chromWidth; i++) {
  465. ydst[2 * i + 0] = src[4 * i + 0];
  466. ydst[2 * i + 1] = src[4 * i + 2];
  467. }
  468. udst += chromStride;
  469. vdst += chromStride;
  470. ydst += lumStride;
  471. src += srcStride;
  472. }
  473. }
  474. static inline void planar2x_c(const uint8_t *src, uint8_t *dst, int srcWidth,
  475. int srcHeight, int srcStride, int dstStride)
  476. {
  477. int x, y;
  478. dst[0] = src[0];
  479. // first line
  480. for (x = 0; x < srcWidth - 1; x++) {
  481. dst[2 * x + 1] = (3 * src[x] + src[x + 1]) >> 2;
  482. dst[2 * x + 2] = (src[x] + 3 * src[x + 1]) >> 2;
  483. }
  484. dst[2 * srcWidth - 1] = src[srcWidth - 1];
  485. dst += dstStride;
  486. for (y = 1; y < srcHeight; y++) {
  487. const int mmxSize = 1;
  488. dst[0] = (src[0] * 3 + src[srcStride]) >> 2;
  489. dst[dstStride] = (src[0] + 3 * src[srcStride]) >> 2;
  490. for (x = mmxSize - 1; x < srcWidth - 1; x++) {
  491. dst[2 * x + 1] = (src[x + 0] * 3 + src[x + srcStride + 1]) >> 2;
  492. dst[2 * x + dstStride + 2] = (src[x + 0] + 3 * src[x + srcStride + 1]) >> 2;
  493. dst[2 * x + dstStride + 1] = (src[x + 1] + 3 * src[x + srcStride]) >> 2;
  494. dst[2 * x + 2] = (src[x + 1] * 3 + src[x + srcStride]) >> 2;
  495. }
  496. dst[srcWidth * 2 - 1] = (src[srcWidth - 1] * 3 + src[srcWidth - 1 + srcStride]) >> 2;
  497. dst[srcWidth * 2 - 1 + dstStride] = (src[srcWidth - 1] + 3 * src[srcWidth - 1 + srcStride]) >> 2;
  498. dst += dstStride * 2;
  499. src += srcStride;
  500. }
  501. // last line
  502. dst[0] = src[0];
  503. for (x = 0; x < srcWidth - 1; x++) {
  504. dst[2 * x + 1] = (src[x] * 3 + src[x + 1]) >> 2;
  505. dst[2 * x + 2] = (src[x] + 3 * src[x + 1]) >> 2;
  506. }
  507. dst[2 * srcWidth - 1] = src[srcWidth - 1];
  508. }
  509. /**
  510. * Height should be a multiple of 2 and width should be a multiple of 16.
  511. * (If this is a problem for anyone then tell me, and I will fix it.)
  512. * Chrominance data is only taken from every second line, others are ignored.
  513. * FIXME: Write HQ version.
  514. */
  515. static inline void uyvytoyv12_c(const uint8_t *src, uint8_t *ydst,
  516. uint8_t *udst, uint8_t *vdst,
  517. int width, int height, int lumStride,
  518. int chromStride, int srcStride)
  519. {
  520. int y;
  521. const int chromWidth = width >> 1;
  522. for (y = 0; y < height; y += 2) {
  523. int i;
  524. for (i = 0; i < chromWidth; i++) {
  525. udst[i] = src[4 * i + 0];
  526. ydst[2 * i + 0] = src[4 * i + 1];
  527. vdst[i] = src[4 * i + 2];
  528. ydst[2 * i + 1] = src[4 * i + 3];
  529. }
  530. ydst += lumStride;
  531. src += srcStride;
  532. for (i = 0; i < chromWidth; i++) {
  533. ydst[2 * i + 0] = src[4 * i + 1];
  534. ydst[2 * i + 1] = src[4 * i + 3];
  535. }
  536. udst += chromStride;
  537. vdst += chromStride;
  538. ydst += lumStride;
  539. src += srcStride;
  540. }
  541. }
  542. /**
  543. * Height should be a multiple of 2 and width should be a multiple of 2.
  544. * (If this is a problem for anyone then tell me, and I will fix it.)
  545. * Chrominance data is only taken from every second line,
  546. * others are ignored in the C version.
  547. * FIXME: Write HQ version.
  548. */
  549. void ff_rgb24toyv12_c(const uint8_t *src, uint8_t *ydst, uint8_t *udst,
  550. uint8_t *vdst, int width, int height, int lumStride,
  551. int chromStride, int srcStride, int32_t *rgb2yuv)
  552. {
  553. int32_t ry = rgb2yuv[RY_IDX], gy = rgb2yuv[GY_IDX], by = rgb2yuv[BY_IDX];
  554. int32_t ru = rgb2yuv[RU_IDX], gu = rgb2yuv[GU_IDX], bu = rgb2yuv[BU_IDX];
  555. int32_t rv = rgb2yuv[RV_IDX], gv = rgb2yuv[GV_IDX], bv = rgb2yuv[BV_IDX];
  556. int y;
  557. const int chromWidth = width >> 1;
  558. for (y = 0; y < height; y += 2) {
  559. int i;
  560. for (i = 0; i < chromWidth; i++) {
  561. unsigned int b = src[6 * i + 0];
  562. unsigned int g = src[6 * i + 1];
  563. unsigned int r = src[6 * i + 2];
  564. unsigned int Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16;
  565. unsigned int V = ((rv * r + gv * g + bv * b) >> RGB2YUV_SHIFT) + 128;
  566. unsigned int U = ((ru * r + gu * g + bu * b) >> RGB2YUV_SHIFT) + 128;
  567. udst[i] = U;
  568. vdst[i] = V;
  569. ydst[2 * i] = Y;
  570. b = src[6 * i + 3];
  571. g = src[6 * i + 4];
  572. r = src[6 * i + 5];
  573. Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16;
  574. ydst[2 * i + 1] = Y;
  575. }
  576. ydst += lumStride;
  577. src += srcStride;
  578. if (y+1 == height)
  579. break;
  580. for (i = 0; i < chromWidth; i++) {
  581. unsigned int b = src[6 * i + 0];
  582. unsigned int g = src[6 * i + 1];
  583. unsigned int r = src[6 * i + 2];
  584. unsigned int Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16;
  585. ydst[2 * i] = Y;
  586. b = src[6 * i + 3];
  587. g = src[6 * i + 4];
  588. r = src[6 * i + 5];
  589. Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16;
  590. ydst[2 * i + 1] = Y;
  591. }
  592. udst += chromStride;
  593. vdst += chromStride;
  594. ydst += lumStride;
  595. src += srcStride;
  596. }
  597. }
  598. static void interleaveBytes_c(const uint8_t *src1, const uint8_t *src2,
  599. uint8_t *dest, int width, int height,
  600. int src1Stride, int src2Stride, int dstStride)
  601. {
  602. int h;
  603. for (h = 0; h < height; h++) {
  604. int w;
  605. for (w = 0; w < width; w++) {
  606. dest[2 * w + 0] = src1[w];
  607. dest[2 * w + 1] = src2[w];
  608. }
  609. dest += dstStride;
  610. src1 += src1Stride;
  611. src2 += src2Stride;
  612. }
  613. }
  614. static inline void vu9_to_vu12_c(const uint8_t *src1, const uint8_t *src2,
  615. uint8_t *dst1, uint8_t *dst2,
  616. int width, int height,
  617. int srcStride1, int srcStride2,
  618. int dstStride1, int dstStride2)
  619. {
  620. int x, y;
  621. int w = width / 2;
  622. int h = height / 2;
  623. for (y = 0; y < h; y++) {
  624. const uint8_t *s1 = src1 + srcStride1 * (y >> 1);
  625. uint8_t *d = dst1 + dstStride1 * y;
  626. for (x = 0; x < w; x++)
  627. d[2 * x] = d[2 * x + 1] = s1[x];
  628. }
  629. for (y = 0; y < h; y++) {
  630. const uint8_t *s2 = src2 + srcStride2 * (y >> 1);
  631. uint8_t *d = dst2 + dstStride2 * y;
  632. for (x = 0; x < w; x++)
  633. d[2 * x] = d[2 * x + 1] = s2[x];
  634. }
  635. }
  636. static inline void yvu9_to_yuy2_c(const uint8_t *src1, const uint8_t *src2,
  637. const uint8_t *src3, uint8_t *dst,
  638. int width, int height,
  639. int srcStride1, int srcStride2,
  640. int srcStride3, int dstStride)
  641. {
  642. int x, y;
  643. int w = width / 2;
  644. int h = height;
  645. for (y = 0; y < h; y++) {
  646. const uint8_t *yp = src1 + srcStride1 * y;
  647. const uint8_t *up = src2 + srcStride2 * (y >> 2);
  648. const uint8_t *vp = src3 + srcStride3 * (y >> 2);
  649. uint8_t *d = dst + dstStride * y;
  650. for (x = 0; x < w; x++) {
  651. const int x2 = x << 2;
  652. d[8 * x + 0] = yp[x2];
  653. d[8 * x + 1] = up[x];
  654. d[8 * x + 2] = yp[x2 + 1];
  655. d[8 * x + 3] = vp[x];
  656. d[8 * x + 4] = yp[x2 + 2];
  657. d[8 * x + 5] = up[x];
  658. d[8 * x + 6] = yp[x2 + 3];
  659. d[8 * x + 7] = vp[x];
  660. }
  661. }
  662. }
  663. static void extract_even_c(const uint8_t *src, uint8_t *dst, int count)
  664. {
  665. dst += count;
  666. src += count * 2;
  667. count = -count;
  668. while (count < 0) {
  669. dst[count] = src[2 * count];
  670. count++;
  671. }
  672. }
  673. static void extract_even2_c(const uint8_t *src, uint8_t *dst0, uint8_t *dst1,
  674. int count)
  675. {
  676. dst0 += count;
  677. dst1 += count;
  678. src += count * 4;
  679. count = -count;
  680. while (count < 0) {
  681. dst0[count] = src[4 * count + 0];
  682. dst1[count] = src[4 * count + 2];
  683. count++;
  684. }
  685. }
  686. static void extract_even2avg_c(const uint8_t *src0, const uint8_t *src1,
  687. uint8_t *dst0, uint8_t *dst1, int count)
  688. {
  689. dst0 += count;
  690. dst1 += count;
  691. src0 += count * 4;
  692. src1 += count * 4;
  693. count = -count;
  694. while (count < 0) {
  695. dst0[count] = (src0[4 * count + 0] + src1[4 * count + 0]) >> 1;
  696. dst1[count] = (src0[4 * count + 2] + src1[4 * count + 2]) >> 1;
  697. count++;
  698. }
  699. }
  700. static void extract_odd2_c(const uint8_t *src, uint8_t *dst0, uint8_t *dst1,
  701. int count)
  702. {
  703. dst0 += count;
  704. dst1 += count;
  705. src += count * 4;
  706. count = -count;
  707. src++;
  708. while (count < 0) {
  709. dst0[count] = src[4 * count + 0];
  710. dst1[count] = src[4 * count + 2];
  711. count++;
  712. }
  713. }
  714. static void extract_odd2avg_c(const uint8_t *src0, const uint8_t *src1,
  715. uint8_t *dst0, uint8_t *dst1, int count)
  716. {
  717. dst0 += count;
  718. dst1 += count;
  719. src0 += count * 4;
  720. src1 += count * 4;
  721. count = -count;
  722. src0++;
  723. src1++;
  724. while (count < 0) {
  725. dst0[count] = (src0[4 * count + 0] + src1[4 * count + 0]) >> 1;
  726. dst1[count] = (src0[4 * count + 2] + src1[4 * count + 2]) >> 1;
  727. count++;
  728. }
  729. }
  730. static void yuyvtoyuv420_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
  731. const uint8_t *src, int width, int height,
  732. int lumStride, int chromStride, int srcStride)
  733. {
  734. int y;
  735. const int chromWidth = -((-width) >> 1);
  736. for (y = 0; y < height; y++) {
  737. extract_even_c(src, ydst, width);
  738. if (y & 1) {
  739. extract_odd2avg_c(src - srcStride, src, udst, vdst, chromWidth);
  740. udst += chromStride;
  741. vdst += chromStride;
  742. }
  743. src += srcStride;
  744. ydst += lumStride;
  745. }
  746. }
  747. static void yuyvtoyuv422_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
  748. const uint8_t *src, int width, int height,
  749. int lumStride, int chromStride, int srcStride)
  750. {
  751. int y;
  752. const int chromWidth = -((-width) >> 1);
  753. for (y = 0; y < height; y++) {
  754. extract_even_c(src, ydst, width);
  755. extract_odd2_c(src, udst, vdst, chromWidth);
  756. src += srcStride;
  757. ydst += lumStride;
  758. udst += chromStride;
  759. vdst += chromStride;
  760. }
  761. }
  762. static void uyvytoyuv420_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
  763. const uint8_t *src, int width, int height,
  764. int lumStride, int chromStride, int srcStride)
  765. {
  766. int y;
  767. const int chromWidth = -((-width) >> 1);
  768. for (y = 0; y < height; y++) {
  769. extract_even_c(src + 1, ydst, width);
  770. if (y & 1) {
  771. extract_even2avg_c(src - srcStride, src, udst, vdst, chromWidth);
  772. udst += chromStride;
  773. vdst += chromStride;
  774. }
  775. src += srcStride;
  776. ydst += lumStride;
  777. }
  778. }
  779. static void uyvytoyuv422_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
  780. const uint8_t *src, int width, int height,
  781. int lumStride, int chromStride, int srcStride)
  782. {
  783. int y;
  784. const int chromWidth = -((-width) >> 1);
  785. for (y = 0; y < height; y++) {
  786. extract_even_c(src + 1, ydst, width);
  787. extract_even2_c(src, udst, vdst, chromWidth);
  788. src += srcStride;
  789. ydst += lumStride;
  790. udst += chromStride;
  791. vdst += chromStride;
  792. }
  793. }
  794. static inline void rgb2rgb_init_c(void)
  795. {
  796. rgb15to16 = rgb15to16_c;
  797. rgb15tobgr24 = rgb15tobgr24_c;
  798. rgb15to32 = rgb15to32_c;
  799. rgb16tobgr24 = rgb16tobgr24_c;
  800. rgb16to32 = rgb16to32_c;
  801. rgb16to15 = rgb16to15_c;
  802. rgb24tobgr16 = rgb24tobgr16_c;
  803. rgb24tobgr15 = rgb24tobgr15_c;
  804. rgb24tobgr32 = rgb24tobgr32_c;
  805. rgb32to16 = rgb32to16_c;
  806. rgb32to15 = rgb32to15_c;
  807. rgb32tobgr24 = rgb32tobgr24_c;
  808. rgb24to15 = rgb24to15_c;
  809. rgb24to16 = rgb24to16_c;
  810. rgb24tobgr24 = rgb24tobgr24_c;
  811. shuffle_bytes_2103 = shuffle_bytes_2103_c;
  812. rgb32tobgr16 = rgb32tobgr16_c;
  813. rgb32tobgr15 = rgb32tobgr15_c;
  814. yv12toyuy2 = yv12toyuy2_c;
  815. yv12touyvy = yv12touyvy_c;
  816. yuv422ptoyuy2 = yuv422ptoyuy2_c;
  817. yuv422ptouyvy = yuv422ptouyvy_c;
  818. yuy2toyv12 = yuy2toyv12_c;
  819. planar2x = planar2x_c;
  820. ff_rgb24toyv12 = ff_rgb24toyv12_c;
  821. interleaveBytes = interleaveBytes_c;
  822. vu9_to_vu12 = vu9_to_vu12_c;
  823. yvu9_to_yuy2 = yvu9_to_yuy2_c;
  824. uyvytoyuv420 = uyvytoyuv420_c;
  825. uyvytoyuv422 = uyvytoyuv422_c;
  826. yuyvtoyuv420 = yuyvtoyuv420_c;
  827. yuyvtoyuv422 = yuyvtoyuv422_c;
  828. }