Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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