Chromium Code Reviews| 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..eefcb5ffeb97f79b43b24c7c2a9c1bd5a70f8db5 |
| --- /dev/null |
| +++ b/content/renderer/media/rtc_video_decoder_unittest.cc |
| @@ -0,0 +1,200 @@ |
| +// 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/threading/platform_thread.h" |
| +#include "content/renderer/media/rtc_video_decoder.h" |
| +#include "media/base/gmock_callback_support.h" |
| +#include "media/base/mock_filters.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +using ::testing::_; |
| + |
| +namespace content { |
| + |
| +class RTCVideoDecoderTest |
| + : public ::testing::Test, |
| + public base::PlatformThread::Delegate, |
| + webrtc::DecodedImageCallback { |
| + public: |
| + RTCVideoDecoderTest() |
| + : 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 RTCVideoDecoder(decoder_, loop_proxy_)); |
|
Ami GONE FROM CHROMIUM
2013/05/14 22:57:24
|bridge_| is now a strange name for the variable c
wuchengli
2013/05/15 15:30:46
Changed |bridge_| to |rtc_decoder_| and changed |d
|
| + } |
| + |
| + 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 int32_t Decoded(webrtc::I420VideoFrame& decoded_image) |
| + OVERRIDE { |
| + num_delivered_frames_++; |
|
Ami GONE FROM CHROMIUM
2013/05/14 22:57:24
nit: prefer pre-{de,in}crement to post-, where the
wuchengli
2013/05/15 15:30:46
All done.
|
| + 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, &RTCVideoDecoderTest::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: |
| + media::MockVideoDecoder* decoder_; |
| + scoped_ptr<RTCVideoDecoder> 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(RTCVideoDecoderTest, InitDecodeReturnsErrorOnNonVP8Codec) { |
| + codec_.codecType = webrtc::kVideoCodecI420; |
| + EXPECT_NE(WEBRTC_VIDEO_CODEC_OK, bridge_->InitDecode(&codec_, 1)); |
| +} |
| + |
| +TEST_F(RTCVideoDecoderTest, InitDecodeReturnsErrorOnFeedbackMode) { |
| + codec_.codecType = webrtc::kVideoCodecVP8; |
| + codec_.codecSpecific.VP8.feedbackModeOn = true; |
| + EXPECT_NE(WEBRTC_VIDEO_CODEC_OK, bridge_->InitDecode(&codec_, 1)); |
| +} |
| + |
| +TEST_F(RTCVideoDecoderTest, 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(RTCVideoDecoderTest, InitDecodeReturnsOkOnSuccessfulDecoderInit) { |
| + Initialize(); |
| +} |
| + |
| +TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorBeforeInitDecode) { |
| + webrtc::EncodedImage input_image; |
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED, |
| + bridge_->Decode(input_image, false, NULL, NULL, 0)); |
| +} |
| + |
| +TEST_F(RTCVideoDecoderTest, 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(RTCVideoDecoderTest, 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(RTCVideoDecoderTest, 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? |
|
Ami GONE FROM CHROMIUM
2013/05/14 22:57:24
If all you need is sequencing (not mutual exclusio
wuchengli
2013/05/15 15:30:46
Yes. It's only sequencing. The comments were remov
|
| +} |
| + |
| +TEST_F(RTCVideoDecoderTest, ResetReturnsOk) { |
| + Initialize(); |
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, bridge_->Reset()); |
| +} |
| + |
| +TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) { |
| + Initialize(); |
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, bridge_->Release()); |
| +} |
| + |
| +} // content |