diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-22 13:51:33 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-22 13:51:33 +0000 |
commit | 986a40a7d57589c7e8db787751fbf822e3a6f0db (patch) | |
tree | f2ca5dc0049233be4de99b245dd922654ebd1446 | |
parent | 8339da46719b5876723b1182b5ca60e9e07c2d81 (diff) | |
download | chromium_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.cc | 61 | ||||
-rw-r--r-- | remoting/base/encoder_vp8.h | 7 | ||||
-rwxr-xr-x | tools/generate_stubs/generate_stubs.py | 19 |
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___); }""") |