| Index: content/renderer/media/rtc_video_decoder_unittest.cc
|
| diff --git a/content/renderer/media/rtc_video_decoder_unittest.cc b/content/renderer/media/rtc_video_decoder_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ceb3051447fcb94b152eed01264ec359e7372f99
|
| --- /dev/null
|
| +++ b/content/renderer/media/rtc_video_decoder_unittest.cc
|
| @@ -0,0 +1,176 @@
|
| +// 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/synchronization/waitable_event.h"
|
| +#include "base/threading/thread.h"
|
| +#include "content/renderer/media/rtc_video_decoder.h"
|
| +#include "media/base/gmock_callback_support.h"
|
| +#include "media/filters/gpu_video_decoder.h"
|
| +#include "media/filters/mock_gpu_video_decoder_factories.h"
|
| +#include "media/video/mock_video_decode_accelerator.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +using ::testing::_;
|
| +using ::testing::Invoke;
|
| +using ::testing::Return;
|
| +using ::testing::SaveArg;
|
| +using ::testing::WithArgs;
|
| +
|
| +namespace content {
|
| +
|
| +class RTCVideoDecoderTest : public ::testing::Test,
|
| + webrtc::DecodedImageCallback {
|
| + public:
|
| + RTCVideoDecoderTest()
|
| + : mock_gpu_factories_(new media::MockGpuVideoDecoderFactories),
|
| + vda_thread_("vda_thread"),
|
| + idle_waiter_(false, false) {
|
| + memset(&codec_, 0, sizeof(codec_));
|
| + }
|
| +
|
| + virtual void SetUp() OVERRIDE {
|
| + ASSERT_TRUE(vda_thread_.Start());
|
| + vda_loop_proxy_ = vda_thread_.message_loop_proxy();
|
| + mock_vda_ = new media::MockVideoDecodeAccelerator;
|
| + EXPECT_CALL(*mock_gpu_factories_, GetMessageLoop())
|
| + .WillRepeatedly(Return(vda_loop_proxy_));
|
| + EXPECT_CALL(*mock_gpu_factories_,
|
| + CreateVideoDecodeAccelerator(media::VP8PROFILE_MAIN, _))
|
| + .WillOnce(Return(mock_vda_));
|
| + EXPECT_CALL(*mock_gpu_factories_, Abort()).WillRepeatedly(Return());
|
| + EXPECT_CALL(*mock_gpu_factories_, CreateSharedMemory(_))
|
| + .WillRepeatedly(Return(static_cast<base::SharedMemory*>(NULL)));
|
| + EXPECT_CALL(*mock_vda_, Destroy());
|
| + rtc_decoder_ = RTCVideoDecoder::Create(mock_gpu_factories_);
|
| + }
|
| +
|
| + virtual void TearDown() OVERRIDE {
|
| + VLOG(2) << "TearDown";
|
| + if (vda_thread_.IsRunning()) {
|
| + RunUntilIdle(); // Wait until all callbascks complete.
|
| + vda_loop_proxy_->DeleteSoon(FROM_HERE, rtc_decoder_.release());
|
| + // Make sure the decoder is released before stopping the thread.
|
| + RunUntilIdle();
|
| + vda_thread_.Stop();
|
| + } else {
|
| + rtc_decoder_.reset();
|
| + }
|
| + }
|
| +
|
| + virtual int32_t Decoded(webrtc::I420VideoFrame& decoded_image) OVERRIDE {
|
| + VLOG(2) << "Decoded";
|
| + EXPECT_EQ(vda_loop_proxy_, base::MessageLoopProxy::current());
|
| + return WEBRTC_VIDEO_CODEC_OK;
|
| + }
|
| +
|
| + void Initialize() {
|
| + VLOG(2) << "Initialize";
|
| + codec_.codecType = webrtc::kVideoCodecVP8;
|
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->InitDecode(&codec_, 1));
|
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
| + rtc_decoder_->RegisterDecodeCompleteCallback(this));
|
| + }
|
| +
|
| + void NotifyResetDone() {
|
| + VLOG(2) << "NotifyResetDone";
|
| + vda_loop_proxy_->PostTask(FROM_HERE,
|
| + base::Bind(&RTCVideoDecoder::NotifyResetDone,
|
| + base::Unretained(rtc_decoder_.get())));
|
| + }
|
| +
|
| + void RunUntilIdle() {
|
| + VLOG(2) << "RunUntilIdle";
|
| + vda_loop_proxy_->PostTask(FROM_HERE,
|
| + base::Bind(&base::WaitableEvent::Signal,
|
| + base::Unretained(&idle_waiter_)));
|
| + idle_waiter_.Wait();
|
| + }
|
| +
|
| + protected:
|
| + scoped_refptr<media::MockGpuVideoDecoderFactories> mock_gpu_factories_;
|
| + media::MockVideoDecodeAccelerator* mock_vda_;
|
| + scoped_ptr<RTCVideoDecoder> rtc_decoder_;
|
| + webrtc::VideoCodec codec_;
|
| + base::Thread vda_thread_;
|
| +
|
| + private:
|
| + scoped_refptr<base::MessageLoopProxy> vda_loop_proxy_;
|
| +
|
| + base::Lock lock_;
|
| + base::WaitableEvent idle_waiter_;
|
| +};
|
| +
|
| +TEST_F(RTCVideoDecoderTest, InitDecodeReturnsErrorOnFeedbackMode) {
|
| + codec_.codecType = webrtc::kVideoCodecVP8;
|
| + codec_.codecSpecific.VP8.feedbackModeOn = true;
|
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, rtc_decoder_->InitDecode(&codec_, 1));
|
| +}
|
| +
|
| +TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorWithoutInitDecode) {
|
| + webrtc::EncodedImage input_image;
|
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED,
|
| + rtc_decoder_->Decode(input_image, false, NULL, NULL, 0));
|
| +}
|
| +
|
| +TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnIncompleteFrame) {
|
| + Initialize();
|
| + webrtc::EncodedImage input_image;
|
| + input_image._completeFrame = false;
|
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
|
| + rtc_decoder_->Decode(input_image, false, NULL, NULL, 0));
|
| +}
|
| +
|
| +TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnMissingFrames) {
|
| + Initialize();
|
| + webrtc::EncodedImage input_image;
|
| + input_image._completeFrame = true;
|
| + bool missingFrames = true;
|
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
|
| + rtc_decoder_->Decode(input_image, missingFrames, NULL, NULL, 0));
|
| +}
|
| +
|
| +TEST_F(RTCVideoDecoderTest, ResetReturnsOk) {
|
| + Initialize();
|
| + EXPECT_CALL(*mock_vda_, Reset())
|
| + .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
|
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Reset());
|
| +}
|
| +
|
| +TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) {
|
| + Initialize();
|
| + EXPECT_CALL(*mock_vda_, Reset())
|
| + .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
|
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
|
| +}
|
| +
|
| +TEST_F(RTCVideoDecoderTest, VdaThreadStops) { vda_thread_.Stop(); }
|
| +
|
| +TEST_F(RTCVideoDecoderTest, IsBufferAfterReset) {
|
| + EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_INVALID));
|
| + EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
|
| + RTCVideoDecoder::ID_INVALID));
|
| + EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_HALF - 2,
|
| + RTCVideoDecoder::ID_HALF + 2));
|
| + EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_HALF + 2,
|
| + RTCVideoDecoder::ID_HALF - 2));
|
| +
|
| + EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(0, 0));
|
| + EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_LAST));
|
| + EXPECT_FALSE(
|
| + rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_HALF - 2));
|
| + EXPECT_TRUE(
|
| + rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_HALF + 2));
|
| +
|
| + EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST, 0));
|
| + EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
|
| + RTCVideoDecoder::ID_HALF - 2));
|
| + EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
|
| + RTCVideoDecoder::ID_HALF + 2));
|
| + EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
|
| + RTCVideoDecoder::ID_LAST));
|
| +}
|
| +
|
| +} // content
|
|
|