summaryrefslogtreecommitdiffstats
path: root/remoting/base/decoder_vp8.cc
diff options
context:
space:
mode:
authorhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-29 17:34:32 +0000
committerhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-29 17:34:32 +0000
commit622b788650a636236c3842f1287126fc60fb80ed (patch)
treeda3e6045ec78f3c4929a6f11779bb8ac21b5adb1 /remoting/base/decoder_vp8.cc
parent3190f36c2f7ac99d06a07b3df1e12ac36fc11d08 (diff)
downloadchromium_src-622b788650a636236c3842f1287126fc60fb80ed.zip
chromium_src-622b788650a636236c3842f1287126fc60fb80ed.tar.gz
chromium_src-622b788650a636236c3842f1287126fc60fb80ed.tar.bz2
VP8 decoder for chromoting
Added DecoderVp8 and unit test for chromoting. TEST=remoting_unittests BUG=50235 Review URL: http://codereview.chromium.org/3032047 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@60960 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/base/decoder_vp8.cc')
-rw-r--r--remoting/base/decoder_vp8.cc165
1 files changed, 165 insertions, 0 deletions
diff --git a/remoting/base/decoder_vp8.cc b/remoting/base/decoder_vp8.cc
new file mode 100644
index 0000000..0ede4ab
--- /dev/null
+++ b/remoting/base/decoder_vp8.cc
@@ -0,0 +1,165 @@
+// Copyright (c) 2010 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/base/decoder_vp8.h"
+
+#include "media/base/media.h"
+#include "media/base/yuv_convert.h"
+#include "remoting/base/protocol_util.h"
+
+extern "C" {
+#define VPX_CODEC_DISABLE_COMPAT 1
+#include "third_party/libvpx/include/vpx/vpx_codec.h"
+#include "third_party/libvpx/include/vpx/vpx_decoder.h"
+#include "third_party/libvpx/include/vpx/vp8dx.h"
+}
+
+namespace remoting {
+
+DecoderVp8::DecoderVp8()
+ : state_(kWaitingForBeginRect),
+ rect_x_(0),
+ rect_y_(0),
+ rect_width_(0),
+ rect_height_(0),
+ updated_rects_(NULL),
+ codec_(NULL) {
+}
+
+DecoderVp8::~DecoderVp8() {
+ if (codec_) {
+ vpx_codec_err_t ret = vpx_codec_destroy(codec_);
+ CHECK(ret == VPX_CODEC_OK) << "Failed to destroy codec";
+ }
+ delete codec_;
+}
+
+bool DecoderVp8::BeginDecode(scoped_refptr<media::VideoFrame> frame,
+ UpdatedRects* updated_rects,
+ Task* partial_decode_done,
+ Task* decode_done) {
+ DCHECK(!partial_decode_done_.get());
+ DCHECK(!decode_done_.get());
+ DCHECK(!updated_rects_);
+ DCHECK_EQ(kWaitingForBeginRect, state_);
+
+ partial_decode_done_.reset(partial_decode_done);
+ decode_done_.reset(decode_done);
+ updated_rects_ = updated_rects;
+
+ if (frame->format() != media::VideoFrame::RGB32) {
+ LOG(INFO) << "DecoderVp8 only supports RGB32 as output";
+ return false;
+ }
+ frame_ = frame;
+ return true;
+}
+
+bool DecoderVp8::PartialDecode(ChromotingHostMessage* message) {
+ scoped_ptr<ChromotingHostMessage> msg_deleter(message);
+ DCHECK(message->has_update_stream_packet());
+
+ bool ret = true;
+ if (message->update_stream_packet().has_begin_rect())
+ ret = HandleBeginRect(message);
+ if (ret && message->update_stream_packet().has_rect_data())
+ ret = HandleRectData(message);
+ if (ret && message->update_stream_packet().has_end_rect())
+ ret = HandleEndRect(message);
+ return ret;
+}
+
+void DecoderVp8::EndDecode() {
+ DCHECK_EQ(kWaitingForBeginRect, state_);
+ decode_done_->Run();
+
+ partial_decode_done_.reset();
+ decode_done_.reset();
+ frame_ = NULL;
+ updated_rects_ = NULL;
+}
+
+bool DecoderVp8::HandleBeginRect(ChromotingHostMessage* message) {
+ DCHECK_EQ(kWaitingForBeginRect, state_);
+ state_ = kWaitingForRectData;
+
+ rect_width_ = message->update_stream_packet().begin_rect().width();
+ rect_height_ = message->update_stream_packet().begin_rect().height();
+ rect_x_ = message->update_stream_packet().begin_rect().x();
+ rect_y_ = message->update_stream_packet().begin_rect().y();
+
+ PixelFormat pixel_format =
+ message->update_stream_packet().begin_rect().pixel_format();
+ if (pixel_format != PixelFormatYv12)
+ return false;
+ return true;
+}
+
+bool DecoderVp8::HandleRectData(ChromotingHostMessage* message) {
+ DCHECK_EQ(kWaitingForRectData, state_);
+ DCHECK_EQ(0,
+ message->update_stream_packet().rect_data().sequence_number());
+
+ // Initialize the codec as needed.
+ if (!codec_) {
+ codec_ = new vpx_codec_ctx_t();
+ vpx_codec_err_t ret =
+ vpx_codec_dec_init(
+ codec_,
+ (const vpx_codec_iface_t*)media::GetVp8DxAlgoAddress(), NULL, 0);
+ if (ret != VPX_CODEC_OK) {
+ LOG(INFO) << "Cannot initialize codec.";
+ delete codec_;
+ codec_ = NULL;
+ return false;
+ }
+ }
+
+ // Do the actual decoding.
+ vpx_codec_err_t ret = vpx_codec_decode(
+ codec_,
+ (uint8_t*)message->update_stream_packet().rect_data().data().c_str(),
+ message->update_stream_packet().rect_data().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_);
+ return false;
+ }
+
+ // Gets the decoded data.
+ vpx_codec_iter_t iter = NULL;
+ vpx_image_t* image = vpx_codec_get_frame(codec_, &iter);
+ if (!image) {
+ LOG(INFO) << "No video frame decoded";
+ return false;
+ }
+
+ // Perform YUV conversion.
+ media::ConvertYUVToRGB32(image->planes[0], image->planes[1], image->planes[2],
+ frame_->data(media::VideoFrame::kRGBPlane),
+ rect_width_, rect_height_,
+ image->stride[0], image->stride[1],
+ frame_->stride(media::VideoFrame::kRGBPlane),
+ media::YV12);
+
+ updated_rects_->clear();
+ updated_rects_->push_back(gfx::Rect(rect_x_, rect_y_,
+ rect_width_, rect_height_));
+ partial_decode_done_->Run();
+ return true;
+}
+
+bool DecoderVp8::HandleEndRect(ChromotingHostMessage* message) {
+ DCHECK_EQ(kWaitingForRectData, state_);
+ state_ = kWaitingForBeginRect;
+ return true;
+}
+
+} // namespace remoting