summaryrefslogtreecommitdiffstats
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
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
-rw-r--r--remoting/base/encoder_vp8.cc61
-rw-r--r--remoting/base/encoder_vp8.h7
-rwxr-xr-xtools/generate_stubs/generate_stubs.py19
3 files changed, 80 insertions, 7 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.
diff --git a/tools/generate_stubs/generate_stubs.py b/tools/generate_stubs/generate_stubs.py
index 97c8106..d8fac2d 100755
--- a/tools/generate_stubs/generate_stubs.py
+++ b/tools/generate_stubs/generate_stubs.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# Copyright (c) 2010 The Chromium Authors. All rights reserved.
+# Copyright (c) 2011 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.
@@ -15,6 +15,19 @@ found via dlsym.
This script takes a set of files, where each file is a list of C-style
signatures (one signature per line). The output is either a windows def file,
or a header + implementation file of stubs suitable for use in a posix system.
+
+This script also handles varidiac functions, e.g.
+void printf(const char* s, ...);
+
+TODO(hclam): Fix the situation for varidiac functions.
+Stub for the above function will be generated and inside the stub function it
+is translated to:
+void printf(const char* s, ...) {
+ printf_ptr(s, (void*)arg1);
+}
+
+Only one argument from the varidiac arguments is used and it will be used as
+type void*.
"""
__author__ = 'ajwong@chromium.org (Albert J. Wong)'
@@ -96,7 +109,7 @@ VARIADIC_STUB_FUNCTION_DEFINITION = (
%(return_type)s %(name)s(%(params)s) {
va_list args___;
va_start(args___, %(last_named_arg)s);
- %(return_type)s ret___ = %(name)s_ptr(%(arg_list)s, args___);
+ %(return_type)s ret___ = %(name)s_ptr(%(arg_list)s, va_arg(args___, void*));
va_end(args___);
return ret___;
}""")
@@ -116,7 +129,7 @@ VOID_VARIADIC_STUB_FUNCTION_DEFINITION = (
void %(name)s(%(params)s) {
va_list args___;
va_start(args___, %(last_named_arg)s);
- %(name)s_ptr(%(arg_list)s, args___);
+ %(name)s_ptr(%(arg_list)s, va_arg(args___, void*));
va_end(args___);
}""")