Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(114)

Unified Diff: media/base/yuv_convert.cc

Issue 7891039: Resubmit - Rewrite color space conversions suite using YASM" (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/base/yuv_convert.h ('k') | media/base/yuv_convert_internal.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/base/yuv_convert.cc
diff --git a/media/base/yuv_convert.cc b/media/base/yuv_convert.cc
index cbf7f57622fdeb909f1d801c9c15a1c12a6ba9b6..7b4586ac07cfa556e55474325faf6eae14aa652a 100644
--- a/media/base/yuv_convert.cc
+++ b/media/base/yuv_convert.cc
@@ -17,151 +17,93 @@
#include "media/base/yuv_convert.h"
+#include "base/logging.h"
#include "build/build_config.h"
#include "media/base/cpu_features.h"
#include "media/base/simd/convert_rgb_to_yuv.h"
+#include "media/base/simd/convert_yuv_to_rgb.h"
+#include "media/base/simd/filter_yuv.h"
#include "media/base/yuv_convert_internal.h"
#include "media/base/yuv_row.h"
-#if USE_MMX
-#if defined(_MSC_VER)
+#if defined(ARCH_CPU_X86_FAMILY)
+#if defined(COMPILER_MSVC)
#include <intrin.h>
#else
#include <mmintrin.h>
#endif
#endif
-#if USE_SSE2
-#include <emmintrin.h>
-#endif
-
namespace media {
-// 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 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,
- int uv_pitch,
- int rgb_pitch,
- YUVType yuv_type) {
- unsigned int y_shift = yuv_type;
- for (int y = 0; y < height; ++y) {
- uint8* rgb_row = rgb_buf + y * rgb_pitch;
- const uint8* y_ptr = y_buf + y * y_pitch;
- const uint8* u_ptr = u_buf + (y >> y_shift) * uv_pitch;
- const uint8* v_ptr = v_buf + (y >> y_shift) * uv_pitch;
-
- FastConvertYUVToRGB32Row(y_ptr,
- u_ptr,
- v_ptr,
- rgb_row,
- width);
- }
-
- // MMX used for FastConvertYUVToRGB32Row requires emms instruction.
- EMMS();
+static FilterYUVRowsProc ChooseFilterYUVRowsProc() {
+#if defined(ARCH_CPU_X86_FAMILY)
+ if (hasSSE2())
+ return &FilterYUVRows_SSE2;
+ if (hasMMX())
+ return &FilterYUVRows_MMX;
+#endif
+ return &FilterYUVRows_C;
}
-#if USE_SSE2
-// FilterRows combines two rows of the image using linear interpolation.
-// SSE2 version does 16 pixels at a time
-
-static void FilterRows(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr,
- int source_width, int source_y_fraction) {
- __m128i zero = _mm_setzero_si128();
- __m128i y1_fraction = _mm_set1_epi16(source_y_fraction);
- __m128i y0_fraction = _mm_set1_epi16(256 - source_y_fraction);
-
- const __m128i* y0_ptr128 = reinterpret_cast<const __m128i*>(y0_ptr);
- const __m128i* y1_ptr128 = reinterpret_cast<const __m128i*>(y1_ptr);
- __m128i* dest128 = reinterpret_cast<__m128i*>(ybuf);
- __m128i* end128 = reinterpret_cast<__m128i*>(ybuf + source_width);
-
- do {
- __m128i y0 = _mm_loadu_si128(y0_ptr128);
- __m128i y1 = _mm_loadu_si128(y1_ptr128);
- __m128i y2 = _mm_unpackhi_epi8(y0, zero);
- __m128i y3 = _mm_unpackhi_epi8(y1, zero);
- y0 = _mm_unpacklo_epi8(y0, zero);
- y1 = _mm_unpacklo_epi8(y1, zero);
- y0 = _mm_mullo_epi16(y0, y0_fraction);
- y1 = _mm_mullo_epi16(y1, y1_fraction);
- y2 = _mm_mullo_epi16(y2, y0_fraction);
- y3 = _mm_mullo_epi16(y3, y1_fraction);
- y0 = _mm_add_epi16(y0, y1);
- y2 = _mm_add_epi16(y2, y3);
- y0 = _mm_srli_epi16(y0, 8);
- y2 = _mm_srli_epi16(y2, 8);
- y0 = _mm_packus_epi16(y0, y2);
- *dest128++ = y0;
- ++y0_ptr128;
- ++y1_ptr128;
- } while (dest128 < end128);
+static ConvertYUVToRGB32RowProc ChooseConvertYUVToRGB32RowProc() {
+#if defined(ARCH_CPU_X86_FAMILY)
+ if (hasSSE())
+ return &ConvertYUVToRGB32Row_SSE;
+ if (hasMMX())
+ return &ConvertYUVToRGB32Row_MMX;
+#endif
+ return &ConvertYUVToRGB32Row_C;
}
-#elif USE_MMX
-// MMX version does 8 pixels at a time
-static void FilterRows(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr,
- int source_width, int source_y_fraction) {
- __m64 zero = _mm_setzero_si64();
- __m64 y1_fraction = _mm_set1_pi16(source_y_fraction);
- __m64 y0_fraction = _mm_set1_pi16(256 - source_y_fraction);
-
- const __m64* y0_ptr64 = reinterpret_cast<const __m64*>(y0_ptr);
- const __m64* y1_ptr64 = reinterpret_cast<const __m64*>(y1_ptr);
- __m64* dest64 = reinterpret_cast<__m64*>(ybuf);
- __m64* end64 = reinterpret_cast<__m64*>(ybuf + source_width);
-
- do {
- __m64 y0 = *y0_ptr64++;
- __m64 y1 = *y1_ptr64++;
- __m64 y2 = _mm_unpackhi_pi8(y0, zero);
- __m64 y3 = _mm_unpackhi_pi8(y1, zero);
- y0 = _mm_unpacklo_pi8(y0, zero);
- y1 = _mm_unpacklo_pi8(y1, zero);
- y0 = _mm_mullo_pi16(y0, y0_fraction);
- y1 = _mm_mullo_pi16(y1, y1_fraction);
- y2 = _mm_mullo_pi16(y2, y0_fraction);
- y3 = _mm_mullo_pi16(y3, y1_fraction);
- y0 = _mm_add_pi16(y0, y1);
- y2 = _mm_add_pi16(y2, y3);
- y0 = _mm_srli_pi16(y0, 8);
- y2 = _mm_srli_pi16(y2, 8);
- y0 = _mm_packs_pu16(y0, y2);
- *dest64++ = y0;
- } while (dest64 < end64);
+
+static ScaleYUVToRGB32RowProc ChooseScaleYUVToRGB32RowProc() {
+#if defined(ARCH_CPU_X86_FAMILY)
+#if defined(ARCH_CPU_X86_64)
+ // Use 64-bits version if possible.
+ return &ScaleYUVToRGB32Row_SSE2_X64;
+#endif
+ // Choose the best one on 32-bits system.
+ if (hasSSE())
+ return &ScaleYUVToRGB32Row_SSE;
+ if (hasMMX())
+ return &ScaleYUVToRGB32Row_MMX;
+#endif
+ return &ScaleYUVToRGB32Row_C;
}
-#else // no MMX or SSE2
-// C version does 8 at a time to mimic MMX code
-static void FilterRows(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr,
- int source_width, int source_y_fraction) {
- int y1_fraction = source_y_fraction;
- int y0_fraction = 256 - y1_fraction;
- uint8* end = ybuf + source_width;
- do {
- ybuf[0] = (y0_ptr[0] * y0_fraction + y1_ptr[0] * y1_fraction) >> 8;
- ybuf[1] = (y0_ptr[1] * y0_fraction + y1_ptr[1] * y1_fraction) >> 8;
- ybuf[2] = (y0_ptr[2] * y0_fraction + y1_ptr[2] * y1_fraction) >> 8;
- ybuf[3] = (y0_ptr[3] * y0_fraction + y1_ptr[3] * y1_fraction) >> 8;
- ybuf[4] = (y0_ptr[4] * y0_fraction + y1_ptr[4] * y1_fraction) >> 8;
- ybuf[5] = (y0_ptr[5] * y0_fraction + y1_ptr[5] * y1_fraction) >> 8;
- ybuf[6] = (y0_ptr[6] * y0_fraction + y1_ptr[6] * y1_fraction) >> 8;
- ybuf[7] = (y0_ptr[7] * y0_fraction + y1_ptr[7] * y1_fraction) >> 8;
- y0_ptr += 8;
- y1_ptr += 8;
- ybuf += 8;
- } while (ybuf < end);
+
+static ScaleYUVToRGB32RowProc ChooseLinearScaleYUVToRGB32RowProc() {
+#if defined(ARCH_CPU_X86_FAMILY)
+#if defined(ARCH_CPU_X86_64)
+ // Use 64-bits version if possible.
+ return &LinearScaleYUVToRGB32Row_MMX_X64;
+#endif
+ // 32-bits system.
+ if (hasSSE())
+ return &LinearScaleYUVToRGB32Row_SSE;
+ if (hasMMX())
+ return &LinearScaleYUVToRGB32Row_MMX;
+#endif
+ return &LinearScaleYUVToRGB32Row_C;
}
+
+// Empty SIMD registers state after using them.
+void EmptyRegisterState() {
+#if defined(ARCH_CPU_X86_FAMILY)
+ static bool checked = false;
+ static bool has_mmx = false;
+ if (!checked) {
+ has_mmx = hasMMX();
+ checked = true;
+ }
+ if (has_mmx)
+ _mm_empty();
#endif
+}
+// 16.16 fixed point arithmetic
+const int kFractionBits = 16;
+const int kFractionMax = 1 << kFractionBits;
+const int kFractionMask = ((1 << kFractionBits) - 1);
// Scale a frame of YUV to 32 bit ARGB.
void ScaleYUVToRGB32(const uint8* y_buf,
@@ -178,6 +120,20 @@ void ScaleYUVToRGB32(const uint8* y_buf,
YUVType yuv_type,
Rotate view_rotate,
ScaleFilter filter) {
+ static FilterYUVRowsProc filter_proc = NULL;
+ static ConvertYUVToRGB32RowProc convert_proc = NULL;
+ static ScaleYUVToRGB32RowProc scale_proc = NULL;
+ static ScaleYUVToRGB32RowProc linear_scale_proc = NULL;
+
+ if (!filter_proc)
+ filter_proc = ChooseFilterYUVRowsProc();
+ if (!convert_proc)
+ convert_proc = ChooseConvertYUVToRGB32RowProc();
+ if (!scale_proc)
+ scale_proc = ChooseScaleYUVToRGB32RowProc();
+ if (!linear_scale_proc)
+ linear_scale_proc = ChooseLinearScaleYUVToRGB32RowProc();
+
// Handle zero sized sources and destinations.
if ((yuv_type == YV12 && (source_width < 2 || source_height < 2)) ||
(yuv_type == YV16 && (source_width < 2 || source_height < 1)) ||
@@ -225,9 +181,6 @@ void ScaleYUVToRGB32(const uint8* y_buf,
int source_dx = source_width * kFractionMax / width;
int source_dy = source_height * kFractionMax / height;
-#if USE_MMX && defined(_MSC_VER)
- int source_dx_uv = source_dx;
-#endif
if ((view_rotate == ROTATE_90) ||
(view_rotate == ROTATE_270)) {
@@ -240,9 +193,6 @@ void ScaleYUVToRGB32(const uint8* y_buf,
int original_dx = source_dx;
int original_dy = source_dy;
source_dx = ((original_dy >> kFractionBits) * y_pitch) << kFractionBits;
-#if USE_MMX && defined(_MSC_VER)
- source_dx_uv = ((original_dy >> kFractionBits) * uv_pitch) << kFractionBits;
-#endif
source_dy = original_dx;
if (view_rotate == ROTATE_90) {
y_pitch = -1;
@@ -294,7 +244,7 @@ void ScaleYUVToRGB32(const uint8* y_buf,
if (filter & media::FILTER_BILINEAR_V) {
if (yscale_fixed != kFractionMax &&
source_y_fraction && ((source_y + 1) < source_height)) {
- FilterRows(ybuf, y0_ptr, y1_ptr, source_width, source_y_fraction);
+ filter_proc(ybuf, y0_ptr, y1_ptr, source_width, source_y_fraction);
} else {
memcpy(ybuf, y0_ptr, source_width);
}
@@ -304,8 +254,8 @@ void ScaleYUVToRGB32(const uint8* y_buf,
if (yscale_fixed != kFractionMax &&
source_uv_fraction &&
(((source_y >> y_shift) + 1) < (source_height >> y_shift))) {
- FilterRows(ubuf, u0_ptr, u1_ptr, uv_source_width, source_uv_fraction);
- FilterRows(vbuf, v0_ptr, v1_ptr, uv_source_width, source_uv_fraction);
+ filter_proc(ubuf, u0_ptr, u1_ptr, uv_source_width, source_uv_fraction);
+ filter_proc(vbuf, v0_ptr, v1_ptr, uv_source_width, source_uv_fraction);
} else {
memcpy(ubuf, u0_ptr, uv_source_width);
memcpy(vbuf, v0_ptr, uv_source_width);
@@ -316,41 +266,17 @@ void ScaleYUVToRGB32(const uint8* y_buf,
vbuf[uv_source_width] = vbuf[uv_source_width - 1];
}
if (source_dx == kFractionMax) { // Not scaled
- FastConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
- dest_pixel, width);
+ convert_proc(y_ptr, u_ptr, v_ptr, dest_pixel, width);
} else {
if (filter & FILTER_BILINEAR_H) {
- LinearScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
- dest_pixel, width, source_dx);
- } else {
-// Specialized scalers and rotation.
-#if USE_MMX && defined(_MSC_VER)
- if (width == (source_width * 2)) {
- DoubleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
- dest_pixel, width);
- } else if ((source_dx & kFractionMask) == 0) {
- // Scaling by integer scale factor. ie half.
- ConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
- dest_pixel, width,
- source_dx >> kFractionBits);
- } else if (source_dx_uv == source_dx) { // Not rotated.
- ScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
- dest_pixel, width, source_dx);
- } else {
- RotateConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
- dest_pixel, width,
- source_dx >> kFractionBits,
- source_dx_uv >> kFractionBits);
- }
-#else
- ScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
- dest_pixel, width, source_dx);
-#endif
+ linear_scale_proc(y_ptr, u_ptr, v_ptr, dest_pixel, width, source_dx);
+ } else {
+ scale_proc(y_ptr, u_ptr, v_ptr, dest_pixel, width, source_dx);
}
}
}
- // MMX used for FastConvertYUVToRGB32Row and FilterRows requires emms.
- EMMS();
+
+ EmptyRegisterState();
}
void ConvertRGB32ToYUV(const uint8* rgbframe,
@@ -370,7 +296,6 @@ void ConvertRGB32ToYUV(const uint8* rgbframe,
// TODO(hclam): Implement a NEON version.
convert_proc = &ConvertRGB32ToYUV_C;
#else
- // For x86 processors, check if SSSE3 (or SSE2) is supported.
if (hasSSE2())
convert_proc = &ConvertRGB32ToYUV_SSE2;
else
@@ -403,4 +328,34 @@ void ConvertYUY2ToYUV(const uint8* src,
int height) {
ConvertYUY2ToYUV_C(src, yplane, uplane, vplane, width, height);
}
+
+void ConvertYUVToRGB32(const uint8* yplane,
+ const uint8* uplane,
+ const uint8* vplane,
+ uint8* rgbframe,
+ int width,
+ int height,
+ int ystride,
+ int uvstride,
+ int rgbstride,
+ YUVType yuv_type) {
+#if defined(ARCH_CPU_ARM_FAMILY)
+ ConvertYUVToRGB32_C(yplane, uplane, vplane, rgbframe,
+ width, height, ystride, uvstride, rgbstride, yuv_type);
+#else
+ static ConvertYUVToRGB32Proc convert_proc = NULL;
+ if (!convert_proc) {
+ if (hasSSE())
+ convert_proc = &ConvertYUVToRGB32_SSE;
+ else if (hasMMX())
+ convert_proc = &ConvertYUVToRGB32_MMX;
+ else
+ convert_proc = &ConvertYUVToRGB32_C;
+ }
+
+ convert_proc(yplane, uplane, vplane, rgbframe,
+ width, height, ystride, uvstride, rgbstride, yuv_type);
+#endif
+}
+
} // namespace media
« no previous file with comments | « media/base/yuv_convert.h ('k') | media/base/yuv_convert_internal.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698