1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "media/base/test_helpers.h" 6 7#include "base/bind.h" 8#include "base/logging.h" 9#include "base/message_loop/message_loop.h" 10#include "base/pickle.h" 11#include "base/test/test_timeouts.h" 12#include "base/time/time.h" 13#include "base/timer/timer.h" 14#include "media/base/audio_buffer.h" 15#include "media/base/bind_to_current_loop.h" 16#include "media/base/decoder_buffer.h" 17#include "ui/gfx/rect.h" 18 19using ::testing::_; 20using ::testing::StrictMock; 21 22namespace media { 23 24// Utility mock for testing methods expecting Closures and PipelineStatusCBs. 25class MockCallback : public base::RefCountedThreadSafe<MockCallback> { 26 public: 27 MockCallback(); 28 MOCK_METHOD0(Run, void()); 29 MOCK_METHOD1(RunWithStatus, void(PipelineStatus)); 30 31 protected: 32 friend class base::RefCountedThreadSafe<MockCallback>; 33 virtual ~MockCallback(); 34 35 private: 36 DISALLOW_COPY_AND_ASSIGN(MockCallback); 37}; 38 39MockCallback::MockCallback() {} 40MockCallback::~MockCallback() {} 41 42base::Closure NewExpectedClosure() { 43 StrictMock<MockCallback>* callback = new StrictMock<MockCallback>(); 44 EXPECT_CALL(*callback, Run()); 45 return base::Bind(&MockCallback::Run, callback); 46} 47 48PipelineStatusCB NewExpectedStatusCB(PipelineStatus status) { 49 StrictMock<MockCallback>* callback = new StrictMock<MockCallback>(); 50 EXPECT_CALL(*callback, RunWithStatus(status)); 51 return base::Bind(&MockCallback::RunWithStatus, callback); 52} 53 54WaitableMessageLoopEvent::WaitableMessageLoopEvent() 55 : message_loop_(base::MessageLoop::current()), 56 signaled_(false), 57 status_(PIPELINE_OK) { 58 DCHECK(message_loop_); 59} 60 61WaitableMessageLoopEvent::~WaitableMessageLoopEvent() {} 62 63base::Closure WaitableMessageLoopEvent::GetClosure() { 64 DCHECK_EQ(message_loop_, base::MessageLoop::current()); 65 return BindToCurrentLoop(base::Bind( 66 &WaitableMessageLoopEvent::OnCallback, base::Unretained(this), 67 PIPELINE_OK)); 68} 69 70PipelineStatusCB WaitableMessageLoopEvent::GetPipelineStatusCB() { 71 DCHECK_EQ(message_loop_, base::MessageLoop::current()); 72 return BindToCurrentLoop(base::Bind( 73 &WaitableMessageLoopEvent::OnCallback, base::Unretained(this))); 74} 75 76void WaitableMessageLoopEvent::RunAndWait() { 77 RunAndWaitForStatus(PIPELINE_OK); 78} 79 80void WaitableMessageLoopEvent::RunAndWaitForStatus(PipelineStatus expected) { 81 DCHECK_EQ(message_loop_, base::MessageLoop::current()); 82 if (signaled_) { 83 EXPECT_EQ(expected, status_); 84 return; 85 } 86 87 base::Timer timer(false, false); 88 timer.Start(FROM_HERE, TestTimeouts::action_timeout(), base::Bind( 89 &WaitableMessageLoopEvent::OnTimeout, base::Unretained(this))); 90 91 message_loop_->Run(); 92 EXPECT_TRUE(signaled_); 93 EXPECT_EQ(expected, status_); 94} 95 96void WaitableMessageLoopEvent::OnCallback(PipelineStatus status) { 97 DCHECK_EQ(message_loop_, base::MessageLoop::current()); 98 signaled_ = true; 99 status_ = status; 100 message_loop_->QuitWhenIdle(); 101} 102 103void WaitableMessageLoopEvent::OnTimeout() { 104 DCHECK_EQ(message_loop_, base::MessageLoop::current()); 105 ADD_FAILURE() << "Timed out waiting for message loop to quit"; 106 message_loop_->QuitWhenIdle(); 107} 108 109static VideoDecoderConfig GetTestConfig(VideoCodec codec, 110 gfx::Size coded_size, 111 bool is_encrypted) { 112 gfx::Rect visible_rect(coded_size.width(), coded_size.height()); 113 gfx::Size natural_size = coded_size; 114 115 return VideoDecoderConfig(codec, VIDEO_CODEC_PROFILE_UNKNOWN, 116 VideoFrame::YV12, coded_size, visible_rect, natural_size, 117 NULL, 0, is_encrypted); 118} 119 120static const gfx::Size kNormalSize(320, 240); 121static const gfx::Size kLargeSize(640, 480); 122 123VideoDecoderConfig TestVideoConfig::Invalid() { 124 return GetTestConfig(kUnknownVideoCodec, kNormalSize, false); 125} 126 127VideoDecoderConfig TestVideoConfig::Normal() { 128 return GetTestConfig(kCodecVP8, kNormalSize, false); 129} 130 131VideoDecoderConfig TestVideoConfig::NormalEncrypted() { 132 return GetTestConfig(kCodecVP8, kNormalSize, true); 133} 134 135VideoDecoderConfig TestVideoConfig::Large() { 136 return GetTestConfig(kCodecVP8, kLargeSize, false); 137} 138 139VideoDecoderConfig TestVideoConfig::LargeEncrypted() { 140 return GetTestConfig(kCodecVP8, kLargeSize, true); 141} 142 143gfx::Size TestVideoConfig::NormalCodedSize() { 144 return kNormalSize; 145} 146 147gfx::Size TestVideoConfig::LargeCodedSize() { 148 return kLargeSize; 149} 150 151template <class T> 152scoped_refptr<AudioBuffer> MakeAudioBuffer(SampleFormat format, 153 ChannelLayout channel_layout, 154 size_t channel_count, 155 int sample_rate, 156 T start, 157 T increment, 158 size_t frames, 159 base::TimeDelta timestamp) { 160 const size_t channels = ChannelLayoutToChannelCount(channel_layout); 161 scoped_refptr<AudioBuffer> output = 162 AudioBuffer::CreateBuffer(format, 163 channel_layout, 164 static_cast<int>(channel_count), 165 sample_rate, 166 static_cast<int>(frames)); 167 output->set_timestamp(timestamp); 168 169 const bool is_planar = 170 format == kSampleFormatPlanarS16 || format == kSampleFormatPlanarF32; 171 172 // Values in channel 0 will be: 173 // start 174 // start + increment 175 // start + 2 * increment, ... 176 // While, values in channel 1 will be: 177 // start + frames * increment 178 // start + (frames + 1) * increment 179 // start + (frames + 2) * increment, ... 180 for (size_t ch = 0; ch < channels; ++ch) { 181 T* buffer = 182 reinterpret_cast<T*>(output->channel_data()[is_planar ? ch : 0]); 183 const T v = static_cast<T>(start + ch * frames * increment); 184 for (size_t i = 0; i < frames; ++i) { 185 buffer[is_planar ? i : ch + i * channels] = 186 static_cast<T>(v + i * increment); 187 } 188 } 189 return output; 190} 191 192// Instantiate all the types of MakeAudioBuffer() and 193// MakeAudioBuffer() needed. 194#define DEFINE_MAKE_AUDIO_BUFFER_INSTANCE(type) \ 195 template scoped_refptr<AudioBuffer> MakeAudioBuffer<type>( \ 196 SampleFormat format, \ 197 ChannelLayout channel_layout, \ 198 size_t channel_count, \ 199 int sample_rate, \ 200 type start, \ 201 type increment, \ 202 size_t frames, \ 203 base::TimeDelta start_time) 204DEFINE_MAKE_AUDIO_BUFFER_INSTANCE(uint8); 205DEFINE_MAKE_AUDIO_BUFFER_INSTANCE(int16); 206DEFINE_MAKE_AUDIO_BUFFER_INSTANCE(int32); 207DEFINE_MAKE_AUDIO_BUFFER_INSTANCE(float); 208 209static const char kFakeVideoBufferHeader[] = "FakeVideoBufferForTest"; 210 211scoped_refptr<DecoderBuffer> CreateFakeVideoBufferForTest( 212 const VideoDecoderConfig& config, 213 base::TimeDelta timestamp, base::TimeDelta duration) { 214 Pickle pickle; 215 pickle.WriteString(kFakeVideoBufferHeader); 216 pickle.WriteInt(config.coded_size().width()); 217 pickle.WriteInt(config.coded_size().height()); 218 pickle.WriteInt64(timestamp.InMilliseconds()); 219 220 scoped_refptr<DecoderBuffer> buffer = DecoderBuffer::CopyFrom( 221 static_cast<const uint8*>(pickle.data()), 222 static_cast<int>(pickle.size())); 223 buffer->set_timestamp(timestamp); 224 buffer->set_duration(duration); 225 226 return buffer; 227} 228 229bool VerifyFakeVideoBufferForTest( 230 const scoped_refptr<DecoderBuffer>& buffer, 231 const VideoDecoderConfig& config) { 232 // Check if the input |buffer| matches the |config|. 233 PickleIterator pickle(Pickle(reinterpret_cast<const char*>(buffer->data()), 234 buffer->data_size())); 235 std::string header; 236 int width = 0; 237 int height = 0; 238 bool success = pickle.ReadString(&header) && pickle.ReadInt(&width) && 239 pickle.ReadInt(&height); 240 return (success && header == kFakeVideoBufferHeader && 241 width == config.coded_size().width() && 242 height == config.coded_size().height()); 243} 244 245CallbackPairChecker::CallbackPairChecker() : expecting_b_(false) { 246} 247 248CallbackPairChecker::~CallbackPairChecker() { 249 EXPECT_FALSE(expecting_b_); 250} 251 252void CallbackPairChecker::RecordACalled() { 253 EXPECT_FALSE(expecting_b_); 254 expecting_b_ = true; 255} 256 257void CallbackPairChecker::RecordBCalled() { 258 EXPECT_TRUE(expecting_b_); 259 expecting_b_ = false; 260} 261 262} // namespace media 263