PageRenderTime 52ms CodeModel.GetById 8ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/ffmpeg/libswscale/rgb2rgb_template.c

http://github.com/xbmc/xbmc
C | 927 lines | 757 code | 102 blank | 68 comment | 64 complexity | 28a9c92988e63aa474e8549e36915065 MD5 | raw file
Possible License(s): GPL-3.0, CC-BY-SA-3.0, LGPL-2.0, 0BSD, Unlicense, GPL-2.0, AGPL-1.0, BSD-3-Clause, LGPL-2.1, LGPL-3.0
  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 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)
  552. {
  553. int y;
  554. const int chromWidth = width >> 1;
  555. for (y = 0; y < height; y += 2) {
  556. int i;
  557. for (i = 0; i < chromWidth; i++) {
  558. unsigned int b = src[6 * i + 0];
  559. unsigned int g = src[6 * i + 1];
  560. unsigned int r = src[6 * i + 2];
  561. unsigned int Y = ((RY * r + GY * g + BY * b) >> RGB2YUV_SHIFT) + 16;
  562. unsigned int V = ((RV * r + GV * g + BV * b) >> RGB2YUV_SHIFT) + 128;
  563. unsigned int U = ((RU * r + GU * g + BU * b) >> RGB2YUV_SHIFT) + 128;
  564. udst[i] = U;
  565. vdst[i] = V;
  566. ydst[2 * i] = Y;
  567. b = src[6 * i + 3];
  568. g = src[6 * i + 4];
  569. r = src[6 * i + 5];
  570. Y = ((RY * r + GY * g + BY * b) >> RGB2YUV_SHIFT) + 16;
  571. ydst[2 * i + 1] = Y;
  572. }
  573. ydst += lumStride;
  574. src += srcStride;
  575. if (y+1 == height)
  576. break;
  577. for (i = 0; i < chromWidth; i++) {
  578. unsigned int b = src[6 * i + 0];
  579. unsigned int g = src[6 * i + 1];
  580. unsigned int r = src[6 * i + 2];
  581. unsigned int Y = ((RY * r + GY * g + BY * b) >> RGB2YUV_SHIFT) + 16;
  582. ydst[2 * i] = Y;
  583. b = src[6 * i + 3];
  584. g = src[6 * i + 4];
  585. r = src[6 * i + 5];
  586. Y = ((RY * r + GY * g + BY * b) >> RGB2YUV_SHIFT) + 16;
  587. ydst[2 * i + 1] = Y;
  588. }
  589. udst += chromStride;
  590. vdst += chromStride;
  591. ydst += lumStride;
  592. src += srcStride;
  593. }
  594. }
  595. static void interleaveBytes_c(const uint8_t *src1, const uint8_t *src2,
  596. uint8_t *dest, int width, int height,
  597. int src1Stride, int src2Stride, int dstStride)
  598. {
  599. int h;
  600. for (h = 0; h < height; h++) {
  601. int w;
  602. for (w = 0; w < width; w++) {
  603. dest[2 * w + 0] = src1[w];
  604. dest[2 * w + 1] = src2[w];
  605. }
  606. dest += dstStride;
  607. src1 += src1Stride;
  608. src2 += src2Stride;
  609. }
  610. }
  611. static inline void vu9_to_vu12_c(const uint8_t *src1, const uint8_t *src2,
  612. uint8_t *dst1, uint8_t *dst2,
  613. int width, int height,
  614. int srcStride1, int srcStride2,
  615. int dstStride1, int dstStride2)
  616. {
  617. int x, y;
  618. int w = width / 2;
  619. int h = height / 2;
  620. for (y = 0; y < h; y++) {
  621. const uint8_t *s1 = src1 + srcStride1 * (y >> 1);
  622. uint8_t *d = dst1 + dstStride1 * y;
  623. for (x = 0; x < w; x++)
  624. d[2 * x] = d[2 * x + 1] = s1[x];
  625. }
  626. for (y = 0; y < h; y++) {
  627. const uint8_t *s2 = src2 + srcStride2 * (y >> 1);
  628. uint8_t *d = dst2 + dstStride2 * y;
  629. for (x = 0; x < w; x++)
  630. d[2 * x] = d[2 * x + 1] = s2[x];
  631. }
  632. }
  633. static inline void yvu9_to_yuy2_c(const uint8_t *src1, const uint8_t *src2,
  634. const uint8_t *src3, uint8_t *dst,
  635. int width, int height,
  636. int srcStride1, int srcStride2,
  637. int srcStride3, int dstStride)
  638. {
  639. int x, y;
  640. int w = width / 2;
  641. int h = height;
  642. for (y = 0; y < h; y++) {
  643. const uint8_t *yp = src1 + srcStride1 * y;
  644. const uint8_t *up = src2 + srcStride2 * (y >> 2);
  645. const uint8_t *vp = src3 + srcStride3 * (y >> 2);
  646. uint8_t *d = dst + dstStride * y;
  647. for (x = 0; x < w; x++) {
  648. const int x2 = x << 2;
  649. d[8 * x + 0] = yp[x2];
  650. d[8 * x + 1] = up[x];
  651. d[8 * x + 2] = yp[x2 + 1];
  652. d[8 * x + 3] = vp[x];
  653. d[8 * x + 4] = yp[x2 + 2];
  654. d[8 * x + 5] = up[x];
  655. d[8 * x + 6] = yp[x2 + 3];
  656. d[8 * x + 7] = vp[x];
  657. }
  658. }
  659. }
  660. static void extract_even_c(const uint8_t *src, uint8_t *dst, int count)
  661. {
  662. dst += count;
  663. src += count * 2;
  664. count = -count;
  665. while (count < 0) {
  666. dst[count] = src[2 * count];
  667. count++;
  668. }
  669. }
  670. static void extract_even2_c(const uint8_t *src, uint8_t *dst0, uint8_t *dst1,
  671. int count)
  672. {
  673. dst0 += count;
  674. dst1 += count;
  675. src += count * 4;
  676. count = -count;
  677. while (count < 0) {
  678. dst0[count] = src[4 * count + 0];
  679. dst1[count] = src[4 * count + 2];
  680. count++;
  681. }
  682. }
  683. static void extract_even2avg_c(const uint8_t *src0, const uint8_t *src1,
  684. uint8_t *dst0, uint8_t *dst1, int count)
  685. {
  686. dst0 += count;
  687. dst1 += count;
  688. src0 += count * 4;
  689. src1 += count * 4;
  690. count = -count;
  691. while (count < 0) {
  692. dst0[count] = (src0[4 * count + 0] + src1[4 * count + 0]) >> 1;
  693. dst1[count] = (src0[4 * count + 2] + src1[4 * count + 2]) >> 1;
  694. count++;
  695. }
  696. }
  697. static void extract_odd2_c(const uint8_t *src, uint8_t *dst0, uint8_t *dst1,
  698. int count)
  699. {
  700. dst0 += count;
  701. dst1 += count;
  702. src += count * 4;
  703. count = -count;
  704. src++;
  705. while (count < 0) {
  706. dst0[count] = src[4 * count + 0];
  707. dst1[count] = src[4 * count + 2];
  708. count++;
  709. }
  710. }
  711. static void extract_odd2avg_c(const uint8_t *src0, const uint8_t *src1,
  712. uint8_t *dst0, uint8_t *dst1, int count)
  713. {
  714. dst0 += count;
  715. dst1 += count;
  716. src0 += count * 4;
  717. src1 += count * 4;
  718. count = -count;
  719. src0++;
  720. src1++;
  721. while (count < 0) {
  722. dst0[count] = (src0[4 * count + 0] + src1[4 * count + 0]) >> 1;
  723. dst1[count] = (src0[4 * count + 2] + src1[4 * count + 2]) >> 1;
  724. count++;
  725. }
  726. }
  727. static void yuyvtoyuv420_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
  728. const uint8_t *src, int width, int height,
  729. int lumStride, int chromStride, int srcStride)
  730. {
  731. int y;
  732. const int chromWidth = -((-width) >> 1);
  733. for (y = 0; y < height; y++) {
  734. extract_even_c(src, ydst, width);
  735. if (y & 1) {
  736. extract_odd2avg_c(src - srcStride, src, udst, vdst, chromWidth);
  737. udst += chromStride;
  738. vdst += chromStride;
  739. }
  740. src += srcStride;
  741. ydst += lumStride;
  742. }
  743. }
  744. static void yuyvtoyuv422_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
  745. const uint8_t *src, int width, int height,
  746. int lumStride, int chromStride, int srcStride)
  747. {
  748. int y;
  749. const int chromWidth = -((-width) >> 1);
  750. for (y = 0; y < height; y++) {
  751. extract_even_c(src, ydst, width);
  752. extract_odd2_c(src, udst, vdst, chromWidth);
  753. src += srcStride;
  754. ydst += lumStride;
  755. udst += chromStride;
  756. vdst += chromStride;
  757. }
  758. }
  759. static void uyvytoyuv420_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
  760. const uint8_t *src, int width, int height,
  761. int lumStride, int chromStride, int srcStride)
  762. {
  763. int y;
  764. const int chromWidth = -((-width) >> 1);
  765. for (y = 0; y < height; y++) {
  766. extract_even_c(src + 1, ydst, width);
  767. if (y & 1) {
  768. extract_even2avg_c(src - srcStride, src, udst, vdst, chromWidth);
  769. udst += chromStride;
  770. vdst += chromStride;
  771. }
  772. src += srcStride;
  773. ydst += lumStride;
  774. }
  775. }
  776. static void uyvytoyuv422_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
  777. const uint8_t *src, int width, int height,
  778. int lumStride, int chromStride, int srcStride)
  779. {
  780. int y;
  781. const int chromWidth = -((-width) >> 1);
  782. for (y = 0; y < height; y++) {
  783. extract_even_c(src + 1, ydst, width);
  784. extract_even2_c(src, udst, vdst, chromWidth);
  785. src += srcStride;
  786. ydst += lumStride;
  787. udst += chromStride;
  788. vdst += chromStride;
  789. }
  790. }
  791. static inline void rgb2rgb_init_c(void)
  792. {
  793. rgb15to16 = rgb15to16_c;
  794. rgb15tobgr24 = rgb15tobgr24_c;
  795. rgb15to32 = rgb15to32_c;
  796. rgb16tobgr24 = rgb16tobgr24_c;
  797. rgb16to32 = rgb16to32_c;
  798. rgb16to15 = rgb16to15_c;
  799. rgb24tobgr16 = rgb24tobgr16_c;
  800. rgb24tobgr15 = rgb24tobgr15_c;
  801. rgb24tobgr32 = rgb24tobgr32_c;
  802. rgb32to16 = rgb32to16_c;
  803. rgb32to15 = rgb32to15_c;
  804. rgb32tobgr24 = rgb32tobgr24_c;
  805. rgb24to15 = rgb24to15_c;
  806. rgb24to16 = rgb24to16_c;
  807. rgb24tobgr24 = rgb24tobgr24_c;
  808. shuffle_bytes_2103 = shuffle_bytes_2103_c;
  809. rgb32tobgr16 = rgb32tobgr16_c;
  810. rgb32tobgr15 = rgb32tobgr15_c;
  811. yv12toyuy2 = yv12toyuy2_c;
  812. yv12touyvy = yv12touyvy_c;
  813. yuv422ptoyuy2 = yuv422ptoyuy2_c;
  814. yuv422ptouyvy = yuv422ptouyvy_c;
  815. yuy2toyv12 = yuy2toyv12_c;
  816. planar2x = planar2x_c;
  817. rgb24toyv12 = rgb24toyv12_c;
  818. interleaveBytes = interleaveBytes_c;
  819. vu9_to_vu12 = vu9_to_vu12_c;
  820. yvu9_to_yuy2 = yvu9_to_yuy2_c;
  821. uyvytoyuv420 = uyvytoyuv420_c;
  822. uyvytoyuv422 = uyvytoyuv422_c;
  823. yuyvtoyuv420 = yuyvtoyuv420_c;
  824. yuyvtoyuv422 = yuyvtoyuv422_c;
  825. }