Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (C) 2007 Marc Hoffman <marc.hoffman@analog.com>
  3.  *                    April 20, 2007
  4.  *
  5.  * Blackfin video color space converter operations
  6.  * convert I420 YV12 to RGB in various formats
  7.  *
  8.  * This file is part of FFmpeg.
  9.  *
  10.  * FFmpeg is free software; you can redistribute it and/or
  11.  * modify it under the terms of the GNU Lesser General Public
  12.  * License as published by the Free Software Foundation; either
  13.  * version 2.1 of the License, or (at your option) any later version.
  14.  *
  15.  * FFmpeg is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18.  * Lesser General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU Lesser General Public
  21.  * License along with FFmpeg; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23.  */
  24.  
  25.  
  26. /*
  27. YUV420 to RGB565 conversion. This routine takes a YUV 420 planar macroblock
  28. and converts it to RGB565. R:5 bits, G:6 bits, B:5 bits.. packed into shorts.
  29.  
  30.  
  31. The following calculation is used for the conversion:
  32.  
  33.   r = clipz((y - oy) * cy  + crv * (v - 128))
  34.   g = clipz((y - oy) * cy  + cgv * (v - 128) + cgu * (u - 128))
  35.   b = clipz((y - oy) * cy  + cbu * (u - 128))
  36.  
  37. y, u, v are prescaled by a factor of 4 i.e. left-shifted to gain precision.
  38.  
  39.  
  40. New factorization to eliminate the truncation error which was
  41. occurring due to the byteop3p.
  42.  
  43.  
  44. 1) Use the bytop16m to subtract quad bytes we use this in U8 this
  45.  then so the offsets need to be renormalized to 8bits.
  46.  
  47. 2) Scale operands up by a factor of 4 not 8 because Blackfin
  48.    multiplies include a shift.
  49.  
  50. 3) Compute into the accumulators cy * yx0, cy * yx1.
  51.  
  52. 4) Compute each of the linear equations:
  53.      r = clipz((y - oy) * cy  + crv * (v - 128))
  54.  
  55.      g = clipz((y - oy) * cy  + cgv * (v - 128) + cgu * (u - 128))
  56.  
  57.      b = clipz((y - oy) * cy  + cbu * (u - 128))
  58.  
  59.    Reuse of the accumulators requires that we actually multiply
  60.    twice once with addition and the second time with a subtraction.
  61.  
  62.    Because of this we need to compute the equations in the order R B
  63.    then G saving the writes for B in the case of 24/32 bit color
  64.    formats.
  65.  
  66.    API: yuv2rgb_kind (uint8_t *Y, uint8_t *U, uint8_t *V, int *out,
  67.                       int dW, uint32_t *coeffs);
  68.  
  69.        A          B
  70.        ---        ---
  71.        i2 = cb    i3 = cr
  72.        i1 = coeff i0 = y
  73.  
  74. Where coeffs have the following layout in memory.
  75.  
  76. uint32_t oy, oc, zero, cy, crv, rmask, cbu, bmask, cgu, cgv;
  77.  
  78. coeffs is a pointer to oy.
  79.  
  80. The {rgb} masks are only utilized by the 565 packing algorithm. Note the data
  81. replication is used to simplify the internal algorithms for the dual Mac
  82. architecture of BlackFin.
  83.  
  84. All routines are exported with _ff_bfin_ as a symbol prefix.
  85.  
  86. Rough performance gain compared against -O3:
  87.  
  88. 2779809/1484290 187.28%
  89.  
  90. which translates to ~33c/pel to ~57c/pel for the reference vs 17.5
  91. c/pel for the optimized implementations. Not sure why there is such a
  92. huge variation on the reference codes on Blackfin I guess it must have
  93. to do with the memory system.
  94. */
  95.  
  96. #define mL3 .text
  97. #if defined(__FDPIC__) && CONFIG_SRAM
  98. #define mL1 .l1.text
  99. #else
  100. #define mL1 mL3
  101. #endif
  102. #define MEM mL1
  103.  
  104. #define DEFUN(fname,where,interface) \
  105.         .section where;              \
  106.         .global _ff_bfin_ ## fname;  \
  107.         .type _ff_bfin_ ## fname, STT_FUNC; \
  108.         .align 8;                    \
  109.         _ff_bfin_ ## fname
  110.  
  111. #define DEFUN_END(fname) \
  112.         .size _ff_bfin_ ## fname, . - _ff_bfin_ ## fname
  113.  
  114.  
  115. .text
  116.  
  117. #define COEFF_LEN        11*4
  118. #define COEFF_REL_CY_OFF 4*4
  119.  
  120. #define ARG_OUT   20
  121. #define ARG_W     24
  122. #define ARG_COEFF 28
  123.  
  124. DEFUN(yuv2rgb565_line,MEM,
  125.    (uint8_t *Y, uint8_t *U, uint8_t *V, int *out, int dW, uint32_t *coeffs)):
  126.         link 0;
  127.         [--sp] = (r7:4);
  128.         p1 = [fp+ARG_OUT];
  129.         r3 = [fp+ARG_W];
  130.  
  131.         i0 = r0;
  132.         i2 = r1;
  133.         i3 = r2;
  134.  
  135.         r0 = [fp+ARG_COEFF];
  136.         i1 = r0;
  137.         b1 = i1;
  138.         l1 = COEFF_LEN;
  139.         m0 = COEFF_REL_CY_OFF;
  140.         p0 = r3;
  141.  
  142.         r0   = [i0++];         // 2Y
  143.         r1.l = w[i2++];        // 2u
  144.         r1.h = w[i3++];        // 2v
  145.         p0 = p0>>2;
  146.  
  147.         lsetup (.L0565, .L1565) lc0 = p0;
  148.  
  149.         /*
  150.            uint32_t oy,oc,zero,cy,crv,rmask,cbu,bmask,cgu,cgv
  151.            r0 -- used to load 4ys
  152.            r1 -- used to load 2us,2vs
  153.            r4 -- y3,y2
  154.            r5 -- y1,y0
  155.            r6 -- u1,u0
  156.            r7 -- v1,v0
  157.         */
  158.                                                               r2=[i1++]; // oy
  159. .L0565:
  160.         /*
  161.         rrrrrrrr gggggggg bbbbbbbb
  162.          5432109876543210
  163.                     bbbbb >>3
  164.               gggggggg    <<3
  165.          rrrrrrrr         <<8
  166.          rrrrrggggggbbbbb
  167.         */
  168.         (r4,r5) = byteop16m (r1:0, r3:2)                   || r3=[i1++]; // oc
  169.         (r7,r6) = byteop16m (r1:0, r3:2) (r);
  170.         r5 = r5 << 2 (v);                                                // y1,y0
  171.         r4 = r4 << 2 (v);                                                // y3,y2
  172.         r6 = r6 << 2 (v)                                   || r0=[i1++]; // u1,u0, r0=zero
  173.         r7 = r7 << 2 (v)                                   || r1=[i1++]; // v1,v0  r1=cy
  174.         /* Y' = y*cy */
  175.         a1 = r1.h*r5.h, a0 = r1.l*r5.l                     || r1=[i1++]; // crv
  176.  
  177.         /* R = Y+ crv*(Cr-128) */
  178.         r2.h = (a1 += r1.h*r7.l), r2.l = (a0 += r1.l*r7.l);
  179.                 a1 -= r1.h*r7.l,          a0 -= r1.l*r7.l  || r5=[i1++]; // rmask
  180.         r2 = byteop3p(r3:2, r1:0)(LO)                      || r1=[i1++]; // cbu
  181.         r2 = r2 >> 3 (v);
  182.         r3 = r2 & r5;
  183.  
  184.         /* B = Y+ cbu*(Cb-128) */
  185.         r2.h = (a1 += r1.h*r6.l), r2.l = (a0 += r1.l*r6.l);
  186.                 a1 -= r1.h*r6.l,          a0 -= r1.l*r6.l  || r5=[i1++]; // bmask
  187.         r2 = byteop3p(r3:2, r1:0)(LO)                      || r1=[i1++]; // cgu
  188.         r2 = r2 << 8 (v);
  189.         r2 = r2 & r5;
  190.         r3 = r3 | r2;
  191.  
  192.         /* G = Y+ cgu*(Cb-128)+cgv*(Cr-128) */
  193.                 a1 += r1.h*r6.l,          a0 += r1.l*r6.l  || r1=[i1++]; // cgv
  194.         r2.h = (a1 += r1.h*r7.l), r2.l = (a0 += r1.l*r7.l);
  195.         r2 = byteop3p(r3:2, r1:0)(LO)                      || r5=[i1++m0]; // gmask
  196.         r2 = r2 << 3 (v);
  197.         r2 = r2 & r5;
  198.         r3 = r3 | r2;
  199.         [p1++]=r3                                          || r1=[i1++]; // cy
  200.  
  201.         /* Y' = y*cy */
  202.  
  203.         a1 = r1.h*r4.h, a0 = r1.l*r4.l                     || r1=[i1++]; // crv
  204.  
  205.         /* R = Y+ crv*(Cr-128) */
  206.         r2.h = (a1 += r1.h*r7.h), r2.l = (a0 += r1.l*r7.h);
  207.                 a1 -= r1.h*r7.h,          a0 -= r1.l*r7.h  || r5=[i1++]; // rmask
  208.         r2 = byteop3p(r3:2, r1:0)(LO)                      || r1=[i1++]; // cbu
  209.         r2 = r2 >> 3 (v);
  210.         r3 = r2 & r5;
  211.  
  212.         /* B = Y+ cbu*(Cb-128) */
  213.         r2.h = (a1 += r1.h*r6.h), r2.l = (a0 += r1.l*r6.h);
  214.                 a1 -= r1.h*r6.h,          a0 -= r1.l*r6.h  || r5=[i1++]; // bmask
  215.         r2 = byteop3p(r3:2, r1:0)(LO)                      || r1=[i1++]; // cgu
  216.         r2 = r2 << 8 (v);
  217.         r2 = r2 & r5;
  218.         r3 = r3 | r2;
  219.  
  220.         /* G = Y+ cgu*(Cb-128)+cgv*(Cr-128) */
  221.                 a1 += r1.h*r6.h,          a0 += r1.l*r6.h  || r1=[i1++]; // cgv
  222.         r2.h = (a1 += r1.h*r7.h), r2.l = (a0 += r1.l*r7.h) || r5=[i1++]; // gmask
  223.         r2 = byteop3p(r3:2, r1:0)(LO)                      || r0   =  [i0++];        // 2Y
  224.         r2 = r2 << 3 (v)                                   || r1.l = w[i2++];        // 2u
  225.         r2 = r2 & r5;
  226.         r3 = r3 | r2;
  227.         [p1++]=r3                                          || r1.h = w[i3++];        // 2v
  228. .L1565:                                                       r2=[i1++]; // oy
  229.  
  230.         l1 = 0;
  231.  
  232.         (r7:4) = [sp++];
  233.         unlink;
  234.         rts;
  235. DEFUN_END(yuv2rgb565_line)
  236.  
  237. DEFUN(yuv2rgb555_line,MEM,
  238.    (uint8_t *Y, uint8_t *U, uint8_t *V, int *out, int dW, uint32_t *coeffs)):
  239.         link 0;
  240.         [--sp] = (r7:4);
  241.         p1 = [fp+ARG_OUT];
  242.         r3 = [fp+ARG_W];
  243.  
  244.         i0 = r0;
  245.         i2 = r1;
  246.         i3 = r2;
  247.  
  248.         r0 = [fp+ARG_COEFF];
  249.         i1 = r0;
  250.         b1 = i1;
  251.         l1 = COEFF_LEN;
  252.         m0 = COEFF_REL_CY_OFF;
  253.         p0 = r3;
  254.  
  255.         r0   = [i0++];         // 2Y
  256.         r1.l = w[i2++];        // 2u
  257.         r1.h = w[i3++];        // 2v
  258.         p0 = p0>>2;
  259.  
  260.         lsetup (.L0555, .L1555) lc0 = p0;
  261.  
  262.         /*
  263.            uint32_t oy,oc,zero,cy,crv,rmask,cbu,bmask,cgu,cgv
  264.            r0 -- used to load 4ys
  265.            r1 -- used to load 2us,2vs
  266.            r4 -- y3,y2
  267.            r5 -- y1,y0
  268.            r6 -- u1,u0
  269.            r7 -- v1,v0
  270.         */
  271.                                                               r2=[i1++]; // oy
  272. .L0555:
  273.         /*
  274.         rrrrrrrr gggggggg bbbbbbbb
  275.          5432109876543210
  276.                     bbbbb >>3
  277.                gggggggg   <<2
  278.           rrrrrrrr        <<7
  279.          xrrrrrgggggbbbbb
  280.         */
  281.  
  282.         (r4,r5) = byteop16m (r1:0, r3:2)                   || r3=[i1++]; // oc
  283.         (r7,r6) = byteop16m (r1:0, r3:2) (r);
  284.         r5 = r5 << 2 (v);                                                // y1,y0
  285.         r4 = r4 << 2 (v);                                                // y3,y2
  286.         r6 = r6 << 2 (v)                                   || r0=[i1++]; // u1,u0, r0=zero
  287.         r7 = r7 << 2 (v)                                   || r1=[i1++]; // v1,v0  r1=cy
  288.         /* Y' = y*cy */
  289.         a1 = r1.h*r5.h, a0 = r1.l*r5.l                     || r1=[i1++]; // crv
  290.  
  291.         /* R = Y+ crv*(Cr-128) */
  292.         r2.h = (a1 += r1.h*r7.l), r2.l = (a0 += r1.l*r7.l);
  293.                 a1 -= r1.h*r7.l,          a0 -= r1.l*r7.l  || r5=[i1++]; // rmask
  294.         r2 = byteop3p(r3:2, r1:0)(LO)                      || r1=[i1++]; // cbu
  295.         r2 = r2 >> 3 (v);
  296.         r3 = r2 & r5;
  297.  
  298.         /* B = Y+ cbu*(Cb-128) */
  299.         r2.h = (a1 += r1.h*r6.l), r2.l = (a0 += r1.l*r6.l);
  300.                 a1 -= r1.h*r6.l,          a0 -= r1.l*r6.l  || r5=[i1++]; // bmask
  301.         r2 = byteop3p(r3:2, r1:0)(LO)                      || r1=[i1++]; // cgu
  302.         r2 = r2 << 7 (v);
  303.         r2 = r2 & r5;
  304.         r3 = r3 | r2;
  305.  
  306.         /* G = Y+ cgu*(Cb-128)+cgv*(Cr-128) */
  307.                 a1 += r1.h*r6.l,          a0 += r1.l*r6.l  || r1=[i1++]; // cgv
  308.         r2.h = (a1 += r1.h*r7.l), r2.l = (a0 += r1.l*r7.l);
  309.         r2 = byteop3p(r3:2, r1:0)(LO)                      || r5=[i1++m0]; // gmask
  310.         r2 = r2 << 2 (v);
  311.         r2 = r2 & r5;
  312.         r3 = r3 | r2;
  313.         [p1++]=r3                                          || r1=[i1++]; // cy
  314.  
  315.         /* Y' = y*cy */
  316.  
  317.         a1 = r1.h*r4.h, a0 = r1.l*r4.l                     || r1=[i1++]; // crv
  318.  
  319.         /* R = Y+ crv*(Cr-128) */
  320.         r2.h = (a1 += r1.h*r7.h), r2.l = (a0 += r1.l*r7.h);
  321.                 a1 -= r1.h*r7.h,          a0 -= r1.l*r7.h  || r5=[i1++]; // rmask
  322.         r2 = byteop3p(r3:2, r1:0)(LO)                      || r1=[i1++]; // cbu
  323.         r2 = r2 >> 3 (v);
  324.         r3 = r2 & r5;
  325.  
  326.         /* B = Y+ cbu*(Cb-128) */
  327.         r2.h = (a1 += r1.h*r6.h), r2.l = (a0 += r1.l*r6.h);
  328.                 a1 -= r1.h*r6.h,          a0 -= r1.l*r6.h  || r5=[i1++]; // bmask
  329.         r2 = byteop3p(r3:2, r1:0)(LO)                      || r1=[i1++]; // cgu
  330.         r2 = r2 << 7 (v);
  331.         r2 = r2 & r5;
  332.         r3 = r3 | r2;
  333.  
  334.         /* G = Y+ cgu*(Cb-128)+cgv*(Cr-128) */
  335.                 a1 += r1.h*r6.h,          a0 += r1.l*r6.h  || r1=[i1++]; // cgv
  336.         r2.h = (a1 += r1.h*r7.h), r2.l = (a0 += r1.l*r7.h) || r5=[i1++]; // gmask
  337.         r2 = byteop3p(r3:2, r1:0)(LO)                      || r0=[i0++];     // 4Y
  338.         r2 = r2 << 2 (v)                                   || r1.l=w[i2++];  // 2u
  339.         r2 = r2 & r5;
  340.         r3 = r3 | r2;
  341.         [p1++]=r3                                          || r1.h=w[i3++]; // 2v
  342.  
  343. .L1555:                                                       r2=[i1++]; // oy
  344.  
  345.         l1 = 0;
  346.  
  347.         (r7:4) = [sp++];
  348.         unlink;
  349.         rts;
  350. DEFUN_END(yuv2rgb555_line)
  351.  
  352. DEFUN(yuv2rgb24_line,MEM,
  353.    (uint8_t *Y, uint8_t *U, uint8_t *V, int *out, int dW, uint32_t *coeffs)):
  354.         link 0;
  355.         [--sp] = (r7:4);
  356.         p1 = [fp+ARG_OUT];
  357.         r3 = [fp+ARG_W];
  358.         p2 = p1;
  359.         p2 += 3;
  360.  
  361.         i0 = r0;
  362.         i2 = r1;
  363.         i3 = r2;
  364.  
  365.         r0 = [fp+ARG_COEFF]; // coeff buffer
  366.         i1 = r0;
  367.         b1 = i1;
  368.         l1 = COEFF_LEN;
  369.         m0 = COEFF_REL_CY_OFF;
  370.         p0 = r3;
  371.  
  372.         r0   = [i0++];         // 2Y
  373.         r1.l = w[i2++];        // 2u
  374.         r1.h = w[i3++];        // 2v
  375.         p0 = p0>>2;
  376.  
  377.         lsetup (.L0888, .L1888) lc0 = p0;
  378.  
  379.         /*
  380.            uint32_t oy,oc,zero,cy,crv,rmask,cbu,bmask,cgu,cgv
  381.            r0 -- used to load 4ys
  382.            r1 -- used to load 2us,2vs
  383.            r4 -- y3,y2
  384.            r5 -- y1,y0
  385.            r6 -- u1,u0
  386.            r7 -- v1,v0
  387.         */
  388.                                                               r2=[i1++]; // oy
  389. .L0888:
  390.         (r4,r5) = byteop16m (r1:0, r3:2)                   || r3=[i1++]; // oc
  391.         (r7,r6) = byteop16m (r1:0, r3:2) (r);
  392.         r5 = r5 << 2 (v);               // y1,y0
  393.         r4 = r4 << 2 (v);               // y3,y2
  394.         r6 = r6 << 2 (v) || r0=[i1++];  // u1,u0, r0=zero
  395.         r7 = r7 << 2 (v) || r1=[i1++];  // v1,v0  r1=cy
  396.  
  397.         /* Y' = y*cy */
  398.         a1 = r1.h*r5.h, a0 = r1.l*r5.l                     || r1=[i1++]; // crv
  399.  
  400.         /* R = Y+ crv*(Cr-128) */
  401.         r2.h = (a1 += r1.h*r7.l), r2.l = (a0 += r1.l*r7.l);
  402.                 a1 -= r1.h*r7.l,          a0 -= r1.l*r7.l  || r5=[i1++]; // rmask
  403.         r2 = byteop3p(r3:2, r1:0)(LO)                      || r1=[i1++]; // cbu
  404.         r2=r2>>16 || B[p1++]=r2;
  405.                      B[p2++]=r2;
  406.  
  407.         /* B = Y+ cbu*(Cb-128) */
  408.         r2.h = (a1 += r1.h*r6.l), r2.l = (a0 += r1.l*r6.l);
  409.                 a1 -= r1.h*r6.l,          a0 -= r1.l*r6.l  || r5=[i1++]; // bmask
  410.         r3 = byteop3p(r3:2, r1:0)(LO)                      || r1=[i1++]; // cgu
  411.  
  412.         /* G = Y+ cgu*(Cb-128)+cgv*(Cr-128) */
  413.                 a1 += r1.h*r6.l,          a0 += r1.l*r6.l  || r1=[i1++]; // cgv
  414.         r2.h = (a1 += r1.h*r7.l), r2.l = (a0 += r1.l*r7.l);
  415.         r2 = byteop3p(r3:2, r1:0)(LO)                      || r5=[i1++m0]; // gmask, oy,cy,zero
  416.  
  417.         r2=r2>>16 || B[p1++]=r2;
  418.                      B[p2++]=r2;
  419.  
  420.         r3=r3>>16 || B[p1++]=r3;
  421.                      B[p2++]=r3                            || r1=[i1++]; // cy
  422.  
  423.         p1+=3;
  424.         p2+=3;
  425.         /* Y' = y*cy */
  426.         a1 = r1.h*r4.h, a0 = r1.l*r4.l                     || r1=[i1++]; // crv
  427.  
  428.         /* R = Y+ crv*(Cr-128) */
  429.         r2.h = (a1 += r1.h*r7.h), r2.l = (a0 += r1.l*r7.h);
  430.                 a1 -= r1.h*r7.h,          a0 -= r1.l*r7.h  || r5=[i1++]; // rmask
  431.         r2 = byteop3p(r3:2, r1:0)(LO)                      || r1=[i1++]; // cbu
  432.         r2=r2>>16 || B[p1++]=r2;
  433.         B[p2++]=r2;
  434.  
  435.         /* B = Y+ cbu*(Cb-128) */
  436.         r2.h = (a1 += r1.h*r6.h), r2.l = (a0 += r1.l*r6.h);
  437.                 a1 -= r1.h*r6.h,          a0 -= r1.l*r6.h  || r5=[i1++]; // bmask
  438.         r3 = byteop3p(r3:2, r1:0)(LO)                      || r1=[i1++]; // cgu
  439.  
  440.         /* G = Y+ cgu*(Cb-128)+cgv*(Cr-128) */
  441.                 a1 += r1.h*r6.h,          a0 += r1.l*r6.h  || r1=[i1++]; // cgv
  442.         r2.h = (a1 += r1.h*r7.h), r2.l = (a0 += r1.l*r7.h);
  443.         r2 = byteop3p(r3:2, r1:0)(LO)                      || r5=[i1++]; // gmask
  444.         r2=r2>>16 || B[p1++]=r2 || r0 = [i0++];    // 4y
  445.                      B[p2++]=r2 || r1.l = w[i2++]; // 2u
  446.         r3=r3>>16 || B[p1++]=r3 || r1.h = w[i3++]; // 2v
  447.                      B[p2++]=r3 || r2=[i1++];      // oy
  448.  
  449.         p1+=3;
  450. .L1888: p2+=3;
  451.  
  452.         l1 = 0;
  453.  
  454.         (r7:4) = [sp++];
  455.         unlink;
  456.         rts;
  457. DEFUN_END(yuv2rgb24_line)
  458.  
  459.  
  460.  
  461. #define ARG_vdst        20
  462. #define ARG_width       24
  463. #define ARG_height      28
  464. #define ARG_lumStride   32
  465. #define ARG_chromStride 36
  466. #define ARG_srcStride   40
  467.  
  468. DEFUN(uyvytoyv12, mL3,  (const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
  469.                          int width, int height,
  470.                          int lumStride, int chromStride, int srcStride)):
  471.         link 0;
  472.         [--sp] = (r7:4,p5:4);
  473.  
  474.         p0 = r1;       // Y top even
  475.  
  476.         i2 = r2; // *u
  477.         r2 = [fp + ARG_vdst];
  478.         i3 = r2; // *v
  479.  
  480.         r1 = [fp + ARG_srcStride];
  481.         r2 = r0 + r1;
  482.         i0 = r0;  // uyvy_T even
  483.         i1 = r2;  // uyvy_B odd
  484.  
  485.         p2 = [fp + ARG_lumStride];
  486.         p1 = p0 + p2;  // Y bot odd
  487.  
  488.         p5 = [fp + ARG_width];
  489.         p4 = [fp + ARG_height];
  490.         r0 = p5;
  491.         p4 = p4 >> 1;
  492.         p5 = p5 >> 2;
  493.  
  494.         r2 = r0 << 1;
  495.         r1 = r1 << 1;
  496.         r1 = r1 - r2;  // srcStride + (srcStride - 2*width)
  497.         r1 += -8;  // i0,i1 is pre read need to correct
  498.         m0 = r1;
  499.  
  500.         r2 = [fp + ARG_chromStride];
  501.         r0 = r0 >> 1;
  502.         r2 = r2 - r0;
  503.         m1 = r2;
  504.  
  505.         /*   I0,I1 - src input line pointers
  506.          *   p0,p1 - luma output line pointers
  507.          *   I2    - dstU
  508.          *   I3    - dstV
  509.          */
  510.  
  511.         lsetup (0f, 1f) lc1 = p4;   // H/2
  512. 0:        r0 = [i0++] || r2 = [i1++];
  513.           r1 = [i0++] || r3 = [i1++];
  514.           r4 = byteop1p(r1:0, r3:2);
  515.           r5 = byteop1p(r1:0, r3:2) (r);
  516.           lsetup (2f, 3f) lc0 = p5; // W/4
  517. 2:          r0 = r0 >> 8(v);
  518.             r1 = r1 >> 8(v);
  519.             r2 = r2 >> 8(v);
  520.             r3 = r3 >> 8(v);
  521.             r0 = bytepack(r0, r1);
  522.             r2 = bytepack(r2, r3)         ||  [p0++] = r0;    // yyyy
  523.             r6 = pack(r5.l, r4.l)         ||  [p1++] = r2;    // yyyy
  524.             r7 = pack(r5.h, r4.h)         ||  r0 = [i0++] || r2 = [i1++];
  525.             r6 = bytepack(r6, r7)         ||  r1 = [i0++] || r3 = [i1++];
  526.             r4 = byteop1p(r1:0, r3:2)     ||  w[i2++] = r6.l; // uu
  527. 3:          r5 = byteop1p(r1:0, r3:2) (r) ||  w[i3++] = r6.h; // vv
  528.  
  529.           i0 += m0;
  530.           i1 += m0;
  531.           i2 += m1;
  532.           i3 += m1;
  533.           p0 = p0 + p2;
  534. 1:        p1 = p1 + p2;
  535.  
  536.         (r7:4,p5:4) = [sp++];
  537.         unlink;
  538.         rts;
  539. DEFUN_END(uyvytoyv12)
  540.  
  541. DEFUN(yuyvtoyv12, mL3,  (const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
  542.                          int width, int height,
  543.                          int lumStride, int chromStride, int srcStride)):
  544.         link 0;
  545.         [--sp] = (r7:4,p5:4);
  546.  
  547.         p0 = r1;       // Y top even
  548.  
  549.         i2 = r2; // *u
  550.         r2 = [fp + ARG_vdst];
  551.         i3 = r2; // *v
  552.  
  553.         r1 = [fp + ARG_srcStride];
  554.         r2 = r0 + r1;
  555.  
  556.         i0 = r0;  // uyvy_T even
  557.         i1 = r2;  // uyvy_B odd
  558.  
  559.         p2 = [fp + ARG_lumStride];
  560.         p1 = p0 + p2;  // Y bot odd
  561.  
  562.         p5 = [fp + ARG_width];
  563.         p4 = [fp + ARG_height];
  564.         r0 = p5;
  565.         p4 = p4 >> 1;
  566.         p5 = p5 >> 2;
  567.  
  568.         r2 = r0 << 1;
  569.         r1 = r1 << 1;
  570.         r1 = r1 - r2;  // srcStride + (srcStride - 2*width)
  571.         r1 += -8;  // i0,i1 is pre read need to correct
  572.         m0 = r1;
  573.  
  574.         r2 = [fp + ARG_chromStride];
  575.         r0 = r0 >> 1;
  576.         r2 = r2 - r0;
  577.         m1 = r2;
  578.  
  579.         /*   I0,I1 - src input line pointers
  580.          *   p0,p1 - luma output line pointers
  581.          *   I2    - dstU
  582.          *   I3    - dstV
  583.          */
  584.  
  585.         lsetup (0f, 1f) lc1 = p4;   // H/2
  586. 0:        r0 = [i0++] || r2 = [i1++];
  587.           r1 = [i0++] || r3 = [i1++];
  588.           r4 = bytepack(r0, r1);
  589.           r5 = bytepack(r2, r3);
  590.           lsetup (2f, 3f) lc0 = p5; // W/4
  591. 2:          r0 = r0 >> 8(v) || [p0++] = r4;  // yyyy-even
  592.             r1 = r1 >> 8(v) || [p1++] = r5;  // yyyy-odd
  593.             r2 = r2 >> 8(v);
  594.             r3 = r3 >> 8(v);
  595.             r4 = byteop1p(r1:0, r3:2);
  596.             r5 = byteop1p(r1:0, r3:2) (r);
  597.             r6 = pack(r5.l, r4.l);
  598.             r7 = pack(r5.h, r4.h)         ||  r0 = [i0++] || r2 = [i1++];
  599.             r6 = bytepack(r6, r7)         ||  r1 = [i0++] || r3 = [i1++];
  600.             r4 = bytepack(r0, r1)         ||  w[i2++] = r6.l; // uu
  601. 3:          r5 = bytepack(r2, r3)         ||  w[i3++] = r6.h; // vv
  602.  
  603.           i0 += m0;
  604.           i1 += m0;
  605.           i2 += m1;
  606.           i3 += m1;
  607.           p0 = p0 + p2;
  608. 1:        p1 = p1 + p2;
  609.  
  610.         (r7:4,p5:4) = [sp++];
  611.         unlink;
  612.         rts;
  613. DEFUN_END(yuyvtoyv12)
  614.