LCOV - code coverage report
Current view: top level - evg - raster_yuv.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1114 1164 95.7 %
Date: 2021-04-29 23:48:07 Functions: 44 44 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2019
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / software 2D rasterizer module
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC 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
      18             :  *  GNU 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 this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  *
      25             :  *
      26             :  */
      27             : 
      28             : #include "rast_soft.h"
      29             : 
      30             : //TODO: support for color spaces, support for more than 10 bits and BigEndian format ?
      31             : 
      32             : #if 1
      33             : 
      34             : #define mul255(_a, _b)  ( (((u32)(_a) + 1) * (u32)(_b) ) >> 8)
      35             : 
      36             : #else
      37             : static s32
      38             : mul255(s32 a, s32 b)
      39             : {
      40             :         return ((a + 1) * b) >> 8;
      41             : }
      42             : #endif
      43             : 
      44             : static s32
      45             : mul255_zero(s32 a, s32 b)
      46             : {
      47     1062636 :         if (!a) return 0;
      48      726794 :         return ((a + 1) * b) >> 8;
      49             : }
      50             : 
      51             : //RGB <-> YUV full range conversion, using integer (1024 factor)
      52             : #define YUV_USE_INT
      53             : 
      54        1498 : void gf_evg_rgb_to_yuv(GF_EVGSurface *surf, GF_Color col, u8*y, u8*cb, u8*cr)
      55             : {
      56        1498 :         u32 r = GF_COL_R(col);
      57        1498 :         u32 g = GF_COL_G(col);
      58             :         u32 b = GF_COL_B(col);
      59             : 
      60             : #ifndef YUV_USE_INT
      61             :         *y = (u8) (0.299*r + 0.587 * g + 0.114 * b);
      62             :         *cb = (u8) (-0.169*(s32)r - 0.331*(s32)g + 0.499*b + 128);
      63             :         *cr = (u8) (0.499 * r - 0.418*(s32)g - 0.0813*(s32)b + 128);
      64             : #else
      65        1498 :         u32 _v = 306*r + 601 * g + 117 * b;
      66        1498 :         *y = (u8) (_v >> 10);
      67        1498 :         _v = (-173*(s32)r - 339*(s32)g + 511*b + 131072);
      68        1498 :         *cb = (u8) (_v >> 10);
      69        1498 :         _v = (511 * r - 428*(s32)g - 83*(s32)b + 131072);
      70        1498 :         *cr = (u8) (_v >> 10);
      71             : #endif
      72        1498 : }
      73     4344554 : GF_Color gf_evg_argb_to_ayuv(GF_EVGSurface *surf, GF_Color col)
      74             : {
      75             :         u8 a, y, cb, cr;
      76             :         a = GF_COL_A(col);
      77     4344554 :         u32 r = GF_COL_R(col);
      78     4344554 :         u32 g = GF_COL_G(col);
      79             :         u32 b = GF_COL_B(col);
      80             : 
      81             : #ifndef YUV_USE_INT
      82             :         y = (u8) (0.299*r + 0.587 * g + 0.114 * b);
      83             :         cb = (u8) (-0.169*(s32)r - 0.331*(s32)g + 0.499*b + 128);
      84             :         cr = (u8) (0.499 * r - 0.418*(s32)g - 0.0813*(s32)b + 128);
      85             : #else
      86     4344554 :         u32 _v = 306*r + 601 * g + 117 * b;
      87     4344554 :         y = (u8) (_v >> 10);
      88     4344554 :         _v = (-173*(s32)r - 339*(s32)g + 511*b + 131072);
      89     4344554 :         cb = (u8) (_v >> 10);
      90     4344554 :         _v = (511 * r - 428*(s32)g - 83*(s32)b + 131072);
      91     4344554 :         cr = (u8) (_v >> 10);
      92             : #endif
      93     4344554 :         return GF_COL_ARGB(a, y, cb, cr);
      94             : }
      95             : 
      96           2 : GF_Err gf_gf_evg_rgb_to_yuv_f(GF_EVGSurface *surf, Float r, Float g, Float b, Float *y, Float *cb, Float *cr)
      97             : {
      98           2 :         *y = (0.299f * r + 0.587f * g + 0.114f * b);
      99           2 :         *cb = (-0.169f * (s32)r - 0.331f * (s32)g + 0.499f * b + 128.0f);
     100           2 :         *cr = (0.499f * r - 0.418f * (s32)g - 0.0813f * (s32)b + 128.0f);
     101           2 :         return GF_OK;
     102             : }
     103           2 : GF_Err gf_evg_yuv_to_rgb_f(GF_EVGSurface *surf, Float y, Float cb, Float cr, Float *r, Float *g, Float *b)
     104             : {
     105           2 :         *r = (y + 1.402f * (cr - 128.0f));
     106           2 :         *g = (y - 0.344136f * (cb - 128.0f) - 0.714136f * (cr-128.0f) );
     107           2 :         *b = (y + 1.772f * (cb - 128.0f) );
     108           2 :         return GF_OK;
     109             : }
     110             : 
     111     1237678 : GF_Color gf_evg_ayuv_to_argb(GF_EVGSurface *surf, GF_Color col)
     112             : {
     113             :         u32 a;
     114             :         s32 y, cb, cr;
     115             :         s32 r, g, b;
     116             :         a = GF_COL_A(col);
     117     1237678 :         y = GF_COL_R(col);
     118     1237678 :         cb = GF_COL_G(col);
     119     1237678 :         cr = GF_COL_B(col);
     120             : 
     121             : #ifndef YUV_USE_INT
     122             :         r = (s32) (y + 1.402 * (cr - 128));
     123             :         g = (s32) (y - 0.344136 * (cb - 128) - 0.714136*(cr-128) );
     124             :         b = (s32) (y + 1.772 * (cb - 128) );
     125             : 
     126             : #define TRUNC_8BIT(_a) if (_a<0) {_a = 0;} else if (_a>255) {_a=255;}
     127             :         TRUNC_8BIT(r)
     128             :         TRUNC_8BIT(g)
     129             :         TRUNC_8BIT(b)
     130             : 
     131             : #else
     132     1237678 :         y *= 1024;
     133     1237678 :         r = (s32) (y + 1436 * (cr - 128));
     134     1237678 :         g = (s32) (y - 352 * (cb - 128) - 731*(cr-128) );
     135     1237678 :         b = (s32) (y + 1814 * (cb - 128) );
     136             : 
     137             : #define TRUNC_8BIT(_a) if (_a<0) {_a = 0;} else { u32 __a = (u32) _a; __a>>=10; if (__a>255) {__a=255;} _a = __a; }
     138     1237678 :         TRUNC_8BIT(r)
     139     1237678 :         TRUNC_8BIT(g)
     140     1237678 :         TRUNC_8BIT(b)
     141             : 
     142             : #endif
     143             : 
     144             : 
     145     1237678 :         return GF_COL_ARGB(a, r, g, b);
     146             : }
     147             : 
     148      584425 : u64 gf_evg_argb_to_ayuv_wide(GF_EVGSurface *surf, u64 col)
     149             : {
     150             :         u16 a, y, cb, cr;
     151             :         u32 r, g, b;
     152             : 
     153             :         a = (col>>48)&0xFFFF;
     154      584425 :         r = (col>>32)&0xFFFF;
     155      584425 :         g = (col>>16)&0xFFFF;
     156      584425 :         b = (col)&0xFFFF;
     157             : 
     158             : #ifndef YUV_USE_INT
     159             :         y = (u16) (0.299*r + 0.587 * g + 0.114 * b);
     160             :         cb = (u16) (-0.169*(s32)r - 0.331*(s32)g + 0.499*b + 32768);
     161             :         cr = (u16) (0.499 * r - 0.418*(s32)g - 0.0813*(s32)b + 32768);
     162             : #else
     163      584425 :         u32 _v = 306*r + 601 * g + 117 * b;
     164      584425 :         y = (u16) (_v >> 10);
     165      584425 :         _v = (-173*(s32)r - 339*(s32)g + 511*b + 33554432);
     166      584425 :         cb = (u16) (_v >> 10);
     167      584425 :         _v = (511 * r - 428*(s32)g - 83*(s32)b + 33554432);
     168      584425 :         cr = (u16) (_v >> 10);
     169             : #endif
     170             : 
     171             : 
     172      584425 :         return evg_make_col_wide(a, y, cb, cr);
     173             : }
     174           2 : u64 gf_evg_ayuv_to_argb_wide(GF_EVGSurface *surf, u64 col)
     175             : {
     176             :         u32 a;
     177             :         s64 y, cb, cr;
     178             :         s32 r, g, b;
     179             :         a = (col>>48)&0xFFFF;
     180           2 :         y = (col>>32)&0xFFFF;
     181           2 :         cb = (col>>16)&0xFFFF;
     182           2 :         cr = (col)&0xFFFF;
     183             : 
     184             : #ifndef YUV_USE_INT
     185             :         r = (s32) (y + 1.402 * (cr - 32768));
     186             :         g = (s32) (y - 0.344136 * (cb - 32768) - 0.714136*(cr-32768) );
     187             :         b = (s32) (y + 1.772 * (cb - 32768) );
     188             : #define TRUNC_16BIT(_a) if (_a<0) {_a = 0;} else if (_a>32768) {_a=32768;}
     189             :         TRUNC_16BIT(r)
     190             :         TRUNC_16BIT(g)
     191             :         TRUNC_16BIT(b)
     192             : 
     193             : #else
     194           2 :         y *= 1024;
     195           2 :         r = (s32) (y + 1436 * (cr - 32768));
     196           2 :         g = (s32) (y - 352 * (cb - 32768) - 731*(cr-32768) );
     197           2 :         b = (s32) (y + 1814 * (cb - 32768) );
     198             : 
     199             : #define TRUNC_16BIT(_a) if (_a<0) {_a = 0;} else { u32 __a = (u32) _a; __a>>=10; if (__a>32768) {__a=32768;} _a = __a; }
     200           2 :         TRUNC_16BIT(r)
     201           2 :         TRUNC_16BIT(g)
     202           2 :         TRUNC_16BIT(b)
     203             : 
     204             : #endif
     205             : 
     206           2 :         return evg_make_col_wide(a, r, g, b);
     207             : }
     208             : 
     209           1 : void evg_make_ayuv_color_mx(GF_ColorMatrix *cmat, GF_ColorMatrix *yuv_cmat)
     210             : {
     211             :         GF_ColorMatrix cmx_y2r, cmx_r2y;
     212           1 :         gf_cmx_init(&cmx_r2y);
     213           1 :         gf_cmx_init(&cmx_y2r);
     214           1 :         cmx_r2y.identity = cmx_y2r.identity = GF_FALSE;
     215             : 
     216             :         //r = (s32) (y + 1.402 * (cr - 128));
     217           1 :         cmx_y2r.m[0] = FIX_ONE; //y
     218           1 :         cmx_y2r.m[2] = FLT2FIX(1.402); //cr
     219           1 :         cmx_y2r.m[4] = FLT2FIX(-1.402 * 0.504); //tr
     220             : 
     221             :         //g = (s32) (y - 0.344136 * (cb - 128) - 0.714136*(cr-128) );
     222           1 :         cmx_y2r.m[5] = FIX_ONE; //y
     223           1 :         cmx_y2r.m[6] = FLT2FIX(- 0.344136); //cb
     224           1 :         cmx_y2r.m[7] = FLT2FIX(- 0.714136); //cr
     225           1 :         cmx_y2r.m[9] = FLT2FIX(0.344136 * 0.504 + 0.714136*0.504); //tr
     226             : 
     227             :         //b = (s32) (y + 1.772 * (cb - 128) );
     228           1 :         cmx_y2r.m[10] = FIX_ONE; //y
     229           1 :         cmx_y2r.m[11] = FLT2FIX(1.772); //cb
     230           1 :         cmx_y2r.m[14] = FLT2FIX(-1.772 * 0.504); //tr
     231             : 
     232             : 
     233             :         //y = (u8) (0.299*r + 0.587 * g + 0.114 * b);
     234           1 :         cmx_r2y.m[0] = FLT2FIX(0.299); //r
     235           1 :         cmx_r2y.m[1] = FLT2FIX(0.587); //g
     236           1 :         cmx_r2y.m[2] = FLT2FIX(0.114); //b
     237             : 
     238             : 
     239             :         //cb = (u8) (-0.169*(s32)r - 0.331*(s32)g + 0.499*b + 128);
     240           1 :         cmx_r2y.m[5] = FLT2FIX(-0.169); //r
     241           1 :         cmx_r2y.m[6] = FLT2FIX(-0.331); //g
     242           1 :         cmx_r2y.m[7] = FLT2FIX(0.499); //b
     243           1 :         cmx_r2y.m[9] = FLT2FIX(0.504); //tr
     244             : 
     245             :         //cr = (u8) (0.499 * r - 0.418*(s32)g - 0.0813*(s32)b + 128);
     246           1 :         cmx_r2y.m[10] = FLT2FIX(0.499); //r
     247           1 :         cmx_r2y.m[11] = FLT2FIX(-0.418); //g
     248           1 :         cmx_r2y.m[12] = FLT2FIX(-0.0813); //b
     249           1 :         cmx_r2y.m[14] = FLT2FIX(0.504); //tr
     250             : 
     251           1 :         gf_cmx_copy(yuv_cmat, &cmx_r2y);
     252           1 :         gf_cmx_multiply(yuv_cmat, cmat);
     253           1 :         gf_cmx_multiply(yuv_cmat, &cmx_y2r);
     254           1 : }
     255             : 
     256             : 
     257             : /*
     258             :                         YUV420p part
     259             : */
     260             : 
     261             : static void overmask_yuv420p(u8 col_a, u8 cy, char *dst, u32 alpha)
     262             : {
     263             :         s32 srca = col_a;
     264             :         u32 srcc = cy;
     265      495871 :         s32 dstc = (*dst) & 0xFF;
     266             : 
     267      487409 :         srca = mul255(srca, alpha);
     268      495871 :         *dst = mul255(srca, srcc - dstc) + dstc;
     269             : }
     270             : 
     271             : static void overmask_yuv420p_const_run(u8 a, u8 val, u8 *ptr, u32 count, short x)
     272             : {
     273     1097177 :         while (count) {
     274      569182 :                 u8 dst = *(ptr);
     275      569182 :                 *ptr = (u8) mul255(a, val - dst) + dst;
     276      569182 :                 ptr ++;
     277      569182 :                 count--;
     278             :         }
     279             : }
     280       31408 : void evg_yuv420p_flush_uv_const(GF_EVGSurface *surf, u8 *surf_uv_alpha, s32 cu, s32 cv, s32 y)
     281             : {
     282             :         u32 i, a;
     283       31408 :         u8 *pU = surf->pixels + surf->height *surf->pitch_y;
     284             :         u8 *pV;
     285       31408 :         pU +=  y/2 * surf->pitch_y/2;
     286       31408 :         pV = pU + surf->height/2 * surf->pitch_y/2;
     287             : 
     288             :         //no need to swap u and V in const flush, they have been swaped when setting up the brush
     289             : 
     290             :         //we are at an odd line, write uv
     291    16306736 :         for (i=0; i<surf->width; i+=2) {
     292             :                 u8 dst;
     293             : 
     294             :                 //even line
     295    16275328 :                 a = surf->uv_alpha[i] + surf->uv_alpha[i+1];
     296             :                 //odd line
     297    16275328 :                 a += surf_uv_alpha[i] + surf_uv_alpha[i+1];
     298             : 
     299    16275328 :                 if (a) {
     300             :                         char *s_ptr_u, *s_ptr_v;
     301             : 
     302      421788 :                         a /= 4;
     303             : 
     304      421788 :                         s_ptr_u = pU + i / 2;
     305      421788 :                         s_ptr_v = pV + i / 2;
     306      421788 :                         if (a==0xFF) {
     307      170891 :                                 *s_ptr_u = (u8) cu;
     308      170891 :                                 *s_ptr_v = (u8) cv;
     309             :                         } else {
     310      250897 :                                 dst = *(s_ptr_u);
     311      250897 :                                 *s_ptr_u = (u8) mul255(a, cu - dst) + dst;
     312             : 
     313      250897 :                                 dst = *(s_ptr_v);
     314      250897 :                                 *s_ptr_v = (u8) mul255(a, cv - dst) + dst;
     315             :                         }
     316             :                 }
     317             :         }
     318       31408 :         memset(surf->uv_alpha, 0, surf->uv_alpha_alloc);
     319       31408 : }
     320             : 
     321       63492 : void evg_yuv420p_fill_const(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
     322             : {
     323       63492 :         char *pY = surf->pixels;
     324             :         u8 *surf_uv_alpha;
     325             :         s32 i;
     326             :         u8 cy, cu, cv;
     327       63492 :         Bool write_uv = (y%2) ? GF_TRUE : GF_FALSE;
     328             : 
     329       63492 :         if (surf->is_422) {
     330             :                 write_uv = GF_TRUE;
     331         307 :                 surf_uv_alpha = surf->uv_alpha;
     332             :         }
     333       63185 :         else if (write_uv) {
     334       31598 :                 surf_uv_alpha = surf->uv_alpha + surf->width;
     335             :         } else {
     336       31587 :                 surf_uv_alpha = surf->uv_alpha;
     337             :         }
     338             : 
     339       63492 :         pY +=  y * surf->pitch_y;
     340             : 
     341       63492 :         cy = GF_COL_R(surf->fill_col);
     342       63492 :         cu = GF_COL_G(surf->fill_col);
     343             :         cv = GF_COL_B(surf->fill_col);
     344             : 
     345      680181 :         for (i=0; i<count; i++) {
     346             :                 u32 a;
     347             :                 char *s_pY;
     348             :                 u32 len;
     349      616689 :                 len = spans[i].len;
     350      616689 :                 s_pY = pY + spans[i].x;
     351             : 
     352      616689 :                 a = spans[i].coverage;
     353      616689 :                 if (a != 0xFF) {
     354      521487 :                         overmask_yuv420p_const_run((u8)a, cy, s_pY, len, 0);
     355      521487 :                         memset(surf_uv_alpha + spans[i].x, (u8)a, len);
     356             :                 } else  {
     357      936822 :                         while (len--) {
     358      841620 :                                 *(s_pY) = cy;
     359      841620 :                                 s_pY ++;
     360             :                         }
     361       95202 :                         memset(surf_uv_alpha + spans[i].x, 0xFF, spans[i].len);
     362             :                 }
     363             :         }
     364       63492 :         if (write_uv) {
     365       31905 :                 surf->yuv_flush_uv(surf, surf_uv_alpha, cu, cv, y);
     366             :         }
     367             : 
     368       63492 : }
     369             : 
     370         396 : void evg_yuv420p_fill_const_a(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
     371             : {
     372             :         u32 a;
     373         396 :         char *pY = surf->pixels;
     374             :         u8 *surf_uv_alpha;
     375             :         s32 i;
     376             :         u8 cy, cu, cv;
     377         396 :         Bool write_uv = (y%2) ? GF_TRUE : GF_FALSE;
     378             : 
     379         396 :         if (surf->is_422) {
     380             :                 write_uv = GF_TRUE;
     381          56 :                 surf_uv_alpha = surf->uv_alpha;
     382         340 :         } else if (write_uv) {
     383         170 :                 surf_uv_alpha = surf->uv_alpha + surf->width;
     384             :         } else {
     385         170 :                 surf_uv_alpha = surf->uv_alpha;
     386             :         }
     387             : 
     388         396 :         pY +=  y * surf->pitch_y;
     389             : 
     390         396 :         cy = GF_COL_R(surf->fill_col);
     391         396 :         cu = GF_COL_G(surf->fill_col);
     392             :         cv = GF_COL_B(surf->fill_col);
     393         396 :         a = GF_COL_A(surf->fill_col);
     394             : 
     395         396 :         if (surf->get_alpha) {
     396           0 :                 for (i=0; i<count; i++) {
     397             :                         u32 fin, j;
     398           0 :                         for (j=0; j<spans[i].len; j++) {
     399           0 :                                 s32 x = spans[i].x + j;
     400           0 :                                 char *s_pY = pY + x;
     401           0 :                                 u8 aa = surf->get_alpha(surf->get_alpha_udta, a, x, y);
     402           0 :                                 fin = mul255(aa, spans[i].coverage);
     403             : 
     404           0 :                                 overmask_yuv420p_const_run((u8)fin, cy, s_pY, 1, 0);
     405             : 
     406           0 :                                 memset(surf_uv_alpha + x, (u8)fin, 1);
     407             :                         }
     408             :                 }
     409             :         } else {
     410        1492 :                 for (i=0; i<count; i++) {
     411             :                         char *s_pY;
     412             :                         u32 fin, len;
     413        1492 :                         len = spans[i].len;
     414        1492 :                         s_pY = pY + spans[i].x;
     415        1492 :                         fin = mul255(a, spans[i].coverage);
     416             : 
     417        1492 :                         overmask_yuv420p_const_run((u8)fin, cy, s_pY, len, 0);
     418             : 
     419        1492 :                         memset(surf_uv_alpha + spans[i].x, (u8)fin, len);
     420             :                 }
     421             :         }
     422             :         //we are at an odd line, write uv
     423         396 :         if (write_uv)
     424         226 :                 surf->yuv_flush_uv(surf, surf_uv_alpha, cu, cv, y);
     425         396 : }
     426             : 
     427             : 
     428       71811 : void evg_yuv420p_flush_uv_var(GF_EVGSurface *surf, u8 *surf_uv_alpha, s32 _cu, s32 _cv,  s32 y)
     429             : {
     430             :         u32 i;
     431             :         u8 *pU, *pV;
     432       71811 :         pU = surf->pixels + surf->height *surf->pitch_y;
     433       71811 :         pU += y/2 * surf->pitch_y/2;
     434       71811 :         pV = pU + surf->height/2 * surf->pitch_y/2;
     435             : 
     436       71811 :         if (surf->swap_uv) {
     437             :                 u8 *tmp = pU;
     438             :                 pU = pV;
     439             :                 pV = tmp;
     440             :         }
     441             : 
     442    44114304 :         for (i=0; i<surf->width; i+=2) {
     443             :                 u32 a, a11, a12, a21, a22;
     444    44114304 :                 u32 idx1=3*i;
     445    44114304 :                 u32 idx2=3*i + 3;
     446             :                 //get alpha
     447    44114304 :                 a11 = (u32)surf->uv_alpha[idx1];
     448    44114304 :                 a12 = (u32)surf->uv_alpha[idx2];
     449    44114304 :                 a21 = (u32)surf_uv_alpha[idx1];
     450    44114304 :                 a22 = (u32)surf_uv_alpha[idx2];
     451             : 
     452    44114304 :                 a = a11 + a12 + a21 + a22;
     453    44114304 :                 if (a) {
     454             :                         u8 cdst=0;
     455             :                         u32 chroma_u, chroma_v, c11, c12, c21, c22;
     456             : 
     457     5283243 :                         a /= 4;
     458             :                         //get cb
     459     5283243 :                         idx1 += 1;
     460     5283243 :                         idx2 += 1;
     461             : 
     462     5283243 :                         if (a!=0xFF) {
     463      207408 :                                 cdst = *pU;
     464             :                         }
     465     5283243 :                         c11 = (u32)surf->uv_alpha[idx1];
     466     5416836 :                         if (a11!=0xFF) c11 = mul255_zero(a11, c11 - cdst) + cdst;
     467     5283243 :                         c12 = (u32)surf->uv_alpha[idx2];
     468     5416649 :                         if (a12!=0xFF) c12 = mul255_zero(a12, c12 - cdst) + cdst;
     469     5283243 :                         c21 = (u32)surf_uv_alpha[idx1];
     470     5406840 :                         if (a21!=0xFF) c21 = mul255_zero(a21, c21 - cdst) + cdst;
     471     5283243 :                         c22 = (u32)surf_uv_alpha[idx2];
     472     5407391 :                         if (a22!=0xFF) c22 = mul255_zero(a22, c22 - cdst) + cdst;
     473             : 
     474     5283243 :                         chroma_u = c11 + c12 + c21 + c22;
     475     5283243 :                         chroma_u /= 4;
     476             : 
     477             :                         //get cr
     478     5283243 :                         idx1 += 1;
     479     5283243 :                         idx2 += 1;
     480             : 
     481     5283243 :                         if (a!=0xFF) {
     482      207408 :                                 cdst = *pV;
     483             :                         }
     484     5283243 :                         c11 = (u32)surf->uv_alpha[idx1];
     485     5416836 :                         if (a11!=0xFF) c11 = mul255_zero(a11, c11 - cdst) + cdst;
     486     5283243 :                         c12 = (u32)surf->uv_alpha[idx2];
     487     5416649 :                         if (a12!=0xFF) c12 = mul255_zero(a12, c12 - cdst) + cdst;
     488     5283243 :                         c21 = (u32)surf_uv_alpha[idx1];
     489     5406840 :                         if (a21!=0xFF) c21 = mul255_zero(a21, c21 - cdst) + cdst;
     490     5283243 :                         c22 = (u32)surf_uv_alpha[idx2];
     491     5407391 :                         if (a22!=0xFF) c22 = mul255_zero(a22, c22 - cdst) + cdst;
     492             : 
     493     5283243 :                         chroma_v = c11 + c12 + c21 + c22;
     494     5283243 :                         chroma_v /= 4;
     495             : 
     496     5283243 :                         *pU = chroma_u;
     497     5283243 :                         *pV = chroma_v;
     498             :                 }
     499    44114304 :                 pU++;
     500    44114304 :                 pV++;
     501             :         }
     502             :         //reset for next pass
     503       71811 :         memset(surf->uv_alpha, 0, surf->uv_alpha_alloc);
     504             : 
     505       71811 : }
     506             : 
     507      148489 : void evg_yuv420p_fill_var(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
     508             : {
     509             :         s32 i;
     510      148489 :         char *pY = surf->pixels;
     511             :         u8 *surf_uv_alpha;
     512      148489 :         Bool write_uv = (y%2) ? GF_TRUE : GF_FALSE;
     513             : 
     514      148489 :         if (surf->is_422) {
     515             :                 write_uv = GF_TRUE;
     516        2539 :                 surf_uv_alpha = surf->uv_alpha;
     517      145950 :         } else if (write_uv) {
     518             :                 //second line of storage (we store alpha, cr, cb for each pixel)
     519       72943 :                 surf_uv_alpha = surf->uv_alpha + 3*surf->width;
     520             :         } else {
     521             :                 //first line of storage
     522       73007 :                 surf_uv_alpha = surf->uv_alpha;
     523             :         }
     524             : 
     525      148489 :         pY +=  y * surf->pitch_y;
     526             : 
     527      589701 :         for (i=0; i<count; i++) {
     528             :                 u8 spanalpha, col_a;
     529             :                 char *s_pY;
     530             :                 short x;
     531             :                 u32 *p_col;
     532             :                 u32 len;
     533      441212 :                 len = spans[i].len;
     534      441212 :                 spanalpha = spans[i].coverage;
     535      441212 :                 evg_fill_run(surf->sten, surf, spans[i].x, y, len);
     536      441212 :                 p_col = surf->stencil_pix_run;
     537             : 
     538      441212 :                 s_pY = pY + spans[i].x;
     539      441212 :                 x = spans[i].x;
     540             : 
     541    22705452 :                 while (len--) {
     542    21823028 :                         u32 col = *p_col;
     543    21823028 :                         col_a = GF_COL_A(col);
     544    21823028 :                         if (col_a) {
     545             :                                 u8 cy, cb, cr;
     546    21576435 :                                 u32 idx=3*x;
     547             :                                 //col is directly packed as AYCbCr
     548    21576435 :                                 cy = GF_COL_R(col);
     549    21576435 :                                 cb = GF_COL_G(col);
     550    21576435 :                                 cr = GF_COL_B(col);
     551             : 
     552    21576435 :                                 if ((spanalpha!=0xFF) || (col_a != 0xFF)) {
     553      466254 :                                         overmask_yuv420p(col_a, cy, s_pY, spanalpha);
     554             : 
     555      466254 :                                         u8 a = mul255(col_a, spanalpha);
     556      466254 :                                         surf_uv_alpha[idx] = a;
     557             :                                 } else {
     558    21110181 :                                         *s_pY = cy;
     559    21110181 :                                         surf_uv_alpha[idx] = 0xFF;
     560             :                                 }
     561    21576435 :                                 surf_uv_alpha[idx+1] = cb;
     562    21576435 :                                 surf_uv_alpha[idx+2] = cr;
     563             :                         }
     564    21823028 :                         s_pY++;
     565    21823028 :                         p_col++;
     566    21823028 :                         x++;
     567             :                 }
     568             :         }
     569             :         //compute final u,v for both lines
     570      148489 :         if (write_uv) {
     571       75482 :                 surf->yuv_flush_uv(surf, surf_uv_alpha, 0, 0, y);
     572             :         }
     573      148489 : }
     574             : 
     575          26 : GF_Err evg_surface_clear_yuv420p(GF_EVGSurface *_surf, GF_IRect rc, GF_Color col)
     576             : {
     577             :         s32 i;
     578             :         u8 cy, cb, cr;
     579             :         GF_EVGSurface *surf = (GF_EVGSurface *)_surf;
     580             :         u8 *pY, *pU, *pV;
     581             : 
     582          26 :         pY = surf->pixels + rc.y * surf->pitch_y + rc.x;
     583          26 :         pU = surf->pixels + surf->height * surf->pitch_y + rc.y/2 * surf->pitch_y/2 + rc.x/2;
     584          26 :         pV = surf->pixels + 5*surf->height * surf->pitch_y/4 + rc.y/2 * surf->pitch_y/2 + rc.x/2;
     585          26 :         if (surf->swap_uv) {
     586             :                 u8 *tmp = pU;
     587             :                 pU = pV;
     588             :                 pV = tmp;
     589             :         }
     590             : 
     591          26 :         gf_evg_rgb_to_yuv(surf, col, &cy, &cb, &cr);
     592             : 
     593        7466 :         for (i = 0; i < rc.height; i++) {
     594        7440 :                 memset(pY, cy, rc.width);
     595        7440 :                 pY += surf->pitch_y;
     596        7440 :                 if (i%2) {
     597        3720 :                         memset(pU, cb, rc.width/2);
     598        3720 :                         pU += surf->pitch_y/2;
     599        3720 :                         memset(pV, cr, rc.width/2);
     600        3720 :                         pV += surf->pitch_y/2;
     601             :                 }
     602             :         }
     603          26 :         return GF_OK;
     604             : }
     605             : 
     606             : 
     607             : /*
     608             :                         NV12 / NV21 part
     609             : */
     610             : 
     611             : 
     612         360 : void evg_nv12_flush_uv_const(GF_EVGSurface *surf, u8 *surf_uv_alpha, s32 cu, s32 cv, s32 y)
     613             : {
     614             :         u32 i, a;
     615         360 :         char *pU = surf->pixels + surf->height *surf->pitch_y;
     616         360 :         pU +=  y/2 * surf->pitch_y;
     617             : 
     618       23400 :         for (i=0; i<surf->width; i+=2) {
     619             :                 u8 dst;
     620             : 
     621             :                 //even line
     622       23040 :                 a = surf->uv_alpha[i] + surf->uv_alpha[i+1];
     623             :                 //odd line
     624       23040 :                 a += surf_uv_alpha[i] + surf_uv_alpha[i+1];
     625             : 
     626       23040 :                 if (a) {
     627             :                         char *s_ptr;
     628        3090 :                         a /= 4;
     629             : 
     630        3090 :                         s_ptr = pU + i;
     631        3090 :                         if (a==0xFF) {
     632        1232 :                                 *s_ptr = cu;
     633             : 
     634             :                                 s_ptr++;
     635        1232 :                                 *s_ptr = cv;
     636             :                         } else {
     637        1858 :                                 dst = *(s_ptr);
     638        1858 :                                 *s_ptr = (u8) mul255(a, cu - dst) + dst;
     639             : 
     640             :                                 s_ptr++;
     641        1858 :                                 dst = *(s_ptr);
     642        1858 :                                 *s_ptr = (u8) mul255(a, cv - dst) + dst;
     643             :                         }
     644             :                 }
     645             :         }
     646         360 :         memset(surf->uv_alpha, 0, surf->uv_alpha_alloc);
     647         360 : }
     648             : 
     649        1132 : void evg_nv12_flush_uv_var(GF_EVGSurface *surf, u8 *surf_uv_alpha, s32 cu, s32 cv, s32 y)
     650             : {
     651             :         u32 i;
     652             :         char *pU;
     653        1132 :         pU = surf->pixels + surf->height *surf->pitch_y;
     654        1132 :         pU += y/2 * surf->pitch_y;
     655             : 
     656       73580 :         for (i=0; i<surf->width; i+=2) {
     657             :                 u32 a, a11, a12, a21, a22;
     658             : 
     659       72448 :                 u32 idx1=3*i;
     660       72448 :                 u32 idx2=3*i + 3;
     661             : 
     662             :                 //get alpha
     663       72448 :                 a11 = (u32)surf->uv_alpha[idx1];
     664       72448 :                 a12 = (u32)surf->uv_alpha[idx2];
     665       72448 :                 a21 = (u32)surf_uv_alpha[idx1];
     666       72448 :                 a22 = (u32)surf_uv_alpha[idx2];
     667       72448 :                 a = a11+a12+a21+a22;
     668             : 
     669       72448 :                 if (a) {
     670             :                         u8 cdst=0;
     671             :                         u32 chroma_u, chroma_v, c11, c12, c21, c22;
     672             : 
     673       54726 :                         a /= 4;
     674             : 
     675             :                         //get cb
     676       54726 :                         idx1 += 1;
     677       54726 :                         idx2 += 1;
     678       54726 :                         if (a!=0xFF)
     679        3640 :                                 cdst = pU[surf->idx_u];
     680             : 
     681       54726 :                         c11 = (u32)surf->uv_alpha[idx1];
     682       57592 :                         if (a11!=0xFF) c11 = mul255_zero(a11, c11 - cdst) + cdst;
     683       54726 :                         c12 = (u32)surf->uv_alpha[idx2];
     684       57596 :                         if (a12!=0xFF) c12 = mul255_zero(a12, c12 - cdst) + cdst;
     685       54726 :                         c21 = (u32)surf_uv_alpha[idx1];
     686       57558 :                         if (a21!=0xFF) c21 = mul255_zero(a21, c21 - cdst) + cdst;
     687       54726 :                         c22 = (u32)surf_uv_alpha[idx2];
     688       57566 :                         if (a22!=0xFF) c22 = mul255_zero(a22, c22 - cdst) + cdst;
     689             : 
     690       54726 :                         chroma_u = c11 + c12 + c21 + c22;
     691       54726 :                         chroma_u /= 4;
     692             : 
     693             :                         //get cr
     694       54726 :                         idx1 += 1;
     695       54726 :                         idx2 += 1;
     696             : 
     697       54726 :                         if (a!=0xFF)
     698        3640 :                                 cdst = pU[surf->idx_v];
     699             : 
     700       54726 :                         c11 = (u32)surf->uv_alpha[idx1];
     701       57592 :                         if (a11!=0xFF) c11 = mul255_zero(a11, c11 - cdst) + cdst;
     702       54726 :                         c12 = (u32)surf->uv_alpha[idx2];
     703       57596 :                         if (a12!=0xFF) c12 = mul255_zero(a12, c12 - cdst) + cdst;
     704       54726 :                         c21 = (u32)surf_uv_alpha[idx1];
     705       57558 :                         if (a21!=0xFF) c21 = mul255_zero(a21, c21 - cdst) + cdst;
     706       54726 :                         c22 = (u32)surf_uv_alpha[idx2];
     707       57566 :                         if (a22!=0xFF) c22 = mul255_zero(a22, c22 - cdst) + cdst;
     708             : 
     709       54726 :                         chroma_v = c11 + c12 + c21 + c22;
     710       54726 :                         chroma_v /= 4;
     711             : 
     712       54726 :                         pU[surf->idx_u] = chroma_u;
     713       54726 :                         pU[surf->idx_v] = chroma_v;
     714             :                 }
     715       72448 :                 pU+=2;
     716             :         }
     717             :         //reset for next pass
     718        1132 :         memset(surf->uv_alpha, 0, surf->uv_alpha_alloc);
     719        1132 : }
     720             : 
     721             : 
     722           8 : GF_Err evg_surface_clear_nv12(GF_EVGSurface *_surf, GF_IRect rc, GF_Color col, Bool swap_uv)
     723             : {
     724             :         s32 i;
     725             :         u8 cy, cb, cr;
     726             :         GF_EVGSurface *surf = (GF_EVGSurface *)_surf;
     727           8 :         char *pY = surf->pixels;
     728           8 :         char *pU = surf->pixels + surf->height *surf->pitch_y;
     729             :         char *pU_first;
     730             : 
     731           8 :         pY += rc.y * surf->pitch_y;
     732           8 :         pU +=  rc.y/2 * surf->pitch_y;
     733             : 
     734           8 :         pY += rc.x;
     735           8 :         pU += rc.x/2;
     736             :         pU_first = pU;
     737             : 
     738           8 :         gf_evg_rgb_to_yuv(surf, col, &cy, &cb, &cr);
     739             : 
     740           8 :         if (swap_uv) {
     741           4 :                 u8 t = cb;
     742           4 :                 cb = cr;
     743           4 :                 cr = t;
     744             :         }
     745        1024 :         for (i = 0; i < rc.height; i++) {
     746        1024 :                 memset(pY, cy, rc.width);
     747        1024 :                 pY += surf->pitch_y;
     748        1024 :                 if (i%2) {
     749             :                         //first uv line, build it
     750         512 :                         if (i==1) {
     751             :                                 s32 j;
     752         512 :                                 for (j=0; j<rc.width/2; j++) {
     753         512 :                                         *pU = cb;
     754             :                                         pU++;
     755         512 :                                         *pU = cr;
     756         512 :                                         pU++;
     757             :                                 }
     758             :                         }
     759             :                         //non-first uv line recopy from first
     760             :                         else {
     761             :                                 memcpy(pU, pU_first, rc.width);
     762         504 :                                 pU += surf->pitch_y;
     763             :                         }
     764             :                 }
     765             :         }
     766           8 :         return GF_OK;
     767             : }
     768             : 
     769             : 
     770             : /*
     771             :                         YUV422 part
     772             : */
     773             : 
     774         363 : void evg_yuv422p_flush_uv_const(GF_EVGSurface *surf, u8 *surf_uv_alpha, s32 cu, s32 cv, s32 y)
     775             : {
     776             :         u32 i, a;
     777         363 :         char *pU = surf->pixels + surf->height *surf->pitch_y;
     778             :         char *pV;
     779         363 :         pU +=  y * surf->pitch_y/2;
     780         363 :         pV = pU + surf->height * surf->pitch_y/2;
     781             : 
     782       23595 :         for (i=0; i<surf->width; i+=2) {
     783             :                 u8 dst;
     784             : 
     785       23232 :                 a = surf->uv_alpha[i] + surf->uv_alpha[i+1];
     786             : 
     787       23232 :                 if (a) {
     788             :                         char *s_ptr_u, *s_ptr_v;
     789             : 
     790        2928 :                         a /= 2;
     791        2928 :                         s_ptr_u = pU + i / 2;
     792        2928 :                         s_ptr_v = pV + i / 2;
     793        2928 :                         if (a==0xFF) {
     794        1313 :                                 *s_ptr_u = (u8) cu;
     795        1313 :                                 *s_ptr_v = (u8) cv;
     796             :                         } else {
     797        1615 :                                 dst = *(s_ptr_u);
     798        1615 :                                 *s_ptr_u = (u8) mul255(a, cu - dst) + dst;
     799             : 
     800        1615 :                                 dst = *(s_ptr_v);
     801        1615 :                                 *s_ptr_v = (u8) mul255(a, cv - dst) + dst;
     802             :                         }
     803             :                 }
     804             :         }
     805         363 :         memset(surf->uv_alpha, 0, surf->uv_alpha_alloc);
     806         363 : }
     807             : 
     808        2539 : void evg_yuv422p_flush_uv_var(GF_EVGSurface *surf, u8 *surf_uv_alpha, s32 _cu, s32 _cv,  s32 y)
     809             : {
     810             :         u32 i;
     811             :         char *pU, *pV;
     812        2539 :         pU = surf->pixels + surf->height *surf->pitch_y;
     813        2539 :         pU += y * surf->pitch_y/2;
     814        2539 :         pV = pU + surf->height * surf->pitch_y/2;
     815             : 
     816      165035 :         for (i=0; i<surf->width; i+=2) {
     817             :                 u32 a, a1, a2;
     818      162496 :                 u32 idx1=3*i;
     819      162496 :                 u32 idx2=3*i + 3;
     820             :                 //get alpha
     821      162496 :                 a1 = (u32)surf->uv_alpha[idx1];
     822      162496 :                 a2 = (u32)surf->uv_alpha[idx2];
     823      162496 :                 a = a1+a2;
     824      162496 :                 if (a) {
     825             :                         u8 cdst=0;
     826             :                         u32 chroma_u, chroma_v, c1, c2;
     827             : 
     828      144569 :                         a /= 2;
     829             : 
     830             :                         //get cb
     831      144569 :                         if (a != 0xFF)
     832        3063 :                                 cdst = *pU;
     833             : 
     834      144569 :                         c1 = (u32)surf->uv_alpha[idx1+1];
     835      147149 :                         if (a1!=0xFF) c1 = mul255_zero(a1, c1 - cdst) + cdst;
     836      144569 :                         c2 = (u32)surf->uv_alpha[idx2+1];
     837      147155 :                         if (a2!=0xFF) c2 = mul255_zero(a2, c1 - cdst) + cdst;
     838      144569 :                         chroma_u = c1 + c2;
     839      144569 :                         chroma_u /= 2;
     840             : 
     841             :                         //get cb
     842      144569 :                         if (a != 0xFF)
     843        3063 :                                 cdst = *pV;
     844             : 
     845      144569 :                         c1 = (u32)surf->uv_alpha[idx1+2];
     846      147149 :                         if (a1!=0xFF) c1 = mul255_zero(a1, c1 - cdst) + cdst;
     847      144569 :                         c2 = (u32)surf->uv_alpha[idx2+2];
     848      147155 :                         if (a2!=0xFF) c2 = mul255_zero(a2, c1 - cdst) + cdst;
     849      144569 :                         chroma_v = c1 + c2;
     850      144569 :                         chroma_v /= 2;
     851             : 
     852             : 
     853      144569 :                         *pU = chroma_u;
     854      144569 :                         *pV = chroma_v;
     855             :                 }
     856      162496 :                 pU++;
     857      162496 :                 pV++;
     858             :         }
     859             :         //reset for next pass
     860        2539 :         memset(surf->uv_alpha, 0, surf->uv_alpha_alloc);
     861        2539 : }
     862             : 
     863             : 
     864           9 : GF_Err evg_surface_clear_yuv422p(GF_EVGSurface *_surf, GF_IRect rc, GF_Color col)
     865             : {
     866             :         s32 i;
     867             :         u8 cy, cb, cr;
     868             :         GF_EVGSurface *surf = (GF_EVGSurface *)_surf;
     869           9 :         char *pY = surf->pixels;
     870           9 :         char *pU = surf->pixels + surf->height *surf->pitch_y;
     871             :         char *pV;
     872             : 
     873           9 :         pY += rc.y * surf->pitch_y;
     874           9 :         pU +=  rc.y/2 * surf->pitch_y/2;
     875           9 :         pV = pU + surf->height/2 * surf->pitch_y/2;
     876             : 
     877           9 :         pY += rc.x;
     878           9 :         pU += rc.x/2;
     879           9 :         pV += rc.x/2;
     880             : 
     881           9 :         gf_evg_rgb_to_yuv(surf, col, &cy, &cb, &cr);
     882             : 
     883        1161 :         for (i = 0; i < rc.height; i++) {
     884        1152 :                 memset(pY, cy, rc.width);
     885        1152 :                 pY += surf->pitch_y;
     886        1152 :                 memset(pU, cb, rc.width/2);
     887        1152 :                 pU += surf->pitch_y/2;
     888        1152 :                 memset(pV, cr, rc.width/2);
     889        1152 :                 pV += surf->pitch_y/2;
     890             :         }
     891           9 :         return GF_OK;
     892             : }
     893             : 
     894             : /*
     895             :                         YUV444 part
     896             : */
     897             : 
     898         307 : void evg_yuv444p_fill_const(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
     899             : {
     900             :         char *pY, *pU, *pV;
     901             :         s32 i;
     902             :         u8 cy, cu, cv;
     903             : 
     904         307 :         pY = surf->pixels + y * surf->pitch_y;
     905         307 :         pU = surf->pixels + surf->height*surf->pitch_y + y * surf->pitch_y;
     906         307 :         pV = surf->pixels + 2*surf->height*surf->pitch_y + y * surf->pitch_y;
     907             : 
     908         307 :         cy = GF_COL_R(surf->fill_col);
     909         307 :         cu = GF_COL_G(surf->fill_col);
     910             :         cv = GF_COL_B(surf->fill_col);
     911             : 
     912        2032 :         for (i=0; i<count; i++) {
     913             :                 u32 a;
     914             :                 char *s_pY, *s_pU, *s_pV;
     915             :                 u32 len;
     916        1725 :                 len = spans[i].len;
     917        1725 :                 s_pY = pY + spans[i].x;
     918        1725 :                 s_pU = pU + spans[i].x;
     919        1725 :                 s_pV = pV + spans[i].x;
     920             : 
     921        1725 :                 a = spans[i].coverage;
     922        1725 :                 if (a != 0xFF) {
     923        1428 :                         overmask_yuv420p_const_run((u8)a, cy, s_pY, len, 0);
     924        1428 :                         overmask_yuv420p_const_run((u8)a, cu, s_pU, len, 0);
     925        1428 :                         overmask_yuv420p_const_run((u8)a, cv, s_pV, len, 0);
     926             :                 } else  {
     927        3226 :                         while (len--) {
     928        2929 :                                 *(s_pY) = cy;
     929        2929 :                                 s_pY ++;
     930        2929 :                                 *(s_pU) = cu;
     931        2929 :                                 s_pU ++;
     932        2929 :                                 *(s_pV) = cv;
     933        2929 :                                 s_pV ++;
     934             :                         }
     935             :                 }
     936             :         }
     937         307 : }
     938             : 
     939          56 : void evg_yuv444p_fill_const_a(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
     940             : {
     941             :         u32 a;
     942             :         char *pY, *pU, *pV;
     943             :         s32 i;
     944             :         u8 cy, cu, cv;
     945             : 
     946          56 :         pY = surf->pixels + y * surf->pitch_y;
     947          56 :         pU = surf->pixels + surf->height*surf->pitch_y + y * surf->pitch_y;
     948          56 :         pV = surf->pixels + 2*surf->height*surf->pitch_y + y * surf->pitch_y;
     949             : 
     950          56 :         cy = GF_COL_R(surf->fill_col);
     951          56 :         cu = GF_COL_G(surf->fill_col);
     952             :         cv = GF_COL_B(surf->fill_col);
     953          56 :         a = GF_COL_A(surf->fill_col);
     954             : 
     955          56 :         if (surf->get_alpha) {
     956           0 :                 for (i=0; i<count; i++) {
     957             :                         u32 j;
     958           0 :                         for (j=0; j<spans[i].len; j++) {
     959             :                                 char *s_pY, *s_pU, *s_pV;
     960             :                                 u32 fin;
     961           0 :                                 s32 x = spans[i].x + j;
     962           0 :                                 s_pY = pY + x;
     963           0 :                                 s_pU = pU + x;
     964           0 :                                 s_pV = pV + x;
     965           0 :                                 u8 aa = surf->get_alpha(surf->get_alpha_udta, a, x, y);
     966           0 :                                 fin = mul255(aa, spans[i].coverage);
     967             : 
     968           0 :                                 overmask_yuv420p_const_run((u8)fin, cy, s_pY, 1, 0);
     969           0 :                                 overmask_yuv420p_const_run((u8)fin, cu, s_pU, 1, 0);
     970           0 :                                 overmask_yuv420p_const_run((u8)fin, cv, s_pV, 1, 0);
     971             :                         }
     972             :                 }
     973             :         } else {
     974         244 :                 for (i=0; i<count; i++) {
     975             :                         char *s_pY, *s_pU, *s_pV;
     976             :                         u32 fin, len;
     977         244 :                         len = spans[i].len;
     978         244 :                         s_pY = pY + spans[i].x;
     979         244 :                         s_pU = pU + spans[i].x;
     980         244 :                         s_pV = pV + spans[i].x;
     981         244 :                         fin = mul255(a, spans[i].coverage);
     982             : 
     983         244 :                         overmask_yuv420p_const_run((u8)fin, cy, s_pY, len, 0);
     984         244 :                         overmask_yuv420p_const_run((u8)fin, cu, s_pU, len, 0);
     985         244 :                         overmask_yuv420p_const_run((u8)fin, cv, s_pV, len, 0);
     986             :                 }
     987             :         }
     988          56 : }
     989             : 
     990        2539 : void evg_yuv444p_fill_var(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
     991             : {
     992             :         s32 i;
     993             :         char *pY, *pU, *pV;
     994             : 
     995        2539 :         pY = surf->pixels + y * surf->pitch_y;
     996        2539 :         pU = pY + surf->height*surf->pitch_y;
     997             :         pV = pU + surf->height*surf->pitch_y;
     998             : 
     999        5798 :         for (i=0; i<count; i++) {
    1000             :                 u8 spanalpha, col_a;
    1001             :                 u32 len;
    1002             :                 u32 *p_col;
    1003             :                 char *s_pY, *s_pU, *s_pV;
    1004        3259 :                 len = spans[i].len;
    1005        3259 :                 spanalpha = spans[i].coverage;
    1006        3259 :                 evg_fill_run(surf->sten, surf, spans[i].x, y, len);
    1007        3259 :                 p_col = surf->stencil_pix_run;
    1008             : 
    1009        3259 :                 s_pY = pY + spans[i].x;
    1010        3259 :                 s_pU = pU + spans[i].x;
    1011        3259 :                 s_pV = pV + spans[i].x;
    1012             : 
    1013      306421 :                 while (len--) {
    1014      299903 :                         u32 col = *p_col;
    1015      299903 :                         col_a = GF_COL_A(col);
    1016      299903 :                         if (col_a) {
    1017             :                                 u8 cy, cb, cr;
    1018      288203 :                                 cy = GF_COL_R(col);
    1019      288203 :                                 cb = GF_COL_G(col);
    1020             :                                 cr = GF_COL_B(col);
    1021             : 
    1022      288203 :                                 if ((spanalpha!=0xFF) || (col_a != 0xFF)) {
    1023        4231 :                                         overmask_yuv420p(col_a, cy, s_pY, spanalpha);
    1024             :                                         overmask_yuv420p(col_a, cb, s_pU, spanalpha);
    1025             :                                         overmask_yuv420p(col_a, cr, s_pV, spanalpha);
    1026             :                                 } else {
    1027      283972 :                                         *s_pY = cy;
    1028      283972 :                                         *s_pU = cb;
    1029      283972 :                                         *s_pV = cr;
    1030             :                                 }
    1031             :                         }
    1032      299903 :                         s_pY++;
    1033      299903 :                         s_pU++;
    1034      299903 :                         s_pV++;
    1035      299903 :                         p_col++;
    1036             :                 }
    1037             :         }
    1038        2539 : }
    1039             : 
    1040           9 : GF_Err evg_surface_clear_yuv444p(GF_EVGSurface *_surf, GF_IRect rc, GF_Color col)
    1041             : {
    1042             :         s32 i;
    1043             :         u8 cy, cb, cr;
    1044             :         GF_EVGSurface *surf = (GF_EVGSurface *)_surf;
    1045           9 :         char *pY = surf->pixels;
    1046           9 :         char *pU = surf->pixels + surf->height *surf->pitch_y;
    1047             :         char *pV;
    1048             : 
    1049           9 :         pY += rc.y * surf->pitch_y;
    1050           9 :         pU += rc.y * surf->pitch_y;
    1051             :         pV = pU + surf->height * surf->pitch_y;
    1052             : 
    1053           9 :         pY += rc.x;
    1054           9 :         pU += rc.x;
    1055           9 :         pV += rc.x;
    1056             : 
    1057           9 :         gf_evg_rgb_to_yuv(surf, col, &cy, &cb, &cr);
    1058             : 
    1059        1161 :         for (i = 0; i < rc.height; i++) {
    1060        1152 :                 memset(pY, cy, rc.width);
    1061        1152 :                 pY += surf->pitch_y;
    1062        1152 :                 memset(pU, cb, rc.width);
    1063        1152 :                 pU += surf->pitch_y;
    1064        1152 :                 memset(pV, cr, rc.width);
    1065        1152 :                 pV += surf->pitch_y;
    1066             :         }
    1067           9 :         return GF_OK;
    1068             : }
    1069             : 
    1070             : 
    1071             : /*
    1072             :                         YUYV part
    1073             : */
    1074             : 
    1075             : static void overmask_yuvy(char *dst, u8 c, u32 alpha)
    1076             : {
    1077             :         s32 srca = alpha;
    1078             :         u32 srcc = c;
    1079       47168 :         s32 dstc = (*dst) & 0xFF;
    1080       47168 :         *dst = mul255(srca, srcc - dstc) + dstc;
    1081             : }
    1082        1228 : void evg_yuyv_fill_const(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
    1083             : {
    1084             :         char *pY;
    1085             :         s32 i;
    1086             :         u8 cy, cu, cv;
    1087             : 
    1088        1228 :         if (!count) return;
    1089             : 
    1090        1212 :         pY = surf->pixels + y * surf->pitch_y;
    1091        1212 :         cy = GF_COL_R(surf->fill_col);
    1092        1212 :         cu = GF_COL_G(surf->fill_col);
    1093             :         cv = GF_COL_B(surf->fill_col);
    1094             : 
    1095        8112 :         for (i=0; i<count; i++) {
    1096             :                 char *s_pY;
    1097             :                 u32 len;
    1098        6900 :                 len = spans[i].len;
    1099             :                 //get start of yuyv block: devide x by 2, multiply by 4 (two Y pix packed in 4 bytes)
    1100        6900 :                 s_pY = pY + (spans[i].x/2) * 4;
    1101             :                 //move to first Y in block
    1102        6900 :                 s_pY += surf->idx_y1;
    1103             :                 //if odd pixel move to next one
    1104        6900 :                 if (spans[i].x%2) s_pY += 2;
    1105             : 
    1106        6900 :                 if (spans[i].coverage != 0xFF) {
    1107        5712 :                         memset(surf->uv_alpha + spans[i].x, spans[i].coverage, len);
    1108       11576 :                         while (len--) {
    1109        5864 :                                 overmask_yuvy(s_pY, cy, spans[i].coverage);
    1110        5864 :                                 s_pY += 2;
    1111             :                         }
    1112             :                 } else  {
    1113        1188 :                         memset(surf->uv_alpha + spans[i].x, 0xFF, len);
    1114             : 
    1115       12904 :                         while (len--) {
    1116       11716 :                                 *s_pY = cy;
    1117       11716 :                                 s_pY += 2;
    1118             :                         }
    1119             :                 }
    1120             :         }
    1121             : 
    1122       77568 :         for (i=0; i<(s32) surf->width; i+=2) {
    1123       77568 :                 u32 a = (u32)surf->uv_alpha[i];
    1124       77568 :                 a += (u32)surf->uv_alpha[i + 1];
    1125       77568 :                 if (a) {
    1126        9592 :                         a /=2;
    1127        9592 :                         if (a==0xFF) {
    1128        5252 :                                 pY[surf->idx_u] = cu;
    1129        5252 :                                 pY[surf->idx_v] = cv;
    1130        4340 :                         } else if (a) {
    1131        4284 :                                 overmask_yuvy(pY + surf->idx_u, cu, a);
    1132        4284 :                                 overmask_yuvy(pY + surf->idx_v, cv, a);
    1133             :                         }
    1134             :                 }
    1135       77568 :                 pY+=4;
    1136             :         }
    1137        1212 :         memset(surf->uv_alpha, 0, surf->uv_alpha_alloc);
    1138             : }
    1139             : 
    1140         224 : void evg_yuyv_fill_const_a(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
    1141             : {
    1142             :         char *pY;
    1143             :         s32 i;
    1144             :         u8 cy, cu, cv, a;
    1145             : 
    1146         224 :         pY = surf->pixels + y * surf->pitch_y;
    1147         224 :         cy = GF_COL_R(surf->fill_col);
    1148         224 :         cu = GF_COL_G(surf->fill_col);
    1149             :         cv = GF_COL_B(surf->fill_col);
    1150         224 :         a = GF_COL_A(surf->fill_col);
    1151             : 
    1152        1200 :         for (i=0; i<count; i++) {
    1153             :                 char *s_pY;
    1154             :                 u32 fin, len;
    1155         976 :                 len = spans[i].len;
    1156         976 :                 s_pY = pY + (spans[i].x/2) * 4;
    1157         976 :                 if (spans[i].x%2) s_pY += 2;
    1158             : 
    1159         976 :                 fin = mul255(a, spans[i].coverage);
    1160             : 
    1161         976 :                 memset(surf->uv_alpha + spans[i].x, (u8)fin, len);
    1162        5000 :                 while (len--) {
    1163        4024 :                         overmask_yuvy(s_pY + surf->idx_y1, cy, fin);
    1164        4024 :                         s_pY += 2;
    1165             :                 }
    1166             :         }
    1167         224 :         pY = surf->pixels + y * surf->pitch_y;
    1168       14560 :         for (i=0; i<(s32) surf->width; i+=2) {
    1169       14336 :                 u32 p_a = surf->uv_alpha[i];
    1170       14336 :                 p_a += surf->uv_alpha[i + 1];
    1171       14336 :                 p_a /=2;
    1172       14336 :                 if (p_a==0xFF) {
    1173           0 :                         pY[surf->idx_u] = cu;
    1174           0 :                         pY[surf->idx_v] = cv;
    1175       14336 :                 } else if (p_a) {
    1176        2104 :                         overmask_yuvy(pY + surf->idx_u, cu, p_a);
    1177        2104 :                         overmask_yuvy(pY + surf->idx_v, cv, p_a);
    1178             :                 }
    1179       14336 :                 pY+=4;
    1180             :         }
    1181         224 :         memset(surf->uv_alpha, 0, surf->uv_alpha_alloc);
    1182             : 
    1183         224 : }
    1184             : 
    1185        4524 : void evg_yuyv_fill_var(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
    1186             : {
    1187             :         s32 i;
    1188             :         char *pY;
    1189             : 
    1190        4524 :         pY = surf->pixels + y * surf->pitch_y;
    1191             : 
    1192       11928 :         for (i=0; i<count; i++) {
    1193             :                 u8 spanalpha, col_a;
    1194             :                 u32 *p_col;
    1195             :                 char *s_pY;
    1196             :                 u32 len, x;
    1197        7404 :                 len = spans[i].len;
    1198        7404 :                 s_pY = pY + (spans[i].x/2) * 4;
    1199        7404 :                 if (spans[i].x%2) s_pY += 2;
    1200             : 
    1201        7404 :                 spanalpha = spans[i].coverage;
    1202        7404 :                 evg_fill_run(surf->sten, surf, spans[i].x, y, len);
    1203        7404 :                 p_col = surf->stencil_pix_run;
    1204             : 
    1205        7404 :                 x = spans[i].x;
    1206             : 
    1207      493524 :                 while (len--) {
    1208      478716 :                         u32 col = *p_col;
    1209      478716 :                         col_a = GF_COL_A(col);
    1210      478716 :                         if (col_a) {
    1211      431916 :                                 u32 idx=3*x;
    1212             :                                 u8 cy, cb, cr;
    1213      431916 :                                 cy = GF_COL_R(col);
    1214      431916 :                                 cb = GF_COL_G(col);
    1215      431916 :                                 cr = GF_COL_B(col);
    1216             : 
    1217      431916 :                                 if ((spanalpha!=0xFF) || (col_a != 0xFF)) {
    1218       16924 :                                         overmask_yuv420p(col_a, cy, s_pY + surf->idx_y1, spanalpha);
    1219             : 
    1220       16924 :                                         u8 a = mul255(col_a, spanalpha);
    1221       16924 :                                         surf->uv_alpha[idx] = a;
    1222             :                                 } else {
    1223      414992 :                                         s_pY[surf->idx_y1] = cy;
    1224      414992 :                                         surf->uv_alpha[idx] = 0xFF;
    1225             :                                 }
    1226      431916 :                                 surf->uv_alpha[idx+1] = cb;
    1227      431916 :                                 surf->uv_alpha[idx+2] = cr;
    1228             :                         }
    1229      478716 :                         s_pY+=2;
    1230      478716 :                         p_col++;
    1231      478716 :                         x++;
    1232             :                 }
    1233             :         }
    1234        4524 :         pY = surf->pixels + y * surf->pitch_y;
    1235      294060 :         for (i=0; i<(s32)surf->width; i+=2) {
    1236             :                 u32 a;
    1237      289536 :                 u32 idx1=3*i;
    1238      289536 :                 u32 idx2=3*i + 3;
    1239             :                 //get alpha
    1240      289536 :                 a = (u32)surf->uv_alpha[idx1] + (u32)surf->uv_alpha[idx2];
    1241      289536 :                 if (a) {
    1242             :                         u32 chroma;
    1243             : 
    1244      217828 :                         a /= 2;
    1245             : 
    1246             :                         //get cb
    1247      217828 :                         chroma = (u32)surf->uv_alpha[idx1+1] + (u32)surf->uv_alpha[idx2+1];
    1248      217828 :                         chroma /= 2;
    1249      217828 :                         if (a==0xFF) {
    1250      205576 :                                 pY[surf->idx_u] = chroma;
    1251             :                         } else {
    1252       12252 :                                 overmask_yuvy(pY + surf->idx_u, chroma, a);
    1253             :                         }
    1254             :                         //get cr
    1255      217828 :                         chroma = (u32)surf->uv_alpha[idx1+2] + (u32)surf->uv_alpha[idx2+2];
    1256      217828 :                         chroma /= 2;
    1257      217828 :                         if (a==0xFF) {
    1258      205576 :                                 pY[surf->idx_v] = chroma;
    1259             :                         } else {
    1260       12252 :                                 overmask_yuvy(pY + surf->idx_v, chroma, a);
    1261             :                         }
    1262             :                 }
    1263      289536 :                 pY+=4;
    1264             :         }
    1265             : 
    1266        4524 :         memset(surf->uv_alpha, 0, surf->uv_alpha_alloc);
    1267             : 
    1268        4524 : }
    1269             : 
    1270          16 : GF_Err evg_surface_clear_yuyv(GF_EVGSurface *_surf, GF_IRect rc, GF_Color col)
    1271             : {
    1272             :         u32 i;
    1273             :         s32 j;
    1274             :         u8 cy, cb, cr;
    1275             :         GF_EVGSurface *surf = (GF_EVGSurface *)_surf;
    1276             :         char *o_pY;
    1277          16 :         char *pY = surf->pixels;
    1278          16 :         pY += rc.y * surf->pitch_y;
    1279          16 :         pY += (rc.x/2) * 4;
    1280             : 
    1281          16 :         gf_evg_rgb_to_yuv(surf, col, &cy, &cb, &cr);
    1282             :         o_pY = pY;
    1283        2064 :         for (i = 0; i <(u32)rc.height; i++) {
    1284        2048 :                 if (!i) {
    1285             :                         char *dst = pY;
    1286        1024 :                         for (j = 0; j < rc.width/2; j++) {
    1287        1024 :                                 dst[surf->idx_y1] = cy;
    1288        1024 :                                 dst[surf->idx_u] = cb;
    1289        1024 :                                 dst[surf->idx_y1 + 2] = cy;
    1290        1024 :                                 dst[surf->idx_v] = cr;
    1291        1024 :                                 dst += 4;
    1292             :                         }
    1293             :                 } else {
    1294        2032 :                         memcpy(pY, o_pY, rc.width*2);
    1295             :                 }
    1296        2048 :                 pY += surf->pitch_y;
    1297             :         }
    1298          16 :         return GF_OK;
    1299             : }
    1300             : 
    1301             : 
    1302             : #ifdef GPAC_BIG_ENDIAN
    1303             : 
    1304             : #define set_u16_le(_ptr, val) { ((u8 *)_ptr)[0] = (val>>8)&0xFF;  ((u8 *)_ptr)[1] = (val&0xFF); }
    1305             : #define set_u16_be(_ptr, val) { *(u16 *) _ptr = (u16) val; }
    1306             : 
    1307             : #define get_u16_le(val, _ptr) { val = ((u32) (*(u8 *) _ptr+1)<< 8) | *(u8 *) _ptr; }
    1308             : #define get_u16_be(val, _ptr) { val = *(u16 *) (_ptr); }
    1309             : 
    1310             : #else
    1311             : 
    1312             : #define set_u16_le(_ptr, val) { (*(u16 *) _ptr) = (u16) val; }
    1313             : #define set_u16_be(_ptr, val) { ((u8 *)_ptr)[0] = (val>>8)&0xFF;  ((u8 *)_ptr)[1] = (val&0xFF); }
    1314             : 
    1315             : #define get_u16_le(val, _ptr) { val = *(u16 *) (_ptr); }
    1316             : #define get_u16_be(val, _ptr) { val = ((u32) (*(u8 *) _ptr)<< 8) | *(u8 *) _ptr+1; }
    1317             : 
    1318             : #endif
    1319             : 
    1320             : 
    1321             : /*
    1322             :                         YUV420p-10 part
    1323             : */
    1324             : static s32
    1325             : mul_10(s64 a, s64 b)
    1326             : {
    1327      224422 :         return (s32) ( ((a + 1) * b) >> 16);
    1328             : }
    1329             : 
    1330             : static s32
    1331             : mul_10_zero(s64 a, s64 b)
    1332             : {
    1333      131480 :         if (!a) return 0;
    1334      128228 :         return (s32) ( ((a + 1) * b) >> 16);
    1335             : }
    1336             : 
    1337             : static void overmask_yuv420p_10(u16 col_a, u16 cy, u16 *dst, u32 alpha)
    1338             : {
    1339             :         s32 srca = col_a;
    1340      111925 :         u32 srcc = cy;
    1341             :         s32 dstc;
    1342      111925 :         get_u16_le(dstc, dst);
    1343             : 
    1344       80063 :         srca = mul_10(srca, alpha);
    1345      223850 :         set_u16_le(dst, (mul_10(srca, srcc - dstc) + dstc) );
    1346             : }
    1347             : 
    1348             : static void overmask_yuv420p_10_const_run(u16 a, u16 val, u16 *ptr, u32 count, short x)
    1349             : {
    1350       29008 :         while (count) {
    1351             :                 u16 dst;
    1352       17304 :                 get_u16_le(dst, ptr);
    1353       34608 :                 set_u16_le(ptr, (u16) (mul_10(a, val - dst) + dst));
    1354       17304 :                 ptr ++;
    1355       17304 :                 count--;
    1356             :         }
    1357             : }
    1358             : 
    1359         180 : void evg_yuv420p_10_flush_uv_const(GF_EVGSurface *surf, u8 *_surf_uv_alpha, s32 cu, s32 cv, s32 y)
    1360             : {
    1361             :         u32 i, a;
    1362         180 :         u16 *surf_uv_alpha_even = (u16 *) surf->uv_alpha;
    1363             :         u16 *surf_uv_alpha_odd = (u16 *) _surf_uv_alpha;
    1364         180 :         char *pU = surf->pixels + surf->height *surf->pitch_y;
    1365             :         char *pV;
    1366         180 :         pU +=  y/2 * surf->pitch_y/2;
    1367         180 :         pV = pU + surf->height/2 * surf->pitch_y/2;
    1368             : 
    1369             :         //we are at an odd line, write uv
    1370       11700 :         for (i=0; i<surf->width; i+=2) {
    1371             :                 u16 dst;
    1372             : 
    1373             :                 //even line
    1374       11520 :                 a = surf_uv_alpha_even[i] + surf_uv_alpha_even[i+1];
    1375             :                 //odd line
    1376       11520 :                 a += surf_uv_alpha_odd[i] + surf_uv_alpha_odd[i+1];
    1377             : 
    1378       11520 :                 if (a) {
    1379             :                         u16 *s_ptr_u, *s_ptr_v;
    1380             : 
    1381        1545 :                         a /= 4;
    1382             : 
    1383        1545 :                         s_ptr_u = ((u16 *) pU) + i/2;
    1384        1545 :                         s_ptr_v = ((u16 *) pV) + i/2;
    1385        1545 :                         if (a==0xFFFF) {
    1386           0 :                                 set_u16_le(s_ptr_u, cu);
    1387           0 :                                 set_u16_le(s_ptr_v, cv);
    1388             :                         } else {
    1389        1545 :                                 get_u16_le(dst, s_ptr_u);
    1390        3090 :                                 set_u16_le(s_ptr_u, (u16) (mul_10(a, cu - dst) + dst) );
    1391        1545 :                                 get_u16_le(dst, s_ptr_v);
    1392        3090 :                                 set_u16_le(s_ptr_v, (u16) (mul_10(a, cv - dst) + dst) );
    1393             :                         }
    1394             :                 }
    1395             :         }
    1396         180 :         memset(surf->uv_alpha, 0, surf->uv_alpha_alloc);
    1397         180 : }
    1398             : 
    1399        1228 : void evg_yuv420p_10_fill_const(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
    1400             : {
    1401             :         u16 *pY;
    1402             :         u16 *surf_uv_alpha;
    1403             :         s32 i;
    1404             :         u16 cy, cu, cv;
    1405        1228 :         Bool write_uv = (y%2) ? GF_TRUE : GF_FALSE;
    1406             : 
    1407        1228 :         if (surf->is_422) {
    1408             :                 write_uv = GF_TRUE;
    1409         307 :                 surf_uv_alpha = (u16 *)surf->uv_alpha;
    1410             :         }
    1411         921 :         else if (write_uv) {
    1412         456 :                 surf_uv_alpha = ((u16 *)surf->uv_alpha) + surf->width;
    1413             :         } else {
    1414         465 :                 surf_uv_alpha = (u16 *)surf->uv_alpha;
    1415             :         }
    1416             : 
    1417        1228 :         pY =  (u16 *) (surf->pixels + y * surf->pitch_y);
    1418             : 
    1419        1228 :         cy = (surf->fill_col_wide>>32) & 0xFFFF;
    1420        1228 :         cy >>=6;
    1421        1228 :         cu = (surf->fill_col_wide>>16) & 0xFFFF;
    1422        1228 :         cu >>=6;
    1423        1228 :         cv = (surf->fill_col_wide) & 0xFFFF;
    1424        1228 :         cv >>=6;
    1425             : 
    1426        8128 :         for (i=0; i<count; i++) {
    1427             :                 u32 a;
    1428             :                 u16 *s_pY;
    1429             :                 u32 j, len;
    1430        6900 :                 len = spans[i].len;
    1431        6900 :                 s_pY = pY + spans[i].x;
    1432             : 
    1433        6900 :                 a = 0xFF * spans[i].coverage;
    1434       24480 :                 for (j=0; j<len; j++) {
    1435       17580 :                         surf_uv_alpha[spans[i].x + j] = a;
    1436             :                 }
    1437             : 
    1438        6900 :                 if (spans[i].coverage != 0xFF) {
    1439        5712 :                         overmask_yuv420p_10_const_run(a, cy, s_pY, len, 0);
    1440             :                 } else  {
    1441       12904 :                         while (len--) {
    1442       11716 :                                 set_u16_le(s_pY, cy);
    1443       11716 :                                 s_pY ++;
    1444             :                         }
    1445             :                 }
    1446             :         }
    1447        1228 :         if (write_uv) {
    1448         763 :                 surf->yuv_flush_uv(surf, (u8 *)surf_uv_alpha, cu, cv, y);
    1449             :         }
    1450             : 
    1451        1228 : }
    1452             : 
    1453         224 : void evg_yuv420p_10_fill_const_a(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
    1454             : {
    1455             :         u32 a;
    1456             :         u16 *pY;
    1457             :         u16 *surf_uv_alpha;
    1458             :         s32 i;
    1459             :         u16 cy, cu, cv;
    1460         224 :         Bool write_uv = (y%2) ? GF_TRUE : GF_FALSE;
    1461             : 
    1462         224 :         if (surf->is_422) {
    1463             :                 write_uv = GF_TRUE;
    1464          56 :                 surf_uv_alpha = (u16 *)surf->uv_alpha;
    1465         168 :         } else if (write_uv) {
    1466          84 :                 surf_uv_alpha = (u16 *)surf->uv_alpha + surf->width;
    1467             :         } else {
    1468          84 :                 surf_uv_alpha = (u16 *)surf->uv_alpha;
    1469             :         }
    1470             : 
    1471         224 :         pY = (u16 *) (surf->pixels + y * surf->pitch_y);
    1472             : 
    1473             : 
    1474         224 :         a = (surf->fill_col_wide>>48) & 0xFFFF;
    1475         224 :         cy = (surf->fill_col_wide>>32) & 0xFFFF;
    1476         224 :         cy >>=6;
    1477         224 :         cu = (surf->fill_col_wide>>16) & 0xFFFF;
    1478         224 :         cu >>=6;
    1479         224 :         cv = (surf->fill_col_wide) & 0xFFFF;
    1480         224 :         cv >>=6;
    1481             : 
    1482         224 :         if (surf->get_alpha) {
    1483           0 :                 for (i=0; i<count; i++) {
    1484             :                         u32 j;
    1485           0 :                         for (j=0; j<spans[i].len; j++) {
    1486             :                                 u16 *s_pY;
    1487             :                                 u32 fin;
    1488           0 :                                 s32 x = spans[i].x + j;
    1489           0 :                                 s_pY = pY + x;
    1490           0 :                                 fin = surf->get_alpha(surf->get_alpha_udta, a, x, y) * spans[i].coverage;
    1491           0 :                                 fin /= 0xFF;
    1492             : 
    1493           0 :                                 overmask_yuv420p_10_const_run(fin, cy, s_pY, 1, 0);
    1494           0 :                                 surf_uv_alpha[x] = fin;
    1495             :                         }
    1496             :                 }
    1497             :         } else {
    1498         976 :                 for (i=0; i<count; i++) {
    1499             :                         u16 *s_pY;
    1500             :                         u32 fin, len, j;
    1501         976 :                         len = spans[i].len;
    1502         976 :                         s_pY = pY + spans[i].x;
    1503         976 :                         fin = a * spans[i].coverage;
    1504         976 :                         fin /= 0xFF;
    1505             : 
    1506         976 :                         overmask_yuv420p_10_const_run(fin, cy, s_pY, len, 0);
    1507             : 
    1508        4024 :                         for (j=0; j<len; j++) {
    1509        4024 :                                 surf_uv_alpha[spans[i].x + j] = fin;
    1510             :                         }
    1511             :                 }
    1512             :         }
    1513             :         //we are at an odd line, write uv
    1514         224 :         if (write_uv)
    1515         140 :                 surf->yuv_flush_uv(surf, (u8*)surf_uv_alpha, cu, cv, y);
    1516         224 : }
    1517             : 
    1518         622 : void evg_yuv420p_10_flush_uv_var(GF_EVGSurface *surf, u8 *_surf_uv_alpha, s32 _cu, s32 _cv,  s32 y)
    1519             : {
    1520             :         u32 i;
    1521         622 :         u16 *surf_uv_alpha_even = (u16 *) surf->uv_alpha;
    1522             :         u16 *surf_uv_alpha_odd = (u16 *) _surf_uv_alpha;
    1523             :         u16 *pU, *pV;
    1524         622 :         pU = (u16 *) (surf->pixels + surf->height *surf->pitch_y + y/2 * surf->pitch_y/2);
    1525         622 :         pV = (u16 *) (surf->pixels + 5*surf->height *surf->pitch_y/4 + y/2 * surf->pitch_y/2);
    1526             : 
    1527       37742 :         for (i=0; i<surf->width; i+=2) {
    1528             :                 u32 a, a11, a12, a21, a22;
    1529       37120 :                 u32 idx1=3*i;
    1530       37120 :                 u32 idx2=3*i + 3;
    1531             : 
    1532             :                 //get alpha
    1533       37120 :                 a11 = (u32)surf_uv_alpha_even[idx1];
    1534       37120 :                 a12 = (u32)surf_uv_alpha_even[idx2];
    1535       37120 :                 a21 = (u32)surf_uv_alpha_odd[idx1];
    1536       37120 :                 a22 = (u32)surf_uv_alpha_odd[idx2];
    1537             : 
    1538       37120 :                 a = a11+a12+a21+a22;
    1539       37120 :                 if (a) {
    1540             :                         s32 cdst=0;
    1541             :                         s32 chroma_u, chroma_v, c11, c12, c21, c22;
    1542             : 
    1543       30177 :                         a /= 4;
    1544             : 
    1545             :                         //get cb
    1546       30177 :                         idx1 += 1;
    1547       30177 :                         idx2 += 1;
    1548             : 
    1549       30177 :                         if (a!=0xFFFF) {
    1550        4634 :                                 get_u16_le(cdst, pU);
    1551             :                         }
    1552       30177 :                         c11 = (u32)surf_uv_alpha_even[idx1];
    1553       34424 :                         if (a11!=0xFFFF) c11 = mul_10_zero(a11, c11 - cdst) + cdst;
    1554       30177 :                         c12 = (u32)surf_uv_alpha_even[idx2];
    1555       34426 :                         if (a12!=0xFFFF) c12 = mul_10_zero(a12, c12 - cdst) + cdst;
    1556       30177 :                         c21 = (u32)surf_uv_alpha_odd[idx1];
    1557       34407 :                         if (a21!=0xFFFF) c21 = mul_10_zero(a21, c21 - cdst) + cdst;
    1558       30177 :                         c22 = (u32)surf_uv_alpha_odd[idx2];
    1559       34411 :                         if (a22!=0xFFFF) c22 = mul_10_zero(a22, c22 - cdst) + cdst;
    1560             : 
    1561       30177 :                         chroma_u = c11 + c12 + c21 + c22;
    1562       30177 :                         chroma_u /= 4;
    1563       30177 :                         set_u16_le(pU, (u16) chroma_u);
    1564             : 
    1565             :                         //get cr
    1566       30177 :                         idx1 += 1;
    1567       30177 :                         idx2 += 1;
    1568             : 
    1569       30177 :                         if (a!=0xFFFF) {
    1570        4634 :                                 get_u16_le(cdst, pV);
    1571             :                         }
    1572       30177 :                         c11 = (u32)surf_uv_alpha_even[idx1];
    1573       34424 :                         if (a11!=0xFFFF) c11 = mul_10_zero(a11, c11 - cdst) + cdst;
    1574       30177 :                         c12 = (u32)surf_uv_alpha_even[idx2];
    1575       34426 :                         if (a12!=0xFFFF) c12 = mul_10_zero(a12, c12 - cdst) + cdst;
    1576       30177 :                         c21 = (u32)surf_uv_alpha_odd[idx1];
    1577       34407 :                         if (a21!=0xFFFF) c21 = mul_10_zero(a21, c21 - cdst) + cdst;
    1578       30177 :                         c22 = (u32)surf_uv_alpha_odd[idx2];
    1579       34411 :                         if (a22!=0xFFFF) c22 = mul_10_zero(a22, c22 - cdst) + cdst;
    1580             : 
    1581       30177 :                         chroma_v = c11 + c12 + c21 + c22;
    1582       30177 :                         chroma_v /= 4;
    1583       30177 :                         set_u16_le(pV, (u16) chroma_v);
    1584             :                 }
    1585       37120 :                 pU++;
    1586       37120 :                 pV++;
    1587             :         }
    1588             :         //reset for next pass
    1589         622 :         memset(surf->uv_alpha, 0, surf->uv_alpha_alloc);
    1590             : 
    1591         622 : }
    1592             : 
    1593        4628 : void evg_yuv420p_10_fill_var(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
    1594             : {
    1595             :         s32 i;
    1596             :         u16 *pY;
    1597             :         u16 *surf_uv_alpha;
    1598        4628 :         Bool write_uv = (y%2) ? GF_TRUE : GF_FALSE;
    1599             : 
    1600        4628 :         if (surf->is_422) {
    1601             :                 write_uv = GF_TRUE;
    1602        1131 :                 surf_uv_alpha = (u16 *) surf->uv_alpha;
    1603        3497 :         } else if (write_uv) {
    1604             :                 //second line of storage (we store alpha, cr, cb for each pixel)
    1605        1754 :                 surf_uv_alpha =  ((u16 *) surf->uv_alpha) + 3*surf->width;
    1606             :         } else {
    1607             :                 //first line of storage
    1608        1743 :                 surf_uv_alpha =  (u16 *) surf->uv_alpha;
    1609             :         }
    1610             : 
    1611        4628 :         pY = (u16 *) (surf->pixels + y * surf->pitch_y);
    1612             : 
    1613       12440 :         for (i=0; i<count; i++) {
    1614             :                 u8 spanalpha;
    1615             :                 u32 len;
    1616             :                 u64 *p_col;
    1617             :                 u16 *s_pY;
    1618             :                 short x;
    1619        7812 :                 len = spans[i].len;
    1620        7812 :                 spanalpha = spans[i].coverage;
    1621        7812 :                 evg_fill_run(surf->sten, surf, spans[i].x, y, len);
    1622        7812 :                 p_col = surf->stencil_pix_run;
    1623             : 
    1624        7812 :                 s_pY = pY + spans[i].x;
    1625        7812 :                 x = spans[i].x;
    1626             : 
    1627      494748 :                 while (len--) {
    1628      479124 :                         u64 col = *p_col;
    1629      479124 :                         u32 col_a = (col>>48)&0xFFFF;
    1630      479124 :                         if (col_a) {
    1631             :                                 u16 cy, cb, cr;
    1632      479124 :                                 u32 idx=3*x;
    1633             :                                 //col is directly packed as AYCbCr
    1634      479124 :                                 cy = ((col>>32) & 0xFFFF) >> 6;
    1635      479124 :                                 cb = ((col>>16) & 0xFFFF) >> 6;
    1636      479124 :                                 cr = ((col) & 0xFFFF) >> 6;
    1637             : 
    1638      479124 :                                 if ((spanalpha!=0xFF) || (col_a != 0xFFFF)) {
    1639       64132 :                                         u16 spana = spanalpha;
    1640       64132 :                                         spana <<= 8;
    1641             :                                         overmask_yuv420p_10(col_a, cy, s_pY, spana);
    1642       64132 :                                         surf_uv_alpha[idx] = mul_10(col_a, spana);
    1643             :                                 } else {
    1644      414992 :                                         set_u16_le(s_pY, cy);
    1645      414992 :                                         surf_uv_alpha[idx] = 0xFFFF;
    1646             :                                 }
    1647      479124 :                                 surf_uv_alpha[idx+1] = cb;
    1648      479124 :                                 surf_uv_alpha[idx+2] = cr;
    1649             :                         }
    1650      479124 :                         s_pY++;
    1651      479124 :                         p_col++;
    1652      479124 :                         x++;
    1653             :                 }
    1654             :         }
    1655             :         //compute final u,v for both lines
    1656        4628 :         if (write_uv) {
    1657        2885 :                 surf->yuv_flush_uv(surf, (u8 *)surf_uv_alpha, 0, 0, y);
    1658             :         }
    1659        4628 : }
    1660             : 
    1661           4 : GF_Err evg_surface_clear_yuv420p_10(GF_EVGSurface *_surf, GF_IRect rc, GF_Color col)
    1662             : {
    1663             :         s32 i, j;
    1664             :         u8 _cy, _cb, _cr;
    1665             :         u16 cy, cb, cr;
    1666             :         GF_EVGSurface *surf = (GF_EVGSurface *)_surf;
    1667             :         u16 *pY, *pU, *pV, *o_pY, *o_pU, *o_pV;
    1668             : 
    1669           4 :         pY = (u16 *) (surf->pixels + rc.y * surf->pitch_y + 2*rc.x);
    1670           4 :         pU = (u16 *) (surf->pixels + surf->height * surf->pitch_y + rc.y/2 * surf->pitch_y/2 + rc.x);
    1671           4 :         pV = (u16 *) (surf->pixels + 5*surf->height * surf->pitch_y/4 + rc.y/2 * surf->pitch_y/2 + rc.x);
    1672             : 
    1673           4 :         gf_evg_rgb_to_yuv(surf, col, &_cy, &_cb, &_cr);
    1674           4 :         cy = ((u16)_cy) << 2;
    1675           4 :         cb = ((u16)_cb) << 2;
    1676           4 :         cr = ((u16)_cr) << 2;
    1677             :         o_pY = pY;
    1678             :         o_pU = pU;
    1679             :         o_pV = pV;
    1680         516 :         for (i = 0; i <rc.height; i++) {
    1681         512 :                 if (!i) {
    1682           4 :                         if (cy) {
    1683           0 :                                 for (j=0; j<rc.width; j++)
    1684           0 :                                         set_u16_le(&pY[j] , cy);
    1685             :                         } else {
    1686           4 :                                 memset(pY, 0, rc.width*2);
    1687             :                         }
    1688             :                 } else {
    1689         508 :                         memcpy(pY, o_pY, rc.width*2);
    1690             :                 }
    1691             :                 //pitch is in bytes, we are in short
    1692         512 :                 pY += surf->pitch_y/2;
    1693             : 
    1694         512 :                 if (i%2) continue;
    1695             : 
    1696         256 :                 if (!i) {
    1697         256 :                         for (j=0; j<rc.width/2; j++) {
    1698         256 :                                 set_u16_le(&pU[j], cb);
    1699         256 :                                 set_u16_le(&pV[j], cr);
    1700             :                         }
    1701             :                 } else {
    1702         252 :                         memcpy(pU, o_pU, rc.width);//half width at 2 bytes per short
    1703             :                         memcpy(pV, o_pV, rc.width);
    1704             :                 }
    1705             :                 //pitch is in bytes, we are in short
    1706         256 :                 pU += surf->pitch_y/4;
    1707         256 :                 pV += surf->pitch_y/4;
    1708             :         }
    1709           4 :         return GF_OK;
    1710             : }
    1711             : 
    1712             : /*
    1713             :                         NV12 / NV21 10 bit part
    1714             : */
    1715             : 
    1716             : 
    1717         360 : void evg_nv12_10_flush_uv_const(GF_EVGSurface *surf, u8 *_surf_uv_alpha, s32 cu, s32 cv, s32 y)
    1718             : {
    1719             :         u32 i, a;
    1720         360 :         u16 *surf_uv_alpha_even = (u16 *) surf->uv_alpha;
    1721             :         u16 *surf_uv_alpha_odd = (u16 *)_surf_uv_alpha;
    1722         360 :         u8 *pUV = surf->pixels + surf->height * surf->pitch_y + y/2 * surf->pitch_y;
    1723         360 :         u8 *pU = pUV + 2*surf->idx_u;
    1724         360 :         u8 *pV = pUV + 2*surf->idx_v;
    1725             : 
    1726       23400 :         for (i=0; i<surf->width; i+=2) {
    1727             :                 //even line
    1728       23040 :                 a = surf_uv_alpha_even[i] + surf_uv_alpha_even[i+1];
    1729             :                 //odd line
    1730       23040 :                 a += surf_uv_alpha_odd[i] + surf_uv_alpha_odd[i+1];
    1731             : 
    1732       23040 :                 if (a) {
    1733             :                         s32 dst;
    1734        3090 :                         a /= 4;
    1735             : 
    1736        3090 :                         if (a==0xFFFF) {
    1737           0 :                                 set_u16_le(pU, cu);
    1738           0 :                                 set_u16_le(pV, cv);
    1739             :                         } else {
    1740        3090 :                                 get_u16_le(dst, pU);
    1741        6180 :                                 set_u16_le(pU, (u16) (mul_10(a, cu - dst) + dst) );
    1742        3090 :                                 get_u16_le(dst, pV);
    1743        6180 :                                 set_u16_le(pV, (u16) (mul_10(a, cv - dst) + dst) );
    1744             :                         }
    1745             :                 }
    1746       23040 :                 pU += 4;
    1747       23040 :                 pV += 4;
    1748             :         }
    1749         360 :         memset(surf->uv_alpha, 0, surf->uv_alpha_alloc);
    1750         360 : }
    1751             : 
    1752             : 
    1753        1132 : void evg_nv12_10_flush_uv_var(GF_EVGSurface *surf, u8 *_surf_uv_alpha, s32 cu, s32 cv, s32 y)
    1754             : {
    1755             :         u32 i;
    1756        1132 :         u16 *surf_uv_alpha_even = (u16 *) surf->uv_alpha;
    1757             :         u16 *surf_uv_alpha_odd = (u16 *) _surf_uv_alpha;
    1758        1132 :         u8 *pUV = surf->pixels + surf->height *surf->pitch_y + y/2 * surf->pitch_y;
    1759        1132 :         u8 *pU = pUV + 2*surf->idx_u;
    1760        1132 :         u8 *pV = pUV + 2*surf->idx_v;
    1761             : 
    1762       73580 :         for (i=0; i<surf->width; i+=2) {
    1763             :                 u32 a, a11, a12, a21, a22;
    1764       72448 :                 u32 idx1=3*i;
    1765       72448 :                 u32 idx2=3*i + 3;
    1766             :                 //get alpha
    1767       72448 :                 a11 = (u32)surf_uv_alpha_even[idx1];
    1768       72448 :                 a12 = (u32)surf_uv_alpha_even[idx2];
    1769       72448 :                 a21 = (u32)surf_uv_alpha_odd[idx1];
    1770       72448 :                 a22 = (u32)surf_uv_alpha_odd[idx2];
    1771       72448 :                 a = a11+a12+a21+a22;
    1772             : 
    1773       72448 :                 if (a) {
    1774             :                         s32 cdst=0, chroma_u, chroma_v, c11, c12, c21, c22;
    1775             : 
    1776       60034 :                         a /= 4;
    1777             : 
    1778             :                         //get cb
    1779       60034 :                         idx1 += 1;
    1780       60034 :                         idx2 += 1;
    1781       60034 :                         if (a!=0xFFFF)
    1782        8948 :                                 get_u16_le(cdst, pU);
    1783             : 
    1784       60034 :                         c11 = (u32)surf_uv_alpha_even[idx1];
    1785       68208 :                         if (a11!=0xFFFF) c11 = mul_10_zero(a11, c11 - cdst) + cdst;
    1786       60034 :                         c12 = (u32)surf_uv_alpha_even[idx2];
    1787       68212 :                         if (a12!=0xFFFF) c12 = mul_10_zero(a12, c12 - cdst) + cdst;
    1788       60034 :                         c21 = (u32)surf_uv_alpha_odd[idx1];
    1789       68174 :                         if (a21!=0xFFFF) c21 = mul_10_zero(a21, c21 - cdst) + cdst;
    1790       60034 :                         c22 = (u32)surf_uv_alpha_odd[idx2];
    1791       68182 :                         if (a22!=0xFFFF) c22 = mul_10_zero(a22, c22 - cdst) + cdst;
    1792             : 
    1793       60034 :                         chroma_u = c11+c12+c21+c22;
    1794       60034 :                         chroma_u /= 4;
    1795             : 
    1796             :                         //get cr
    1797       60034 :                         idx1 += 1;
    1798       60034 :                         idx2 += 1;
    1799       60034 :                         if (a!=0xFFFF)
    1800        8948 :                                 get_u16_le(cdst, pV);
    1801             : 
    1802       60034 :                         c11 = (u32)surf_uv_alpha_even[idx1];
    1803       68208 :                         if (a11!=0xFFFF) c11 = mul_10_zero(a11, c11 - cdst) + cdst;
    1804       60034 :                         c12 = (u32)surf_uv_alpha_even[idx2];
    1805       68212 :                         if (a12!=0xFFFF) c12 = mul_10_zero(a12, c12 - cdst) + cdst;
    1806       60034 :                         c21 = (u32)surf_uv_alpha_odd[idx1];
    1807       68174 :                         if (a21!=0xFFFF) c21 = mul_10_zero(a21, c21 - cdst) + cdst;
    1808       60034 :                         c22 = (u32)surf_uv_alpha_odd[idx2];
    1809       68182 :                         if (a22!=0xFFFF) c22 = mul_10_zero(a22, c22 - cdst) + cdst;
    1810             : 
    1811       60034 :                         chroma_v = c11+c12+c21+c22;
    1812       60034 :                         chroma_v /= 4;
    1813             : 
    1814             : 
    1815       60034 :                         set_u16_le(pU, chroma_u);
    1816       60034 :                         set_u16_le(pV, chroma_v);
    1817             :                 }
    1818       72448 :                 pU += 4;
    1819       72448 :                 pV += 4;
    1820             :         }
    1821             :         //reset for next pass
    1822        1132 :         memset(surf->uv_alpha, 0, surf->uv_alpha_alloc);
    1823        1132 : }
    1824             : 
    1825             : 
    1826           8 : GF_Err evg_surface_clear_nv12_10(GF_EVGSurface *_surf, GF_IRect rc, GF_Color col, Bool swap_uv)
    1827             : {
    1828             :         s32 i, j;
    1829             :         u8 _cy, _cb, _cr;
    1830             :         u16 cy, cb, cr;
    1831             :         GF_EVGSurface *surf = (GF_EVGSurface *)_surf;
    1832             :         u16 *s_pY, *s_pU;
    1833           8 :         char *pY = surf->pixels;
    1834           8 :         char *pU = surf->pixels + surf->height *surf->pitch_y;
    1835             :         char *pU_first, *pY_first;
    1836             : 
    1837           8 :         pY += rc.y * surf->pitch_y;
    1838           8 :         pU +=  rc.y/2 * surf->pitch_y;
    1839             : 
    1840           8 :         pY += 2*rc.x;
    1841           8 :         pU += 2*rc.x;
    1842             :         pU_first = pU;
    1843             :         pY_first = pY;
    1844             : 
    1845           8 :         gf_evg_rgb_to_yuv(surf, col, &_cy, &_cb, &_cr);
    1846             : 
    1847           8 :         if (swap_uv) {
    1848           4 :                 u8 t = _cb;
    1849           4 :                 _cb = _cr;
    1850           4 :                 _cr = t;
    1851             :         }
    1852           8 :         cy = ((u16)_cy) << 2;
    1853           8 :         cb = ((u16)_cb) << 2;
    1854           8 :         cr = ((u16)_cr) << 2;
    1855             : 
    1856             :         s_pY = (u16 *) pY;
    1857             :         s_pU = (u16 *) pU;
    1858             : 
    1859             :         //init first lines
    1860           8 :         if (cy) {
    1861           0 :                 for (j=0; j<rc.width;j++) {
    1862           0 :                         set_u16_le(&s_pY[j], cy);
    1863             :                 }
    1864             :         } else {
    1865           8 :                 memset(s_pY, 0, 2*rc.width);
    1866             :         }
    1867           8 :         s_pY += surf->pitch_y/2;
    1868             : 
    1869         520 :         for (j=0; j<rc.width/2; j++) {
    1870         512 :                 set_u16_le(&s_pU[2*j], cb);
    1871         512 :                 set_u16_le(&s_pU[2*j + 1], cr);
    1872             :         }
    1873           8 :         s_pU += surf->pitch_y/2;
    1874             : 
    1875        1024 :         for (i = 1; i < rc.height; i++) {
    1876             : 
    1877        1016 :                 memcpy(s_pY, pY_first, 2*rc.width);
    1878        1016 :                 s_pY += surf->pitch_y/2;
    1879             : 
    1880        1016 :                 if (i%2) continue;
    1881             : 
    1882             :                 //non-first uv line recopy from first (half width, U and V mix, 2 bytes = width*2)
    1883             :                 memcpy(s_pU, pU_first, 2*rc.width);
    1884         504 :                 s_pU += surf->pitch_y/2;
    1885             :         }
    1886           8 :         return GF_OK;
    1887             : }
    1888             : 
    1889             : 
    1890             : 
    1891             : /*
    1892             :                         YUV422 10 part
    1893             : */
    1894             : 
    1895         363 : void evg_yuv422p_10_flush_uv_const(GF_EVGSurface *surf, u8 *_surf_uv_alpha, s32 cu, s32 cv, s32 y)
    1896             : {
    1897             :         u32 i, a;
    1898         363 :         char *pU = surf->pixels + surf->height *surf->pitch_y;
    1899             :         char *pV;
    1900         363 :         u16 *surf_uv_alpha = (u16 *) surf->uv_alpha;
    1901         363 :         pU +=  y * surf->pitch_y/2;
    1902         363 :         pV = pU + surf->height * surf->pitch_y/2;
    1903             : 
    1904       23595 :         for (i=0; i<surf->width; i+=2) {
    1905       23232 :                 a = surf_uv_alpha[i] + surf_uv_alpha[i+1];
    1906             : 
    1907       23232 :                 if (a) {
    1908             :                         s32 dst;
    1909             :                         u16 *s_ptr_u, *s_ptr_v;
    1910             : 
    1911        2930 :                         a /= 2;
    1912             : 
    1913        2930 :                         s_ptr_u = (u16*)pU + i / 2;
    1914        2930 :                         s_ptr_v = (u16*)pV + i / 2;
    1915        2930 :                         if (a==0xFFFF) {
    1916           0 :                                 set_u16_le(s_ptr_u, (u16) cu);
    1917           0 :                                 set_u16_le(s_ptr_v, (u16) cv);
    1918             : 
    1919             :                         } else {
    1920        2930 :                                 get_u16_le(dst, s_ptr_u);
    1921        5860 :                                 set_u16_le(s_ptr_u, (u16) (mul_10(a, cu - dst) + dst) );
    1922             : 
    1923        2930 :                                 get_u16_le(dst, s_ptr_v);
    1924        5860 :                                 set_u16_le(s_ptr_v, (u16) (mul_10(a, cv - dst) + dst));
    1925             :                         }
    1926             :                 }
    1927             :         }
    1928         363 :         memset(surf->uv_alpha, 0, surf->uv_alpha_alloc);
    1929         363 : }
    1930             : 
    1931        1131 : void evg_yuv422p_10_flush_uv_var(GF_EVGSurface *surf, u8 *_surf_uv_alpha, s32 _cu, s32 _cv,  s32 y)
    1932             : {
    1933             :         u32 i;
    1934        1131 :         u16 *surf_uv_alpha = (u16 *) surf->uv_alpha;
    1935        1131 :         u16 *pU = (u16 *) (surf->pixels + surf->height *surf->pitch_y + y * surf->pitch_y/2);
    1936        1131 :         u16 *pV = (u16 *) (surf->pixels + surf->height *surf->pitch_y + surf->height * surf->pitch_y/2 + y * surf->pitch_y/2);
    1937             : 
    1938       73515 :         for (i=0; i<surf->width; i+=2) {
    1939             :                 u32 a, a11, a12;
    1940       72384 :                 u32 idx1=3*i;
    1941       72384 :                 u32 idx2=3*i + 3;
    1942             :                 //get alpha
    1943       72384 :                 a11 = surf_uv_alpha[idx1];
    1944       72384 :                 a12 = surf_uv_alpha[idx2];
    1945       72384 :                 a=a11+a12;
    1946             : 
    1947       72384 :                 if (a) {
    1948             :                         s32 cdst=0, chroma_u, chroma_v, c11, c12;
    1949             : 
    1950       59944 :                         a /= 2;
    1951             : 
    1952             :                         //get cb
    1953       59944 :                         if (a!=0xFFFF)
    1954        8550 :                                 get_u16_le(cdst, pU);
    1955             : 
    1956       59944 :                         c11 = (u32)surf_uv_alpha[idx1+1];
    1957       68011 :                         if (a11!=0xFFFF) c11 = mul_10_zero(a11, c11 - cdst) + cdst;
    1958       59944 :                         c12 = (u32)surf_uv_alpha[idx2+1];
    1959       68017 :                         if (a12!=0xFFFF) c12 = mul_10_zero(a12, c12 - cdst) + cdst;
    1960             : 
    1961       59944 :                         chroma_u = c11 + c12;
    1962       59944 :                         chroma_u /= 2;
    1963       59944 :                         set_u16_le(pU, (u16) chroma_u);
    1964             : 
    1965             :                         //get cr
    1966       59944 :                         if (a!=0xFFFF)
    1967        8550 :                                 get_u16_le(cdst, pV);
    1968             : 
    1969       59944 :                         c11 = (u32)surf_uv_alpha[idx1+2];
    1970       68011 :                         if (a11!=0xFFFF) c11 = mul_10_zero(a11, c11 - cdst) + cdst;
    1971       59944 :                         c12 = (u32)surf_uv_alpha[idx2+2];
    1972       68017 :                         if (a12!=0xFFFF) c12 = mul_10_zero(a12, c12 - cdst) + cdst;
    1973             : 
    1974       59944 :                         chroma_v = c11 + c12;
    1975       59944 :                         chroma_v /= 2;
    1976       59944 :                         set_u16_le(pV, (u16) chroma_v);
    1977             :                 }
    1978       72384 :                 pU++;
    1979       72384 :                 pV++;
    1980             :         }
    1981             :         //reset for next pass
    1982        1131 :         memset(surf->uv_alpha, 0, surf->uv_alpha_alloc);
    1983        1131 : }
    1984             : 
    1985             : 
    1986           4 : GF_Err evg_surface_clear_yuv422p_10(GF_EVGSurface *_surf, GF_IRect rc, GF_Color col)
    1987             : {
    1988             :         s32 i, j;
    1989             :         u8 _cy, _cb, _cr;
    1990             :         u16 cy, cb, cr;
    1991             :         GF_EVGSurface *surf = (GF_EVGSurface *)_surf;
    1992           4 :         char *pY = surf->pixels;
    1993           4 :         char *pU = surf->pixels + surf->height *surf->pitch_y;
    1994             :         char *pV;
    1995             :         char *o_pY, *o_pU, *o_pV;
    1996             : 
    1997           4 :         pY += rc.y * surf->pitch_y;
    1998           4 :         pU +=  rc.y/2 * surf->pitch_y/2;
    1999           4 :         pV = pU + surf->height/2 * surf->pitch_y/2;
    2000             : 
    2001           4 :         pY += 2*rc.x;
    2002           4 :         pU += rc.x;
    2003           4 :         pV += rc.x;
    2004             : 
    2005             :         o_pY = pY;
    2006             :         o_pU = pU;
    2007             :         o_pV = pV;
    2008           4 :         gf_evg_rgb_to_yuv(surf, col, &_cy, &_cb, &_cr);
    2009             : 
    2010           4 :         cy = ((u16)_cy) << 2;
    2011           4 :         cb = ((u16)_cb) << 2;
    2012           4 :         cr = ((u16)_cr) << 2;
    2013             : 
    2014         516 :         for (i = 0; i < rc.height; i++) {
    2015         512 :                 if (!i) {
    2016         512 :                         for (j=0; j<rc.width; j++) {
    2017         512 :                                 set_u16_le(&((u16 *)pY)[j], cy);
    2018         512 :                                 if (j%2) {
    2019         256 :                                         set_u16_le(&((u16 *)pU)[j/2], cb);
    2020         256 :                                         set_u16_le(& ((u16 *)pV)[j/2], cr);
    2021             :                                 }
    2022             :                         }
    2023             :                 } else {
    2024         508 :                         memcpy(pY, o_pY, 2*rc.width);
    2025         508 :                         memcpy(pU, o_pU, rc.width);
    2026             :                         memcpy(pV, o_pV, rc.width);
    2027             :                 }
    2028         512 :                 pY += surf->pitch_y;
    2029         512 :                 pU += surf->pitch_y/2;
    2030         512 :                 pV += surf->pitch_y/2;
    2031             :         }
    2032           4 :         return GF_OK;
    2033             : }
    2034             : 
    2035             : 
    2036             : /*
    2037             :                         YUV444 10bits part
    2038             : */
    2039             : 
    2040         307 : void evg_yuv444p_10_fill_const(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
    2041             : {
    2042             :         u16 *pY, *pU, *pV;
    2043             :         s32 i;
    2044             :         u32 cy, cu, cv;
    2045             : 
    2046         307 :         pY = (u16 *) (surf->pixels + y * surf->pitch_y);
    2047         307 :         pU = (u16 *) (surf->pixels + surf->height*surf->pitch_y + y * surf->pitch_y);
    2048         307 :         pV = (u16 *) (surf->pixels + 2*surf->height*surf->pitch_y + y * surf->pitch_y);
    2049             : 
    2050         307 :         cy = (surf->fill_col_wide>>32) & 0xFFFF;
    2051         307 :         cy >>=6;
    2052         307 :         cu = (surf->fill_col_wide>>16) & 0xFFFF;
    2053         307 :         cu >>=6;
    2054         307 :         cv = (surf->fill_col_wide) & 0xFFFF;
    2055         307 :         cv >>=6;
    2056             : 
    2057        2032 :         for (i=0; i<count; i++) {
    2058             :                 u32 a;
    2059             :                 u16 *s_pY, *s_pU, *s_pV;
    2060             :                 u32 len;
    2061        1725 :                 len = spans[i].len;
    2062        1725 :                 s_pY = pY + spans[i].x;
    2063        1725 :                 s_pU = pU + spans[i].x;
    2064        1725 :                 s_pV = pV + spans[i].x;
    2065             : 
    2066        1725 :                 if (spans[i].coverage != 0xFF) {
    2067        1428 :                         a = 0xFF * spans[i].coverage;
    2068             : 
    2069        1428 :                         overmask_yuv420p_10_const_run(a, cy, s_pY, len, 0);
    2070        1428 :                         overmask_yuv420p_10_const_run(a, cu, s_pU, len, 0);
    2071        1428 :                         overmask_yuv420p_10_const_run(a, cv, s_pV, len, 0);
    2072             :                 } else {
    2073        3226 :                         while (len--) {
    2074        2929 :                                 set_u16_le(s_pY, cy);
    2075        2929 :                                 s_pY ++;
    2076        2929 :                                 set_u16_le(s_pU, cu);
    2077        2929 :                                 s_pU ++;
    2078        2929 :                                 set_u16_le(s_pV, cv);
    2079        2929 :                                 s_pV ++;
    2080             :                         }
    2081             :                 }
    2082             :         }
    2083         307 : }
    2084             : 
    2085          56 : void evg_yuv444p_10_fill_const_a(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
    2086             : {
    2087             :         u32 a;
    2088             :         u16 *pY, *pU, *pV;
    2089             :         s32 i;
    2090             :         u32 cy, cu, cv;
    2091             : 
    2092          56 :         pY = (u16 *) (surf->pixels + y * surf->pitch_y);
    2093          56 :         pU = (u16 *) (surf->pixels + surf->height*surf->pitch_y + y * surf->pitch_y);
    2094          56 :         pV = (u16 *) (surf->pixels + 2*surf->height*surf->pitch_y + y * surf->pitch_y);
    2095             : 
    2096          56 :         a = (surf->fill_col_wide>>48) & 0xFFFF;
    2097          56 :         cy = (surf->fill_col_wide>>32) & 0xFFFF;
    2098          56 :         cy >>=6;
    2099          56 :         cu = (surf->fill_col_wide>>16) & 0xFFFF;
    2100          56 :         cu >>=6;
    2101          56 :         cv = (surf->fill_col_wide) & 0xFFFF;
    2102          56 :         cv >>=6;
    2103             : 
    2104          56 :         if (surf->get_alpha) {
    2105           0 :                 for (i=0; i<count; i++) {
    2106             :                         u32 j;
    2107           0 :                         for (j=0; j<spans[i].len; j++) {
    2108             :                                 u16 *s_pY, *s_pU, *s_pV;
    2109             :                                 u32 fin;
    2110           0 :                                 s32 x = spans[i].x + j;
    2111           0 :                                 s_pY = pY + x;
    2112           0 :                                 s_pU = pU + x;
    2113           0 :                                 s_pV = pV + x;
    2114             : 
    2115           0 :                                 fin = surf->get_alpha(surf->get_alpha_udta, a, x, y) * spans[i].coverage;
    2116           0 :                                 fin /= 0xFF;
    2117             : 
    2118           0 :                                 overmask_yuv420p_10_const_run(fin, cy, s_pY, 1, 0);
    2119           0 :                                 overmask_yuv420p_10_const_run(fin, cu, s_pU, 1, 0);
    2120           0 :                                 overmask_yuv420p_10_const_run(fin, cv, s_pV, 1, 0);
    2121             :                         }
    2122             :                 }
    2123             :         } else {
    2124         244 :                 for (i=0; i<count; i++) {
    2125             :                         u16 *s_pY, *s_pU, *s_pV;
    2126             :                         u32 fin, len;
    2127         244 :                         len = spans[i].len;
    2128         244 :                         s_pY = pY + spans[i].x;
    2129         244 :                         s_pU = pU + spans[i].x;
    2130         244 :                         s_pV = pV + spans[i].x;
    2131             : 
    2132         244 :                         fin = a * spans[i].coverage;
    2133         244 :                         fin /= 0xFF;
    2134             : 
    2135         244 :                         overmask_yuv420p_10_const_run(fin, cy, s_pY, len, 0);
    2136         244 :                         overmask_yuv420p_10_const_run(fin, cu, s_pU, len, 0);
    2137         244 :                         overmask_yuv420p_10_const_run(fin, cv, s_pV, len, 0);
    2138             :                 }
    2139             :         }
    2140          56 : }
    2141             : 
    2142        1131 : void evg_yuv444p_10_fill_var(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
    2143             : {
    2144             :         s32 i;
    2145             :         u16 *pY, *pU, *pV;
    2146             : 
    2147        1131 :         pY = (u16 *) (surf->pixels + y * surf->pitch_y);
    2148        1131 :         pU = (u16 *) (surf->pixels + surf->height*surf->pitch_y + y * surf->pitch_y);
    2149        1131 :         pV = (u16 *) (surf->pixels + 2*surf->height*surf->pitch_y + y * surf->pitch_y);
    2150             : 
    2151        2982 :         for (i=0; i<count; i++) {
    2152             :                 u8 spanalpha;
    2153             :                 u32 len;
    2154             :                 u64 *p_col;
    2155             :                 u16 *s_pY, *s_pU, *s_pV;
    2156        1851 :                 len = spans[i].len;
    2157        1851 :                 spanalpha = spans[i].coverage;
    2158        1851 :                 evg_fill_run(surf->sten, surf, spans[i].x, y, len);
    2159        1851 :                 p_col = surf->stencil_pix_run;
    2160             : 
    2161        1851 :                 s_pY = pY + spans[i].x;
    2162        1851 :                 s_pU = pU + spans[i].x;
    2163        1851 :                 s_pV = pV + spans[i].x;
    2164             : 
    2165      123381 :                 while (len--) {
    2166      119679 :                         u64 col = *p_col;
    2167      119679 :                         u32 col_a = (col>>48)&0xFFFF;
    2168      119679 :                         if (col_a) {
    2169             :                                 u16 cy, cb, cr;
    2170             :                                 //col is directly packed as AYCbCr
    2171      119679 :                                 cy = ((col>>32) & 0xFFFF) >> 6;
    2172      119679 :                                 cb = ((col>>16) & 0xFFFF) >> 6;
    2173      119679 :                                 cr = ((col) & 0xFFFF) >> 6;
    2174             : 
    2175      119679 :                                 if ((spanalpha!=0xFF) || (col_a != 0xFFFF)) {
    2176       15931 :                                         u16 spana = spanalpha;
    2177       15931 :                                         spana <<= 8;
    2178             :                                         overmask_yuv420p_10(col_a, cy, s_pY, spana);
    2179             :                                         overmask_yuv420p_10(col_a, cb, s_pU, spana);
    2180             :                                         overmask_yuv420p_10(col_a, cr, s_pV, spana);
    2181             :                                 } else {
    2182      103748 :                                         set_u16_le(s_pY, cy);
    2183      103748 :                                         set_u16_le(s_pU, cb);
    2184      103748 :                                         set_u16_le(s_pV, cr);
    2185             :                                 }
    2186             :                         }
    2187      119679 :                         s_pY++;
    2188      119679 :                         s_pU++;
    2189      119679 :                         s_pV++;
    2190      119679 :                         p_col++;
    2191             :                 }
    2192             :         }
    2193        1131 : }
    2194             : 
    2195           4 : GF_Err evg_surface_clear_yuv444p_10(GF_EVGSurface *_surf, GF_IRect rc, GF_Color col)
    2196             : {
    2197             :         s32 i;
    2198             :         u8 _cy, _cb, _cr;
    2199             :         u16 cy, cb, cr;
    2200             :         GF_EVGSurface *surf = (GF_EVGSurface *)_surf;
    2201           4 :         char *pY = surf->pixels;
    2202           4 :         char *pU = surf->pixels + surf->height *surf->pitch_y;
    2203             :         char *pV, *o_pY, *o_pU, *o_pV;
    2204             : 
    2205           4 :         pY += rc.y * surf->pitch_y;
    2206           4 :         pU += rc.y * surf->pitch_y;
    2207             :         pV = pU + surf->height * surf->pitch_y;
    2208             : 
    2209           4 :         pY += 2*rc.x;
    2210           4 :         pU += 2*rc.x;
    2211           4 :         pV += 2*rc.x;
    2212             : 
    2213           4 :         gf_evg_rgb_to_yuv(surf, col, &_cy, &_cb, &_cr);
    2214             : 
    2215           4 :         cy = ((u16)_cy) << 2;
    2216           4 :         cb = ((u16)_cb) << 2;
    2217           4 :         cr = ((u16)_cr) << 2;
    2218             : 
    2219             :         o_pY = pY;
    2220             :         o_pU = pU;
    2221             :         o_pV = pV;
    2222             : 
    2223         516 :         for (i = 0; i < rc.height; i++) {
    2224         512 :                 if (!i) {
    2225             :                         s32 j;
    2226         512 :                         for (j=0; j<rc.width; j++) {
    2227         512 :                                 set_u16_le(& ((u16 *)pY)[j], cy);
    2228         512 :                                 set_u16_le(& ((u16 *)pU)[j], cb);
    2229         512 :                                 set_u16_le(& ((u16 *)pV)[j], cr);
    2230             :                         }
    2231             :                 } else {
    2232         508 :                         memcpy(pY, o_pY, 2*rc.width);
    2233             :                         memcpy(pU, o_pU, 2*rc.width);
    2234             :                         memcpy(pV, o_pV, 2*rc.width);
    2235             :                 }
    2236         512 :                 pY += surf->pitch_y;
    2237         512 :                 pU += surf->pitch_y;
    2238         512 :                 pV += surf->pitch_y;
    2239             :         }
    2240           4 :         return GF_OK;
    2241             : }

Generated by: LCOV version 1.13