summaryrefslogtreecommitdiffstats
path: root/remoting
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
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')
-rw-r--r--remoting/base/codec_test.cc6
-rw-r--r--remoting/base/decoder_vp8.cc165
-rw-r--r--remoting/base/decoder_vp8.h56
-rw-r--r--remoting/base/decoder_vp8_unittest.cc21
-rw-r--r--remoting/remoting.gyp3
5 files changed, 248 insertions, 3 deletions
diff --git a/remoting/base/codec_test.cc b/remoting/base/codec_test.cc
index e8f17ca..ae5c9eb 100644
--- a/remoting/base/codec_test.cc
+++ b/remoting/base/codec_test.cc
@@ -165,15 +165,15 @@ class DecoderTester {
void ReceivedMessage(ChromotingHostMessage* message) {
if (message->has_update_stream_packet()) {
- decoder_->PartialDecode(message);
+ EXPECT_TRUE(decoder_->PartialDecode(message));
return;
}
if (message->has_begin_update_stream()) {
- decoder_->BeginDecode(
+ EXPECT_TRUE(decoder_->BeginDecode(
frame_, &update_rects_,
NewRunnableMethod(this, &DecoderTester::OnPartialDecodeDone),
- NewRunnableMethod(this, &DecoderTester::OnDecodeDone));
+ NewRunnableMethod(this, &DecoderTester::OnDecodeDone)));
}
if (message->has_end_update_stream()) {
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
diff --git a/remoting/base/decoder_vp8.h b/remoting/base/decoder_vp8.h
new file mode 100644
index 0000000..5fe0169
--- /dev/null
+++ b/remoting/base/decoder_vp8.h
@@ -0,0 +1,56 @@
+// 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.
+
+#ifndef REMOTING_BASE_DECODER_VP8_H_
+#define REMOTING_BASE_DECODER_VP8_H_
+
+#include "remoting/base/decoder.h"
+
+typedef struct vpx_codec_ctx vpx_codec_ctx_t;
+
+namespace remoting {
+
+class DecoderVp8 : public Decoder {
+ public:
+ DecoderVp8();
+ ~DecoderVp8();
+
+ // Decoder implementations.
+ virtual bool BeginDecode(scoped_refptr<media::VideoFrame> frame,
+ UpdatedRects* update_rects,
+ Task* partial_decode_done,
+ Task* decode_done);
+ virtual bool PartialDecode(ChromotingHostMessage* message);
+ virtual void EndDecode();
+
+ private:
+ bool HandleBeginRect(ChromotingHostMessage* message);
+ bool HandleRectData(ChromotingHostMessage* message);
+ bool HandleEndRect(ChromotingHostMessage* message);
+
+ // The internal state of the decoder.
+ State state_;
+
+ // Keeps track of the updating rect.
+ int rect_x_;
+ int rect_y_;
+ int rect_width_;
+ int rect_height_;
+
+ // Tasks to call when decode is done.
+ scoped_ptr<Task> partial_decode_done_;
+ scoped_ptr<Task> decode_done_;
+
+ // The video frame to write to.
+ scoped_refptr<media::VideoFrame> frame_;
+ UpdatedRects* updated_rects_;
+
+ vpx_codec_ctx_t* codec_;
+
+ DISALLOW_COPY_AND_ASSIGN(DecoderVp8);
+};
+
+} // namespace remoting
+
+#endif // REMOTING_BASE_DECODER_VP8_H_
diff --git a/remoting/base/decoder_vp8_unittest.cc b/remoting/base/decoder_vp8_unittest.cc
new file mode 100644
index 0000000..25ff6ac
--- /dev/null
+++ b/remoting/base/decoder_vp8_unittest.cc
@@ -0,0 +1,21 @@
+// 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 "media/base/video_frame.h"
+#include "remoting/base/codec_test.h"
+#include "remoting/base/decoder_vp8.h"
+#include "remoting/base/encoder_vp8.h"
+#include "remoting/client/mock_objects.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+
+namespace remoting {
+
+TEST(DecoderVp8Test, EncodeAndDecode) {
+ EncoderVp8 encoder;
+ DecoderVp8 decoder;
+ TestEncoderDecoder(&encoder, &decoder, false);
+}
+
+} // namespace remoting
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index 33339cb..47d498c 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -137,6 +137,8 @@
'base/decoder.h',
'base/decoder_verbatim.cc',
'base/decoder_verbatim.h',
+ 'base/decoder_vp8.cc',
+ 'base/decoder_vp8.h',
'base/decoder_zlib.cc',
'base/decoder_zlib.h',
'base/decompressor.h',
@@ -400,6 +402,7 @@
'base/codec_test.h',
'base/compressor_zlib_unittest.cc',
'base/decoder_verbatim_unittest.cc',
+ 'base/decoder_vp8_unittest.cc',
'base/decoder_zlib_unittest.cc',
'base/decompressor_zlib_unittest.cc',
'base/encoder_verbatim_unittest.cc',