Skip to content

Commit

Permalink
Move VideoDecoderVp8 to VideoDecoderVpx base that will support VP8/9.
Browse files Browse the repository at this point in the history
BUG=260879

Review URL: https://codereview.chromium.org/26888009

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@229624 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
wez@chromium.org committed Oct 19, 2013
1 parent ffd8afd commit a43cfae
Show file tree
Hide file tree
Showing 11 changed files with 348 additions and 303 deletions.
6 changes: 3 additions & 3 deletions remoting/client/rectangle_update_decoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
#include "remoting/base/util.h"
#include "remoting/client/frame_consumer.h"
#include "remoting/codec/video_decoder.h"
#include "remoting/codec/video_decoder_verbatim.h"
#include "remoting/codec/video_decoder_vp8.h"
#include "remoting/client/frame_consumer.h"
#include "remoting/codec/video_decoder_vpx.h"
#include "remoting/protocol/session_config.h"
#include "third_party/libyuv/include/libyuv/convert_argb.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
Expand Down Expand Up @@ -101,7 +101,7 @@ void RectangleUpdateDecoder::Initialize(const SessionConfig& config) {
if (codec == ChannelConfig::CODEC_VERBATIM) {
decoder_.reset(new VideoDecoderVerbatim());
} else if (codec == ChannelConfig::CODEC_VP8) {
decoder_.reset(new VideoDecoderVp8());
decoder_ = VideoDecoderVpx::CreateForVP8();
} else {
NOTREACHED() << "Invalid Encoding found: " << codec;
}
Expand Down
23 changes: 23 additions & 0 deletions remoting/codec/scoped_vpx_codec.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2013 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.

#include "remoting/codec/scoped_vpx_codec.h"

#include "base/logging.h"

extern "C" {
#define VPX_CODEC_DISABLE_COMPAT 1
#include "third_party/libvpx/source/libvpx/vpx/vpx_codec.h"
}
namespace remoting {

void VpxCodecDeleter::operator()(vpx_codec_ctx_t* codec) {
if (codec) {
vpx_codec_err_t ret = vpx_codec_destroy(codec);
CHECK_EQ(ret, VPX_CODEC_OK) << "Failed to destroy codec";
delete codec;
}
}

} // namespace remoting
24 changes: 24 additions & 0 deletions remoting/codec/scoped_vpx_codec.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2013 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.

#ifndef REMOTING_CODEC_SCOPED_VPX_CODEC_H_
#define REMOTING_CODEC_SCOPED_VPX_CODEC_H_

#include "base/memory/scoped_ptr.h"

extern "C" {
typedef struct vpx_codec_ctx vpx_codec_ctx_t;
}

namespace remoting {

struct VpxCodecDeleter {
void operator()(vpx_codec_ctx_t* codec);
};

typedef scoped_ptr<vpx_codec_ctx_t, VpxCodecDeleter> ScopedVpxCodec;

} // namespace remoting

#endif // REMOTING_CODEC_SCOPED_VPX_CODEC_H_
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Copyright 2013 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.

#include "remoting/codec/video_decoder_vp8.h"
#include "remoting/codec/video_decoder_vpx.h"

#include <math.h>

Expand All @@ -21,69 +21,73 @@ extern "C" {

namespace remoting {

const uint32 kTransparent = 0;
namespace {

VideoDecoderVp8::VideoDecoderVp8()
: state_(kUninitialized),
codec_(NULL),
last_image_(NULL) {
const uint32 kTransparentColor = 0;

// Fills the rectangle |rect| with the given ARGB color |color| in |buffer|.
void FillRect(uint8* buffer,
int stride,
const webrtc::DesktopRect& rect,
uint32 color) {
uint32* ptr = reinterpret_cast<uint32*>(buffer + (rect.top() * stride) +
(rect.left() * VideoDecoder::kBytesPerPixel));
int width = rect.width();
for (int height = rect.height(); height > 0; --height) {
std::fill(ptr, ptr + width, color);
ptr += stride / VideoDecoder::kBytesPerPixel;
}
}

VideoDecoderVp8::~VideoDecoderVp8() {
if (codec_) {
vpx_codec_err_t ret = vpx_codec_destroy(codec_);
CHECK(ret == VPX_CODEC_OK) << "Failed to destroy codec";
} // namespace

// static
scoped_ptr<VideoDecoderVpx> VideoDecoderVpx::CreateForVP8() {
ScopedVpxCodec codec(new vpx_codec_ctx_t);

// TODO(hclam): Scale the number of threads with number of cores of the
// machine.
vpx_codec_dec_cfg config;
config.w = 0;
config.h = 0;
config.threads = 2;
vpx_codec_err_t ret =
vpx_codec_dec_init(codec.get(), vpx_codec_vp8_dx(), &config, 0);
if (ret != VPX_CODEC_OK) {
LOG(INFO) << "Cannot initialize codec.";
return scoped_ptr<VideoDecoderVpx>();
}
delete codec_;

return scoped_ptr<VideoDecoderVpx>(new VideoDecoderVpx(codec.Pass()));
}

void VideoDecoderVp8::Initialize(const webrtc::DesktopSize& screen_size) {
VideoDecoderVpx::~VideoDecoderVpx() {}

void VideoDecoderVpx::Initialize(const webrtc::DesktopSize& screen_size) {
DCHECK(!screen_size.is_empty());

screen_size_ = screen_size;
state_ = kReady;

transparent_region_.SetRect(webrtc::DesktopRect::MakeSize(screen_size_));
}

bool VideoDecoderVp8::DecodePacket(const VideoPacket& packet) {
DCHECK_EQ(kReady, state_);

// Initialize the codec as needed.
if (!codec_) {
codec_ = new vpx_codec_ctx_t();

// TODO(hclam): Scale the number of threads with number of cores of the
// machine.
vpx_codec_dec_cfg config;
config.w = 0;
config.h = 0;
config.threads = 2;
vpx_codec_err_t ret =
vpx_codec_dec_init(codec_, vpx_codec_vp8_dx(), &config, 0);
if (ret != VPX_CODEC_OK) {
LOG(INFO) << "Cannot initialize codec.";
delete codec_;
codec_ = NULL;
state_ = kError;
return false;
}
}
bool VideoDecoderVpx::DecodePacket(const VideoPacket& packet) {
DCHECK(!screen_size_.is_empty());

// Do the actual decoding.
vpx_codec_err_t ret = vpx_codec_decode(
codec_, reinterpret_cast<const uint8*>(packet.data().data()),
codec_.get(), reinterpret_cast<const uint8*>(packet.data().data()),
packet.data().size(), NULL, 0);
if (ret != VPX_CODEC_OK) {
LOG(INFO) << "Decoding failed:" << vpx_codec_err_to_string(ret) << "\n"
<< "Details: " << vpx_codec_error(codec_) << "\n"
<< vpx_codec_error_detail(codec_);
<< "Details: " << vpx_codec_error(codec_.get()) << "\n"
<< vpx_codec_error_detail(codec_.get());
return false;
}

// Gets the decoded data.
vpx_codec_iter_t iter = NULL;
vpx_image_t* image = vpx_codec_get_frame(codec_, &iter);
vpx_image_t* image = vpx_codec_get_frame(codec_.get(), &iter);
if (!image) {
LOG(INFO) << "No video frame decoded";
return false;
Expand Down Expand Up @@ -121,9 +125,8 @@ bool VideoDecoderVp8::DecodePacket(const VideoPacket& packet) {
return true;
}

void VideoDecoderVp8::Invalidate(const webrtc::DesktopSize& view_size,
void VideoDecoderVpx::Invalidate(const webrtc::DesktopSize& view_size,
const webrtc::DesktopRegion& region) {
DCHECK_EQ(kReady, state_);
DCHECK(!view_size.is_empty());

for (webrtc::DesktopRegion::Iterator i(region); !i.IsAtEnd(); i.Advance()) {
Expand All @@ -138,12 +141,12 @@ void VideoDecoderVp8::Invalidate(const webrtc::DesktopSize& view_size,
transparent_region_.AddRegion(difference);
}

void VideoDecoderVp8::RenderFrame(const webrtc::DesktopSize& view_size,
void VideoDecoderVpx::RenderFrame(const webrtc::DesktopSize& view_size,
const webrtc::DesktopRect& clip_area,
uint8* image_buffer,
int image_stride,
webrtc::DesktopRegion* output_region) {
DCHECK_EQ(kReady, state_);
DCHECK(!screen_size_.is_empty());
DCHECK(!view_size.is_empty());

// Early-return and do nothing if we haven't yet decoded any frames.
Expand Down Expand Up @@ -244,7 +247,7 @@ void VideoDecoderVp8::RenderFrame(const webrtc::DesktopSize& view_size,
continue;

// Fill the rectange with transparent pixels.
FillRect(image_buffer, image_stride, rect, kTransparent);
FillRect(image_buffer, image_stride, rect, kTransparentColor);
output_region->AddRect(rect);
}

Expand All @@ -254,24 +257,17 @@ void VideoDecoderVp8::RenderFrame(const webrtc::DesktopSize& view_size,
transparent_region_.Subtract(scaled_clip_area);
}

const webrtc::DesktopRegion* VideoDecoderVp8::GetImageShape() {
const webrtc::DesktopRegion* VideoDecoderVpx::GetImageShape() {
return &desktop_shape_;
}

void VideoDecoderVp8::FillRect(uint8* buffer,
int stride,
const webrtc::DesktopRect& rect,
uint32 color) {
uint32* ptr = reinterpret_cast<uint32*>(buffer + (rect.top() * stride) +
(rect.left() * kBytesPerPixel));
int width = rect.width();
for (int height = rect.height(); height > 0; --height) {
std::fill(ptr, ptr + width, color);
ptr += stride / kBytesPerPixel;
}
VideoDecoderVpx::VideoDecoderVpx(ScopedVpxCodec codec)
: codec_(codec.Pass()),
last_image_(NULL) {
DCHECK(codec_);
}

void VideoDecoderVp8::UpdateImageShapeRegion(
void VideoDecoderVpx::UpdateImageShapeRegion(
webrtc::DesktopRegion* new_desktop_shape) {
// Add all areas that have been updated or become transparent to the
// transparent region. Exclude anything within the new desktop shape.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Copyright 2013 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.

#ifndef REMOTING_CODEC_VIDEO_DECODER_VP8_H_
#define REMOTING_CODEC_VIDEO_DECODER_VP8_H_
#ifndef REMOTING_CODEC_VIDEO_DECODER_VPX_H_
#define REMOTING_CODEC_VIDEO_DECODER_VPX_H_

#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "remoting/codec/scoped_vpx_codec.h"
#include "remoting/codec/video_decoder.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_region.h"

typedef struct vpx_codec_ctx vpx_codec_ctx_t;
typedef struct vpx_image vpx_image_t;

namespace remoting {

class VideoDecoderVp8 : public VideoDecoder {
class VideoDecoderVpx : public VideoDecoder {
public:
VideoDecoderVp8();
virtual ~VideoDecoderVp8();
// Creates a decoder for VP8.
static scoped_ptr<VideoDecoderVpx> CreateForVP8();

// VideoDecoder implementations.
virtual ~VideoDecoderVpx();

// VideoDecoder interface.
virtual void Initialize(const webrtc::DesktopSize& screen_size) OVERRIDE;
virtual bool DecodePacket(const VideoPacket& packet) OVERRIDE;
virtual void Invalidate(const webrtc::DesktopSize& view_size,
Expand All @@ -33,26 +36,14 @@ class VideoDecoderVp8 : public VideoDecoder {
virtual const webrtc::DesktopRegion* GetImageShape() OVERRIDE;

private:
enum State {
kUninitialized,
kReady,
kError,
};

// Fills the rectangle |rect| with the given ARGB color |color| in |buffer|.
void FillRect(uint8* buffer, int stride,
const webrtc::DesktopRect& rect,
uint32 color);
explicit VideoDecoderVpx(ScopedVpxCodec codec);

// Calculates the difference between the desktop shape regions in two
// consecutive frames and updates |updated_region_| and |transparent_region_|
// accordingly.
void UpdateImageShapeRegion(webrtc::DesktopRegion* new_desktop_shape);

// The internal state of the decoder.
State state_;

vpx_codec_ctx_t* codec_;
ScopedVpxCodec codec_;

// Pointer to the last decoded image.
vpx_image_t* last_image_;
Expand All @@ -69,7 +60,7 @@ class VideoDecoderVp8 : public VideoDecoder {
// The region that should be make transparent.
webrtc::DesktopRegion transparent_region_;

DISALLOW_COPY_AND_ASSIGN(VideoDecoderVp8);
DISALLOW_COPY_AND_ASSIGN(VideoDecoderVpx);
};

} // namespace remoting
Expand Down
Loading

0 comments on commit a43cfae

Please sign in to comment.