Bug 641014 - Fix broken NEO Y'CbCr to RGB conversion - r=doublec
authorTim Terribe <tterribe@vt.edu>
Sat, 09 Apr 2011 06:59:22 +1200
changeset 67676 acf9030b80b4c6478bfe7ec469ce9de370bf40a1
parent 67675 3b33622916e25577951983861865fb9358afff4d
child 67677 b59f443dd42f3cb1fedd62fe793b2c268bd7fde1
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersdoublec
bugs641014
milestone2.2a1pre
Bug 641014 - Fix broken NEO Y'CbCr to RGB conversion - r=doublec
gfx/layers/basic/BasicImages.cpp
gfx/ycbcr/README
gfx/ycbcr/convert.patch
gfx/ycbcr/ycbcr_to_rgb565.cpp
gfx/ycbcr/ycbcr_to_rgb565.h
gfx/ycbcr/yuv_convert.cpp
gfx/ycbcr/yuv_convert.h
gfx/ycbcr/yuv_convert_arm.cpp
--- a/gfx/layers/basic/BasicImages.cpp
+++ b/gfx/layers/basic/BasicImages.cpp
@@ -139,57 +139,67 @@ BasicPlanarYCbCrImage::SetData(const Dat
   // Do some sanity checks to prevent integer overflow
   if (aData.mYSize.width > 16384 || aData.mYSize.height > 16384) {
     NS_ERROR("Illegal width or height");
     return;
   }
 
   gfxASurface::gfxImageFormat format = GetOffscreenFormat();
 
-  // 'prescale' is true if the scaling is to be done as part of the
-  // YCbCr to RGB conversion rather than on the RGB data when rendered.
-  // We don't prescale if the image has an offset. See bug 639415.
-  PRBool prescale = mScaleHint.width > 0 && mScaleHint.height > 0 &&
-                    aData.mPicX == 0 && aData.mPicY == 0;
-  if (format == gfxASurface::ImageFormatRGB16_565) {
-    if (have_ycbcr_to_rgb565()) {
-      // yuv2rgb16 with scale function not yet available for NEON
-      prescale = PR_FALSE;
-    } else {
-      // yuv2rgb16 function not yet available for non-NEON
-      format = gfxASurface::ImageFormatRGB24;
-    }
-  }
-  gfxIntSize size(prescale ? mScaleHint.width : aData.mPicSize.width,
-                  prescale ? mScaleHint.height : aData.mPicSize.height);
-
-  mStride = gfxASurface::FormatStrideForWidth(format, size.width);
-  mBuffer = new PRUint8[size.height * mStride];
-  if (!mBuffer) {
-    // out of memory
-    return;
-  }
-
   gfx::YUVType type = gfx::YV12;
   if (aData.mYSize.width == aData.mCbCrSize.width &&
       aData.mYSize.height == aData.mCbCrSize.height) {
     type = gfx::YV24;
   }
   else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
            aData.mYSize.height == aData.mCbCrSize.height) {
     type = gfx::YV16;
   }
   else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
            aData.mYSize.height / 2 == aData.mCbCrSize.height ) {
     type = gfx::YV12;
   }
   else {
     NS_ERROR("YCbCr format not supported");
   }
- 
+
+  // 'prescale' is true if the scaling is to be done as part of the
+  // YCbCr to RGB conversion rather than on the RGB data when rendered.
+  // We don't prescale if the image has an offset. See bug 639415.
+  PRBool prescale = mScaleHint.width > 0 && mScaleHint.height > 0 &&
+                    aData.mPicX == 0 && aData.mPicY == 0;
+  if (format == gfxASurface::ImageFormatRGB16_565) {
+#if defined(HAVE_YCBCR_TO_RGB565)
+    if (prescale && gfx::IsConvertYCbCrToRGB565Fast(aData.mPicX,
+                                                    aData.mPicY,
+                                                    aData.mPicSize.width,
+                                                    aData.mPicSize.height,
+                                                    type)) {
+      // yuv2rgb16 with scale function not yet available for NEON
+      prescale = PR_FALSE;
+    } else
+#endif
+    {
+      // yuv2rgb16 function not yet available for non-NEON, and currently
+      // using it requires a number of extra graphics operations, so it's
+      // probably better to fall back to 24-bit RGB.
+      // See https://bugzilla.mozilla.org/show_bug.cgi?id=641196
+      format = gfxASurface::ImageFormatRGB24;
+    }
+  }
+  gfxIntSize size(prescale ? mScaleHint.width : aData.mPicSize.width,
+                  prescale ? mScaleHint.height : aData.mPicSize.height);
+
+  mStride = gfxASurface::FormatStrideForWidth(format, size.width);
+  mBuffer = new PRUint8[size.height * mStride];
+  if (!mBuffer) {
+    // out of memory
+    return;
+  }
+
   // Convert from YCbCr to RGB now, scaling the image if needed.
   if (size != aData.mPicSize) {
     if (format == gfxASurface::ImageFormatRGB24) {
       gfx::ScaleYCbCrToRGB32(aData.mYChannel,
                              aData.mCbChannel,
                              aData.mCrChannel,
                              mBuffer,
                              aData.mPicSize.width,
@@ -201,44 +211,44 @@ BasicPlanarYCbCrImage::SetData(const Dat
                              mStride,
                              type,
                              gfx::ROTATE_0,
                              gfx::FILTER_BILINEAR);
     } else {
        NS_ERROR("Fail, ScaleYCbCrToRGB format not supported\n");
     }
   } else { // no prescale
+#if defined(HAVE_YCBCR_TO_RGB565)
     if (format == gfxASurface::ImageFormatRGB16_565) {
-      NS_ASSERTION(have_ycbcr_to_rgb565(), "Cannot convert YCbCr to RGB565");
       gfx::ConvertYCbCrToRGB565(aData.mYChannel,
                                 aData.mCbChannel,
                                 aData.mCrChannel,
                                 mBuffer,
                                 aData.mPicX,
                                 aData.mPicY,
                                 aData.mPicSize.width,
                                 aData.mPicSize.height,
                                 aData.mYStride,
                                 aData.mCbCrStride,
                                 mStride,
                                 type);
-    } else { // format != gfxASurface::ImageFormatRGB16_565
+    } else // format != gfxASurface::ImageFormatRGB16_565
+#endif
       gfx::ConvertYCbCrToRGB32(aData.mYChannel,
                                aData.mCbChannel,
                                aData.mCrChannel,
                                mBuffer,
                                aData.mPicX,
                                aData.mPicY,
                                aData.mPicSize.width,
                                aData.mPicSize.height,
                                aData.mYStride,
                                aData.mCbCrStride,
                                mStride,
                                type);
-    }
   }
   SetOffscreenFormat(format);
   mSize = size;
 }
 
 static cairo_user_data_key_t imageSurfaceDataKey;
 
 static void
--- a/gfx/ycbcr/README
+++ b/gfx/ycbcr/README
@@ -1,20 +1,23 @@
 This color conversion code is from the Chromium open source project available here:
 
 http://code.google.com/chromium/
 
 The code comes from svn revision 63840 on 2010-10-26.
 
+If you just want to check out this individual directory, use:
+
+svn co -r 63840 http://src.chromium.org/svn/trunk/src/media/base
+
 The code was copied from a Chromium svn checkout using the 'update.sh' script which then applies patches for our build and to add dynamic CPU detection.
 
 convert.patch contains the following changes:
 
   * Change Chromium code to build using Mozilla build system.
   * Add runtime CPU detection for MMX
   * Move default C implementation to work on all platforms.
   * Change Chromium code to allow a picture region.
   * The YUV conversion will convert within this picture region only.
   * Add YCbCr 4:4:4 support
-  * Bug 616469 - Add YCbCr to rgb16_565 conversion support.
   * Bug 619178 - Update CPU detection in yuv_convert to new SSE.h interface.
   * Bug 616778 - Split yuv_convert FilterRows vectorized code into separate files so it can
     be properly guarded with cpuid() calls.
--- a/gfx/ycbcr/convert.patch
+++ b/gfx/ycbcr/convert.patch
@@ -1,12 +1,12 @@
 diff --git a/gfx/ycbcr/yuv_convert.cpp b/gfx/ycbcr/yuv_convert.cpp
 --- a/gfx/ycbcr/yuv_convert.cpp
 +++ b/gfx/ycbcr/yuv_convert.cpp
-@@ -6,145 +6,133 @@
+@@ -6,145 +6,102 @@
  // http://www.fourcc.org/yuv.php
  // The actual conversion is best described here
  // http://en.wikipedia.org/wiki/YUV
  // An article on optimizing YUV conversion using tables instead of multiplies
  // http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
  //
  // YV12 is a full plane of Y and a half height, half width chroma planes
  // YV16 is a full plane of Y and a full height, half width chroma planes
@@ -33,56 +33,25 @@ diff --git a/gfx/ycbcr/yuv_convert.cpp b
 -#include <emmintrin.h>
 -#endif
 -
 -namespace media {
 -
 +#include "yuv_row.h"
 +#include "mozilla/SSE.h"
 +
-+#ifdef HAVE_YCBCR_TO_RGB565
-+void __attribute((noinline)) yv12_to_rgb565_neon(uint16 *dst, const uint8 *y, const uint8 *u, const uint8 *v, int n, int oddflag);
-+#endif
-+
 +namespace mozilla {
 +
 +namespace gfx {
 + 
  // 16.16 fixed point arithmetic
  const int kFractionBits = 16;
  const int kFractionMax = 1 << kFractionBits;
  const int kFractionMask = ((1 << kFractionBits) - 1);
  
-+
-+// Convert a frame of YUV to 16 bit RGB565.
-+NS_GFX_(void) ConvertYCbCrToRGB565(const uint8* y_buf,
-+                                  const uint8* u_buf,
-+                                  const uint8* v_buf,
-+                                  uint8* rgb_buf,
-+                                  int pic_x,
-+                                  int pic_y,
-+                                  int pic_width,
-+                                  int pic_height,
-+                                  int y_pitch,
-+                                  int uv_pitch,
-+                                  int rgb_pitch,
-+                                  YUVType yuv_type)
-+{
-+#ifdef HAVE_YCBCR_TO_RGB565
-+  for (int i = 0; i < pic_height; i++) {
-+    yv12_to_rgb565_neon((uint16*)(rgb_buf + rgb_pitch * i),
-+                         y_buf + y_pitch * i,
-+                         u_buf + uv_pitch * (i / 2),
-+                         v_buf + uv_pitch * (i / 2),
-+                         pic_width,
-+                         0);
-+  }
-+#endif
-+}
-+
  // Convert a frame of YUV to 32 bit ARGB.
 -void ConvertYUVToRGB32(const uint8* y_buf,
 -                       const uint8* u_buf,
 -                       const uint8* v_buf,
 -                       uint8* rgb_buf,
 -                       int width,
 -                       int height,
 -                       int y_pitch,
@@ -450,35 +419,31 @@ diff --git a/gfx/ycbcr/yuv_convert.cpp b
 +    EMMS();
 +}
 +
 +}  // namespace gfx
 +}  // namespace mozilla
 diff --git a/gfx/ycbcr/yuv_convert.h b/gfx/ycbcr/yuv_convert.h
 --- a/gfx/ycbcr/yuv_convert.h
 +++ b/gfx/ycbcr/yuv_convert.h
-@@ -1,72 +1,98 @@
+@@ -1,72 +1,79 @@
  // Copyright (c) 2010 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #ifndef MEDIA_BASE_YUV_CONVERT_H_
  #define MEDIA_BASE_YUV_CONVERT_H_
  
 -#include "base/basictypes.h"
 -
 -namespace media {
 -
 +#include "chromium_types.h"
 +#include "gfxCore.h"
 +
-+#ifdef __arm__
-+#define HAVE_YCBCR_TO_RGB565 1
-+#endif
-+ 
 +namespace mozilla {
 +
 +namespace gfx {
 + 
  // Type of YUV surface.
  // The value of these enums matter as they are used to shift vertical indices.
  enum YUVType {
 -  YV16 = 0,           // YV16 is half width and full height chroma channels.
@@ -506,31 +471,16 @@ diff --git a/gfx/ycbcr/yuv_convert.h b/g
  enum ScaleFilter {
    FILTER_NONE = 0,        // No filter (point sampled).
    FILTER_BILINEAR_H = 1,  // Bilinear horizontal filter.
    FILTER_BILINEAR_V = 2,  // Bilinear vertical filter.
 -  FILTER_BILINEAR = 3,    // Bilinear filter.
 +  FILTER_BILINEAR = 3     // Bilinear filter.
  };
  
-+// Convert a frame of YUV to 16 bit RGB565.
-+// Pass in YV12 formats
-+NS_GFX_(void) ConvertYCbCrToRGB565(const uint8* yplane,
-+                                  const uint8* uplane,
-+                                  const uint8* vplane,
-+                                  uint8* rgbframe,
-+                                  int pic_x,
-+                                  int pic_y,
-+                                  int pic_width,
-+                                  int pic_height,
-+                                  int ystride,
-+                                  int uvstride,
-+                                  int rgbstride,
-+                                  YUVType yuv_type);
-+
  // Convert a frame of YUV to 32 bit ARGB.
  // Pass in YV16/YV12 depending on source format
 -void ConvertYUVToRGB32(const uint8* yplane,
 -                       const uint8* uplane,
 -                       const uint8* vplane,
 -                       uint8* rgbframe,
 -                       int width,
 -                       int height,
--- a/gfx/ycbcr/ycbcr_to_rgb565.cpp
+++ b/gfx/ycbcr/ycbcr_to_rgb565.cpp
@@ -16,16 +16,18 @@
  *
  * The Initial Developer of the Original Code is
  * Netscape Communications Corporation.
  * Portions created by the Initial Developer are Copyright (C) 2002
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *  Tom Brinkman <reportbase@gmail.com>
+ *  Siarhei Siamashka <siarhei.siamashka@gmail.com>
+ *  Timothy B. Terriberry <tterriberry@mozilla.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -33,23 +35,125 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "ycbcr_to_rgb565.h"
 
-#if !defined (MOZILLA_MAY_SUPPORT_NEON)
+#ifdef HAVE_YCBCR_TO_RGB565
+
+namespace mozilla {
+
+namespace gfx {
+
+# if defined(MOZILLA_MAY_SUPPORT_NEON)
+
+void __attribute((noinline)) yuv42x_to_rgb565_row_neon(uint16 *dst,
+                                                       const uint8 *y,
+                                                       const uint8 *u,
+                                                       const uint8 *v,
+                                                       int n,
+                                                       int oddflag);
+
+#endif
 
-int have_ycbcr_to_rgb565 ()
+/*Convert a single pixel from Y'CbCr to RGB565.*/
+static PRUint16 yu2rgb565(int y, int u, int v) {
+  int r;
+  int g;
+  int b;
+  r = NS_CLAMP((74*y+102*v-14240+256)>>9, 0, 31);
+  g = NS_CLAMP((74*y-25*u-52*v+8704+128)>>8, 0, 63);
+  b = NS_CLAMP((74*y+129*u-17696+256)>>9, 0, 31);
+  return (PRUint16)(r<<11 | g<<5 | b);
+}
+
+
+
+void yuv_to_rgb565_row_c(uint16 *dst,
+                         const uint8 *y,
+                         const uint8 *u,
+                         const uint8 *v,
+                         int x_shift,
+                         int pic_x,
+                         int pic_width)
 {
-    return 0;
+  int x;
+  for (x = 0; x < pic_width; x++)
+  {
+    dst[x] = yu2rgb565(y[pic_x+x],
+                       u[(pic_x+x)>>x_shift],
+                       v[(pic_x+x)>>x_shift]);
+  }
 }
 
-#else
-
-int have_ycbcr_to_rgb565 ()
+NS_GFX_(void) ConvertYCbCrToRGB565(const uint8* y_buf,
+                                   const uint8* u_buf,
+                                   const uint8* v_buf,
+                                   uint8* rgb_buf,
+                                   int pic_x,
+                                   int pic_y,
+                                   int pic_width,
+                                   int pic_height,
+                                   int y_pitch,
+                                   int uv_pitch,
+                                   int rgb_pitch,
+                                   YUVType yuv_type)
 {
-    return mozilla::supports_neon();
+  int x_shift;
+  int y_shift;
+  x_shift = yuv_type != YV24;
+  y_shift = yuv_type == YV12;
+#  ifdef MOZILLA_MAY_SUPPORT_NEON
+  if (yuv_type != YV24 && supports_neon())
+  {
+    for (int i = 0; i < pic_height; i++) {
+      int yoffs;
+      int uvoffs;
+      yoffs = y_pitch * (pic_y+i) + pic_x;
+      uvoffs = uv_pitch * ((pic_y+i)>>y_shift) + (pic_x>>x_shift);
+      yuv42x_to_rgb565_row_neon((uint16*)(rgb_buf + rgb_pitch * i),
+                                y_buf + yoffs,
+                                u_buf + uvoffs,
+                                v_buf + uvoffs,
+                                pic_width,
+                                pic_x&x_shift);
+    }
+  }
+  else
+#  endif
+  {
+    for (int i = 0; i < pic_height; i++) {
+      int yoffs;
+      int uvoffs;
+      yoffs = y_pitch * (pic_y+i);
+      uvoffs = uv_pitch * ((pic_y+i)>>y_shift);
+      yuv_to_rgb565_row_c((uint16*)(rgb_buf + rgb_pitch * i),
+                          y_buf + yoffs,
+                          u_buf + uvoffs,
+                          v_buf + uvoffs,
+                          x_shift,
+                          pic_x,
+                          pic_width);
+    }
+  }
 }
 
-#endif //MOZILLA_MAY_SUPPORT_NEON
+NS_GFX_(bool) IsConvertYCbCrToRGB565Fast(int pic_x,
+                                         int pic_y,
+                                         int pic_width,
+                                         int pic_height,
+                                         YUVType yuv_type)
+{
+#  if defined(MOZILLA_MAY_SUPPORT_NEON)
+  return (yuv_type != YV24 && supports_neon());
+#  else
+  return false;
+#  endif
+}
+
+} // namespace gfx
+
+} // namespace mozilla
+
+#endif // HAVE_YCBCR_TO_RGB565
--- a/gfx/ycbcr/ycbcr_to_rgb565.h
+++ b/gfx/ycbcr/ycbcr_to_rgb565.h
@@ -1,10 +1,45 @@
 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 #ifndef MEDIA_BASE_YCBCR_TO_RGB565_H_
 #define MEDIA_BASE_YCBCR_TO_RGB565_H_
+#include "yuv_convert.h"
 #include "mozilla/arm.h"
 
-int have_ycbcr_to_rgb565();
+// It's currently only worth including this if we have NEON support.
+#ifdef MOZILLA_MAY_SUPPORT_NEON
+#define HAVE_YCBCR_TO_RGB565 1
+#endif
+
+namespace mozilla {
+
+namespace gfx {
+
+#ifdef HAVE_YCBCR_TO_RGB565
+// Convert a frame of YUV to 16 bit RGB565.
+NS_GFX_(void) ConvertYCbCrToRGB565(const uint8* yplane,
+                                   const uint8* uplane,
+                                   const uint8* vplane,
+                                   uint8* rgbframe,
+                                   int pic_x,
+                                   int pic_y,
+                                   int pic_width,
+                                   int pic_height,
+                                   int ystride,
+                                   int uvstride,
+                                   int rgbstride,
+                                   YUVType yuv_type);
+
+// Used to test if we have an accelerated version.
+NS_GFX_(bool) IsConvertYCbCrToRGB565Fast(int pic_x,
+                                         int pic_y,
+                                         int pic_width,
+                                         int pic_height,
+                                         YUVType yuv_type);
+#endif // HAVE_YCBCR_TO_RGB565
+
+}  // namespace gfx
+
+}  // namespace mozilla
 
 #endif // MEDIA_BASE_YCBCR_TO_RGB565_H_
--- a/gfx/ycbcr/yuv_convert.cpp
+++ b/gfx/ycbcr/yuv_convert.cpp
@@ -17,56 +17,25 @@
 // The alpha is set to 255, allowing the application to use RGBA or RGB32.
 
 #include "yuv_convert.h"
 
 // Header for low level row functions.
 #include "yuv_row.h"
 #include "mozilla/SSE.h"
 
-#ifdef HAVE_YCBCR_TO_RGB565
-void __attribute((noinline)) yv12_to_rgb565_neon(uint16 *dst, const uint8 *y, const uint8 *u, const uint8 *v, int n, int oddflag);
-#endif
-
 namespace mozilla {
 
 namespace gfx {
  
 // 16.16 fixed point arithmetic
 const int kFractionBits = 16;
 const int kFractionMax = 1 << kFractionBits;
 const int kFractionMask = ((1 << kFractionBits) - 1);
 
-
-// Convert a frame of YUV to 16 bit RGB565.
-NS_GFX_(void) ConvertYCbCrToRGB565(const uint8* y_buf,
-                                  const uint8* u_buf,
-                                  const uint8* v_buf,
-                                  uint8* rgb_buf,
-                                  int pic_x,
-                                  int pic_y,
-                                  int pic_width,
-                                  int pic_height,
-                                  int y_pitch,
-                                  int uv_pitch,
-                                  int rgb_pitch,
-                                  YUVType yuv_type)
-{
-#ifdef HAVE_YCBCR_TO_RGB565
-  for (int i = 0; i < pic_height; i++) {
-    yv12_to_rgb565_neon((uint16*)(rgb_buf + rgb_pitch * i),
-                         y_buf + y_pitch * i,
-                         u_buf + uv_pitch * (i / 2),
-                         v_buf + uv_pitch * (i / 2),
-                         pic_width,
-                         0);
-  }
-#endif
-}
-
 // Convert a frame of YUV to 32 bit ARGB.
 NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* y_buf,
                                   const uint8* u_buf,
                                   const uint8* v_buf,
                                   uint8* rgb_buf,
                                   int pic_x,
                                   int pic_y,
                                   int pic_width,
--- a/gfx/ycbcr/yuv_convert.h
+++ b/gfx/ycbcr/yuv_convert.h
@@ -3,20 +3,16 @@
 // found in the LICENSE file.
 
 #ifndef MEDIA_BASE_YUV_CONVERT_H_
 #define MEDIA_BASE_YUV_CONVERT_H_
 
 #include "chromium_types.h"
 #include "gfxCore.h"
 
-#ifdef HAVE_ARM_NEON
-#define HAVE_YCBCR_TO_RGB565 1
-#endif
- 
 namespace mozilla {
 
 namespace gfx {
  
 // Type of YUV surface.
 // The value of these enums matter as they are used to shift vertical indices.
 enum YUVType {
   YV12 = 0,           // YV12 is half width and half height chroma channels.
@@ -40,31 +36,16 @@ enum Rotate {
 // Filter affects how scaling looks.
 enum ScaleFilter {
   FILTER_NONE = 0,        // No filter (point sampled).
   FILTER_BILINEAR_H = 1,  // Bilinear horizontal filter.
   FILTER_BILINEAR_V = 2,  // Bilinear vertical filter.
   FILTER_BILINEAR = 3     // Bilinear filter.
 };
 
-// Convert a frame of YUV to 16 bit RGB565.
-// Pass in YV12 formats
-NS_GFX_(void) ConvertYCbCrToRGB565(const uint8* yplane,
-                                  const uint8* uplane,
-                                  const uint8* vplane,
-                                  uint8* rgbframe,
-                                  int pic_x,
-                                  int pic_y,
-                                  int pic_width,
-                                  int pic_height,
-                                  int ystride,
-                                  int uvstride,
-                                  int rgbstride,
-                                  YUVType yuv_type);
-
 // Convert a frame of YUV to 32 bit ARGB.
 // Pass in YV16/YV12 depending on source format
 NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* yplane,
                                   const uint8* uplane,
                                   const uint8* vplane,
                                   uint8* rgbframe,
                                   int pic_x,
                                   int pic_y,
--- a/gfx/ycbcr/yuv_convert_arm.cpp
+++ b/gfx/ycbcr/yuv_convert_arm.cpp
@@ -1,17 +1,32 @@
 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 // contributor Siarhei Siamashka <siarhei.siamashka@gmail.com>
 
 #include "yuv_convert.h"
+#include "ycbcr_to_rgb565.h"
 
-void __attribute((noinline)) yv12_to_rgb565_neon(uint16 *dst, const uint8 *y, const uint8 *u, const uint8 *v, int n, int oddflag)
+
+
+#ifdef HAVE_YCBCR_TO_RGB565
+
+namespace mozilla {
+
+namespace gfx {
+
+#  if defined(MOZILLA_MAY_SUPPORT_NEON)
+void __attribute((noinline)) yuv42x_to_rgb565_row_neon(uint16 *dst,
+                                                       const uint8 *y,
+                                                       const uint8 *u,
+                                                       const uint8 *v,
+                                                       int n,
+                                                       int oddflag)
 {
     static __attribute__((aligned(16))) uint16 acc_r[8] = {
         22840, 22840, 22840, 22840, 22840, 22840, 22840, 22840,
     };
     static __attribute__((aligned(16))) uint16 acc_g[8] = {
         17312, 17312, 17312, 17312, 17312, 17312, 17312, 17312,
     };
     static __attribute__((aligned(16))) uint16 acc_b[8] = {
@@ -194,8 +209,15 @@ void __attribute((noinline)) yv12_to_rgb
 	  [oddflag] "r" (oddflag)
 	: "cc", "memory",
 	  "d0",  "d1",  "d2",  "d3",  "d4",  "d5",  "d6",  "d7",
 	  "d8",  "d9",  "d10", "d11", /* "d12", "d13", "d14", "d15", */
 	  "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
 	  "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"
     );
 }
+#  endif // MOZILLA_MAY_SUPPORT_NEON
+
+} // namespace gfx
+
+} // namespace mozilla
+
+#endif // HAVE_YCBCR_TO_RGB565