summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-03 00:21:03 +0000
committerhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-03 00:21:03 +0000
commit986e5d0c4c7dcde0b099ed8dfbfd804dac642497 (patch)
treefd62278df4268779c7f0cf22f0e9c6b01e720e81
parent047baea7ea26dde64cab0b0bb255a238ac0955c1 (diff)
downloadchromium_src-986e5d0c4c7dcde0b099ed8dfbfd804dac642497.zip
chromium_src-986e5d0c4c7dcde0b099ed8dfbfd804dac642497.tar.gz
chromium_src-986e5d0c4c7dcde0b099ed8dfbfd804dac642497.tar.bz2
Chromoting host to convert only changed regions
This significantly reduces the number of pixels we need to perform color space conversion. BUG=71253 TEST=None Review URL: http://codereview.chromium.org/6334040 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@73553 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--remoting/base/encoder_vp8.cc83
1 files changed, 48 insertions, 35 deletions
diff --git a/remoting/base/encoder_vp8.cc b/remoting/base/encoder_vp8.cc
index 24d6ba4..7ac75d3 100644
--- a/remoting/base/encoder_vp8.cc
+++ b/remoting/base/encoder_vp8.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "media/base/callback.h"
+#include "media/base/yuv_convert.h"
#include "remoting/base/capture_data.h"
#include "remoting/proto/video.pb.h"
@@ -70,13 +71,27 @@ bool EncoderVp8::Init(int width, int height) {
return true;
}
-static int clip_byte(int x) {
- if (x > 255)
- return 255;
- else if (x < 0)
- return 0;
- else
- return x;
+static int RoundToTwosMultiple(int x) {
+ return x & (~1);
+}
+
+// Align the sides of the rectange to multiples of 2.
+static gfx::Rect AlignRect(const gfx::Rect& rect, int width, int height) {
+ CHECK(rect.width() > 0 && rect.height() > 0);
+ int x = RoundToTwosMultiple(rect.x());
+ int y = RoundToTwosMultiple(rect.y());
+ int right = std::min(RoundToTwosMultiple(rect.right() + 1),
+ RoundToTwosMultiple(width));
+ int bottom = std::min(RoundToTwosMultiple(rect.bottom() + 1),
+ RoundToTwosMultiple(height));
+
+ // Do the final check to make sure the width and height are not negative.
+ gfx::Rect r(x, y, right - x, bottom - y);
+ if (r.width() <= 0 || r.height() <= 0) {
+ r.set_width(0);
+ r.set_height(0);
+ }
+ return r;
}
bool EncoderVp8::PrepareImage(scoped_refptr<CaptureData> capture_data) {
@@ -108,38 +123,36 @@ bool EncoderVp8::PrepareImage(scoped_refptr<CaptureData> capture_data) {
image_->stride[2] = image_->w / 2;
}
- // And then do RGB->YUV conversion.
- // Currently we just produce the Y channel as the average of RGB. This will
- // giv ae gray scale image after conversion.
- // TODO(sergeyu): Move this code to a separate routine.
- // TODO(sergeyu): Optimize this code.
- DCHECK(capture_data->pixel_format() == media::VideoFrame::RGB32)
- << "Only RGB32 is supported";
- uint8* in = capture_data->data_planes().data[0];
+ // Perform RGB->YUV conversion.
+ if (capture_data->pixel_format() != media::VideoFrame::RGB32) {
+ LOG(ERROR) << "Only RGB32 is supported";
+ return false;
+ }
+
+ const InvalidRects& rects = capture_data->dirty_rects();
+ const uint8* in = capture_data->data_planes().data[0];
const int in_stride = capture_data->data_planes().strides[0];
uint8* y_out = yuv_image_.get();
uint8* u_out = yuv_image_.get() + plane_size;
uint8* v_out = yuv_image_.get() + plane_size + plane_size / 4;
- const int out_stride = image_->stride[0];
- for (int i = 0; i < capture_data->height(); ++i) {
- for (int j = 0; j < capture_data->width(); ++j) {
- // Since the input pixel format is RGB32, there are 4 bytes per pixel.
- uint8* pixel = in + 4 * j;
- y_out[j] = clip_byte(((pixel[2] * 66 + pixel[1] * 129 +
- pixel[0] * 25 + 128) >> 8) + 16);
- if (i % 2 == 0 && j % 2 == 0) {
- u_out[j / 2] = clip_byte(((pixel[2] * -38 + pixel[1] * -74 +
- pixel[0] * 112 + 128) >> 8) + 128);
- v_out[j / 2] = clip_byte(((pixel[2] * 112 + pixel[1] * -94 +
- pixel[1] * -18 + 128) >> 8) + 128);
- }
- }
- in += in_stride;
- y_out += out_stride;
- if (i % 2 == 0) {
- u_out += out_stride / 2;
- v_out += out_stride / 2;
- }
+ const int y_stride = image_->stride[0];
+ const int uv_stride = image_->stride[1];
+
+ for (InvalidRects::const_iterator r = rects.begin(); r != rects.end(); ++r) {
+ gfx::Rect rect = AlignRect(*r, image_->w, image_->h);
+ int in_offset = in_stride * rect.y() + 4 * rect.x();
+ int y_offset = y_stride * rect.y() + rect.x();
+ int uv_offset = (uv_stride * rect.y() + rect.x()) / 2;
+
+ media::ConvertRGB32ToYUV(in + in_offset,
+ y_out + y_offset,
+ u_out + uv_offset,
+ v_out + uv_offset,
+ rect.width(),
+ rect.height(),
+ in_stride,
+ y_stride,
+ uv_stride);
}
return true;
}