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

Unified Diff: media/base/yuv_convert.cc

Issue 9138050: Merge 117748 - Linear sub-rectangle scaler for use in Chromoting. (Closed) Base URL: svn://svn.chromium.org/chrome/branches/963/src/
Patch Set: Created 8 years, 11 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_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/base/yuv_convert.cc
===================================================================
--- media/base/yuv_convert.cc (revision 118600)
+++ media/base/yuv_convert.cc (working copy)
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -18,6 +18,7 @@
#include "media/base/yuv_convert.h"
#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
#include "build/build_config.h"
#include "media/base/cpu_features.h"
#include "media/base/simd/convert_rgb_to_yuv.h"
@@ -277,6 +278,157 @@
EmptyRegisterState();
}
+// Scale a frame of YV12 to 32 bit ARGB for a specific rectangle.
+void ScaleYUVToRGB32WithRect(const uint8* y_buf,
+ const uint8* u_buf,
+ const uint8* v_buf,
+ uint8* rgb_buf,
+ int source_width,
+ int source_height,
+ int dest_width,
+ int dest_height,
+ int dest_rect_left,
+ int dest_rect_top,
+ int dest_rect_right,
+ int dest_rect_bottom,
+ int y_pitch,
+ int uv_pitch,
+ int rgb_pitch) {
+ static FilterYUVRowsProc filter_proc = NULL;
+ if (!filter_proc)
+ filter_proc = ChooseFilterYUVRowsProc();
+
+ // This routine doesn't currently support up-scaling.
+ CHECK(dest_width <= source_width && dest_height <= source_height);
+
+ // Sanity-check the destination rectangle.
+ DCHECK(dest_rect_left >= 0 && dest_rect_right <= dest_width);
+ DCHECK(dest_rect_top >= 0 && dest_rect_bottom <= dest_height);
+ DCHECK(dest_rect_right > dest_rect_left);
+ DCHECK(dest_rect_bottom > dest_rect_top);
+
+ // Fixed-point value of vertical and horizontal scale down factor.
+ // Values are in the format 16.16.
+ int y_step = kFractionMax * source_height / dest_height;
+ int x_step = kFractionMax * source_width / dest_width;
+
+ // Determine the coordinates of the rectangle in 16.16 coords.
+ // NB: Our origin is the *center* of the top/left pixel, NOT its top/left.
+ // If we're down-scaling by more than a factor of two, we start with a 50%
+ // fraction to avoid degenerating to point-sampling - we should really just
+ // fix the fraction at 50% for all pixels in that case.
+ int source_left = dest_rect_left * x_step;
+ int source_right = (dest_rect_right - 1) * x_step;
+ if (x_step < kFractionMax * 2) {
+ source_left += ((x_step - kFractionMax) / 2);
+ source_right += ((x_step - kFractionMax) / 2);
+ } else {
+ source_left += kFractionMax / 2;
+ source_right += kFractionMax / 2;
+ }
+ int source_top = dest_rect_top * y_step;
+ if (y_step < kFractionMax * 2) {
+ source_top += ((y_step - kFractionMax) / 2);
+ } else {
+ source_top += kFractionMax / 2;
+ }
+
+ // Determine the parts of the Y, U and V buffers to interpolate.
+ int source_y_left = source_left >> kFractionBits;
+ int source_y_right = (source_right >> kFractionBits) + 2;
+ DCHECK(source_y_right <= source_width);
+
+ int source_uv_left = source_y_left / 2;
+ int source_uv_right = std::min(
+ (source_right >> (kFractionBits + 1)) + 2,
+ (source_width + 1) / 2);
+
+ int source_y_width = source_y_right - source_y_left;
+ int source_uv_width = source_uv_right - source_uv_left;
+
+ // Determine number of pixels in each output row.
+ int dest_rect_width = dest_rect_right - dest_rect_left;
+
+ // Intermediate buffer for vertical interpolation.
+ // 4096 bytes allows 3 buffers to fit in 12k, which fits in a 16K L1 cache,
+ // and is bigger than most users will generally need.
+ // The buffer is 16-byte aligned and padded with 16 extra bytes; some of the
+ // FilterYUVRowProcs have alignment requirements, and the SSE version can
+ // write up to 16 bytes past the end of the buffer.
+ const int kFilterBufferSize = 4096;
+ if (source_width > kFilterBufferSize)
+ filter_proc = NULL;
+ uint8 yuv_temp[16 + kFilterBufferSize * 3 + 16];
+ uint8* y_temp =
+ reinterpret_cast<uint8*>(
+ reinterpret_cast<uintptr_t>(yuv_temp + 15) & ~15);
+ uint8* u_temp = y_temp + kFilterBufferSize;
+ uint8* v_temp = u_temp + kFilterBufferSize;
+
+ // Move to the top-left pixel of output.
+ rgb_buf += dest_rect_top * rgb_pitch;
+ rgb_buf += dest_rect_left * 4;
+
+ // For each destination row perform interpolation and color space
+ // conversion to produce the output.
+ for (int row = dest_rect_top; row < dest_rect_bottom; ++row) {
+ // Round the fixed-point y position to get the current row.
+ int source_row = source_top >> kFractionBits;
+ int source_uv_row = source_row / 2;
+ DCHECK(source_row < source_height);
+
+ // Locate the first row for each plane for interpolation.
+ const uint8* y0_ptr = y_buf + y_pitch * source_row + source_y_left;
+ const uint8* u0_ptr = u_buf + uv_pitch * source_uv_row + source_uv_left;
+ const uint8* v0_ptr = v_buf + uv_pitch * source_uv_row + source_uv_left;
+ const uint8* y1_ptr = NULL;
+ const uint8* u1_ptr = NULL;
+ const uint8* v1_ptr = NULL;
+
+ // Locate the second row for interpolation, being careful not to overrun.
+ if (source_row + 1 >= source_height) {
+ y1_ptr = y0_ptr;
+ } else {
+ y1_ptr = y0_ptr + y_pitch;
+ }
+ if (source_uv_row + 1 >= (source_height + 1) / 2) {
+ u1_ptr = u0_ptr;
+ v1_ptr = v0_ptr;
+ } else {
+ u1_ptr = u0_ptr + uv_pitch;
+ v1_ptr = v0_ptr + uv_pitch;
+ }
+
+ if (filter_proc) {
+ // Vertical scaler uses 16.8 fixed point.
+ int fraction = (source_top & kFractionMask) >> 8;
+ filter_proc(y_temp + source_y_left, y0_ptr, y1_ptr,
+ source_y_width, fraction);
+ filter_proc(u_temp + source_uv_left, u0_ptr, u1_ptr,
+ source_uv_width, fraction);
+ filter_proc(v_temp + source_uv_left, v0_ptr, v1_ptr,
+ source_uv_width, fraction);
+
+ // Perform horizontal interpolation and color space conversion.
+ // TODO(hclam): Use the MMX version after more testing.
+ LinearScaleYUVToRGB32RowWithRange_C(
+ y_temp, u_temp, v_temp, rgb_buf,
+ dest_rect_width, source_left, x_step);
+ } else {
+ // If the frame is too large then we linear scale a single row.
+ LinearScaleYUVToRGB32RowWithRange_C(
+ y0_ptr, u0_ptr, v0_ptr, rgb_buf,
+ dest_rect_width, source_left, x_step);
+ }
+
+ // Advance vertically in the source and destination image.
+ source_top += y_step;
+ rgb_buf += rgb_pitch;
+ }
+
+ EmptyRegisterState();
+}
+
void ConvertRGB32ToYUV(const uint8* rgbframe,
uint8* yplane,
uint8* uplane,
« no previous file with comments | « media/base/yuv_convert.h ('k') | media/base/yuv_convert_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698