yuv2yuv.c
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:145k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: yuv2yuv.c,v 1.4.28.1 2004/07/09 02:00:19 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. /*** #includes: ********************************************/
  50. #include "hxassert.h"
  51. #include "env.h"
  52. #include "yuv.h"    /* YUV-to-RGB conversion tables & macros */
  53. #include "clip.h"   /* macros for clipping & dithering */
  54. #include "hxassert.h"
  55. #include "colorlib.h"
  56. int PackedYUVMemcpyWithPitch( unsigned char *dest_ptr,
  57.                               int dest_width, int dest_height,
  58.                               int dest_pitch,
  59.                               int dest_x, int dest_y, int dest_dx, int dest_dy,
  60.                               unsigned char *src_ptr,
  61.                               int src_width, int src_height, int src_pitch,
  62.                               int src_x, int src_y, int src_dx, int src_dy);
  63. /*** YUV to YUV color converters: **************************/
  64. /*
  65.  * These functions were borrowed from our "old" color conversion library,
  66.  * and they do not support things like stretching or color adjustments.
  67.  * Given some more time this module should be completely rewritten.
  68.  *
  69.  ***************/
  70. static int YUY2toPlanarYUV(unsigned char *dY, unsigned char *dU, unsigned char *dV,
  71.                            int dest_width, int dest_height,
  72.                            int dyPitch, int duPitch, int dvPitch,
  73.                            int dest_x, int dest_y, int dest_dx, int dest_dy,
  74.                            unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  75.                            int src_x, int src_y, int src_dx, int src_dy);
  76. static int UYVYtoPlanarYUV(unsigned char *dY, unsigned char *dU, unsigned char *dV,
  77.                            int dest_width, int dest_height,
  78.                            int dyPitch, int duPitch, int dvPitch,
  79.                            int dest_x, int dest_y, int dest_dx, int dest_dy,
  80.                            unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  81.                            int src_x, int src_y, int src_dx, int src_dy);
  82. /*
  83.  * Checks format conversion parameters.
  84.  * Use:
  85.  *  int chk_args (unsigned char *dest_ptr, int dest_width, int dest_height,
  86.  *      int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  87.  *      unsigned char *src_ptr, int src_width, int src_height,
  88.  *      int src_pitch, int src_x, int src_y, int src_dx, int src_dy,
  89.  *      int *p_scale_x, int *p_scale_y);
  90.  * Input:
  91.  *  dest_ptr - pointer to a destination buffer
  92.  *  dest_width, dest_height - width/height of the destination image (pixels)
  93.  *  dest_pitch - pitch of the dest. buffer (in bytes; <0 - if bottom up image)
  94.  *  dest_x, dest_y, dest_dx, dest_dy - destination rectangle (pixels)
  95.  *  src_ptr - pointer to an input image
  96.  *  src_width, src_height - width/height of the input image (pixels)
  97.  *  src_pitch - pitch of the source buffer (in bytes; <0 - if bottom up image)
  98.  *  src_x, src_y, src_dx, src_dy - source rectangle (pixels)
  99.  * Output:
  100.  *  p_scale_x, p_scale_y - scale factors for x,y axes
  101.  *      (currently only 1:1, and 2:1 scale factors are allowed)
  102.  * Returns:
  103.  *  0 - if success; -1 if failure.
  104.  */
  105. static int
  106. chk_args (unsigned char *dest_ptr, int dest_width, int dest_height,
  107.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  108.     unsigned char *src_ptr, int src_width, int src_height,
  109.     int src_pitch, int src_x, int src_y, int src_dx, int src_dy,
  110.     int *p_scale_x, int *p_scale_y)
  111. {
  112.     /* alignments: */
  113.     if (((unsigned)dest_ptr & 3) || (dest_pitch & 3) ||
  114.         ((unsigned)src_ptr  & 3) || (src_pitch  & 3) ||
  115.     /* image sizes: */
  116.         dest_width <= 0 || dest_height <= 0 ||
  117.         src_width  <= 0 || src_height  <= 0 ||
  118.     /* rectangles: */
  119.         dest_x < 0 || dest_y < 0 || dest_dx <= 0 || dest_dy <= 0 ||
  120.         src_x  < 0 || src_y  < 0 || src_dx  <= 0 || src_dy  <= 0 ||
  121.     /* overlaps: */
  122.         dest_width < dest_x + dest_dx || dest_height < dest_y + dest_dy ||
  123.         src_width  < src_x  + src_dx  || src_height  < src_y  + src_dy)
  124.         goto fail;
  125.     /* scale factors: */
  126.     if (dest_dx == src_dx)          *p_scale_x = 1;
  127.     else if (dest_dx == 2 * src_dx) *p_scale_x = 2;
  128.     else goto fail;
  129.     if (dest_dy == src_dy)          *p_scale_y = 1;
  130.     else if (dest_dy == 2 * src_dy) *p_scale_y = 2;
  131.     else goto fail;
  132.     /* success: */
  133.     return 1;
  134.     /* failure: */
  135. fail:
  136.     return 0;
  137. }
  138. static int adjust_range (int *z1, int *dz1, int *z2, int *dz2, int inc2)
  139. {
  140.     /* skip odd start pixel: */
  141.     if (*z1 & 1) {
  142.         *z1 += 1;
  143.         *dz1 -= 1;
  144.         *z2 += inc2;
  145.         *dz2 -= inc2;
  146.     }
  147.     /* clip the range: */
  148.     if (*dz1 & 1) {
  149.         *dz1 -= 1;
  150.         *dz2 -= inc2;
  151.     }
  152.     return (*dz1 > 0 && *dz2 > 0);
  153. }
  154. /*** "from I420" converters: *******************************/
  155. /*
  156.  * I420toI420x() converter:
  157.  */
  158. int I420toI420x (unsigned char *dest_ptr, int dest_width, int dest_height,
  159.                  int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  160.                  unsigned char *pY, unsigned char *pU, unsigned char *pV,
  161.                  int src_width, int src_height, int yPitch, int uPitch, int vPitch,
  162.                  int src_x, int src_y, int src_dx, int src_dy)
  163. {
  164.     /* scale factors: */
  165.     int scale_x, scale_y;
  166. /* Chroma Shifting Allowed */
  167. int OddPattern;
  168.     /* check arguments: */
  169.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  170.         dest_x, dest_y, dest_dx, dest_dy, pY, src_width, src_height,
  171.         yPitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  172.         return -1;
  173.     /* remove odd destination pixels: */
  174.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x) ||
  175.         !adjust_range (&dest_y, &dest_dy, &src_y, &src_dy, scale_y))
  176.         return 0;
  177.     /* check if we have matching chroma components: */
  178.     //if ((src_x & 1) || (src_y & 1))
  179.     //   OddCrop= true;                          /* can't shift chromas */
  180. //else
  181. // OddCrop = false;
  182.     /* check if bottop-up images: */
  183.     if (dest_pitch <= 0 || yPitch <= 0)
  184.         return -1;                          /* not supported for this format */
  185.     /* check if 1:1 scale: */
  186.     if (scale_x == 1 && scale_y == 1) {
  187.         /* check if no color adjustmenst: */
  188.         if (!(is_alpha | is_beta | is_gamma | is_kappa)) {
  189.             /* no color adjustments: */
  190.             unsigned char *s, *d, *v, *s2, *v2;
  191.             int dest_uv_offs;
  192.             register int i,j;
  193.             /* copy Y plane: */
  194.             s = pY + src_x + src_y * yPitch;
  195.             d = dest_ptr + dest_x + dest_y * dest_pitch;
  196.             for (i = 0; i < dest_dy; i ++) {
  197.                 memcpy (d, s, dest_dx); /* Flawfinder: ignore */
  198.                 s += yPitch;
  199.                 d += dest_pitch;
  200.             }
  201.             /* get Cr/Cb offsets: */
  202.             dest_uv_offs = dest_height * dest_pitch / 4;
  203.             /* copy Cr/Cb planes: */
  204.             s = pU + src_x/2 + src_y/2 * uPitch;
  205.             v = pV + src_x/2 + src_y/2 * vPitch;
  206.             d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  207. // extremely cheap way to handle 1 pel cropping
  208. OddPattern = ((src_y & 1) << 1) | (src_x & 1);
  209.             for (i = 0; i < dest_dy/2; i++) 
  210. {
  211. if((i+1) < dest_dy/2) {
  212. s2 = s+uPitch;
  213. v2 = v+vPitch;
  214. } else {
  215. s2 = s;
  216. v2 = v;
  217. }
  218. /* convert pixels: */
  219. switch(OddPattern)
  220. {
  221. case(0):
  222. memcpy (d, s, dest_dx/2); /* Flawfinder: ignore */
  223. memcpy (d + dest_uv_offs, v, dest_dx/2); /* Flawfinder: ignore */
  224. //memcpy (d + dest_uv_offs, s + src_uv_offs, dest_dx/2);
  225. break;
  226. case(1):
  227. for (j = 0; j < dest_dx/2 -1; j ++) {
  228. d[j] = ((unsigned int)s[j] + (unsigned int)s[j+1] + 1)>>1;
  229. d[j + dest_uv_offs] = ((unsigned int)v[j] + (unsigned int)v[j+1] + 1)>>1;
  230. }
  231. d[j] = s[j];
  232. d[j + dest_uv_offs] = v[j];
  233. break;
  234. case(2):
  235. for (j = 0; j < dest_dx/2; j ++) {
  236. d[j] = (s[j] + s2[j] + 1)>>1;
  237. d[j + dest_uv_offs] = ((unsigned int)v[j] + (unsigned int)v2[j] + 1)>>1;
  238. }
  239. break;
  240. case(3):
  241. for (j = 0; j < dest_dx/2 -1; j ++) {
  242. d[j] = ((unsigned int)s[j] + (unsigned int)s[j+1] + (unsigned int)s2[j] + (unsigned int)s2[j+1] + 2)>>2;
  243. d[j + dest_uv_offs] = ((unsigned int)v[j] + (unsigned int)v[j+1] + (unsigned int)v2[j] + (unsigned int)v2[j+1] + 2)>>2;
  244. }
  245. d[j] = ((unsigned int)s[j]+ (unsigned int)s2[j] + 1)>>1;
  246. d[j + dest_uv_offs] = ((unsigned int)v[j] + (unsigned int)v2[j] + 1) >> 1;
  247. break;
  248. }
  249.                 s += uPitch;
  250.                 v += vPitch;
  251.                 d += (dest_pitch/2);
  252.             }
  253.         } else {
  254.             /* adjust colors: */
  255.             unsigned char *s, *d, *v, *s2, *v2;
  256.             int dest_uv_offs;
  257.             register int i, j;
  258.             /* convert Y plane: */
  259.             s = pY + src_x + src_y * yPitch;
  260.             d = dest_ptr + dest_x + dest_y * dest_pitch;
  261.             for (i = 0; i < dest_dy; i ++) {
  262.                 /* convert pixels: */
  263.                 for (j = 0; j < dest_dx; j ++)
  264.                     d[j] = _yytab[s[j]];
  265.                 s += yPitch;
  266.                 d += dest_pitch;
  267.             }
  268.             /* get Cr/Cb offsets: */
  269.             dest_uv_offs = dest_height * dest_pitch / 4;
  270.             /* get chroma pointers: */
  271.             s = pU + src_x/2 + src_y/2 * uPitch;
  272.             v = pV + src_x/2 + src_y/2 * vPitch;
  273.             d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  274. OddPattern = ((src_y & 1) << 1) | (src_x & 1);
  275.             /* check if no hue adjustment: */
  276.             if (!is_alpha) {
  277.                 /* no chroma rotation: */
  278.                 for (i = 0; i < dest_dy/2; i ++) {
  279.                     if((i+1) < dest_dy/2) {
  280. s2 = s+uPitch;
  281. v2 = v+vPitch;
  282. } else {
  283. s2 = s;
  284. v2 = v;
  285. }
  286. /* convert pixels: */
  287. switch(OddPattern)
  288. {
  289. case(0):
  290. for (j = 0; j < dest_dx/2; j ++) {
  291. d[j] = _vvtab[s[j]];
  292. d[j + dest_uv_offs] = _uutab[v[j]];
  293. }
  294. break;
  295. case(1):
  296. for (j = 0; j < dest_dx/2 -1; j ++) {
  297. register unsigned int s1 = ((unsigned int)s[j] + (unsigned int)s[j+1] + 1)>>1;
  298. register unsigned int v1 = ((unsigned int)v[j] + (unsigned int)v[j+1] + 1)>>1;
  299. d[j] = _vvtab[s1];
  300. d[j + dest_uv_offs] = _uutab[v1];
  301. }
  302. d[j] = _vvtab[s[j]];
  303. d[j + dest_uv_offs] = _uutab[v[j]];
  304. break;
  305. case(2):
  306. for (j = 0; j < dest_dx/2; j ++) {
  307. register unsigned int s1 = ((unsigned int)s[j] + (unsigned int)s2[j] + 1)>>1;
  308. register unsigned int v1 = ((unsigned int)v[j] + (unsigned int)v2[j] + 1)>>1;
  309. d[j] = _vvtab[s1];
  310. d[j + dest_uv_offs] = _uutab[v1];
  311. }
  312. break;
  313. case(3):
  314. {
  315. register unsigned int s1, v1;
  316. for (j = 0; j < dest_dx/2 -1; j ++) {
  317. s1 = ((unsigned int)s[j] + (unsigned int)s[j+1] + (unsigned int)s2[j] + (unsigned int)s2[j+1] + 2)>>2;
  318. v1 = ((unsigned int)v[j] + (unsigned int)v[j+1] + (unsigned int)v2[j] + (unsigned int)v2[j+1] + 2)>>2; 
  319. d[j] = _vvtab[s1];
  320. d[j + dest_uv_offs] = _uutab[v1];
  321. }
  322. s1 =((unsigned int)s[j]+ (unsigned int)s2[j] + 1) >> 1;
  323. v1 = ((unsigned int)v[j] + (unsigned int)v2[j] + 1) >> 1;
  324. d[j] = _vvtab[s1];
  325. d[j + dest_uv_offs] = _uutab[v1];
  326. }
  327. break;
  328. }
  329.                     s += uPitch;
  330.                     v += vPitch;
  331.                     d += dest_pitch/2;
  332.                 }
  333.             } else {
  334.                 /* adjust hue: */
  335.                 for (i = 0; i < dest_dy/2; i ++) {
  336. if((i+1) < dest_dy/2) {
  337. s2 = s+uPitch;
  338. v2 = v+vPitch;
  339. } else {
  340. s2 = s;
  341. v2 = v;
  342. }
  343.                     /* convert pixels: */
  344.                     switch(OddPattern)
  345. {
  346. case(0):
  347. for (j = 0; j < dest_dx/2; j ++) {
  348. register unsigned v1 = v[j], u1 = s[j];
  349. d[j] = _CLIP(8,_vvtab[v1] + _vutab[u1]);
  350. d[j + dest_uv_offs] = _CLIP(8,_uutab[u1] + _uvtab[v1]);
  351. }
  352. break;
  353. case(1):
  354. {
  355. register unsigned s1, v1;
  356. for (j = 0; j < dest_dx/2 -1; j ++) {
  357. s1 = ((unsigned int)s[j] + (unsigned int)s[j+1] + 1)>>1;
  358. v1 = ((unsigned int)v[j] + (unsigned int)v[j+1] + 1)>>1;
  359. d[j] = _CLIP(8,_vvtab[v1] + _vutab[s1]);
  360. d[j + dest_uv_offs] = _CLIP(8,_uutab[s1] + _uvtab[v1]);
  361. }
  362. v1 = v[j];
  363. s1 = s[j];
  364. d[j] = _CLIP(8,_vvtab[v1] + _vutab[s1]);
  365. d[j + dest_uv_offs] = _CLIP(8,_uutab[s1] + _uvtab[v1]);
  366. }
  367. break;
  368. case(2):
  369. for (j = 0; j < dest_dx/2; j ++) {
  370. register unsigned s1 = ((unsigned int)s[j] + (unsigned int)s2[j] + 1)>>1;
  371. register unsigned v1 = ((unsigned int)v[j] + (unsigned int)v2[j] + 1)>>1;
  372. d[j] = _CLIP(8,_vvtab[v1] + _vutab[s1]);
  373. d[j + dest_uv_offs] = _CLIP(8,_uutab[s1] + _uvtab[v1]);
  374. }
  375. break;
  376. case(3):
  377. {
  378. register unsigned s1, v1;
  379. for (j = 0; j < dest_dx/2 -1; j ++) {
  380. s1 =((unsigned int)s[j] + (unsigned int)s[j+1] + (unsigned int)s2[j] + (unsigned int)s2[j+1] + 2)>>2;
  381. v1 =((unsigned int)v[j] + (unsigned int)v[j+1] + (unsigned int)v2[j] + (unsigned int)v2[j+1] + 2)>>2;
  382. d[j] = _CLIP(8,_vvtab[v1] + _vutab[s1]);
  383. d[j + dest_uv_offs] = _CLIP(8,_uutab[s1] + _uvtab[v1]);
  384. }
  385. s1 = ((unsigned int)s[j]+ (unsigned int)s2[j] + 1)>>1;
  386. v1 = ((unsigned int)v[j] + (unsigned int)v2[j] + 1) >> 1;
  387. d[j] = _CLIP(8,_vvtab[v1] + _vutab[s1]);
  388. d[j + dest_uv_offs] = _CLIP(8,_uutab[s1] + _uvtab[v1]);
  389. }
  390. break;
  391. }
  392.                     s += uPitch;
  393.                     v += vPitch;
  394.                     d += dest_pitch/2;
  395.                 }
  396.             }
  397.         }
  398.         return 0;
  399.     }
  400.     /* conversion is not supported */
  401.     return -1;
  402. }
  403. /*
  404.  * I420toI420() converter:
  405.  */
  406. int I420toI420 (unsigned char *dest_ptr, int dest_width, int dest_height,
  407.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  408.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  409.     int src_x, int src_y, int src_dx, int src_dy)
  410. {
  411. #if 1
  412.     unsigned char *pU = src_ptr+src_height*src_pitch,
  413.                   *pV = pU + src_height*src_pitch/4;
  414.     return I420toI420x(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  415.                        src_ptr, pU, pV, 
  416.                        src_width, src_height, src_pitch, src_pitch/2, src_pitch/2,
  417.                        src_x, src_y, src_dx, src_dy);
  418.                     
  419. #else
  420.     /* scale factors: */
  421.     int scale_x, scale_y;
  422.     /* check arguments: */
  423.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  424.         dest_x, dest_y, dest_dx, dest_dy, src_ptr, src_width, src_height,
  425.         src_pitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  426.         return -1;
  427.     /* remove odd destination pixels: */
  428.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x) ||
  429.         !adjust_range (&dest_y, &dest_dy, &src_y, &src_dy, scale_y))
  430.         return 0;
  431.     /* check if we have matching chroma components: */
  432.     if ((src_x & 1) || (src_y & 1))
  433.         return -1;                          /* can't shift chromas */
  434.     /* check if bottop-up images: */
  435.     if (dest_pitch <= 0 || src_pitch <= 0)
  436.         return -1;                          /* not supported for this format */
  437.     /* check if 1:1 scale: */
  438.     if (scale_x == 1 && scale_y == 1) {
  439.         /* check if no color adjustmenst: */
  440.         if (!(is_alpha | is_beta | is_gamma | is_kappa)) {
  441.             /* no color adjustments: */
  442.             unsigned char *s, *d;
  443.             int src_uv_offs, dest_uv_offs;
  444.             register int i;
  445.             /* copy Y plane: */
  446.             s = src_ptr + src_x + src_y * src_pitch;
  447.             d = dest_ptr + dest_x + dest_y * dest_pitch;
  448.             for (i = 0; i < dest_dy; i ++) {
  449.                 memcpy (d, s, dest_dx); /* Flawfinder: ignore */
  450.                 s += src_pitch;
  451.                 d += dest_pitch;
  452.             }
  453.             /* get Cr/Cb offsets: */
  454.             src_uv_offs = src_height * src_pitch / 4;
  455.             dest_uv_offs = dest_height * dest_pitch / 4;
  456.             /* copy Cr/Cb planes: */
  457.             s = (src_ptr + src_height * src_pitch) + src_x/2 + src_y/2 * src_pitch/2;
  458.             d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  459.             for (i = 0; i < dest_dy/2; i ++) {
  460.                 memcpy (d, s, dest_dx/2); /* Flawfinder: ignore */
  461.                 memcpy (d + dest_uv_offs, s + src_uv_offs, dest_dx/2); /* Flawfinder: ignore */
  462.                 s += src_pitch/2;
  463.                 d += dest_pitch/2;
  464.             }
  465.         } else {
  466.             /* adjust colors: */
  467.             unsigned char *s, *d;
  468.             int src_uv_offs, dest_uv_offs;
  469.             register int i, j;
  470.             /* convert Y plane: */
  471.             s = src_ptr + src_x + src_y * src_pitch;
  472.             d = dest_ptr + dest_x + dest_y * dest_pitch;
  473.             for (i = 0; i < dest_dy; i ++) {
  474.                 /* convert pixels: */
  475.                 for (j = 0; j < dest_dx; j ++)
  476.                     d[j] = _yytab[s[j]];
  477.                 s += src_pitch;
  478.                 d += dest_pitch;
  479.             }
  480.             /* get Cr/Cb offsets: */
  481.             src_uv_offs = src_height * src_pitch / 4;
  482.             dest_uv_offs = dest_height * dest_pitch / 4;
  483.             /* get chroma pointers: */
  484.             s = (src_ptr + src_height * src_pitch) + src_x/2 + src_y/2 * src_pitch/2;
  485.             d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  486.             /* check if no hue adjustment: */
  487.             if (!is_alpha) {
  488.                 /* no chroma rotation: */
  489.                 for (i = 0; i < dest_dy/2; i ++) {
  490.                     /* convert pixels: */
  491.                     for (j = 0; j < dest_dx/2; j ++) {
  492.                         d[j] = _vvtab[s[j]];
  493.                         d[j + dest_uv_offs] = _uutab[s[j + src_uv_offs]];
  494.                     }
  495.                     s += src_pitch/2;
  496.                     d += dest_pitch/2;
  497.                 }
  498.             } else {
  499.                 /* adjust hue: */
  500.                 for (i = 0; i < dest_dy/2; i ++) {
  501.                     /* convert pixels: */
  502.                     for (j = 0; j < dest_dx/2; j ++) {
  503.                         register unsigned v = s[j], u = s[j + src_uv_offs];
  504.                         d[j] = _CLIP(8,_vvtab[v] + _vutab[u]);
  505.                         d[j + dest_uv_offs] = _CLIP(8,_uutab[u] + _uvtab[v]);
  506.                     }
  507.                     s += src_pitch/2;
  508.                     d += dest_pitch/2;
  509.                 }
  510.             }
  511.         }
  512.         return 0;
  513.     }
  514.     /* conversion is not supported */
  515.     return -1;
  516. #endif
  517. }
  518. int I420toYV12x (unsigned char *dest_ptr, int dest_width, int dest_height,
  519.                  int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  520.                  unsigned char *pY, unsigned char *pU, unsigned char *pV,
  521.                  int src_width, int src_height, int yPitch, int uPitch, int vPitch,
  522.                  int src_x, int src_y, int src_dx, int src_dy)
  523. {
  524.     /* scale factors: */
  525.     int scale_x, scale_y;
  526.     /* check arguments: */
  527.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  528.         dest_x, dest_y, dest_dx, dest_dy, pY, src_width, src_height,
  529.         yPitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  530.         return -1;
  531.     /* remove odd destination pixels: */
  532.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x) ||
  533.         !adjust_range (&dest_y, &dest_dy, &src_y, &src_dy, scale_y))
  534.         return 0;
  535.     /* check if we have matching chroma components: */
  536.     if ((src_x & 1) || (src_y & 1))
  537.         return -1;                          /* can't shift chromas */
  538.     /* check if bottop-up images: */
  539.     if (dest_pitch <= 0 || yPitch <= 0)
  540.         return -1;                          /* not supported for this format */
  541.     /* check if 1:1 scale: */
  542.     if (scale_x == 1 && scale_y == 1) {
  543.         /* check if no color adjustments: */
  544.         if (!(is_alpha | is_beta | is_gamma | is_kappa)) {
  545.             /* no color adjustments: */
  546.             unsigned char *sy, *su, *sv, *d;
  547.             int dest_uv_offs;
  548.             register int i;
  549.             /* copy Y plane: */
  550.             sy = pY + src_x + src_y * yPitch;
  551.             d = dest_ptr + dest_x + dest_y * dest_pitch;
  552.             for (i = 0; i < dest_dy; i ++) {
  553.                 memcpy (d, sy, dest_dx); /* Flawfinder: ignore */
  554.                 sy += yPitch;
  555.                 d += dest_pitch;
  556.             }
  557.             /* get Cr/Cb offsets: */
  558.             dest_uv_offs = dest_height * dest_pitch / 4;
  559.             /* copy Cr/Cb planes: */
  560.             su = pU + src_x/2 + src_y/2 * uPitch;
  561.             sv = pV + src_x/2 + src_y/2 * vPitch;
  562.             
  563.             d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  564.             for (i = 0; i < dest_dy/2; i ++) {
  565.                 memcpy (d, sv, dest_dx/2); /* Flawfinder: ignore */
  566.                 memcpy (d + dest_uv_offs, su, dest_dx/2); /* Flawfinder: ignore */
  567.                 su += uPitch;
  568.                 sv += vPitch;
  569.                 d += dest_pitch/2;
  570.             }
  571.         } else {
  572.             /* adjust colors: */
  573.             unsigned char *sy, *su, *sv, *d;
  574.             int dest_uv_offs;
  575.             register int i, j;
  576.             /* convert Y plane: */
  577.             sy = pY + src_x + src_y * yPitch;
  578.             d = dest_ptr + dest_x + dest_y * dest_pitch;
  579.             for (i = 0; i < dest_dy; i ++) {
  580.                 /* convert pixels: */
  581.                 for (j = 0; j < dest_dx; j ++)
  582.                     d[j] = _yytab[sy[j]];
  583.                 sy += yPitch;
  584.                 d += dest_pitch;
  585.             }
  586.             /* get Cr/Cb offsets: */
  587.             dest_uv_offs = dest_height * dest_pitch / 4;
  588.             /* get chroma pointers: */
  589.             su = pU + src_x/2 + src_y/2 * uPitch;
  590.             sv = pV + src_x/2 + src_y/2 * vPitch;
  591.             d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  592.             /* check if no hue adjustment: */
  593.             if (!is_alpha) {
  594.                 /* no chroma rotation: */
  595.                 for (i = 0; i < dest_dy/2; i ++) {
  596.                     /* convert pixels: */
  597.                     for (j = 0; j < dest_dx/2; j ++) {
  598.                         d[j] = _vvtab[sv[j]];
  599.                         d[j + dest_uv_offs] = _uutab[su[j]];
  600.                     }
  601.                     su += uPitch;
  602.                     sv += vPitch;
  603.                     d += dest_pitch/2;
  604.                 }
  605.             } else {
  606.                 /* adjust hue: */
  607.                 for (i = 0; i < dest_dy/2; i ++) {
  608.                     /* convert pixels: */
  609.                     for (j = 0; j < dest_dx/2; j ++) {
  610.                         register unsigned v = sv[j], u = su[j];
  611.                         d[j] = _CLIP(8,_vvtab[v] + _vutab[u]);
  612.                         d[j + dest_uv_offs] = _CLIP(8,_uutab[u] + _uvtab[v]);
  613.                     }
  614.                     su += uPitch;
  615.                     sv += vPitch;
  616.                     d += dest_pitch/2;
  617.                 }
  618.             }
  619.         }
  620.         return 0;
  621.     }
  622.     /* conversion is not supported */
  623.     return -1;
  624. }
  625. /*
  626.  * I420toYV12() converter:
  627.  */
  628. int I420toYV12 (unsigned char *dest_ptr, int dest_width, int dest_height,
  629.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  630.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  631.     int src_x, int src_y, int src_dx, int src_dy)
  632. {
  633. #if 1
  634.     unsigned char *pU = src_ptr+src_height*src_pitch,
  635.                   *pV = pU + src_height*src_pitch/4;
  636.     return I420toYV12x(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  637.                        src_ptr, pU, pV, 
  638.                        src_width, src_height, src_pitch, src_pitch/2, src_pitch/2,
  639.                        src_x, src_y, src_dx, src_dy);
  640.                     
  641. #else
  642.     /* scale factors: */
  643.     int scale_x, scale_y;
  644.     /* check arguments: */
  645.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  646.         dest_x, dest_y, dest_dx, dest_dy, src_ptr, src_width, src_height,
  647.         src_pitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  648.         return -1;
  649.     /* remove odd destination pixels: */
  650.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x) ||
  651.         !adjust_range (&dest_y, &dest_dy, &src_y, &src_dy, scale_y))
  652.         return 0;
  653.     /* check if we have matching chroma components: */
  654.     if ((src_x & 1) || (src_y & 1))
  655.         return -1;                          /* can't shift chromas */
  656.     /* check if bottop-up images: */
  657.     if (dest_pitch <= 0 || src_pitch <= 0)
  658.         return -1;                          /* not supported for this format */
  659.     /* check if 1:1 scale: */
  660.     if (scale_x == 1 && scale_y == 1) {
  661.         /* check if no color adjustments: */
  662.         if (!(is_alpha | is_beta | is_gamma | is_kappa)) {
  663.             /* no color adjustments: */
  664.             unsigned char *s, *d;
  665.             int src_uv_offs, dest_uv_offs;
  666.             register int i;
  667.             /* copy Y plane: */
  668.             s = src_ptr + src_x + src_y * src_pitch;
  669.             d = dest_ptr + dest_x + dest_y * dest_pitch;
  670.             for (i = 0; i < dest_dy; i ++) {
  671.                 memcpy (d, s, dest_dx); /* Flawfinder: ignore */
  672.                 s += src_pitch;
  673.                 d += dest_pitch;
  674.             }
  675.             /* get Cr/Cb offsets: */
  676.             src_uv_offs = src_height * src_pitch / 4;
  677.             dest_uv_offs = dest_height * dest_pitch / 4;
  678.             /* copy Cr/Cb planes: */
  679.             s = (src_ptr + src_height * src_pitch) + src_x/2 + src_y/2 * src_pitch/2;
  680.             d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  681.             for (i = 0; i < dest_dy/2; i ++) {
  682.                 memcpy (d, s + src_uv_offs, dest_dx/2); /* Flawfinder: ignore */
  683.                 memcpy (d + dest_uv_offs, s, dest_dx/2); /* Flawfinder: ignore */
  684.                 s += src_pitch/2;
  685.                 d += dest_pitch/2;
  686.             }
  687.         } else {
  688.             /* adjust colors: */
  689.             unsigned char *s, *d;
  690.             int src_uv_offs, dest_uv_offs;
  691.             register int i, j;
  692.             /* convert Y plane: */
  693.             s = src_ptr + src_x + src_y * src_pitch;
  694.             d = dest_ptr + dest_x + dest_y * dest_pitch;
  695.             for (i = 0; i < dest_dy; i ++) {
  696.                 /* convert pixels: */
  697.                 for (j = 0; j < dest_dx; j ++)
  698.                     d[j] = _yytab[s[j]];
  699.                 s += src_pitch;
  700.                 d += dest_pitch;
  701.             }
  702.             /* get Cr/Cb offsets: */
  703.             src_uv_offs = src_height * src_pitch / 4;
  704.             dest_uv_offs = dest_height * dest_pitch / 4;
  705.             /* get chroma pointers: */
  706.             s = (src_ptr + src_height * src_pitch) + src_x/2 + src_y/2 * src_pitch/2;
  707.             d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  708.             /* check if no hue adjustment: */
  709.             if (!is_alpha) {
  710.                 /* no chroma rotation: */
  711.                 for (i = 0; i < dest_dy/2; i ++) {
  712.                     /* convert pixels: */
  713.                     for (j = 0; j < dest_dx/2; j ++) {
  714.                         d[j] = _vvtab[s[j + src_uv_offs]];
  715.                         d[j + dest_uv_offs] = _uutab[s[j]];
  716.                     }
  717.                     s += src_pitch/2;
  718.                     d += dest_pitch/2;
  719.                 }
  720.             } else {
  721.                 /* adjust hue: */
  722.                 for (i = 0; i < dest_dy/2; i ++) {
  723.                     /* convert pixels: */
  724.                     for (j = 0; j < dest_dx/2; j ++) {
  725.                         register unsigned v = s[j + src_uv_offs], u = s[j];
  726.                         d[j] = _CLIP(8,_vvtab[v] + _vutab[u]);
  727.                         d[j + dest_uv_offs] = _CLIP(8,_uutab[u] + _uvtab[v]);
  728.                     }
  729.                     s += src_pitch/2;
  730.                     d += dest_pitch/2;
  731.                 }
  732.             }
  733.         }
  734.         return 0;
  735.     }
  736.     /* conversion is not supported */
  737.     return -1;
  738. #endif
  739. }
  740. #if (defined(_M_IX86) || defined(_USE_MMX_BLENDERS)) && !defined(WINCE_EMULATOR)
  741. //Our MMX optimized YUY2 and UYVY to YUV converters.
  742. //No scaling supported yet.
  743. extern void YUY2ToPlanarYUV_MMX( unsigned char* d1,      
  744.                                  unsigned char* d2,      
  745.                                  unsigned char* du,      
  746.                                  unsigned char* dv,      
  747.                                  INT32          dyPitch, 
  748.                                  INT32          duPitch, 
  749.                                  INT32          dvPitch, 
  750.                                  INT32          dest_dx, 
  751.                                  INT32          dest_dy, 
  752.                                  unsigned char* s1,      
  753.                                  unsigned char* s2,      
  754.                                  INT32          src_pitch
  755.                                  );
  756. extern void UYVYToPlanarYUV_MMX( unsigned char* d1,      
  757.                                  unsigned char* d2,      
  758.                                  unsigned char* du,      
  759.                                  unsigned char* dv,      
  760.                                  INT32          dyPitch, 
  761.                                  INT32          duPitch, 
  762.                                  INT32          dvPitch, 
  763.                                  INT32          dest_dx, 
  764.                                  INT32          dest_dy, 
  765.                                  unsigned char* s1,      
  766.                                  unsigned char* s2,      
  767.                                  INT32          src_pitch
  768.                                  );
  769. extern  YUY2toUYVY_MMX( unsigned char* src,
  770.                         unsigned char* dest,
  771.                         ULONG32        dx
  772.                         );
  773. /* MMX version of I420toYUY2 converter: */
  774. extern void _MMX_lineI420toYUY2( unsigned char *sy,
  775.                                  unsigned char *su,
  776.                                  unsigned char *sv,
  777.                                  unsigned char *d,
  778.                                  int count
  779.                                  );
  780. /*  MMX version of I420toUYVY converter */
  781. extern void _MMX_lineI420toUYVY( unsigned char *sy,
  782.                                  unsigned char *su,
  783.                                  unsigned char *sv,
  784.                                  unsigned char *d,
  785.                                  int count
  786.                                  );
  787. #endif
  788. #ifdef _MACINTOSH
  789. #ifdef __cplusplus
  790. extern "C"
  791. #endif
  792. void
  793. AltiVec_lineI420toYUY2 (
  794. unsigned char *sy, 
  795. unsigned char *su, 
  796. unsigned char *sv,
  797. unsigned char *d,
  798. int dest_dx);
  799. #endif
  800. /*
  801.  * Combine 4 bytes in a register for fast transfer to
  802.  * the main memory:
  803.  */
  804. #if BYTE_ORDER == LITTLE_ENDIAN
  805. #define COMBINE(b0,b1,b2,b3)  
  806.     ((unsigned int)(b0) | ((unsigned int)(b1) << 8) | 
  807.     ((unsigned int)(b2) << 16) | ((unsigned int)(b3) << 24))
  808. #else /* BYTE_ORDER != LITTLE_ENDIAN */
  809. #define COMBINE(b0,b1,b2,b3)  
  810.     ((unsigned int)(b3) | ((unsigned int)(b2) << 8) | 
  811.     ((unsigned int)(b1) << 16) | ((unsigned int)(b0) << 24))
  812. #endif
  813. int I420toYUY2x (unsigned char *dest_ptr, int dest_width, int dest_height,
  814.                  int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  815.                  unsigned char *pY, unsigned char *pU, unsigned char *pV,
  816.                  int src_width, int src_height, int yPitch, int uPitch, int vPitch,
  817.                  int src_x, int src_y, int src_dx, int src_dy)
  818. {
  819.     /* scale factors: */
  820.     int scale_x, scale_y;
  821.     /* check arguments: */
  822.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  823.         dest_x, dest_y, dest_dx, dest_dy, pY, src_width, src_height,
  824.         yPitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  825.         return -1;
  826.     /* remove odd destination columns: */
  827.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x))
  828.         return 0;
  829.     /* check if we have misaligned input: */
  830.     if (src_x & 1)
  831.         return -1;                          /* can't shift chromas */
  832.     /* check if bottop-up images: */
  833.     if (dest_pitch < 0) dest_ptr -= (dest_height-1) * dest_pitch;
  834.     if (yPitch <= 0 ||
  835.         uPitch <= 0 ||
  836.         vPitch <= 0)
  837.         return -1;          /* not supported */
  838.     /* check if 1:1 scale: */
  839.     if (scale_x == 1 && scale_y == 1) {
  840.         /* check if no color adjustments: */
  841.         if (!(is_alpha | is_beta | is_gamma | is_kappa)) {
  842.             /* no color adjustments: */
  843.             unsigned char *sy, *sv, *su, *d;
  844.             register int i, j;
  845.             /* get pointers: */
  846.             sy = pY + src_x + src_y * yPitch;           /* luma offset */
  847.             su = pU + (src_x/2 + src_y/2 * uPitch);
  848.             sv = pV + (src_x/2 + src_y/2 * vPitch);
  849.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  850. #if (defined(_M_IX86) || defined(_USE_MMX_BLENDERS))  && !defined(WINCE_EMULATOR)
  851.             /* check if we can use MMX-optimized code here: */
  852.             if (_x86_MMX_Available)
  853.             {
  854.                 /* process top line (if chroma is not pairable): */
  855.                 if (dest_y & 1) {
  856.                     _MMX_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  857.                     sy += yPitch;
  858.                     su += uPitch;
  859.                     sv += vPitch;
  860.                     d  += dest_pitch;
  861.                     dest_dy --;
  862.                 }
  863.                 /* the main loop (processes two lines a time): */
  864.                 for (i = 0; i < dest_dy/2; i ++) {
  865.                     _MMX_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  866.                     sy += yPitch;
  867.                     d  += dest_pitch;
  868.                     _MMX_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  869.                     sy += yPitch;
  870.                     su += uPitch;
  871.                     sv += vPitch;
  872.                     d  += dest_pitch;
  873.                 }
  874.                 /* process the last line (if dy is odd): */
  875.                 if (dest_dy & 1) {
  876.                     _MMX_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  877.                 }
  878.                 /* end of MMX code */
  879. #if defined(_M_IX86) && !defined(WINCE_EMULATOR)                
  880.                 __asm emms
  881. #elif defined(_USE_MMX_BLENDERS) && !defined(WINCE_EMULATOR)
  882.                __asm__ __volatile__ ( "emms" );
  883. #endif                    
  884.             } else
  885. #endif
  886. #ifdef _MACINTOSH
  887.             /* check if we can use MMX-optimized code here: */
  888.             if (_AltiVec_Available)
  889.             {
  890.                 /* process top line (if chroma is not pairable): */
  891.                 if (dest_y & 1) {
  892.                     AltiVec_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  893.                     sy += yPitch;
  894.                     su += uPitch;
  895.                     sv += vPitch;
  896.                     d  += dest_pitch;
  897.                     dest_dy --;
  898.                 }
  899.                 /* the main loop (processes two lines a time): */
  900.                 for (i = 0; i < dest_dy/2; i ++) {
  901.                     AltiVec_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  902.                     sy += yPitch;
  903.                     d  += dest_pitch;
  904.                     AltiVec_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  905.                     sy += yPitch;
  906.                     su += uPitch;
  907.                     sv += vPitch;
  908.                     d  += dest_pitch;
  909.                 }
  910.                 /* process the last line (if dy is odd): */
  911.                 if (dest_dy & 1) {
  912.                     AltiVec_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  913.                 }
  914.                 /* end of MMX code */
  915.             } else
  916. #endif
  917.             /* a generic "C" version: */
  918.             {
  919.                 /* process top line (if chroma is not pairable): */
  920.                 if (dest_y & 1) {
  921.                     for (j = 0; j < dest_dx/2; j ++)
  922.                         *(unsigned int *)(d + j*4) = COMBINE(sy[j*2], su[j], sy[j*2+1], sv[j]);
  923.                     sy += yPitch;
  924.                     su += uPitch;
  925.                     sv += vPitch;
  926.                     d  += dest_pitch;
  927.                     dest_dy --;
  928.                 }
  929.                 /* the main loop (processes two lines a time): */
  930.                 for (i = 0; i < dest_dy/2; i ++) {
  931.                     for (j = 0; j < dest_dx/2; j ++)
  932.                         *(unsigned int *)(d + j*4) = COMBINE(sy[j*2], su[j], sy[j*2+1], sv[j]);
  933.                     sy += yPitch;
  934.                     d  += dest_pitch;
  935.                     for (j = 0; j < dest_dx/2; j ++)
  936.                         *(unsigned int *)(d + j*4) = COMBINE(sy[j*2], su[j], sy[j*2+1], sv[j]);
  937.                     sy += yPitch;
  938.                     su += uPitch;
  939.                     sv += vPitch;
  940.                     d  += dest_pitch;
  941.                 }
  942.                 /* process the last line (if dy is odd): */
  943.                 if (dest_dy & 1) {
  944.                     for (j = 0; j < dest_dx/2; j ++)
  945.                         *(unsigned int *)(d + j*4) = COMBINE(sy[j*2], su[j], sy[j*2+1], sv[j]);
  946.                 }
  947.             }
  948.         } else
  949.         /* check if no hue adjustment: */
  950.         if (!is_alpha) {
  951.             /* no chroma rotation: */
  952.             unsigned char *sy, *sv, *su, *d;
  953.             register int i, j;
  954.             /* get pointers: */
  955.             sy = pY + src_x + src_y * yPitch;           /* luma offset */
  956.             su = pU + (src_x/2 + src_y/2 * uPitch);
  957.             sv = pV + (src_x/2 + src_y/2 * vPitch);
  958.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  959.             /* process top line (if chroma is not pairable): */
  960.             if (dest_y & 1) {
  961.                 for (j = 0; j < dest_dx/2; j ++)
  962.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], _uutab[su[j]], _yytab[sy[j*2+1]], _vvtab[sv[j]]);
  963.                 sy += yPitch;
  964.                 su += uPitch;
  965.                 sv += vPitch;
  966.                 d  += dest_pitch;
  967.                 dest_dy --;
  968.             }
  969.             /* the main loop (processes two lines a time): */
  970.             for (i = 0; i < dest_dy/2; i ++) {
  971.                 for (j = 0; j < dest_dx/2; j ++)
  972.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], _uutab[su[j]], _yytab[sy[j*2+1]], _vvtab[sv[j]]);
  973.                 sy += yPitch;
  974.                 d  += dest_pitch;
  975.                 for (j = 0; j < dest_dx/2; j ++)
  976.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], _uutab[su[j]], _yytab[sy[j*2+1]], _vvtab[sv[j]]);
  977.                 sy += yPitch;
  978.                 su += uPitch;
  979.                 sv += vPitch;
  980.                 d  += dest_pitch;
  981.             }
  982.             /* process the last line (if dy is odd): */
  983.             if (dest_dy & 1) {
  984.                 for (j = 0; j < dest_dx/2; j ++)
  985.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], _uutab[su[j]], _yytab[sy[j*2+1]], _vvtab[sv[j]]);
  986.             }
  987.         } else {
  988.             /* the most complex case (w. hue adjustment): */
  989.             unsigned char *sy, *sv, *su, *d;
  990.             register int i, j, u, v;
  991.             /* get pointers: */
  992.             sy = pY + src_x + src_y * yPitch;           /* luma offset */
  993.             su = pU + (src_x/2 + src_y/2 * uPitch);
  994.             sv = pV + (src_x/2 + src_y/2 * vPitch);
  995.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  996.             /* process top line (if chroma is not pairable): */
  997.             if (dest_y & 1) {
  998.                 for (j = 0; j < dest_dx/2; j ++) {
  999.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1000.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1001.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], u, _yytab[sy[j*2+1]], v);
  1002.                 }
  1003.                 sy += yPitch;
  1004.                 su += uPitch;
  1005.                 sv += vPitch;
  1006.                 d  += dest_pitch;
  1007.                 dest_dy --;
  1008.             }
  1009.             /* the main loop (processes two lines a time): */
  1010.             for (i = 0; i < dest_dy/2; i ++) {
  1011.                 for (j = 0; j < dest_dx/2; j ++) {
  1012.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1013.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1014.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], u, _yytab[sy[j*2+1]], v);
  1015.                     *(unsigned int *)(d + j*4 + dest_pitch) = COMBINE(_yytab[sy[j*2 + yPitch]], u, _yytab[sy[j*2+1+yPitch]], v);
  1016.                 }
  1017.                 sy += yPitch*2;
  1018.                 su += uPitch;
  1019.                 sv += vPitch;
  1020.                 d  += dest_pitch*2;
  1021.             }
  1022.             /* process the last line (if dy is odd): */
  1023.             if (dest_dy & 1) {
  1024.                 for (j = 0; j < dest_dx/2; j ++) {
  1025.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1026.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1027.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], u, _yytab[sy[j*2+1]], v);
  1028.                 }
  1029.             }
  1030.         }
  1031.         return 0;
  1032.     }
  1033.     /* conversion is not supported */
  1034.     return -1;
  1035. }
  1036. /*
  1037.  * I420toYUY2() converter:
  1038.  */
  1039. int I420toYUY2 (unsigned char *dest_ptr, int dest_width, int dest_height,
  1040.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1041.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  1042.     int src_x, int src_y, int src_dx, int src_dy)
  1043. {
  1044. #if 1
  1045.     unsigned char *pU = src_ptr+src_height*src_pitch,
  1046.                   *pV = pU + src_height*src_pitch/4;
  1047.     return I420toYUY2x(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  1048.                        src_ptr, pU, pV, 
  1049.                        src_width, src_height, src_pitch, src_pitch/2, src_pitch/2,
  1050.                        src_x, src_y, src_dx, src_dy);
  1051.                     
  1052. #else
  1053.     /* scale factors: */
  1054.     int scale_x, scale_y;
  1055.     /* check arguments: */
  1056.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  1057.         dest_x, dest_y, dest_dx, dest_dy, src_ptr, src_width, src_height,
  1058.         src_pitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  1059.         return -1;
  1060.     /* remove odd destination columns: */
  1061.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x))
  1062.         return 0;
  1063.     /* check if we have misaligned input: */
  1064.     if (src_x & 1)
  1065.         return -1;                          /* can't shift chromas */
  1066.     /* check if bottop-up images: */
  1067.     if (dest_pitch < 0) dest_ptr -= (dest_height-1) * dest_pitch;
  1068.     if (src_pitch <= 0) return -1;          /* not supported */
  1069.     /* check if 1:1 scale: */
  1070.     if (scale_x == 1 && scale_y == 1) {
  1071.         /* check if no color adjustments: */
  1072.         if (!(is_alpha | is_beta | is_gamma | is_kappa)) {
  1073.             /* no color adjustments: */
  1074.             unsigned char *sy, *sv, *su, *d;
  1075.             register int i, j;
  1076.             /* get pointers: */
  1077.             sy = src_ptr + src_x + src_y * src_pitch;           /* luma offset */
  1078.             su = src_ptr + src_height * src_pitch + (src_x/2 + src_y/2 * src_pitch);
  1079.             sv = su + src_height * src_pitch / 4;
  1080.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  1081. #if (defined(_M_IX86) || defined(_USE_MMX_BLENDERS)) && !defined(WINCE_EMULATOR)
  1082.             /* check if we can use MMX-optimized code here: */
  1083.             if (_x86_MMX_Available)
  1084.             {
  1085.                 /* process top line (if chroma is not pairable): */
  1086.                 if (dest_y & 1) {
  1087.                     _MMX_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  1088.                     sy += src_pitch;
  1089.                     su += src_pitch/2;
  1090.                     sv += src_pitch/2;
  1091.                     d  += dest_pitch;
  1092.                     dest_dy --;
  1093.                 }
  1094.                 /* the main loop (processes two lines a time): */
  1095.                 for (i = 0; i < dest_dy/2; i ++) {
  1096.                     _MMX_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  1097.                     sy += src_pitch;
  1098.                     d  += dest_pitch;
  1099.                     _MMX_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  1100.                     sy += src_pitch;
  1101.                     su += src_pitch/2;
  1102.                     sv += src_pitch/2;
  1103.                     d  += dest_pitch;
  1104.                 }
  1105.                 /* process the last line (if dy is odd): */
  1106.                 if (dest_dy & 1) {
  1107.                     _MMX_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  1108.                 }
  1109.                 /* end of MMX code */
  1110. #if defined(_M_IX86)  && !defined(WINCE_EMULATOR)                
  1111.                 __asm emms
  1112. #elif defined(_USE_MMX_BLENDERS) && !defined(WINCE_EMULATOR)
  1113.                 __asm__ __volatile__ ( "emms" );
  1114. #endif                    
  1115.             } else
  1116. #endif
  1117.             /* a generic "C" version: */
  1118.             {
  1119.                 /* process top line (if chroma is not pairable): */
  1120.                 if (dest_y & 1) {
  1121.                     for (j = 0; j < dest_dx/2; j ++)
  1122.                         *(unsigned int *)(d + j*4) = COMBINE(sy[j*2], su[j], sy[j*2+1], sv[j]);
  1123.                     sy += src_pitch;
  1124.                     su += src_pitch/2;
  1125.                     sv += src_pitch/2;
  1126.                     d  += dest_pitch;
  1127.                     dest_dy --;
  1128.                 }
  1129.                 /* the main loop (processes two lines a time): */
  1130.                 for (i = 0; i < dest_dy/2; i ++) {
  1131.                     for (j = 0; j < dest_dx/2; j ++)
  1132.                         *(unsigned int *)(d + j*4) = COMBINE(sy[j*2], su[j], sy[j*2+1], sv[j]);
  1133.                     sy += src_pitch;
  1134.                     d  += dest_pitch;
  1135.                     for (j = 0; j < dest_dx/2; j ++)
  1136.                         *(unsigned int *)(d + j*4) = COMBINE(sy[j*2], su[j], sy[j*2+1], sv[j]);
  1137.                     sy += src_pitch;
  1138.                     su += src_pitch/2;
  1139.                     sv += src_pitch/2;
  1140.                     d  += dest_pitch;
  1141.                 }
  1142.                 /* process the last line (if dy is odd): */
  1143.                 if (dest_dy & 1) {
  1144.                     for (j = 0; j < dest_dx/2; j ++)
  1145.                         *(unsigned int *)(d + j*4) = COMBINE(sy[j*2], su[j], sy[j*2+1], sv[j]);
  1146.                 }
  1147.             }
  1148.         } else
  1149.         /* check if no hue adjustment: */
  1150.         if (!is_alpha) {
  1151.             /* no chroma rotation: */
  1152.             unsigned char *sy, *sv, *su, *d;
  1153.             register int i, j;
  1154.             /* get pointers: */
  1155.             sy = src_ptr + src_x + src_y * src_pitch;           /* luma offset */
  1156.             su = src_ptr + src_height * src_pitch + (src_x/2 + src_y/2 * src_pitch);
  1157.             sv = su + src_height * src_pitch / 4;
  1158.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  1159.             /* process top line (if chroma is not pairable): */
  1160.             if (dest_y & 1) {
  1161.                 for (j = 0; j < dest_dx/2; j ++)
  1162.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], _uutab[su[j]], _yytab[sy[j*2+1]], _vvtab[sv[j]]);
  1163.                 sy += src_pitch;
  1164.                 su += src_pitch/2;
  1165.                 sv += src_pitch/2;
  1166.                 d  += dest_pitch;
  1167.                 dest_dy --;
  1168.             }
  1169.             /* the main loop (processes two lines a time): */
  1170.             for (i = 0; i < dest_dy/2; i ++) {
  1171.                 for (j = 0; j < dest_dx/2; j ++)
  1172.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], _uutab[su[j]], _yytab[sy[j*2+1]], _vvtab[sv[j]]);
  1173.                 sy += src_pitch;
  1174.                 d  += dest_pitch;
  1175.                 for (j = 0; j < dest_dx/2; j ++)
  1176.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], _uutab[su[j]], _yytab[sy[j*2+1]], _vvtab[sv[j]]);
  1177.                 sy += src_pitch;
  1178.                 su += src_pitch/2;
  1179.                 sv += src_pitch/2;
  1180.                 d  += dest_pitch;
  1181.             }
  1182.             /* process the last line (if dy is odd): */
  1183.             if (dest_dy & 1) {
  1184.                 for (j = 0; j < dest_dx/2; j ++)
  1185.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], _uutab[su[j]], _yytab[sy[j*2+1]], _vvtab[sv[j]]);
  1186.             }
  1187.         } else {
  1188.             /* the most complex case (w. hue adjustment): */
  1189.             unsigned char *sy, *sv, *su, *d;
  1190.             register int i, j, u, v;
  1191.             /* get pointers: */
  1192.             sy = src_ptr + src_x + src_y * src_pitch;           /* luma offset */
  1193.             su = src_ptr + src_height * src_pitch + (src_x/2 + src_y/2 * src_pitch/2);
  1194.             sv = su + src_height * src_pitch / 4;
  1195.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  1196.             /* process top line (if chroma is not pairable): */
  1197.             if (dest_y & 1) {
  1198.                 for (j = 0; j < dest_dx/2; j ++) {
  1199.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1200.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1201.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], u, _yytab[sy[j*2+1]], v);
  1202.                 }
  1203.                 sy += src_pitch;
  1204.                 su += src_pitch/2;
  1205.                 sv += src_pitch/2;
  1206.                 d  += dest_pitch;
  1207.                 dest_dy --;
  1208.             }
  1209.             /* the main loop (processes two lines a time): */
  1210.             for (i = 0; i < dest_dy/2; i ++) {
  1211.                 for (j = 0; j < dest_dx/2; j ++) {
  1212.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1213.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1214.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], u, _yytab[sy[j*2+1]], v);
  1215.                     *(unsigned int *)(d + j*4 + dest_pitch) = COMBINE(_yytab[sy[j*2 + src_pitch]], u, _yytab[sy[j*2+1+src_pitch]], v);
  1216.                 }
  1217.                 sy += src_pitch*2;
  1218.                 su += src_pitch/2;
  1219.                 sv += src_pitch/2;
  1220.                 d  += dest_pitch*2;
  1221.             }
  1222.             /* process the last line (if dy is odd): */
  1223.             if (dest_dy & 1) {
  1224.                 for (j = 0; j < dest_dx/2; j ++) {
  1225.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1226.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1227.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], u, _yytab[sy[j*2+1]], v);
  1228.                 }
  1229.             }
  1230.         }
  1231.         return 0;
  1232.     }
  1233.     /* conversion is not supported */
  1234.     return -1;
  1235. #endif //0
  1236. }
  1237. int I420toUYVYx (unsigned char *dest_ptr, int dest_width, int dest_height,
  1238.                  int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1239.                  unsigned char *pY, unsigned char *pU, unsigned char *pV,
  1240.                  int src_width, int src_height, int yPitch, int uPitch, int vPitch,
  1241.                  int src_x, int src_y, int src_dx, int src_dy)
  1242. {
  1243.     /* scale factors: */
  1244.     int scale_x, scale_y;
  1245.     /* check arguments: */
  1246.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  1247.         dest_x, dest_y, dest_dx, dest_dy, pY, src_width, src_height,
  1248.         yPitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  1249.         return -1;
  1250.     /* remove odd destination columns: */
  1251.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x))
  1252.         return 0;
  1253.     /* check if we have misaligned input: */
  1254.     if (src_x & 1)
  1255.         return -1;                          /* can't shift chromas */
  1256.     /* check if bottop-up images: */
  1257.     if (dest_pitch < 0) dest_ptr -= (dest_height-1) * dest_pitch;
  1258.     if (yPitch <= 0 ||
  1259.         uPitch <= 0 ||
  1260.         vPitch <= 0)
  1261.         return -1;          /* not supported */
  1262.     /* check if 1:1 scale: */
  1263.     if (scale_x == 1 && scale_y == 1) {
  1264.         /* check if no color adjustments: */
  1265.         if (!(is_alpha | is_beta | is_gamma | is_kappa)) {
  1266.             /* no color adjustments: */
  1267.             unsigned char *sy, *sv, *su, *d;
  1268.             register int i, j;
  1269.             /* get pointers: */
  1270.             sy = pY + src_x + src_y * yPitch;           /* luma offset */
  1271.             su = pU + (src_x/2 + src_y/2 * uPitch);
  1272.             sv = pV + (src_x/2 + src_y/2 * vPitch);
  1273.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  1274. #if (defined(_M_IX86) || defined(_USE_MMX_BLENDERS)) && !defined(WINCE_EMULATOR)
  1275.             /* check if we can use MMX-optimized code here: */
  1276.             if (_x86_MMX_Available)
  1277.             {
  1278.                 /* process top line (if chroma is not pairable): */
  1279.                 if (dest_y & 1) {
  1280.                     _MMX_lineI420toUYVY (sy, su, sv, d, dest_dx);
  1281.                     sy += yPitch;
  1282.                     su += uPitch;
  1283.                     sv += vPitch;
  1284.                     d  += dest_pitch;
  1285.                     dest_dy --;
  1286.                 }
  1287.                 /* the main loop (processes two lines a time): */
  1288.                 for (i = 0; i < dest_dy/2; i ++) {
  1289.                     _MMX_lineI420toUYVY (sy, su, sv, d, dest_dx);
  1290.                     sy += yPitch;
  1291.                     d  += dest_pitch;
  1292.                     _MMX_lineI420toUYVY (sy, su, sv, d, dest_dx);
  1293.                     sy += yPitch;
  1294.                     su += uPitch;
  1295.                     sv += vPitch;
  1296.                     d  += dest_pitch;
  1297.                 }
  1298.                 /* process the last line (if dy is odd): */
  1299.                 if (dest_dy & 1) {
  1300.                     _MMX_lineI420toUYVY (sy, su, sv, d, dest_dx);
  1301.                 }
  1302.                 /* end of MMX code */
  1303. #if defined(_M_IX86) && !defined(WINCE_EMULATOR)                
  1304.                 __asm emms
  1305. #elif defined(_USE_MMX_BLENDERS) && !defined(WINCE_EMULATOR)
  1306.                 __asm__ __volatile__ ( "emms" );
  1307. #endif                    
  1308.             } else
  1309. #endif
  1310.             /* a generic "C" version: */
  1311.             {
  1312.                 /* process top line (if chroma is not pairable): */
  1313.                 if (dest_y & 1) {
  1314.                     for (j = 0; j < dest_dx/2; j ++)
  1315.                         *(unsigned int *)(d + j*4) = su[j] | (sy[j*2] << 8) | (sv[j] << 16) | (sy[j*2+1] << 24);
  1316.                     sy += yPitch;
  1317.                     su += uPitch;
  1318.                     sv += vPitch;
  1319.                     d  += dest_pitch;
  1320.                     dest_dy --;
  1321.                 }
  1322.                 /* the main loop (processes two lines a time): */
  1323.                 for (i = 0; i < dest_dy/2; i ++) {
  1324.                     for (j = 0; j < dest_dx/2; j ++)
  1325.                         *(unsigned int *)(d + j*4) = su[j] | (sy[j*2] << 8) | (sv[j] << 16) | (sy[j*2+1] << 24);
  1326.                     sy += yPitch;
  1327.                     d  += dest_pitch;
  1328.                     for (j = 0; j < dest_dx/2; j ++)
  1329.                         *(unsigned int *)(d + j*4) = su[j] | (sy[j*2] << 8) | (sv[j] << 16) | (sy[j*2+1] << 24);
  1330.                     sy += yPitch;
  1331.                     su += uPitch;
  1332.                     sv += vPitch;
  1333.                     d  += dest_pitch;
  1334.                 }
  1335.                 /* process the last line (if dy is odd): */
  1336.                 if (dest_dy & 1) {
  1337.                     for (j = 0; j < dest_dx/2; j ++)
  1338.                         *(unsigned int *)(d + j*4) = su[j] | (sy[j*2] << 8) | (sv[j] << 16) | (sy[j*2+1] << 24);
  1339.                 }
  1340.             }
  1341.         } else
  1342.         /* check if no hue adjustment: */
  1343.         if (!is_alpha) {
  1344.             /* no chroma rotation: */
  1345.             unsigned char *sy, *sv, *su, *d;
  1346.             register int i, j;
  1347.             /* get pointers: */
  1348.             sy = pY + src_x + src_y * yPitch;           /* luma offset */
  1349.             su = pU + (src_x/2 + src_y/2 * uPitch);
  1350.             sv = pV + (src_x/2 + src_y/2 * vPitch);
  1351.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  1352.             /* process top line (if chroma is not pairable): */
  1353.             if (dest_y & 1) {
  1354.                 for (j = 0; j < dest_dx/2; j ++)
  1355.                     *(unsigned int *)(d + j*4) = _uutab[su[j]] | (_yytab[sy[j*2]] << 8) | (_vvtab[sv[j]] << 16) | (_yytab[sy[j*2+1]] << 24);
  1356.                 sy += yPitch;
  1357.                 su += uPitch;
  1358.                 sv += vPitch;
  1359.                 d  += dest_pitch;
  1360.                 dest_dy --;
  1361.             }
  1362.             /* the main loop (processes two lines a time): */
  1363.             for (i = 0; i < dest_dy/2; i ++) {
  1364.                 for (j = 0; j < dest_dx/2; j ++)
  1365.                     *(unsigned int *)(d + j*4) = _uutab[su[j]] | (_yytab[sy[j*2]] << 8) | (_vvtab[sv[j]] << 16) | (_yytab[sy[j*2+1]] << 24);
  1366.                 sy += yPitch;
  1367.                 d  += dest_pitch;
  1368.                 for (j = 0; j < dest_dx/2; j ++)
  1369.                     *(unsigned int *)(d + j*4) = _uutab[su[j]] | (_yytab[sy[j*2]] << 8) | (_vvtab[sv[j]] << 16) | (_yytab[sy[j*2+1]] << 24);
  1370.                 sy += yPitch;
  1371.                 su += uPitch;
  1372.                 sv += vPitch;
  1373.                 d  += dest_pitch;
  1374.             }
  1375.             /* process the last line (if dy is odd): */
  1376.             if (dest_dy & 1) {
  1377.                 for (j = 0; j < dest_dx/2; j ++)
  1378.                     *(unsigned int *)(d + j*4) = _uutab[su[j]] | (_yytab[sy[j*2]] << 8) | (_vvtab[sv[j]] << 16) | (_yytab[sy[j*2+1]] << 24);
  1379.             }
  1380.         } else {
  1381.             /* the most complex case (w. hue adjustement): */
  1382.             unsigned char *sy, *sv, *su, *d;
  1383.             register int i, j, u, v;
  1384.             /* get pointers: */
  1385.             sy = pY + src_x + src_y * yPitch;           /* luma offset */
  1386.             su = pU + (src_x/2 + src_y/2 * uPitch);
  1387.             sv = pV + (src_x/2 + src_y/2 * vPitch);
  1388.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  1389.             /* process top line (if chroma is not pairable): */
  1390.             if (dest_y & 1) {
  1391.                 for (j = 0; j < dest_dx/2; j ++) {
  1392.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1393.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1394.                     *(unsigned int *)(d + j*4) = u | (_yytab[sy[j*2]] << 8) | (v << 16) | (_yytab[sy[j*2+1]] << 24);
  1395.                 }
  1396.                 sy += yPitch;
  1397.                 su += uPitch;
  1398.                 sv += vPitch;
  1399.                 d  += dest_pitch;
  1400.                 dest_dy --;
  1401.             }
  1402.             /* the main loop (processes two lines a time): */
  1403.             for (i = 0; i < dest_dy/2; i ++) {
  1404.                 for (j = 0; j < dest_dx/2; j ++) {
  1405.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1406.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1407.                     *(unsigned int *)(d + j*4) = u | (_yytab[sy[j*2]] << 8) | (v << 16) | (_yytab[sy[j*2+1]] << 24);
  1408.                     *(unsigned int *)(d + j*4 + dest_pitch) = u | (_yytab[sy[j*2 + yPitch]] << 8) | (v << 16) | (_yytab[sy[j*2+1 + yPitch]] << 24);
  1409.                 }
  1410.                 sy += yPitch*2;
  1411.                 su += uPitch;
  1412.                 sv += vPitch;
  1413.                 d  += dest_pitch*2;
  1414.             }
  1415.             /* process the last line (if dy is odd): */
  1416.             if (dest_dy & 1) {
  1417.                 for (j = 0; j < dest_dx/2; j ++) {
  1418.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1419.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1420.                     *(unsigned int *)(d + j*4) = u | (_yytab[sy[j*2]] << 8) | (v << 16) | (_yytab[sy[j*2+1]] << 24);
  1421.                 }
  1422.             }
  1423.         }
  1424.         return 0;
  1425.     }
  1426.     /* conversion is not supported */
  1427.     return -1;
  1428. }
  1429. /*
  1430.  * I420toUYVY() converter:
  1431.  */
  1432. int I420toUYVY (unsigned char *dest_ptr, int dest_width, int dest_height,
  1433.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1434.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  1435.     int src_x, int src_y, int src_dx, int src_dy)
  1436. {
  1437. #if 1
  1438.     unsigned char *pU = src_ptr+src_height*src_pitch,
  1439.                   *pV = pU + src_height*src_pitch/4;
  1440.     return I420toUYVYx(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  1441.                        src_ptr, pU, pV, 
  1442.                        src_width, src_height, src_pitch, src_pitch/2, src_pitch/2,
  1443.                        src_x, src_y, src_dx, src_dy);
  1444.                     
  1445. #else
  1446.     /* scale factors: */
  1447.     int scale_x, scale_y;
  1448.     /* check arguments: */
  1449.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  1450.         dest_x, dest_y, dest_dx, dest_dy, src_ptr, src_width, src_height,
  1451.         src_pitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  1452.         return -1;
  1453.     /* remove odd destination columns: */
  1454.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x))
  1455.         return 0;
  1456.     /* check if we have misaligned input: */
  1457.     if (src_x & 1)
  1458.         return -1;                          /* can't shift chromas */
  1459.     /* check if bottop-up images: */
  1460.     if (dest_pitch < 0) dest_ptr -= (dest_height-1) * dest_pitch;
  1461.     if (src_pitch <= 0) return -1;          /* not supported */
  1462.     /* check if 1:1 scale: */
  1463.     if (scale_x == 1 && scale_y == 1) {
  1464.         /* check if no color adjustments: */
  1465.         if (!(is_alpha | is_beta | is_gamma | is_kappa)) {
  1466.             /* no color adjustments: */
  1467.             unsigned char *sy, *sv, *su, *d;
  1468.             register int i, j;
  1469.             /* get pointers: */
  1470.             sy = src_ptr + src_x + src_y * src_pitch;           /* luma offset */
  1471.             su = src_ptr + src_height * src_pitch + (src_x/2 + src_y/2 * src_pitch);
  1472.             sv = su + src_height * src_pitch / 4;
  1473.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  1474. #if (defined(_M_IX86) || defined(_USE_MMX_BLENDERS))  && !defined(WINCE_EMULATOR)
  1475.             /* check if we can use MMX-optimized code here: */
  1476.             if (_x86_MMX_Available)
  1477.             {
  1478.                 /* process top line (if chroma is not pairable): */
  1479.                 if (dest_y & 1) {
  1480.                     _MMX_lineI420toUYVY (sy, su, sv, d, dest_dx);
  1481.                     sy += src_pitch;
  1482.                     su += src_pitch/2;
  1483.                     sv += src_pitch/2;
  1484.                     d  += dest_pitch;
  1485.                     dest_dy --;
  1486.                 }
  1487.                 /* the main loop (processes two lines a time): */
  1488.                 for (i = 0; i < dest_dy/2; i ++) {
  1489.                     _MMX_lineI420toUYVY (sy, su, sv, d, dest_dx);
  1490.                     sy += src_pitch;
  1491.                     d  += dest_pitch;
  1492.                     _MMX_lineI420toUYVY (sy, su, sv, d, dest_dx);
  1493.                     sy += src_pitch;
  1494.                     su += src_pitch/2;
  1495.                     sv += src_pitch/2;
  1496.                     d  += dest_pitch;
  1497.                 }
  1498.                 /* process the last line (if dy is odd): */
  1499.                 if (dest_dy & 1) {
  1500.                     _MMX_lineI420toUYVY (sy, su, sv, d, dest_dx);
  1501.                 }
  1502.                 /* end of MMX code */
  1503. #if defined(_M_IX86) && !defined(WINCE_EMULATOR)                
  1504.                 __asm emms
  1505. #elif defined(_USE_MMX_BLENDERS) && !defined(WINCE_EMULATOR)
  1506.                 __asm__ __volatile__ ( "emms" );
  1507. #endif                    
  1508.             } else
  1509. #endif
  1510.             /* a generic "C" version: */
  1511.             {
  1512.                 /* process top line (if chroma is not pairable): */
  1513.                 if (dest_y & 1) {
  1514.                     for (j = 0; j < dest_dx/2; j ++)
  1515.                         *(unsigned int *)(d + j*4) = su[j] | (sy[j*2] << 8) | (sv[j] << 16) | (sy[j*2+1] << 24);
  1516.                     sy += src_pitch;
  1517.                     su += src_pitch/2;
  1518.                     sv += src_pitch/2;
  1519.                     d  += dest_pitch;
  1520.                     dest_dy --;
  1521.                 }
  1522.                 /* the main loop (processes two lines a time): */
  1523.                 for (i = 0; i < dest_dy/2; i ++) {
  1524.                     for (j = 0; j < dest_dx/2; j ++)
  1525.                         *(unsigned int *)(d + j*4) = su[j] | (sy[j*2] << 8) | (sv[j] << 16) | (sy[j*2+1] << 24);
  1526.                     sy += src_pitch;
  1527.                     d  += dest_pitch;
  1528.                     for (j = 0; j < dest_dx/2; j ++)
  1529.                         *(unsigned int *)(d + j*4) = su[j] | (sy[j*2] << 8) | (sv[j] << 16) | (sy[j*2+1] << 24);
  1530.                     sy += src_pitch;
  1531.                     su += src_pitch/2;
  1532.                     sv += src_pitch/2;
  1533.                     d  += dest_pitch;
  1534.                 }
  1535.                 /* process the last line (if dy is odd): */
  1536.                 if (dest_dy & 1) {
  1537.                     for (j = 0; j < dest_dx/2; j ++)
  1538.                         *(unsigned int *)(d + j*4) = su[j] | (sy[j*2] << 8) | (sv[j] << 16) | (sy[j*2+1] << 24);
  1539.                 }
  1540.             }
  1541.         } else
  1542.         /* check if no hue adjustment: */
  1543.         if (!is_alpha) {
  1544.             /* no chroma rotation: */
  1545.             unsigned char *sy, *sv, *su, *d;
  1546.             register int i, j;
  1547.             /* get pointers: */
  1548.             sy = src_ptr + src_x + src_y * src_pitch;           /* luma offset */
  1549.             su = src_ptr + src_height * src_pitch + (src_x/2 + src_y/2 * src_pitch);
  1550.             sv = su + src_height * src_pitch / 4;
  1551.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  1552.             /* process top line (if chroma is not pairable): */
  1553.             if (dest_y & 1) {
  1554.                 for (j = 0; j < dest_dx/2; j ++)
  1555.                     *(unsigned int *)(d + j*4) = _uutab[su[j]] | (_yytab[sy[j*2]] << 8) | (_vvtab[sv[j]] << 16) | (_yytab[sy[j*2+1]] << 24);
  1556.                 sy += src_pitch;
  1557.                 su += src_pitch/2;
  1558.                 sv += src_pitch/2;
  1559.                 d  += dest_pitch;
  1560.                 dest_dy --;
  1561.             }
  1562.             /* the main loop (processes two lines a time): */
  1563.             for (i = 0; i < dest_dy/2; i ++) {
  1564.                 for (j = 0; j < dest_dx/2; j ++)
  1565.                     *(unsigned int *)(d + j*4) = _uutab[su[j]] | (_yytab[sy[j*2]] << 8) | (_vvtab[sv[j]] << 16) | (_yytab[sy[j*2+1]] << 24);
  1566.                 sy += src_pitch;
  1567.                 d  += dest_pitch;
  1568.                 for (j = 0; j < dest_dx/2; j ++)
  1569.                     *(unsigned int *)(d + j*4) = _uutab[su[j]] | (_yytab[sy[j*2]] << 8) | (_vvtab[sv[j]] << 16) | (_yytab[sy[j*2+1]] << 24);
  1570.                 sy += src_pitch;
  1571.                 su += src_pitch/2;
  1572.                 sv += src_pitch/2;
  1573.                 d  += dest_pitch;
  1574.             }
  1575.             /* process the last line (if dy is odd): */
  1576.             if (dest_dy & 1) {
  1577.                 for (j = 0; j < dest_dx/2; j ++)
  1578.                     *(unsigned int *)(d + j*4) = _uutab[su[j]] | (_yytab[sy[j*2]] << 8) | (_vvtab[sv[j]] << 16) | (_yytab[sy[j*2+1]] << 24);
  1579.             }
  1580.         } else {
  1581.             /* the most complex case (w. hue adjustement): */
  1582.             unsigned char *sy, *sv, *su, *d;
  1583.             register int i, j, u, v;
  1584.             /* get pointers: */
  1585.             sy = src_ptr + src_x + src_y * src_pitch;           /* luma offset */
  1586.             su = src_ptr + src_height * src_pitch + (src_x/2 + src_y/2 * src_pitch/2);
  1587.             sv = su + src_height * src_pitch / 4;
  1588.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  1589.             /* process top line (if chroma is not pairable): */
  1590.             if (dest_y & 1) {
  1591.                 for (j = 0; j < dest_dx/2; j ++) {
  1592.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1593.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1594.                     *(unsigned int *)(d + j*4) = u | (_yytab[sy[j*2]] << 8) | (v << 16) | (_yytab[sy[j*2+1]] << 24);
  1595.                 }
  1596.                 sy += src_pitch;
  1597.                 su += src_pitch/2;
  1598.                 sv += src_pitch/2;
  1599.                 d  += dest_pitch;
  1600.                 dest_dy --;
  1601.             }
  1602.             /* the main loop (processes two lines a time): */
  1603.             for (i = 0; i < dest_dy/2; i ++) {
  1604.                 for (j = 0; j < dest_dx/2; j ++) {
  1605.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1606.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1607.                     *(unsigned int *)(d + j*4) = u | (_yytab[sy[j*2]] << 8) | (v << 16) | (_yytab[sy[j*2+1]] << 24);
  1608.                     *(unsigned int *)(d + j*4 + dest_pitch) = u | (_yytab[sy[j*2 + src_pitch]] << 8) | (v << 16) | (_yytab[sy[j*2+1 + src_pitch]] << 24);
  1609.                 }
  1610.                 sy += src_pitch*2;
  1611.                 su += src_pitch/2;
  1612.                 sv += src_pitch/2;
  1613.                 d  += dest_pitch*2;
  1614.             }
  1615.             /* process the last line (if dy is odd): */
  1616.             if (dest_dy & 1) {
  1617.                 for (j = 0; j < dest_dx/2; j ++) {
  1618.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1619.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1620.                     *(unsigned int *)(d + j*4) = u | (_yytab[sy[j*2]] << 8) | (v << 16) | (_yytab[sy[j*2+1]] << 24);
  1621.                 }
  1622.             }
  1623.         }
  1624.         return 0;
  1625.     }
  1626.     /* conversion is not supported */
  1627.     return -1;
  1628. #endif //0
  1629. }
  1630. /*** "to I420" converters: *********************************/
  1631. int YV12toI420x (unsigned char *dest_ptr, int dest_width, int dest_height,
  1632.                  int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1633.                  unsigned char *pY, unsigned char *pU, unsigned char *pV,
  1634.                  int src_width, int src_height, int yPitch, int uPitch, int vPitch,
  1635.                  int src_x, int src_y, int src_dx, int src_dy)
  1636. {
  1637.     /* scale factors: */
  1638.     int scale_x, scale_y;
  1639. /* Chroma Shifting Allowed */
  1640. int OddPattern;
  1641.     /* check arguments: */
  1642.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  1643.         dest_x, dest_y, dest_dx, dest_dy, pY, src_width, src_height,
  1644.         yPitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  1645.         return -1;
  1646.     /* remove odd destination pixels: */
  1647.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x) ||
  1648.         !adjust_range (&dest_y, &dest_dy, &src_y, &src_dy, scale_y))
  1649.         return 0;
  1650.     /* check if we have matching chroma components: */
  1651.     //if ((src_x & 1) || (src_y & 1))
  1652.     //    return -1;                          /* can't shift chromas */
  1653.     /* check if bottop-up images: */
  1654.     if (dest_pitch <= 0 || yPitch <= 0)
  1655.         return -1;                          /* not supported */
  1656. /*
  1657.  *  if (!is_dest_alpha && !is_dest_beta && !is_dest_gamma && !is_dest_kappa)
  1658.  */
  1659.     {
  1660.         /* just move data in, no color adjustments: */
  1661.         unsigned char *sy, *su, *sv, *d, *su2, *sv2;
  1662.         int dest_uv_offs;
  1663.         register int i,j;
  1664.         /* copy Y plane: */
  1665.         sy = pY + src_x + src_y * yPitch;
  1666.         d = dest_ptr + dest_x + dest_y * dest_pitch;
  1667.         for (i = 0; i < dest_dy; i ++) {
  1668.             memcpy (d, sy, dest_dx); /* Flawfinder: ignore */
  1669.             sy += yPitch;
  1670.             d += dest_pitch;
  1671.         }
  1672.         /* get Cr/Cb offsets: */
  1673.         dest_uv_offs = dest_height * dest_pitch / 4;
  1674.         /* copy & flip Cr/Cb planes: */
  1675.         su = pU + src_x/2 + src_y/2 * uPitch;
  1676.         sv = pV + src_x/2 + src_y/2 * vPitch;
  1677.         d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  1678. OddPattern = ((src_y & 1) << 1) | (src_x & 1);
  1679. // extremely cheap way to handle 1 pel cropping
  1680.         for (i = 0; i < dest_dy/2; i ++) {
  1681. if((i+1) < dest_dy/2) {
  1682. su2 = su+uPitch;
  1683. sv2 = sv+vPitch;
  1684. } else {
  1685. su2 = su;
  1686. sv2 = sv;
  1687. }
  1688. /* convert pixels: */
  1689. switch(OddPattern)
  1690. {
  1691. case(0):
  1692. memcpy (d, su, dest_dx/2); /* Flawfinder: ignore */
  1693. memcpy (d + dest_uv_offs, sv, dest_dx/2); /* Flawfinder: ignore */
  1694. break;
  1695. case(1):
  1696. for (j = 0; j < dest_dx/2 -1; j ++) {
  1697. d[j] = ((unsigned int)su[j] + (unsigned int)su[j+1] + 1)>>1;
  1698. d[j + dest_uv_offs] = ((unsigned int)sv[j] + (unsigned int)sv[j+1] + 1)>>1;
  1699. }
  1700. d[j] = su[j];
  1701. d[j + dest_uv_offs] = sv[j];
  1702. break;
  1703. case(2):
  1704. for (j = 0; j < dest_dx/2; j ++) {
  1705. d[j] = ((unsigned int)su[j] + (unsigned int)su2[j] + 1)>>1;
  1706. d[j + dest_uv_offs] = ((unsigned int)sv[j] + (unsigned int)sv2[j] + 1)>>1;
  1707. }
  1708. break;
  1709. case(3):
  1710. for (j = 0; j < dest_dx/2 -1; j ++) {
  1711. d[j] = ((unsigned int)su[j] + (unsigned int)su[j+1] + (unsigned int)su2[j] + (unsigned int)su2[j+1] + 2)>>2;
  1712. d[j + dest_uv_offs] = ((unsigned int)sv[j] + (unsigned int)sv[j+1] + (unsigned int)sv2[j] + (unsigned int)sv2[j+1] + 2)>>2;
  1713. }
  1714. d[j] = ((unsigned int)su[j]+ (unsigned int)su2[j] + 1)>>1;
  1715. d[j + dest_uv_offs] = ((unsigned int)sv[j] + (unsigned int)sv2[j] + 1) >> 1;
  1716. break;
  1717. }
  1718. su += uPitch;
  1719. sv += vPitch;
  1720.             d += dest_pitch/2;
  1721.         }
  1722.     }
  1723. /*
  1724.  *  else {
  1725.  *      put all the color-dependent stuff here ...
  1726.  *  }
  1727.  */
  1728.     return 0;
  1729. }
  1730. int YV12toI420 (unsigned char *dest_ptr, int dest_width, int dest_height,
  1731.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1732.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  1733.     int src_x, int src_y, int src_dx, int src_dy)
  1734. {
  1735. #if 1
  1736.     unsigned char *pV = src_ptr+src_height*src_pitch,
  1737.                   *pU = pV + src_height*src_pitch/4;
  1738.     return YV12toI420x(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  1739.                        src_ptr, pU, pV, 
  1740.                        src_width, src_height, src_pitch, src_pitch/2, src_pitch/2,
  1741.                        src_x, src_y, src_dx, src_dy);
  1742. #else    
  1743.     /* scale factors: */
  1744.     int scale_x, scale_y;
  1745.     /* check arguments: */
  1746.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  1747.         dest_x, dest_y, dest_dx, dest_dy, src_ptr, src_width, src_height,
  1748.         src_pitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  1749.         return -1;
  1750.     /* remove odd destination pixels: */
  1751.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x) ||
  1752.         !adjust_range (&dest_y, &dest_dy, &src_y, &src_dy, scale_y))
  1753.         return 0;
  1754.     /* check if we have matching chroma components: */
  1755.     if ((src_x & 1) || (src_y & 1))
  1756.         return -1;                          /* can't shift chromas */
  1757.     /* check if bottop-up images: */
  1758.     if (dest_pitch <= 0 || src_pitch <= 0)
  1759.         return -1;                          /* not supported */
  1760. /*
  1761.  *  if (!is_dest_alpha && !is_dest_beta && !is_dest_gamma && !is_dest_kappa)
  1762.  */
  1763.     {
  1764.         /* just move data in, no color adjustments: */
  1765.         unsigned char *s, *d;
  1766.         int src_uv_offs, dest_uv_offs;
  1767.         register int i;
  1768.         /* copy Y plane: */
  1769.         s = src_ptr + src_x + src_y * src_pitch;
  1770.         d = dest_ptr + dest_x + dest_y * dest_pitch;
  1771.         for (i = 0; i < dest_dy; i ++) {
  1772.             memcpy (d, s, dest_dx); /* Flawfinder: ignore */
  1773.             s += src_pitch;
  1774.             d += dest_pitch;
  1775.         }
  1776.         /* get Cr/Cb offsets: */
  1777.         src_uv_offs = src_height * src_pitch / 4;
  1778.         dest_uv_offs = dest_height * dest_pitch / 4;
  1779.         /* copy & flip Cr/Cb planes: */
  1780.         s = (src_ptr + src_height * src_pitch) + src_x/2 + src_y/2 * src_pitch/2;
  1781.         d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  1782.         for (i = 0; i < dest_dy/2; i ++) {
  1783.             memcpy (d, s + src_uv_offs, dest_dx/2); /* Flawfinder: ignore */
  1784.             memcpy (d + dest_uv_offs, s, dest_dx/2); /* Flawfinder: ignore */
  1785.             s += src_pitch/2;
  1786.             d += dest_pitch/2;
  1787.         }
  1788.     }
  1789. /*
  1790.  *  else {
  1791.  *      put all the color-dependent stuff here ...
  1792.  *  }
  1793.  */
  1794.     return 0;
  1795. #endif
  1796. }
  1797. int YV12toYV12x (unsigned char *dest_ptr, int dest_width, int dest_height,
  1798.                  int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1799.                  unsigned char *pY, unsigned char *pU, unsigned char *pV,
  1800.                  int src_width, int src_height, int yPitch, int uPitch, int vPitch,
  1801.                  int src_x, int src_y, int src_dx, int src_dy)
  1802. {
  1803.     return I420toYV12x(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  1804.                        pY, pU, pV, 
  1805.                        src_width, src_height, yPitch, uPitch, vPitch,
  1806.                        src_x, src_y, src_dx, src_dy);
  1807. }
  1808. int YV12toYV12 (unsigned char *dest_ptr, int dest_width, int dest_height,
  1809.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1810.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  1811.     int src_x, int src_y, int src_dx, int src_dy)
  1812. {
  1813.     unsigned char *pV = src_ptr+src_height*src_pitch,
  1814.                   *pU = pV + src_height*src_pitch/4;
  1815.     return I420toYV12x(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  1816.                        src_ptr, pU, pV, 
  1817.                        src_width, src_height, src_pitch, src_pitch/2, src_pitch/2,
  1818.                        src_x, src_y, src_dx, src_dy);
  1819. }
  1820. int YV12toYUY2x (unsigned char *dest_ptr, int dest_width, int dest_height,
  1821.                  int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1822.                  unsigned char *pY, unsigned char *pU, unsigned char *pV,
  1823.                  int src_width, int src_height, int yPitch, int uPitch, int vPitch,
  1824.                  int src_x, int src_y, int src_dx, int src_dy)
  1825. {
  1826.     return I420toYUY2x(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  1827.                        pY, pU, pV, 
  1828.                        src_width, src_height, yPitch, uPitch, vPitch,
  1829.                        src_x, src_y, src_dx, src_dy);
  1830. }
  1831. int YV12toYUY2 (unsigned char *dest_ptr, int dest_width, int dest_height,
  1832.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1833.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  1834.     int src_x, int src_y, int src_dx, int src_dy)
  1835. {
  1836.     unsigned char *pV = src_ptr+src_height*src_pitch,
  1837.                   *pU = pV + src_height*src_pitch/4;
  1838.     return I420toYUY2x(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  1839.                        src_ptr, pU, pV, 
  1840.                        src_width, src_height, src_pitch, src_pitch/2, src_pitch/2,
  1841.                        src_x, src_y, src_dx, src_dy);
  1842. }
  1843. int YV12toUYVYx (unsigned char *dest_ptr, int dest_width, int dest_height,
  1844.                  int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1845.                  unsigned char *pY, unsigned char *pU, unsigned char *pV,
  1846.                  int src_width, int src_height, int yPitch, int uPitch, int vPitch,
  1847.                  int src_x, int src_y, int src_dx, int src_dy)
  1848. {
  1849.     return I420toUYVYx(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  1850.                        pY, pU, pV, 
  1851.                        src_width, src_height, yPitch, uPitch, vPitch,
  1852.                        src_x, src_y, src_dx, src_dy);
  1853. }
  1854. int YV12toUYVY (unsigned char *dest_ptr, int dest_width, int dest_height,
  1855.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1856.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  1857.     int src_x, int src_y, int src_dx, int src_dy)
  1858. {
  1859.     unsigned char *pV = src_ptr+src_height*src_pitch,
  1860.                   *pU = pV + src_height*src_pitch/4;
  1861.     return I420toUYVYx(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  1862.                        src_ptr, pU, pV, 
  1863.                        src_width, src_height, src_pitch, src_pitch/2, src_pitch/2,
  1864.                        src_x, src_y, src_dx, src_dy);
  1865. }
  1866. static void lineYVU9toI420 (unsigned char *d, unsigned char *s, int x, int dx)
  1867. {
  1868.     register int i;
  1869.     /* first pixel: */
  1870. // extremely cheap way to handle 1 pel cropping
  1871.     switch(x&3)
  1872. {
  1873. case(0):
  1874. case(1):
  1875. break;    
  1876. case(2):
  1877.         d[0] = s[0];
  1878.         s += 1;
  1879.         d += 1;
  1880.         dx -= 2;
  1881. break;
  1882. case(3):
  1883. //d[0] = s[0];
  1884. s += 1;
  1885. //d += 1;
  1886.         //dx -= 2;
  1887. break;
  1888. }    
  1889.     /* the main loop: */
  1890.     for (i = 0; i < dx/4; i ++) {
  1891.         d[i*2] = s[i];
  1892.         d[i*2+1] = s[i];
  1893.     }
  1894.     /* last pixel: */
  1895.     if (dx & 2)
  1896.         d[dx/2] = s[dx/4];
  1897. }
  1898. #if 1
  1899. /*-----------------2/24/2002 2:01PM-----------------
  1900.  * fixes:
  1901.  *  - switched u and v pointers
  1902.  * --------------------------------------------------*/
  1903. int YVU9toI420 (unsigned char *dest_ptr, int dest_width, int dest_height,
  1904.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1905.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  1906.     int src_x, int src_y, int src_dx, int src_dy)
  1907. {
  1908.     /* scale factors: */
  1909.     int scale_x, scale_y;
  1910.     /* check arguments: */
  1911.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  1912.         dest_x, dest_y, dest_dx, dest_dy, src_ptr, src_width, src_height,
  1913.         src_pitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  1914.         return -1;
  1915.     /* remove odd destination pixels: */
  1916.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x) ||
  1917.         !adjust_range (&dest_y, &dest_dy, &src_y, &src_dy, scale_y))
  1918.         return 0;
  1919.     /* check if we have matching chroma components: */
  1920.     //if ((src_x & 1) || (src_y & 1))
  1921.     //return -1;                          /* can't shift chromas */
  1922.     /* check if bottop-up images: */
  1923.     if (dest_pitch <= 0 || src_pitch <= 0)
  1924.         return -1;                          /* not supported */
  1925. /*
  1926.  *  if (!is_dest_alpha && !is_dest_beta && !is_dest_gamma && !is_dest_kappa)
  1927.  */
  1928.     {
  1929.         /* no color adjustments: */
  1930.         unsigned char *s, *d;
  1931.         int src_uv_offs, dest_uv_offs;
  1932.         register int j;
  1933.         /* copy Y plane: */
  1934.         s = src_ptr + src_x + src_y * src_pitch;
  1935.         d = dest_ptr + dest_x + dest_y * dest_pitch;
  1936.         for (j = 0; j < dest_dy; j ++) {
  1937.             memcpy (d, s, dest_dx); /* Flawfinder: ignore */
  1938.             s += src_pitch;
  1939.             d += dest_pitch;
  1940.         }
  1941.         /* get Cr/Cb offsets: */
  1942.         src_uv_offs = src_height * src_pitch / 16;
  1943.         dest_uv_offs = dest_height * dest_pitch / 4;
  1944.         /* get pointers: */
  1945.         s = (src_ptr + src_height * src_pitch) + src_x/4 + src_y/4 * src_pitch/4;
  1946.         d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  1947.         /* top lines: */
  1948. // extremely cheap way to handle 1 pel cropping
  1949.         switch(src_y & 3) 
  1950. {
  1951. case(2):
  1952. case(3):
  1953.             lineYVU9toI420 (d, s + src_uv_offs, src_x, dest_dx);   /* Cr */
  1954.             lineYVU9toI420 (d + dest_uv_offs, s, src_x, dest_dx);  /* Cb */
  1955.             s += src_pitch/4;
  1956.             d += dest_pitch/2;
  1957.             dest_dy -= 2;
  1958. break;
  1959. case(0):
  1960. case(1):
  1961. break;
  1962.         }
  1963.         /* the main loop (processes two lines a time): */
  1964.         for (j = 0; j < dest_dy/4; j ++) {
  1965.             lineYVU9toI420 (d, s + src_uv_offs, src_x, dest_dx);   /* Cr */
  1966.             memcpy (d + dest_pitch/2, d, dest_dx/2); /* Flawfinder: ignore */
  1967.             lineYVU9toI420 (d + dest_uv_offs, s, src_x, dest_dx);  /* Cb */
  1968.             memcpy (d + dest_pitch/2 + dest_uv_offs, d + dest_uv_offs, dest_dx/2); /* Flawfinder: ignore */
  1969.             s += src_pitch/4;
  1970.             d += dest_pitch;
  1971.         }
  1972.         /* bottom lines: */
  1973.         if (dest_dy & 2) {
  1974.             lineYVU9toI420 (d, s + src_uv_offs, src_x, dest_dx);   /* Cr */
  1975.             lineYVU9toI420 (d + dest_uv_offs, s, src_x, dest_dx);  /* Cb */
  1976.         }
  1977.     }
  1978. /*
  1979.  *  else {
  1980.  *      put all the color-dependent stuff here ...
  1981.  *  }
  1982.  */
  1983.     return 0;
  1984. }
  1985. #else
  1986. int YVU9toI420 (unsigned char *dest_ptr, int dest_width, int dest_height,
  1987.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1988.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  1989.     int src_x, int src_y, int src_dx, int src_dy)
  1990. {
  1991.     /* scale factors: */
  1992.     int scale_x, scale_y;
  1993.     /* check arguments: */
  1994.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  1995.         dest_x, dest_y, dest_dx, dest_dy, src_ptr, src_width, src_height,
  1996.         src_pitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  1997.         return -1;
  1998.     /* remove odd destination pixels: */
  1999.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x) ||
  2000.         !adjust_range (&dest_y, &dest_dy, &src_y, &src_dy, scale_y))
  2001.         return 0;
  2002.     /* check if we have matching chroma components: */
  2003.     if ((src_x & 1) || (src_y & 1))
  2004.         return -1;                          /* can't shift chromas */
  2005.     /* check if bottop-up images: */
  2006.     if (dest_pitch <= 0 || src_pitch <= 0)
  2007.         return -1;                          /* not supported */
  2008. /*
  2009.  *  if (!is_dest_alpha && !is_dest_beta && !is_dest_gamma && !is_dest_kappa)
  2010.  */
  2011.     {
  2012.         /* no color adjustments: */
  2013.         unsigned char *s, *d;
  2014.         int src_uv_offs, dest_uv_offs;
  2015.         register int j;
  2016.         /* copy Y plane: */
  2017.         s = src_ptr + src_x + src_y * src_pitch;
  2018.         d = dest_ptr + dest_x + dest_y * dest_pitch;
  2019.         for (j = 0; j < dest_dy; j ++) {
  2020.             memcpy (d, s, dest_dx); /* Flawfinder: ignore */
  2021.             s += src_pitch;
  2022.             d += dest_pitch;
  2023.         }
  2024.         /* get Cr/Cb offsets: */
  2025.         src_uv_offs = src_height * src_pitch / 16;
  2026.         dest_uv_offs = dest_height * dest_pitch / 4;
  2027.         /* get pointers: */
  2028.         s = (src_ptr + src_height * src_pitch) + src_x/4 + src_y/4 * src_pitch/4;
  2029.         d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  2030.         /* top lines: */
  2031.         if (src_y & 2) {
  2032.             lineYVU9toI420 (d, s, src_x, dest_dx);   /* Cr */
  2033.             lineYVU9toI420 (d + dest_uv_offs, s + src_uv_offs, src_x, dest_dx);  /* Cb */
  2034.             s += src_pitch/4;
  2035.             d += dest_pitch/2;
  2036.             dest_dy -= 2;
  2037.         }
  2038.         /* the main loop (processes two lines a time): */
  2039.         for (j = 0; j < dest_dy/4; j ++) {
  2040.             lineYVU9toI420 (d, s, src_x, dest_dx);   /* Cr */
  2041.             memcpy (d + dest_pitch/2, d, dest_dx/2); /* Flawfinder: ignore */
  2042.             lineYVU9toI420 (d + dest_uv_offs, s + src_uv_offs, src_x, dest_dx);  /* Cb */
  2043.             memcpy (d + dest_pitch/2 + dest_uv_offs, d + dest_uv_offs, dest_dx/2); /* Flawfinder: ignore */
  2044.             s += src_pitch/4;
  2045.             d += dest_pitch;
  2046.         }
  2047.         /* bottom lines: */
  2048.         if (dest_dy & 2) {
  2049.             lineYVU9toI420 (d, s, src_x, dest_dx);   /* Cr */
  2050.             lineYVU9toI420 (d + dest_uv_offs, s + src_uv_offs, src_x, dest_dx);  /* Cb */
  2051.         }
  2052.     }
  2053. /*
  2054.  *  else {
  2055.  *      put all the color-dependent stuff here ...
  2056.  *  }
  2057.  */
  2058.     return 0;
  2059. }
  2060. #endif /* YUV9 */
  2061. static int YUY2toPlanarYUV(unsigned char *dY, unsigned char *dU, unsigned char *dV,
  2062.                            int dest_width, int dest_height,
  2063.                            int dyPitch, int duPitch, int dvPitch,
  2064.                            int dest_x, int dest_y, int dest_dx, int dest_dy,
  2065.                            unsigned char *src_ptr,
  2066.                            int src_width, int src_height, int src_pitch,
  2067.                            int src_x, int src_y, int src_dx, int src_dy)
  2068. {
  2069.     /* scale factors: */
  2070.     int scale_x, scale_y;
  2071.     unsigned char *s1, *s2, *d1, *d2, *dv, *du;
  2072.     register int i, j;
  2073.     /* check arguments: */
  2074.     if (!chk_args (dY, dest_width, dest_height, dyPitch,
  2075.         dest_x, dest_y, dest_dx, dest_dy, src_ptr, src_width, src_height,
  2076.         src_pitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  2077.         return -1;
  2078.     /* remove odd destination pixels: */
  2079.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x) ||
  2080.         !adjust_range (&dest_y, &dest_dy, &src_y, &src_dy, scale_y))
  2081.         return 0;
  2082.     /* check if we have misaligned source: */
  2083.     if (src_x & 1)
  2084.         return -1; /* can't shift chromas */
  2085.     /* check if bottop-up images: */
  2086.     if (dyPitch <= 0)
  2087.         return -1;     /* not supported */
  2088.     if (src_pitch < 0)
  2089.         src_ptr -= (src_height-1) * src_pitch;
  2090.     /* just move data in, no color adjustments: */
  2091.     /* get pointers: */
  2092.     s1 = src_ptr + src_x * 2 + src_y * src_pitch;    /* 2 bytes/pixel */
  2093.     s2 = s1 + src_pitch;
  2094.     d1 = dY + dest_x + dest_y * dyPitch;   /* luma offsets  */
  2095.     d2 = d1 + dyPitch;
  2096.     
  2097.     du = dU + (dest_x/2 + dest_y/2 * duPitch);
  2098.     dv = dV + (dest_x/2 + dest_y/2 * dvPitch);
  2099. #if (defined(_M_IX86) || defined(_USE_MMX_BLENDERS)) && !defined(WINCE_EMULATOR)
  2100.     if (_x86_MMX_Available )
  2101.     {
  2102.         //Use our MMX versions.....
  2103.         HX_ASSERT( src_dx==dest_dx && src_dy==dest_dy );
  2104.         YUY2ToPlanarYUV_MMX( d1, d2, du, dv,
  2105.                              dyPitch, duPitch, dvPitch,
  2106.                              dest_dx, dest_dy, 
  2107.                              s1, s2, src_pitch
  2108.                              );
  2109.     }
  2110.     else
  2111. #endif    
  2112.     {
  2113.         /* the main loop (processes lines a time): */
  2114.         for (i = 0; i < dest_dy/2; i ++)
  2115.         {
  2116.             /* copy 2x2 pixels: */
  2117.             for (j = 0; j < dest_dx/2; j ++)
  2118.             {
  2119.                 /* copy luma components: */
  2120.                 d1[j*2]   = s1[j*4];
  2121.                 d1[j*2+1] = s1[j*4+2];
  2122.                 d2[j*2]   = s2[j*4];
  2123.                 d2[j*2+1] = s2[j*4+2];
  2124.                 
  2125.                 /* average chromas: */
  2126.                 du[j] = ((unsigned int) s1[j*4+1] + (unsigned int)s2[j*4+1]) >> 1;
  2127.                 dv[j] = ((unsigned int) s1[j*4+3] + (unsigned int)s2[j*4+3]) >> 1;
  2128.             }
  2129.             
  2130.             s1 += src_pitch*2;  s2 += src_pitch*2;
  2131.             d1 += dyPitch*2;    d2 += dyPitch*2;
  2132.             du += duPitch;      dv += dvPitch;
  2133.         }
  2134.     }
  2135.     return 0;
  2136. }
  2137. int YUY2toI420x (unsigned char *dest_ptr, int dest_width, int dest_height,
  2138.                  int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  2139.                  unsigned char *pY, unsigned char *pU, unsigned char *pV,
  2140.                  int src_width, int src_height, int yPitch, int uPitch, int vPitch,
  2141.                  int src_x, int src_y, int src_dx, int src_dy)
  2142. {
  2143.     // No need for seperate yuv pointers since yuy2 is packed
  2144.     return YUY2toI420(dest_ptr, dest_width, dest_height,
  2145.                       dest_pitch, dest_x, dest_y, dest_dx, dest_dy,  
  2146.                       pY, src_width, src_height, yPitch,
  2147.                       src_x, src_y, src_dx, src_dy);
  2148. }
  2149. /*
  2150.  * Mac YUVU/YVU2 formats: 
  2151.  * 8-bit 4:2:2 Component Y扖bCr format. 
  2152.  * Each 16 bit pixel is represented by an unsigned eight bit luminance 
  2153.  * component and two two抯 complement signed eight bit chroma components. 
  2154.  * Each pair of pixels shares a common set of chroma values. 
  2155.  * The components are ordered in memory; Y0, Cb, Y1, Cr. 
  2156.  * The luminance components have a range of [0, 255], 
  2157.  * the chroma values have a range of [-127, +127]. 
  2158.  * This format is equivalent to the 憏uv2