summaryrefslogtreecommitdiffstats
path: root/remoting/base
diff options
context:
space:
mode:
authorhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-22 13:51:33 +0000
committerhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-22 13:51:33 +0000
commit986a40a7d57589c7e8db787751fbf822e3a6f0db (patch)
treef2ca5dc0049233be4de99b245dd922654ebd1446 /remoting/base
parent8339da46719b5876723b1182b5ca60e9e07c2d81 (diff)
downloadchromium_src-986a40a7d57589c7e8db787751fbf822e3a6f0db.zip
chromium_src-986a40a7d57589c7e8db787751fbf822e3a6f0db.tar.gz
chromium_src-986a40a7d57589c7e8db787751fbf822e3a6f0db.tar.bz2
Speed up encoding by using active map
Using active map can greatly reduce the amount of macro blocks need to be encoded by vp8. This brings average encoding time from 35ms per frame to about 8ms on the tested system. However this change depends on an updated version of libvpx. BUG=None TEST=chromoting still works & no visual problems Review URL: http://codereview.chromium.org/6518011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75586 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/base')
-rw-r--r--remoting/base/encoder_vp8.cc61
-rw-r--r--remoting/base/encoder_vp8.h7
2 files changed, 64 insertions, 4 deletions
diff --git a/remoting/base/encoder_vp8.cc b/remoting/base/encoder_vp8.cc
index 4c1bc7b..1d8f8c6 100644
--- a/remoting/base/encoder_vp8.cc
+++ b/remoting/base/encoder_vp8.cc
@@ -18,12 +18,22 @@ extern "C" {
#include "third_party/libvpx/source/libvpx/vpx/vp8cx.h"
}
+namespace {
+
+// Defines the dimension of a macro block. This is used to compute the active
+// map for the encoder.
+const int kMacroBlockSize = 16;
+
+} // namespace remoting
+
namespace remoting {
EncoderVp8::EncoderVp8()
: initialized_(false),
codec_(NULL),
image_(NULL),
+ active_map_width_(0),
+ active_map_height_(0),
last_timestamp_(0) {
}
@@ -54,6 +64,11 @@ bool EncoderVp8::Init(int width, int height) {
if (ret != VPX_CODEC_OK)
return false;
+ // Initialize active map.
+ active_map_width_ = (width + kMacroBlockSize - 1) / kMacroBlockSize;
+ active_map_height_ = (height + kMacroBlockSize - 1) / kMacroBlockSize;
+ active_map_.reset(new uint8[active_map_width_ * active_map_height_]);
+
// TODO(hclam): Tune the parameters to better suit the application.
config.rc_target_bitrate = width * height * config.rc_target_bitrate
/ config.g_w / config.g_h;
@@ -61,11 +76,11 @@ bool EncoderVp8::Init(int width, int height) {
config.g_h = height;
config.g_pass = VPX_RC_ONE_PASS;
config.g_profile = 1;
- config.g_threads = 2;
+ config.g_threads = 1;
config.rc_min_quantizer = 20;
config.rc_max_quantizer = 30;
config.g_timebase.num = 1;
- config.g_timebase.den = 30;
+ config.g_timebase.den = 20;
if (vpx_codec_enc_init(codec_.get(), algo, &config, 0))
return false;
@@ -161,6 +176,32 @@ bool EncoderVp8::PrepareImage(scoped_refptr<CaptureData> capture_data,
return true;
}
+void EncoderVp8::PrepareActiveMap(
+ const std::vector<gfx::Rect>& updated_rects) {
+ // Clear active map first.
+ memset(active_map_.get(), 0, active_map_width_ * active_map_height_);
+
+ // Mark blocks at active.
+ for (size_t i = 0; i < updated_rects.size(); ++i) {
+ const gfx::Rect& r = updated_rects[i];
+ CHECK(r.width() && r.height());
+
+ int left = r.x() / kMacroBlockSize;
+ int right = (r.right() - 1) / kMacroBlockSize;
+ int top = r.y() / kMacroBlockSize;
+ int bottom = (r.bottom() - 1) / kMacroBlockSize;
+ CHECK(right < active_map_width_);
+ CHECK(bottom < active_map_height_);
+
+ uint8* map = active_map_.get() + top * active_map_width_;
+ for (int y = top; y <= bottom; ++y) {
+ for (int x = left; x <= right; ++x)
+ map[x] = 1;
+ map += active_map_width_;
+ }
+ }
+}
+
void EncoderVp8::Encode(scoped_refptr<CaptureData> capture_data,
bool key_frame,
DataAvailableCallback* data_available_callback) {
@@ -176,6 +217,18 @@ void EncoderVp8::Encode(scoped_refptr<CaptureData> capture_data,
NOTREACHED() << "Can't image data for encoding";
}
+ // Update active map based on updated rectangles.
+ PrepareActiveMap(updated_rects);
+
+ // Apply active map to the encoder.
+ vpx_active_map_t act_map;
+ act_map.rows = active_map_height_;
+ act_map.cols = active_map_width_;
+ act_map.active_map = active_map_.get();
+ if(vpx_codec_control(codec_.get(), VP8E_SET_ACTIVEMAP, &act_map)) {
+ LOG(ERROR) << "Unable to apply active map";
+ }
+
// Do the actual encoding.
vpx_codec_err_t ret = vpx_codec_encode(codec_.get(), image_.get(),
last_timestamp_,
@@ -185,8 +238,8 @@ void EncoderVp8::Encode(scoped_refptr<CaptureData> capture_data,
<< "Details: " << vpx_codec_error(codec_.get()) << "\n"
<< vpx_codec_error_detail(codec_.get());
- // TODO(hclam): fix this.
- last_timestamp_ += 100;
+ // TODO(hclam): Apply the proper timestamp here.
+ last_timestamp_ += 50;
// Read the encoded data.
vpx_codec_iter_t iter = NULL;
diff --git a/remoting/base/encoder_vp8.h b/remoting/base/encoder_vp8.h
index f2869e4..e283d16 100644
--- a/remoting/base/encoder_vp8.h
+++ b/remoting/base/encoder_vp8.h
@@ -34,11 +34,18 @@ class EncoderVp8 : public Encoder {
bool PrepareImage(scoped_refptr<CaptureData> capture_data,
std::vector<gfx::Rect>* updated_rects);
+ // Update the active map according to |updated_rects|. Active map is then
+ // given to the encoder to speed up encoding.
+ void PrepareActiveMap(const std::vector<gfx::Rect>& updated_rects);
+
// True if the encoder is initialized.
bool initialized_;
scoped_ptr<vpx_codec_ctx_t> codec_;
scoped_ptr<vpx_image_t> image_;
+ scoped_array<uint8> active_map_;
+ int active_map_width_;
+ int active_map_height_;
int last_timestamp_;
// Buffer for storing the yuv image.