| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 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 <stddef.h> | |
| 6 #include <stdint.h> | |
| 7 | |
| 8 #include <list> | |
| 9 #include <memory> | |
| 10 #include <utility> | |
| 11 #include <vector> | |
| 12 | |
| 13 #include "base/bind.h" | |
| 14 #include "base/macros.h" | |
| 15 #include "base/memory/ref_counted.h" | |
| 16 #include "base/threading/thread.h" | |
| 17 #include "base/threading/thread_task_runner_handle.h" | |
| 18 #include "base/time/time.h" | |
| 19 #include "chromecast/media/cma/ipc/media_memory_chunk.h" | |
| 20 #include "chromecast/media/cma/ipc/media_message_fifo.h" | |
| 21 #include "chromecast/media/cma/ipc_streamer/av_streamer_proxy.h" | |
| 22 #include "chromecast/media/cma/ipc_streamer/coded_frame_provider_host.h" | |
| 23 #include "chromecast/media/cma/test/frame_generator_for_test.h" | |
| 24 #include "chromecast/media/cma/test/mock_frame_consumer.h" | |
| 25 #include "chromecast/media/cma/test/mock_frame_provider.h" | |
| 26 #include "chromecast/public/media/cast_decoder_buffer.h" | |
| 27 #include "media/base/audio_decoder_config.h" | |
| 28 #include "media/base/decoder_buffer.h" | |
| 29 #include "media/base/video_decoder_config.h" | |
| 30 #include "testing/gtest/include/gtest/gtest.h" | |
| 31 | |
| 32 namespace chromecast { | |
| 33 namespace media { | |
| 34 | |
| 35 namespace { | |
| 36 | |
| 37 class FifoMemoryChunk : public MediaMemoryChunk { | |
| 38 public: | |
| 39 FifoMemoryChunk(void* mem, size_t size) | |
| 40 : mem_(mem), size_(size) {} | |
| 41 ~FifoMemoryChunk() override {} | |
| 42 | |
| 43 void* data() const override { return mem_; } | |
| 44 size_t size() const override { return size_; } | |
| 45 bool valid() const override { return true; } | |
| 46 | |
| 47 private: | |
| 48 void* mem_; | |
| 49 size_t size_; | |
| 50 | |
| 51 DISALLOW_COPY_AND_ASSIGN(FifoMemoryChunk); | |
| 52 }; | |
| 53 | |
| 54 } // namespace | |
| 55 | |
| 56 class AvStreamerTest : public testing::Test { | |
| 57 public: | |
| 58 AvStreamerTest(); | |
| 59 ~AvStreamerTest() override; | |
| 60 | |
| 61 // Setups the test. | |
| 62 void Configure(size_t frame_count, | |
| 63 const std::vector<bool>& provider_delayed_pattern, | |
| 64 const std::vector<bool>& consumer_delayed_pattern, | |
| 65 bool delay_flush); | |
| 66 | |
| 67 // Starts the test. | |
| 68 void Start(); | |
| 69 | |
| 70 // Back to back flush | |
| 71 void FlushThenStop(); | |
| 72 | |
| 73 // Timeout indicates test failure | |
| 74 void OnTestTimeout(); | |
| 75 | |
| 76 protected: | |
| 77 std::unique_ptr<uint64_t[]> fifo_mem_; | |
| 78 | |
| 79 std::unique_ptr<AvStreamerProxy> av_buffer_proxy_; | |
| 80 std::unique_ptr<CodedFrameProviderHost> coded_frame_provider_host_; | |
| 81 std::unique_ptr<MockFrameConsumer> frame_consumer_; | |
| 82 | |
| 83 // number of pending cb in StopAndFlush | |
| 84 int stop_and_flush_cb_count_; | |
| 85 | |
| 86 private: | |
| 87 void OnTestCompleted(); | |
| 88 | |
| 89 void OnFifoRead(); | |
| 90 void OnFifoWrite(); | |
| 91 | |
| 92 void OnStopAndFlush(); | |
| 93 | |
| 94 DISALLOW_COPY_AND_ASSIGN(AvStreamerTest); | |
| 95 }; | |
| 96 | |
| 97 AvStreamerTest::AvStreamerTest() { | |
| 98 } | |
| 99 | |
| 100 AvStreamerTest::~AvStreamerTest() { | |
| 101 } | |
| 102 | |
| 103 void AvStreamerTest::Configure( | |
| 104 size_t frame_count, | |
| 105 const std::vector<bool>& provider_delayed_pattern, | |
| 106 const std::vector<bool>& consumer_delayed_pattern, | |
| 107 bool delay_flush) { | |
| 108 // Frame generation on the producer and consumer side. | |
| 109 std::vector<FrameGeneratorForTest::FrameSpec> frame_specs; | |
| 110 frame_specs.resize(frame_count); | |
| 111 for (size_t k = 0; k < frame_specs.size() - 1; k++) { | |
| 112 frame_specs[k].has_config = (k == 0); | |
| 113 frame_specs[k].timestamp = base::TimeDelta::FromMilliseconds(40) * k; | |
| 114 frame_specs[k].size = 512; | |
| 115 frame_specs[k].has_decrypt_config = ((k % 3) == 0); | |
| 116 } | |
| 117 frame_specs.back().is_eos = true; | |
| 118 | |
| 119 std::unique_ptr<FrameGeneratorForTest> frame_generator_provider( | |
| 120 new FrameGeneratorForTest(frame_specs)); | |
| 121 std::unique_ptr<FrameGeneratorForTest> frame_generator_consumer( | |
| 122 new FrameGeneratorForTest(frame_specs)); | |
| 123 | |
| 124 std::unique_ptr<MockFrameProvider> frame_provider(new MockFrameProvider()); | |
| 125 frame_provider->Configure(provider_delayed_pattern, | |
| 126 std::move(frame_generator_provider)); | |
| 127 frame_provider->SetDelayFlush(delay_flush); | |
| 128 | |
| 129 size_t fifo_size_div_8 = 512; | |
| 130 fifo_mem_.reset(new uint64_t[fifo_size_div_8]); | |
| 131 std::unique_ptr<MediaMessageFifo> producer_fifo(new MediaMessageFifo( | |
| 132 std::unique_ptr<MediaMemoryChunk>( | |
| 133 new FifoMemoryChunk(&fifo_mem_[0], fifo_size_div_8 * 8)), | |
| 134 true)); | |
| 135 std::unique_ptr<MediaMessageFifo> consumer_fifo(new MediaMessageFifo( | |
| 136 std::unique_ptr<MediaMemoryChunk>( | |
| 137 new FifoMemoryChunk(&fifo_mem_[0], fifo_size_div_8 * 8)), | |
| 138 false)); | |
| 139 producer_fifo->ObserveWriteActivity( | |
| 140 base::Bind(&AvStreamerTest::OnFifoWrite, base::Unretained(this))); | |
| 141 consumer_fifo->ObserveReadActivity( | |
| 142 base::Bind(&AvStreamerTest::OnFifoRead, base::Unretained(this))); | |
| 143 | |
| 144 av_buffer_proxy_.reset( | |
| 145 new AvStreamerProxy()); | |
| 146 av_buffer_proxy_->SetCodedFrameProvider( | |
| 147 std::unique_ptr<CodedFrameProvider>(frame_provider.release())); | |
| 148 av_buffer_proxy_->SetMediaMessageFifo(std::move(producer_fifo)); | |
| 149 | |
| 150 coded_frame_provider_host_.reset( | |
| 151 new CodedFrameProviderHost(std::move(consumer_fifo))); | |
| 152 | |
| 153 frame_consumer_.reset( | |
| 154 new MockFrameConsumer(coded_frame_provider_host_.get())); | |
| 155 frame_consumer_->Configure(consumer_delayed_pattern, false, | |
| 156 std::move(frame_generator_consumer)); | |
| 157 | |
| 158 stop_and_flush_cb_count_ = 0; | |
| 159 } | |
| 160 | |
| 161 void AvStreamerTest::Start() { | |
| 162 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 163 FROM_HERE, base::Bind(&AvStreamerProxy::Start, | |
| 164 base::Unretained(av_buffer_proxy_.get()))); | |
| 165 | |
| 166 frame_consumer_->Start( | |
| 167 base::Bind(&AvStreamerTest::OnTestCompleted, | |
| 168 base::Unretained(this))); | |
| 169 } | |
| 170 | |
| 171 void AvStreamerTest::FlushThenStop() { | |
| 172 base::Closure cb = | |
| 173 base::Bind(&AvStreamerTest::OnStopAndFlush, base::Unretained(this)); | |
| 174 | |
| 175 stop_and_flush_cb_count_++; | |
| 176 av_buffer_proxy_->StopAndFlush(cb); | |
| 177 | |
| 178 ASSERT_EQ(stop_and_flush_cb_count_, 1); | |
| 179 | |
| 180 stop_and_flush_cb_count_++; | |
| 181 av_buffer_proxy_->StopAndFlush(cb); | |
| 182 } | |
| 183 | |
| 184 void AvStreamerTest::OnTestTimeout() { | |
| 185 ADD_FAILURE() << "Test timed out"; | |
| 186 if (base::MessageLoop::current()) | |
| 187 base::MessageLoop::current()->QuitWhenIdle(); | |
| 188 } | |
| 189 | |
| 190 void AvStreamerTest::OnTestCompleted() { | |
| 191 base::MessageLoop::current()->QuitWhenIdle(); | |
| 192 } | |
| 193 | |
| 194 void AvStreamerTest::OnFifoWrite() { | |
| 195 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 196 FROM_HERE, | |
| 197 base::Bind(&CodedFrameProviderHost::OnFifoWriteEvent, | |
| 198 base::Unretained(coded_frame_provider_host_.get()))); | |
| 199 } | |
| 200 | |
| 201 void AvStreamerTest::OnFifoRead() { | |
| 202 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 203 FROM_HERE, base::Bind(&AvStreamerProxy::OnFifoReadEvent, | |
| 204 base::Unretained(av_buffer_proxy_.get()))); | |
| 205 } | |
| 206 | |
| 207 void AvStreamerTest::OnStopAndFlush() { | |
| 208 stop_and_flush_cb_count_--; | |
| 209 if (stop_and_flush_cb_count_ == 0) { | |
| 210 OnTestCompleted(); | |
| 211 } | |
| 212 } | |
| 213 | |
| 214 TEST_F(AvStreamerTest, FastProviderSlowConsumer) { | |
| 215 bool provider_delayed_pattern[] = { false }; | |
| 216 bool consumer_delayed_pattern[] = { true }; | |
| 217 | |
| 218 const size_t frame_count = 100u; | |
| 219 Configure(frame_count, | |
| 220 std::vector<bool>( | |
| 221 provider_delayed_pattern, | |
| 222 provider_delayed_pattern + arraysize(provider_delayed_pattern)), | |
| 223 std::vector<bool>( | |
| 224 consumer_delayed_pattern, | |
| 225 consumer_delayed_pattern + arraysize(consumer_delayed_pattern)), | |
| 226 false); | |
| 227 | |
| 228 std::unique_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); | |
| 229 message_loop->PostTask( | |
| 230 FROM_HERE, | |
| 231 base::Bind(&AvStreamerTest::Start, base::Unretained(this))); | |
| 232 message_loop->Run(); | |
| 233 } | |
| 234 | |
| 235 TEST_F(AvStreamerTest, SlowProviderFastConsumer) { | |
| 236 bool provider_delayed_pattern[] = { true }; | |
| 237 bool consumer_delayed_pattern[] = { false }; | |
| 238 | |
| 239 const size_t frame_count = 100u; | |
| 240 Configure(frame_count, | |
| 241 std::vector<bool>( | |
| 242 provider_delayed_pattern, | |
| 243 provider_delayed_pattern + arraysize(provider_delayed_pattern)), | |
| 244 std::vector<bool>( | |
| 245 consumer_delayed_pattern, | |
| 246 consumer_delayed_pattern + arraysize(consumer_delayed_pattern)), | |
| 247 false); | |
| 248 | |
| 249 std::unique_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); | |
| 250 message_loop->PostTask( | |
| 251 FROM_HERE, | |
| 252 base::Bind(&AvStreamerTest::Start, base::Unretained(this))); | |
| 253 message_loop->Run(); | |
| 254 } | |
| 255 | |
| 256 TEST_F(AvStreamerTest, SlowFastProducerConsumer) { | |
| 257 // Pattern lengths are prime between each other | |
| 258 // so that a lot of combinations can be tested. | |
| 259 bool provider_delayed_pattern[] = { | |
| 260 true, true, true, true, true, | |
| 261 false, false, false, false | |
| 262 }; | |
| 263 bool consumer_delayed_pattern[] = { | |
| 264 true, true, true, true, true, true, true, | |
| 265 false, false, false, false, false, false, false | |
| 266 }; | |
| 267 | |
| 268 const size_t frame_count = 100u; | |
| 269 Configure(frame_count, | |
| 270 std::vector<bool>( | |
| 271 provider_delayed_pattern, | |
| 272 provider_delayed_pattern + arraysize(provider_delayed_pattern)), | |
| 273 std::vector<bool>( | |
| 274 consumer_delayed_pattern, | |
| 275 consumer_delayed_pattern + arraysize(consumer_delayed_pattern)), | |
| 276 false); | |
| 277 | |
| 278 std::unique_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); | |
| 279 message_loop->PostTask( | |
| 280 FROM_HERE, | |
| 281 base::Bind(&AvStreamerTest::Start, base::Unretained(this))); | |
| 282 message_loop->Run(); | |
| 283 } | |
| 284 | |
| 285 // Test case for when AvStreamerProxy::StopAndFlush is invoked while a previous | |
| 286 // flush is pending. This can happen when pipeline is stopped while a seek/flush | |
| 287 // is pending. | |
| 288 TEST_F(AvStreamerTest, StopInFlush) { | |
| 289 // We don't care about the delayed pattern. Setting to true to make sure the | |
| 290 // test won't exit before flush is called. | |
| 291 bool dummy_delayed_pattern[] = {true}; | |
| 292 std::vector<bool> dummy_delayed_pattern_vector( | |
| 293 dummy_delayed_pattern, | |
| 294 dummy_delayed_pattern + arraysize(dummy_delayed_pattern)); | |
| 295 const size_t frame_count = 100u; | |
| 296 | |
| 297 // Delay flush callback in frame provider | |
| 298 Configure(frame_count, dummy_delayed_pattern_vector, | |
| 299 dummy_delayed_pattern_vector, true); | |
| 300 | |
| 301 std::unique_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); | |
| 302 | |
| 303 // Flush takes 10ms to finish. 1s timeout is enough for this test. | |
| 304 message_loop->PostDelayedTask( | |
| 305 FROM_HERE, | |
| 306 base::Bind(&AvStreamerTest::OnTestTimeout, base::Unretained(this)), | |
| 307 base::TimeDelta::FromSeconds(1)); | |
| 308 | |
| 309 message_loop->PostTask( | |
| 310 FROM_HERE, base::Bind(&AvStreamerTest::Start, base::Unretained(this))); | |
| 311 | |
| 312 // Let AvStreamerProxy run for a while. Fire flush and stop later | |
| 313 message_loop->PostDelayedTask( | |
| 314 FROM_HERE, | |
| 315 base::Bind(&AvStreamerTest::FlushThenStop, base::Unretained(this)), | |
| 316 base::TimeDelta::FromMilliseconds(10)); | |
| 317 | |
| 318 message_loop->Run(); | |
| 319 } | |
| 320 | |
| 321 } // namespace media | |
| 322 } // namespace chromecast | |
| OLD | NEW |