зеркало из https://github.com/mozilla/gecko-dev.git
Bug 641014 - Fix broken NEO Y'CbCr to RGB conversion - r=doublec
--HG-- extra : rebase_source : fddd6ccddd083484c8b46a53747fb2058a46463e
This commit is contained in:
Родитель
21090ba813
Коммит
962584e61d
|
@ -144,30 +144,6 @@ BasicPlanarYCbCrImage::SetData(const Data& aData)
|
|||
|
||||
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) {
|
||||
|
@ -185,6 +161,40 @@ BasicPlanarYCbCrImage::SetData(const Data& aData)
|
|||
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) {
|
||||
|
@ -206,8 +216,8 @@ BasicPlanarYCbCrImage::SetData(const Data& aData)
|
|||
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,
|
||||
|
@ -220,7 +230,8 @@ BasicPlanarYCbCrImage::SetData(const Data& aData)
|
|||
aData.mCbCrStride,
|
||||
mStride,
|
||||
type);
|
||||
} else { // format != gfxASurface::ImageFormatRGB16_565
|
||||
} else // format != gfxASurface::ImageFormatRGB16_565
|
||||
#endif
|
||||
gfx::ConvertYCbCrToRGB32(aData.mYChannel,
|
||||
aData.mCbChannel,
|
||||
aData.mCrChannel,
|
||||
|
@ -234,7 +245,6 @@ BasicPlanarYCbCrImage::SetData(const Data& aData)
|
|||
mStride,
|
||||
type);
|
||||
}
|
||||
}
|
||||
SetOffscreenFormat(format);
|
||||
mSize = size;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,10 @@ 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:
|
||||
|
@ -14,7 +18,6 @@ convert.patch contains the following changes:
|
|||
* 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.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
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
|
||||
|
@ -38,10 +38,6 @@ diff --git a/gfx/ycbcr/yuv_convert.cpp b/gfx/ycbcr/yuv_convert.cpp
|
|||
+#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 {
|
||||
|
@ -51,33 +47,6 @@ diff --git a/gfx/ycbcr/yuv_convert.cpp b/gfx/ycbcr/yuv_convert.cpp
|
|||
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,
|
||||
|
@ -455,7 +424,7 @@ diff --git a/gfx/ycbcr/yuv_convert.cpp b/gfx/ycbcr/yuv_convert.cpp
|
|||
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.
|
||||
|
@ -470,10 +439,6 @@ diff --git a/gfx/ycbcr/yuv_convert.h b/gfx/ycbcr/yuv_convert.h
|
|||
+#include "chromium_types.h"
|
||||
+#include "gfxCore.h"
|
||||
+
|
||||
+#ifdef __arm__
|
||||
+#define HAVE_YCBCR_TO_RGB565 1
|
||||
+#endif
|
||||
+
|
||||
+namespace mozilla {
|
||||
+
|
||||
+namespace gfx {
|
||||
|
@ -511,21 +476,6 @@ diff --git a/gfx/ycbcr/yuv_convert.h b/gfx/ycbcr/yuv_convert.h
|
|||
+ 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,
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
*
|
||||
* 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
|
||||
|
@ -38,18 +40,120 @@
|
|||
|
||||
#include "ycbcr_to_rgb565.h"
|
||||
|
||||
#if !defined (MOZILLA_MAY_SUPPORT_NEON)
|
||||
#ifdef HAVE_YCBCR_TO_RGB565
|
||||
|
||||
int have_ycbcr_to_rgb565 ()
|
||||
{
|
||||
return 0;
|
||||
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
|
||||
|
||||
/*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);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int have_ycbcr_to_rgb565 ()
|
||||
|
||||
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 mozilla::supports_neon();
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
#endif //MOZILLA_MAY_SUPPORT_NEON
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -3,8 +3,43 @@
|
|||
// 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_
|
||||
|
|
|
@ -22,10 +22,6 @@
|
|||
#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 {
|
||||
|
@ -35,33 +31,6 @@ 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,
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
#include "chromium_types.h"
|
||||
#include "gfxCore.h"
|
||||
|
||||
#ifdef HAVE_ARM_NEON
|
||||
#define HAVE_YCBCR_TO_RGB565 1
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace gfx {
|
||||
|
@ -45,21 +41,6 @@ enum ScaleFilter {
|
|||
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,
|
||||
|
|
|
@ -5,8 +5,23 @@
|
|||
// 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,
|
||||
|
@ -199,3 +214,10 @@ void __attribute((noinline)) yv12_to_rgb565_neon(uint16 *dst, const uint8 *y, co
|
|||
"d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"
|
||||
);
|
||||
}
|
||||
# endif // MOZILLA_MAY_SUPPORT_NEON
|
||||
|
||||
} // namespace gfx
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // HAVE_YCBCR_TO_RGB565
|
||||
|
|
Загрузка…
Ссылка в новой задаче