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 dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdoublec
bugs641014
milestone2.2a1pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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