LCOV - code coverage report
Current view: top level - gfx/ycbcr - yuv_convert.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 208 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 9 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2010 The Chromium Authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : // This webpage shows layout of YV12 and other YUV formats
       6             : // http://www.fourcc.org/yuv.php
       7             : // The actual conversion is best described here
       8             : // http://en.wikipedia.org/wiki/YUV
       9             : // An article on optimizing YUV conversion using tables instead of multiplies
      10             : // http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
      11             : //
      12             : // YV12 is a full plane of Y and a half height, half width chroma planes
      13             : // YV16 is a full plane of Y and a full height, half width chroma planes
      14             : // YV24 is a full plane of Y and a full height, full width chroma planes
      15             : //
      16             : // ARGB pixel format is output, which on little endian is stored as BGRA.
      17             : // The alpha is set to 255, allowing the application to use RGBA or RGB32.
      18             : 
      19             : #include "yuv_convert.h"
      20             : 
      21             : #include "gfxPrefs.h"
      22             : #include "libyuv.h"
      23             : #include "scale_yuv_argb.h"
      24             : // Header for low level row functions.
      25             : #include "yuv_row.h"
      26             : #include "mozilla/SSE.h"
      27             : 
      28             : namespace mozilla {
      29             : 
      30             : namespace gfx {
      31             : 
      32             : // 16.16 fixed point arithmetic
      33             : const int kFractionBits = 16;
      34             : const int kFractionMax = 1 << kFractionBits;
      35             : const int kFractionMask = ((1 << kFractionBits) - 1);
      36             : 
      37           0 : YUVType TypeFromSize(int ywidth,
      38             :                      int yheight,
      39             :                      int cbcrwidth,
      40             :                      int cbcrheight)
      41             : {
      42           0 :   if (ywidth == cbcrwidth && yheight == cbcrheight) {
      43           0 :     return YV24;
      44             :   }
      45           0 :   else if ((ywidth + 1) / 2 == cbcrwidth && yheight == cbcrheight) {
      46           0 :     return YV16;
      47             :   }
      48             :   else {
      49           0 :     return YV12;
      50             :   }
      51             : }
      52             : 
      53           0 : libyuv::FourCC FourCCFromYUVType(YUVType aYUVType)
      54             : {
      55           0 :   if (aYUVType == YV24) {
      56           0 :     return libyuv::FOURCC_I444;
      57           0 :   } else if (aYUVType == YV16) {
      58           0 :     return libyuv::FOURCC_I422;
      59           0 :   } else if (aYUVType == YV12) {
      60           0 :     return libyuv::FOURCC_I420;
      61             :   } else {
      62           0 :     return libyuv::FOURCC_ANY;
      63             :   }
      64             : }
      65             : 
      66             : // Convert a frame of YUV to 32 bit ARGB.
      67           0 : void ConvertYCbCrToRGB32(const uint8* y_buf,
      68             :                          const uint8* u_buf,
      69             :                          const uint8* v_buf,
      70             :                          uint8* rgb_buf,
      71             :                          int pic_x,
      72             :                          int pic_y,
      73             :                          int pic_width,
      74             :                          int pic_height,
      75             :                          int y_pitch,
      76             :                          int uv_pitch,
      77             :                          int rgb_pitch,
      78             :                          YUVType yuv_type,
      79             :                          YUVColorSpace yuv_color_space) {
      80             : 
      81             : 
      82             :   // Deprecated function's conversion is accurate.
      83             :   // libyuv converion is a bit inaccurate to get performance. It dynamically
      84             :   // calculates RGB from YUV to use simd. In it, signed byte is used for conversion's
      85             :   // coefficient, but it requests 129. libyuv cut 129 to 127. And only 6 bits are
      86             :   // used for a decimal part during the dynamic calculation.
      87             :   //
      88             :   // The function is still fast on some old intel chips.
      89             :   // See Bug 1256475.
      90           0 :   bool use_deprecated = gfxPrefs::YCbCrAccurateConversion() ||
      91           0 :                         (supports_mmx() && supports_sse() && !supports_sse3() &&
      92           0 :                          yuv_color_space == YUVColorSpace::BT601);
      93             :   // The deprecated function only support BT601.
      94             :   // See Bug 1210357.
      95           0 :   if (yuv_color_space != YUVColorSpace::BT601) {
      96           0 :     use_deprecated = false;
      97             :   }
      98           0 :   if (use_deprecated) {
      99             :     ConvertYCbCrToRGB32_deprecated(y_buf, u_buf, v_buf, rgb_buf,
     100             :                                    pic_x, pic_y, pic_width, pic_height,
     101           0 :                                    y_pitch, uv_pitch, rgb_pitch, yuv_type);
     102           0 :     return;
     103             :   }
     104             : 
     105           0 :   if (yuv_type == YV24) {
     106           0 :     const uint8* src_y = y_buf + y_pitch * pic_y + pic_x;
     107           0 :     const uint8* src_u = u_buf + uv_pitch * pic_y + pic_x;
     108           0 :     const uint8* src_v = v_buf + uv_pitch * pic_y + pic_x;
     109           0 :     if (yuv_color_space == mozilla::YUVColorSpace::BT709) {
     110           0 :       DebugOnly<int> err = libyuv::H444ToARGB(src_y, y_pitch,
     111             :                                               src_u, uv_pitch,
     112             :                                               src_v, uv_pitch,
     113             :                                               rgb_buf, rgb_pitch,
     114           0 :                                               pic_width, pic_height);
     115           0 :       MOZ_ASSERT(!err);
     116             :     } else {
     117           0 :       DebugOnly<int> err = libyuv::I444ToARGB(src_y, y_pitch,
     118             :                                               src_u, uv_pitch,
     119             :                                               src_v, uv_pitch,
     120             :                                               rgb_buf, rgb_pitch,
     121           0 :                                               pic_width, pic_height);
     122           0 :       MOZ_ASSERT(!err);
     123             :     }
     124           0 :   } else if (yuv_type == YV16) {
     125           0 :     const uint8* src_y = y_buf + y_pitch * pic_y + pic_x;
     126           0 :     const uint8* src_u = u_buf + uv_pitch * pic_y + pic_x / 2;
     127           0 :     const uint8* src_v = v_buf + uv_pitch * pic_y + pic_x / 2;
     128           0 :     if (yuv_color_space == mozilla::YUVColorSpace::BT709) {
     129           0 :       DebugOnly<int> err = libyuv::H422ToARGB(src_y, y_pitch,
     130             :                                               src_u, uv_pitch,
     131             :                                               src_v, uv_pitch,
     132             :                                               rgb_buf, rgb_pitch,
     133           0 :                                               pic_width, pic_height);
     134           0 :       MOZ_ASSERT(!err);
     135             :     } else {
     136           0 :       DebugOnly<int> err = libyuv::I422ToARGB(src_y, y_pitch,
     137             :                                               src_u, uv_pitch,
     138             :                                               src_v, uv_pitch,
     139             :                                               rgb_buf, rgb_pitch,
     140           0 :                                               pic_width, pic_height);
     141           0 :       MOZ_ASSERT(!err);
     142             :     }
     143             :   } else {
     144           0 :     MOZ_ASSERT(yuv_type == YV12);
     145           0 :     const uint8* src_y = y_buf + y_pitch * pic_y + pic_x;
     146           0 :     const uint8* src_u = u_buf + (uv_pitch * pic_y + pic_x) / 2;
     147           0 :     const uint8* src_v = v_buf + (uv_pitch * pic_y + pic_x) / 2;
     148           0 :     if (yuv_color_space == mozilla::YUVColorSpace::BT709) {
     149           0 :       DebugOnly<int> err = libyuv::H420ToARGB(src_y, y_pitch,
     150             :                                               src_u, uv_pitch,
     151             :                                               src_v, uv_pitch,
     152             :                                               rgb_buf, rgb_pitch,
     153           0 :                                               pic_width, pic_height);
     154           0 :       MOZ_ASSERT(!err);
     155             :     } else {
     156           0 :       DebugOnly<int> err = libyuv::I420ToARGB(src_y, y_pitch,
     157             :                                               src_u, uv_pitch,
     158             :                                               src_v, uv_pitch,
     159             :                                               rgb_buf, rgb_pitch,
     160           0 :                                               pic_width, pic_height);
     161           0 :       MOZ_ASSERT(!err);
     162             :     }
     163             :   }
     164             : }
     165             : 
     166             : // Convert a frame of YUV to 32 bit ARGB.
     167           0 : void ConvertYCbCrToRGB32_deprecated(const uint8* y_buf,
     168             :                                     const uint8* u_buf,
     169             :                                     const uint8* v_buf,
     170             :                                     uint8* rgb_buf,
     171             :                                     int pic_x,
     172             :                                     int pic_y,
     173             :                                     int pic_width,
     174             :                                     int pic_height,
     175             :                                     int y_pitch,
     176             :                                     int uv_pitch,
     177             :                                     int rgb_pitch,
     178             :                                     YUVType yuv_type) {
     179           0 :   unsigned int y_shift = yuv_type == YV12 ? 1 : 0;
     180           0 :   unsigned int x_shift = yuv_type == YV24 ? 0 : 1;
     181             :   // Test for SSE because the optimized code uses movntq, which is not part of MMX.
     182           0 :   bool has_sse = supports_mmx() && supports_sse();
     183             :   // There is no optimized YV24 SSE routine so we check for this and
     184             :   // fall back to the C code.
     185           0 :   has_sse &= yuv_type != YV24;
     186           0 :   bool odd_pic_x = yuv_type != YV24 && pic_x % 2 != 0;
     187           0 :   int x_width = odd_pic_x ? pic_width - 1 : pic_width;
     188             : 
     189           0 :   for (int y = pic_y; y < pic_height + pic_y; ++y) {
     190           0 :     uint8* rgb_row = rgb_buf + (y - pic_y) * rgb_pitch;
     191           0 :     const uint8* y_ptr = y_buf + y * y_pitch + pic_x;
     192           0 :     const uint8* u_ptr = u_buf + (y >> y_shift) * uv_pitch + (pic_x >> x_shift);
     193           0 :     const uint8* v_ptr = v_buf + (y >> y_shift) * uv_pitch + (pic_x >> x_shift);
     194             : 
     195           0 :     if (odd_pic_x) {
     196             :       // Handle the single odd pixel manually and use the
     197             :       // fast routines for the remaining.
     198           0 :       FastConvertYUVToRGB32Row_C(y_ptr++,
     199             :                                  u_ptr++,
     200             :                                  v_ptr++,
     201             :                                  rgb_row,
     202             :                                  1,
     203           0 :                                  x_shift);
     204           0 :       rgb_row += 4;
     205             :     }
     206             : 
     207           0 :     if (has_sse) {
     208             :       FastConvertYUVToRGB32Row(y_ptr,
     209             :                                u_ptr,
     210             :                                v_ptr,
     211             :                                rgb_row,
     212           0 :                                x_width);
     213             :     }
     214             :     else {
     215             :       FastConvertYUVToRGB32Row_C(y_ptr,
     216             :                                  u_ptr,
     217             :                                  v_ptr,
     218             :                                  rgb_row,
     219             :                                  x_width,
     220           0 :                                  x_shift);
     221             :     }
     222             :   }
     223             : 
     224             :   // MMX used for FastConvertYUVToRGB32Row requires emms instruction.
     225             :   if (has_sse)
     226             :     EMMS();
     227           0 : }
     228             : 
     229             : // C version does 8 at a time to mimic MMX code
     230           0 : static void FilterRows_C(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr,
     231             :                          int source_width, int source_y_fraction) {
     232           0 :   int y1_fraction = source_y_fraction;
     233           0 :   int y0_fraction = 256 - y1_fraction;
     234           0 :   uint8* end = ybuf + source_width;
     235           0 :   do {
     236           0 :     ybuf[0] = (y0_ptr[0] * y0_fraction + y1_ptr[0] * y1_fraction) >> 8;
     237           0 :     ybuf[1] = (y0_ptr[1] * y0_fraction + y1_ptr[1] * y1_fraction) >> 8;
     238           0 :     ybuf[2] = (y0_ptr[2] * y0_fraction + y1_ptr[2] * y1_fraction) >> 8;
     239           0 :     ybuf[3] = (y0_ptr[3] * y0_fraction + y1_ptr[3] * y1_fraction) >> 8;
     240           0 :     ybuf[4] = (y0_ptr[4] * y0_fraction + y1_ptr[4] * y1_fraction) >> 8;
     241           0 :     ybuf[5] = (y0_ptr[5] * y0_fraction + y1_ptr[5] * y1_fraction) >> 8;
     242           0 :     ybuf[6] = (y0_ptr[6] * y0_fraction + y1_ptr[6] * y1_fraction) >> 8;
     243           0 :     ybuf[7] = (y0_ptr[7] * y0_fraction + y1_ptr[7] * y1_fraction) >> 8;
     244           0 :     y0_ptr += 8;
     245           0 :     y1_ptr += 8;
     246           0 :     ybuf += 8;
     247           0 :   } while (ybuf < end);
     248           0 : }
     249             : 
     250             : #ifdef MOZILLA_MAY_SUPPORT_MMX
     251             : void FilterRows_MMX(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr,
     252             :                     int source_width, int source_y_fraction);
     253             : #endif
     254             : 
     255             : #ifdef MOZILLA_MAY_SUPPORT_SSE2
     256             : void FilterRows_SSE2(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr,
     257             :                      int source_width, int source_y_fraction);
     258             : #endif
     259             : 
     260           0 : static inline void FilterRows(uint8* ybuf, const uint8* y0_ptr,
     261             :                               const uint8* y1_ptr, int source_width,
     262             :                               int source_y_fraction) {
     263             : #ifdef MOZILLA_MAY_SUPPORT_SSE2
     264           0 :   if (mozilla::supports_sse2()) {
     265           0 :     FilterRows_SSE2(ybuf, y0_ptr, y1_ptr, source_width, source_y_fraction);
     266           0 :     return;
     267             :   }
     268             : #endif
     269             : 
     270             : #ifdef MOZILLA_MAY_SUPPORT_MMX
     271           0 :   if (mozilla::supports_mmx()) {
     272           0 :     FilterRows_MMX(ybuf, y0_ptr, y1_ptr, source_width, source_y_fraction);
     273           0 :     return;
     274             :   }
     275             : #endif
     276             : 
     277           0 :   FilterRows_C(ybuf, y0_ptr, y1_ptr, source_width, source_y_fraction);
     278             : }
     279             : 
     280             : 
     281             : // Scale a frame of YUV to 32 bit ARGB.
     282           0 : void ScaleYCbCrToRGB32(const uint8* y_buf,
     283             :                        const uint8* u_buf,
     284             :                        const uint8* v_buf,
     285             :                        uint8* rgb_buf,
     286             :                        int source_width,
     287             :                        int source_height,
     288             :                        int width,
     289             :                        int height,
     290             :                        int y_pitch,
     291             :                        int uv_pitch,
     292             :                        int rgb_pitch,
     293             :                        YUVType yuv_type,
     294             :                        YUVColorSpace yuv_color_space,
     295             :                        ScaleFilter filter) {
     296             : 
     297           0 :   bool use_deprecated = gfxPrefs::YCbCrAccurateConversion() ||
     298             : #if defined(XP_WIN) && defined(_M_X64)
     299             :                         // libyuv does not support SIMD scaling on win 64bit. See Bug 1295927.
     300             :                         supports_sse3() ||
     301             : #endif
     302           0 :                         (supports_mmx() && supports_sse() && !supports_sse3());
     303             :   // The deprecated function only support BT601.
     304             :   // See Bug 1210357.
     305           0 :   if (yuv_color_space != YUVColorSpace::BT601) {
     306           0 :     use_deprecated = false;
     307             :   }
     308           0 :   if (use_deprecated) {
     309             :     ScaleYCbCrToRGB32_deprecated(y_buf, u_buf, v_buf,
     310             :                                  rgb_buf,
     311             :                                  source_width, source_height,
     312             :                                  width, height,
     313             :                                  y_pitch, uv_pitch,
     314             :                                  rgb_pitch,
     315             :                                  yuv_type,
     316             :                                  ROTATE_0,
     317           0 :                                  filter);
     318           0 :     return;
     319             :   }
     320             : 
     321             :   DebugOnly<int> err =
     322           0 :     libyuv::YUVToARGBScale(y_buf, y_pitch,
     323             :                            u_buf, uv_pitch,
     324             :                            v_buf, uv_pitch,
     325           0 :                            FourCCFromYUVType(yuv_type),
     326             :                            yuv_color_space,
     327             :                            source_width, source_height,
     328             :                            rgb_buf, rgb_pitch,
     329             :                            width, height,
     330           0 :                            libyuv::kFilterBilinear);
     331           0 :   MOZ_ASSERT(!err);
     332           0 :   return;
     333             : }
     334             : 
     335             : // Scale a frame of YUV to 32 bit ARGB.
     336           0 : void ScaleYCbCrToRGB32_deprecated(const uint8* y_buf,
     337             :                                   const uint8* u_buf,
     338             :                                   const uint8* v_buf,
     339             :                                   uint8* rgb_buf,
     340             :                                   int source_width,
     341             :                                   int source_height,
     342             :                                   int width,
     343             :                                   int height,
     344             :                                   int y_pitch,
     345             :                                   int uv_pitch,
     346             :                                   int rgb_pitch,
     347             :                                   YUVType yuv_type,
     348             :                                   Rotate view_rotate,
     349             :                                   ScaleFilter filter) {
     350           0 :   bool has_mmx = supports_mmx();
     351             : 
     352             :   // 4096 allows 3 buffers to fit in 12k.
     353             :   // Helps performance on CPU with 16K L1 cache.
     354             :   // Large enough for 3830x2160 and 30" displays which are 2560x1600.
     355           0 :   const int kFilterBufferSize = 4096;
     356             :   // Disable filtering if the screen is too big (to avoid buffer overflows).
     357             :   // This should never happen to regular users: they don't have monitors
     358             :   // wider than 4096 pixels.
     359             :   // TODO(fbarchard): Allow rotated videos to filter.
     360           0 :   if (source_width > kFilterBufferSize || view_rotate)
     361           0 :     filter = FILTER_NONE;
     362             : 
     363           0 :   unsigned int y_shift = yuv_type == YV12 ? 1 : 0;
     364             :   // Diagram showing origin and direction of source sampling.
     365             :   // ->0   4<-
     366             :   // 7       3
     367             :   //
     368             :   // 6       5
     369             :   // ->1   2<-
     370             :   // Rotations that start at right side of image.
     371           0 :   if ((view_rotate == ROTATE_180) ||
     372           0 :       (view_rotate == ROTATE_270) ||
     373           0 :       (view_rotate == MIRROR_ROTATE_0) ||
     374             :       (view_rotate == MIRROR_ROTATE_90)) {
     375           0 :     y_buf += source_width - 1;
     376           0 :     u_buf += source_width / 2 - 1;
     377           0 :     v_buf += source_width / 2 - 1;
     378           0 :     source_width = -source_width;
     379             :   }
     380             :   // Rotations that start at bottom of image.
     381           0 :   if ((view_rotate == ROTATE_90) ||
     382           0 :       (view_rotate == ROTATE_180) ||
     383           0 :       (view_rotate == MIRROR_ROTATE_90) ||
     384             :       (view_rotate == MIRROR_ROTATE_180)) {
     385           0 :     y_buf += (source_height - 1) * y_pitch;
     386           0 :     u_buf += ((source_height >> y_shift) - 1) * uv_pitch;
     387           0 :     v_buf += ((source_height >> y_shift) - 1) * uv_pitch;
     388           0 :     source_height = -source_height;
     389             :   }
     390             : 
     391             :   // Handle zero sized destination.
     392           0 :   if (width == 0 || height == 0)
     393           0 :     return;
     394           0 :   int source_dx = source_width * kFractionMax / width;
     395           0 :   int source_dy = source_height * kFractionMax / height;
     396           0 :   int source_dx_uv = source_dx;
     397             : 
     398           0 :   if ((view_rotate == ROTATE_90) ||
     399             :       (view_rotate == ROTATE_270)) {
     400           0 :     int tmp = height;
     401           0 :     height = width;
     402           0 :     width = tmp;
     403           0 :     tmp = source_height;
     404           0 :     source_height = source_width;
     405           0 :     source_width = tmp;
     406           0 :     int original_dx = source_dx;
     407           0 :     int original_dy = source_dy;
     408           0 :     source_dx = ((original_dy >> kFractionBits) * y_pitch) << kFractionBits;
     409           0 :     source_dx_uv = ((original_dy >> kFractionBits) * uv_pitch) << kFractionBits;
     410           0 :     source_dy = original_dx;
     411           0 :     if (view_rotate == ROTATE_90) {
     412           0 :       y_pitch = -1;
     413           0 :       uv_pitch = -1;
     414           0 :       source_height = -source_height;
     415             :     } else {
     416           0 :       y_pitch = 1;
     417           0 :       uv_pitch = 1;
     418             :     }
     419             :   }
     420             : 
     421             :   // Need padding because FilterRows() will write 1 to 16 extra pixels
     422             :   // after the end for SSE2 version.
     423             :   uint8 yuvbuf[16 + kFilterBufferSize * 3 + 16];
     424             :   uint8* ybuf =
     425           0 :       reinterpret_cast<uint8*>(reinterpret_cast<uintptr_t>(yuvbuf + 15) & ~15);
     426           0 :   uint8* ubuf = ybuf + kFilterBufferSize;
     427           0 :   uint8* vbuf = ubuf + kFilterBufferSize;
     428             :   // TODO(fbarchard): Fixed point math is off by 1 on negatives.
     429           0 :   int yscale_fixed = (source_height << kFractionBits) / height;
     430             : 
     431             :   // TODO(fbarchard): Split this into separate function for better efficiency.
     432           0 :   for (int y = 0; y < height; ++y) {
     433           0 :     uint8* dest_pixel = rgb_buf + y * rgb_pitch;
     434           0 :     int source_y_subpixel = (y * yscale_fixed);
     435           0 :     if (yscale_fixed >= (kFractionMax * 2)) {
     436           0 :       source_y_subpixel += kFractionMax / 2;  // For 1/2 or less, center filter.
     437             :     }
     438           0 :     int source_y = source_y_subpixel >> kFractionBits;
     439             : 
     440           0 :     const uint8* y0_ptr = y_buf + source_y * y_pitch;
     441           0 :     const uint8* y1_ptr = y0_ptr + y_pitch;
     442             : 
     443           0 :     const uint8* u0_ptr = u_buf + (source_y >> y_shift) * uv_pitch;
     444           0 :     const uint8* u1_ptr = u0_ptr + uv_pitch;
     445           0 :     const uint8* v0_ptr = v_buf + (source_y >> y_shift) * uv_pitch;
     446           0 :     const uint8* v1_ptr = v0_ptr + uv_pitch;
     447             : 
     448             :     // vertical scaler uses 16.8 fixed point
     449           0 :     int source_y_fraction = (source_y_subpixel & kFractionMask) >> 8;
     450             :     int source_uv_fraction =
     451           0 :         ((source_y_subpixel >> y_shift) & kFractionMask) >> 8;
     452             : 
     453           0 :     const uint8* y_ptr = y0_ptr;
     454           0 :     const uint8* u_ptr = u0_ptr;
     455           0 :     const uint8* v_ptr = v0_ptr;
     456             :     // Apply vertical filtering if necessary.
     457             :     // TODO(fbarchard): Remove memcpy when not necessary.
     458           0 :     if (filter & mozilla::gfx::FILTER_BILINEAR_V) {
     459           0 :       if (yscale_fixed != kFractionMax &&
     460           0 :           source_y_fraction && ((source_y + 1) < source_height)) {
     461           0 :         FilterRows(ybuf, y0_ptr, y1_ptr, source_width, source_y_fraction);
     462             :       } else {
     463           0 :         memcpy(ybuf, y0_ptr, source_width);
     464             :       }
     465           0 :       y_ptr = ybuf;
     466           0 :       ybuf[source_width] = ybuf[source_width-1];
     467           0 :       int uv_source_width = (source_width + 1) / 2;
     468           0 :       if (yscale_fixed != kFractionMax &&
     469           0 :           source_uv_fraction &&
     470           0 :           (((source_y >> y_shift) + 1) < (source_height >> y_shift))) {
     471           0 :         FilterRows(ubuf, u0_ptr, u1_ptr, uv_source_width, source_uv_fraction);
     472           0 :         FilterRows(vbuf, v0_ptr, v1_ptr, uv_source_width, source_uv_fraction);
     473             :       } else {
     474           0 :         memcpy(ubuf, u0_ptr, uv_source_width);
     475           0 :         memcpy(vbuf, v0_ptr, uv_source_width);
     476             :       }
     477           0 :       u_ptr = ubuf;
     478           0 :       v_ptr = vbuf;
     479           0 :       ubuf[uv_source_width] = ubuf[uv_source_width - 1];
     480           0 :       vbuf[uv_source_width] = vbuf[uv_source_width - 1];
     481             :     }
     482           0 :     if (source_dx == kFractionMax) {  // Not scaled
     483             :       FastConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
     484           0 :                                dest_pixel, width);
     485           0 :     } else if (filter & FILTER_BILINEAR_H) {
     486             :         LinearScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
     487           0 :                                  dest_pixel, width, source_dx);
     488             :     } else {
     489             : // Specialized scalers and rotation.
     490             : #if defined(MOZILLA_MAY_SUPPORT_SSE) && defined(_MSC_VER) && defined(_M_IX86)
     491             :       if(mozilla::supports_sse()) {
     492             :         if (width == (source_width * 2)) {
     493             :           DoubleYUVToRGB32Row_SSE(y_ptr, u_ptr, v_ptr,
     494             :                                   dest_pixel, width);
     495             :         } else if ((source_dx & kFractionMask) == 0) {
     496             :           // Scaling by integer scale factor. ie half.
     497             :           ConvertYUVToRGB32Row_SSE(y_ptr, u_ptr, v_ptr,
     498             :                                    dest_pixel, width,
     499             :                                    source_dx >> kFractionBits);
     500             :         } else if (source_dx_uv == source_dx) {  // Not rotated.
     501             :           ScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
     502             :                              dest_pixel, width, source_dx);
     503             :         } else {
     504             :           RotateConvertYUVToRGB32Row_SSE(y_ptr, u_ptr, v_ptr,
     505             :                                          dest_pixel, width,
     506             :                                          source_dx >> kFractionBits,
     507             :                                          source_dx_uv >> kFractionBits);
     508             :         }
     509             :       }
     510             :       else {
     511             :         ScaleYUVToRGB32Row_C(y_ptr, u_ptr, v_ptr,
     512             :                              dest_pixel, width, source_dx);
     513             :       }
     514             : #else
     515             :       (void)source_dx_uv;
     516             :       ScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
     517           0 :                          dest_pixel, width, source_dx);
     518             : #endif
     519             :     }
     520             :   }
     521             :   // MMX used for FastConvertYUVToRGB32Row and FilterRows requires emms.
     522             :   if (has_mmx)
     523             :     EMMS();
     524             : }
     525           0 : void ConvertYCbCrAToARGB32(const uint8* y_buf,
     526             :                            const uint8* u_buf,
     527             :                            const uint8* v_buf,
     528             :                            const uint8* a_buf,
     529             :                            uint8* argb_buf,
     530             :                            int pic_width,
     531             :                            int pic_height,
     532             :                            int ya_pitch,
     533             :                            int uv_pitch,
     534             :                            int argb_pitch) {
     535             : 
     536             :   // The downstream graphics stack expects an attenuated input, hence why the
     537             :   // attenuation parameter is set.
     538           0 :   DebugOnly<int> err = libyuv::I420AlphaToARGB(y_buf, ya_pitch,
     539             :                                                u_buf, uv_pitch,
     540             :                                                v_buf, uv_pitch,
     541             :                                                a_buf, ya_pitch,
     542             :                                                argb_buf, argb_pitch,
     543           0 :                                                pic_width, pic_height, 1);
     544           0 :   MOZ_ASSERT(!err);
     545           0 : }
     546             : 
     547             : } // namespace gfx
     548             : } // namespace mozilla

Generated by: LCOV version 1.13