Skip to content

Commit

Permalink
Speed up encoding by using active map
Browse files Browse the repository at this point in the history
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
  • Loading branch information
[email protected] committed Feb 22, 2011
1 parent 8339da4 commit 986a40a
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 7 deletions.
61 changes: 57 additions & 4 deletions remoting/base/encoder_vp8.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
}

Expand Down Expand Up @@ -54,18 +64,23 @@ 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;
config.g_w = width;
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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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_,
Expand All @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions remoting/base/encoder_vp8.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
19 changes: 16 additions & 3 deletions tools/generate_stubs/generate_stubs.py
Original file line number Diff line number Diff line change
@@ -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.

Expand All @@ -15,6 +15,19 @@
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__ = '[email protected] (Albert J. Wong)'
Expand Down Expand Up @@ -96,7 +109,7 @@ def __str__(self):
%(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___;
}""")
Expand All @@ -116,7 +129,7 @@ def __str__(self):
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___);
}""")

Expand Down

0 comments on commit 986a40a

Please sign in to comment.