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

Unified Diff: media/base/yuv_convert.cc

Issue 8954003: Revised sub-rectangle scaling for use in Chromoting. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Replace bounds-check on loop with a DCHECK. Created 9 years 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
Index: media/base/yuv_convert.cc
diff --git a/media/base/yuv_convert.cc b/media/base/yuv_convert.cc
index 93af853b3d60a871154d30e716a82fc160d11fa2..b3c72d1c333c2c0530fca60049059397cefc1844 100644
--- a/media/base/yuv_convert.cc
+++ b/media/base/yuv_convert.cc
@@ -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,124 @@ void ScaleYUVToRGB32(const uint8* y_buf,
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();
+
+ // 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 * 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 = std::min(source_width,
+ (source_right + kFractionMax - 1) >> kFractionBits);
+ int source_uv_left = source_y_left / 2;
+ int source_uv_right = std::min((source_width + 1) / 2,
+ (source_right + (kFractionMax*2 - 1)) >>
+ (kFractionBits + 1));
+ 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;
+
+ // Create intermediate buffer for vertical interpolation.
+ scoped_array<uint8> y_temp(new uint8[source_width]);
+ scoped_array<uint8> u_temp(new uint8[source_width / 2]);
+ scoped_array<uint8> v_temp(new uint8[source_width / 2]);
+
+ // 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;
+ 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_row / 2) + source_uv_left;
+ const uint8* v0_ptr = v_buf + uv_pitch * (source_row / 2) + source_uv_left;
+ const uint8* y1_ptr = NULL;
+ const uint8* u1_ptr = NULL;
+ const uint8* v1_ptr = NULL;
+
+ // Locate the second row for interpolation and need to be careful
+ // about bounds checking here.
+ if (source_row + 1 >= source_height) {
+ y1_ptr = y0_ptr;
+ u1_ptr = u0_ptr;
+ v1_ptr = v0_ptr;
+ } else {
+ y1_ptr = y0_ptr + y_pitch;
+ u1_ptr = u0_ptr + uv_pitch;
+ v1_ptr = v0_ptr + uv_pitch;
+ }
+
+ // Vertical scaler uses 16.8 fixed point.
+ int fraction = (source_top & kFractionMask) >> 8;
+ filter_proc(y_temp.get() + source_y_left, y0_ptr, y1_ptr,
+ source_y_width, fraction);
+ filter_proc(u_temp.get() + source_uv_left, u0_ptr, u1_ptr,
+ source_uv_width, fraction);
+ filter_proc(v_temp.get() + 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.get(), u_temp.get(), v_temp.get(), 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,

Powered by Google App Engine
This is Rietveld 408576698