| Index: content/renderer/media/rtc_video_decoder_bridge_unittest.cc
|
| diff --git a/content/renderer/media/rtc_video_decoder_bridge_unittest.cc b/content/renderer/media/rtc_video_decoder_bridge_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..babc9ce2f4ab1bad0d2f325549fb1101090c7f76
|
| --- /dev/null
|
| +++ b/content/renderer/media/rtc_video_decoder_bridge_unittest.cc
|
| @@ -0,0 +1,202 @@
|
| +// Copyright (c) 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 "base/bind.h"
|
| +#include "base/message_loop.h"
|
| +#include "base/run_loop.h"
|
| +#include "base/threading/platform_thread.h"
|
| +#include "content/renderer/media/rtc_video_decoder_bridge.h"
|
| +#include "media/base/gmock_callback_support.h"
|
| +#include "media/base/mock_filters.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +using ::testing::_;
|
| +using ::testing::AnyNumber;
|
| +
|
| +namespace content {
|
| +
|
| +class RTCVideoDecoderBridgeTest
|
| + : public ::testing::Test,
|
| + public base::PlatformThread::Delegate,
|
| + webrtc::DecodedImageCallback {
|
| + public:
|
| + RTCVideoDecoderBridgeTest()
|
| + : decoder_(new media::MockVideoDecoder()),
|
| + loop_idle_waiter_(false, false),
|
| + num_delivered_frames_(0),
|
| + num_delivered_encoded_image_(0),
|
| + loop_ready_waiter_(false, false),
|
| + thread_(base::kNullThreadHandle),
|
| + is_tearing_down_(false) {
|
| + memset(&codec_, 0, sizeof(codec_));
|
| + }
|
| +
|
| + virtual void SetUp() OVERRIDE {
|
| + CHECK(base::PlatformThread::Create(0, this, &thread_));
|
| + loop_ready_waiter_.Wait();
|
| + bridge_.reset(new RTCVideoDecoderBridge(decoder_, loop_proxy_));
|
| + }
|
| +
|
| + virtual void TearDown() OVERRIDE {
|
| + if (thread_ != base::kNullThreadHandle) {
|
| + {
|
| + base::AutoLock auto_lock(lock_);
|
| + is_tearing_down_ = true;
|
| + }
|
| + base::PlatformThread::Join(thread_);
|
| + }
|
| + }
|
| +
|
| + virtual void ThreadMain() OVERRIDE {
|
| + MessageLoop message_loop;
|
| + loop_proxy_ = message_loop.message_loop_proxy();
|
| + loop_ready_waiter_.Signal();
|
| + LOG(INFO) << "ThreadMain()";
|
| + while (true) {
|
| + message_loop.RunUntilIdle();
|
| + loop_idle_waiter_.Signal();
|
| + loop_idle_waiter_.Reset();
|
| + base::AutoLock auto_lock(lock_);
|
| + if (is_tearing_down_) {
|
| + break;
|
| + }
|
| + }
|
| + }
|
| +
|
| + virtual WebRtc_Word32 Decoded(webrtc::I420VideoFrame& decoded_image)
|
| + OVERRIDE {
|
| + num_delivered_frames_++;
|
| + return WEBRTC_VIDEO_CODEC_OK;
|
| + }
|
| +
|
| + void Initialize() {
|
| + EXPECT_CALL(*decoder_, Initialize(_, _, _))
|
| + .WillOnce(media::RunCallback<1>(media::PIPELINE_OK));
|
| + EXPECT_CALL(*decoder_, Read(_))
|
| + .WillRepeatedly(
|
| + Invoke(this, &RTCVideoDecoderBridgeTest::FrameRequested));
|
| + EXPECT_CALL(*decoder_, Stop(_))
|
| + .WillRepeatedly(media::RunClosure<0>());
|
| + EXPECT_CALL(*decoder_, Reset(_))
|
| + .WillRepeatedly(media::RunClosure<0>());
|
| +
|
| + codec_.codecType = webrtc::kVideoCodecVP8;
|
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, bridge_->InitDecode(&codec_, 1));
|
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
| + bridge_->RegisterDecodeCompleteCallback(this));
|
| + }
|
| +
|
| + void FrameRequested(const media::VideoDecoder::ReadCB& read_cb) {
|
| + DCHECK_EQ(loop_proxy_, base::MessageLoopProxy::current());
|
| + EXPECT_TRUE(read_cb_.is_null());
|
| + read_cb_ = read_cb;
|
| + SimulateDecoding();
|
| + }
|
| +
|
| + void SimulateDecoding() {
|
| + CHECK(!read_cb_.is_null());
|
| + base::AutoLock auto_lock(lock_);
|
| + if (num_delivered_encoded_image_ <= 0) {
|
| + return;
|
| + }
|
| + num_delivered_encoded_image_--;
|
| +
|
| + loop_proxy_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(read_cb_, media::VideoDecoder::kOk,
|
| + media::VideoFrame::CreateEmptyFrame()));
|
| + read_cb_.Reset();
|
| + }
|
| +
|
| +protected:
|
| + scoped_refptr<media::MockVideoDecoder> decoder_;
|
| + scoped_ptr<RTCVideoDecoderBridge> bridge_;
|
| + webrtc::VideoCodec codec_;
|
| + base::WaitableEvent loop_idle_waiter_;
|
| + int num_delivered_frames_;
|
| + int num_delivered_encoded_image_;
|
| +
|
| + private:
|
| + scoped_refptr<base::MessageLoopProxy> loop_proxy_;
|
| + base::WaitableEvent loop_ready_waiter_;
|
| + base::PlatformThreadHandle thread_;
|
| +
|
| + base::Lock lock_;
|
| + bool is_tearing_down_;
|
| + media::VideoDecoder::ReadCB read_cb_;
|
| +};
|
| +
|
| +TEST_F(RTCVideoDecoderBridgeTest, InitDecodeReturnsErrorOnNonVP8Codec) {
|
| + codec_.codecType = webrtc::kVideoCodecI420;
|
| + EXPECT_NE(WEBRTC_VIDEO_CODEC_OK, bridge_->InitDecode(&codec_, 1));
|
| +}
|
| +
|
| +TEST_F(RTCVideoDecoderBridgeTest, InitDecodeReturnsErrorOnFeedbackMode) {
|
| + codec_.codecType = webrtc::kVideoCodecVP8;
|
| + codec_.codecSpecific.VP8.feedbackModeOn = true;
|
| + EXPECT_NE(WEBRTC_VIDEO_CODEC_OK, bridge_->InitDecode(&codec_, 1));
|
| +}
|
| +
|
| +TEST_F(RTCVideoDecoderBridgeTest, InitDecodeReturnsErrorOnDecoderInitFailure) {
|
| + EXPECT_CALL(*decoder_, Initialize(_, _, _))
|
| + .WillOnce(media::RunCallback<1>(media::DECODER_ERROR_NOT_SUPPORTED));
|
| +
|
| + codec_.codecType = webrtc::kVideoCodecVP8;
|
| + EXPECT_NE(WEBRTC_VIDEO_CODEC_OK, bridge_->InitDecode(&codec_, 1));
|
| +}
|
| +
|
| +TEST_F(RTCVideoDecoderBridgeTest, InitDecodeReturnsOkOnSuccessfulDecoderInit) {
|
| + Initialize();
|
| +}
|
| +
|
| +TEST_F(RTCVideoDecoderBridgeTest, DecodeReturnsErrorBeforeInitDecode) {
|
| + webrtc::EncodedImage input_image;
|
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED,
|
| + bridge_->Decode(input_image, false, NULL, NULL, 0));
|
| +}
|
| +
|
| +TEST_F(RTCVideoDecoderBridgeTest, DecodeReturnsErrorOnDamagedBitstream) {
|
| + Initialize();
|
| + webrtc::EncodedImage input_image;
|
| + input_image._completeFrame = false;
|
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
|
| + bridge_->Decode(input_image, false, NULL, NULL, 0));
|
| +}
|
| +
|
| +TEST_F(RTCVideoDecoderBridgeTest, DecodeReturnsErrorOnMissingFrames) {
|
| + Initialize();
|
| + webrtc::EncodedImage input_image;
|
| + input_image._completeFrame = true;
|
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
|
| + bridge_->Decode(input_image, true, NULL, NULL, 0));
|
| +}
|
| +
|
| +TEST_F(RTCVideoDecoderBridgeTest, DecodeReturnsOkAndGetsDecodedFrame) {
|
| + Initialize();
|
| + webrtc::EncodedImage input_image;
|
| + input_image._completeFrame = true;
|
| + unsigned char data = 123;
|
| + input_image._buffer = &data;
|
| + input_image._length = sizeof(data);
|
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
| + bridge_->Decode(input_image, false, NULL, NULL, 0));
|
| + num_delivered_encoded_image_++; //XXX : lock?
|
| + loop_idle_waiter_.Wait();
|
| + SimulateDecoding();
|
| + loop_idle_waiter_.Wait();
|
| + // Check output.
|
| + EXPECT_EQ(1, num_delivered_frames_); //XXX: lock?
|
| +}
|
| +
|
| +TEST_F(RTCVideoDecoderBridgeTest, ResetReturnsOk) {
|
| + Initialize();
|
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, bridge_->Reset());
|
| +}
|
| +
|
| +TEST_F(RTCVideoDecoderBridgeTest, ReleaseReturnsOk) {
|
| + Initialize();
|
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, bridge_->Release());
|
| +}
|
| +
|
| +} // content
|
|
|