Bug 641014 - Fix broken NEO Y'CbCr to RGB conversion - r=doublec

--HG--
extra : rebase_source : fddd6ccddd083484c8b46a53747fb2058a46463e
This commit is contained in:
Tim Terribe 2011-04-09 06:59:22 +12:00
Родитель 21090ba813
Коммит 962584e61d
8 изменённых файлов: 215 добавлений и 141 удалений

Просмотреть файл

@ -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) {
@ -184,7 +160,41 @@ BasicPlanarYCbCrImage::SetData(const Data& aData)
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) {
@ -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,
@ -233,7 +244,6 @@ BasicPlanarYCbCrImage::SetData(const Data& aData)
aData.mCbCrStride,
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