Cast: Skip receiver log messages with time delta that can't be encoded.
[chromium-blink-merge.git] / media / filters / pipeline_integration_test.cc
blobff846d62e4c837f19e5222e7e51467efc0becac7
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.
5 #include "media/filters/pipeline_integration_test_base.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/strings/string_util.h"
11 #include "build/build_config.h"
12 #include "media/base/decoder_buffer.h"
13 #include "media/base/media_keys.h"
14 #include "media/base/media_switches.h"
15 #include "media/base/test_data_util.h"
16 #include "media/cdm/aes_decryptor.h"
17 #include "media/cdm/json_web_key.h"
18 #include "media/filters/chunk_demuxer.h"
20 using testing::AnyNumber;
21 using testing::AtMost;
23 namespace media {
25 const char kSourceId[] = "SourceId";
26 const uint8 kInitData[] = { 0x69, 0x6e, 0x69, 0x74 };
28 const char kWebM[] = "video/webm; codecs=\"vp8,vorbis\"";
29 const char kWebMVP9[] = "video/webm; codecs=\"vp9\"";
30 const char kAudioOnlyWebM[] = "video/webm; codecs=\"vorbis\"";
31 const char kOpusAudioOnlyWebM[] = "video/webm; codecs=\"opus\"";
32 const char kVideoOnlyWebM[] = "video/webm; codecs=\"vp8\"";
33 const char kMP4VideoType[] = "video/mp4";
34 const char kMP4AudioType[] = "audio/mp4";
35 #if defined(USE_PROPRIETARY_CODECS)
36 const char kMP4[] = "video/mp4; codecs=\"avc1.4D4041,mp4a.40.2\"";
37 const char kMP4Video[] = "video/mp4; codecs=\"avc1.4D4041\"";
38 const char kMP4VideoAVC3[] = "video/mp4; codecs=\"avc3.64001f\"";
39 const char kMP4Audio[] = "audio/mp4; codecs=\"mp4a.40.2\"";
40 const char kMP3[] = "audio/mpeg";
41 #endif // defined(USE_PROPRIETARY_CODECS)
43 // Key used to encrypt test files.
44 const uint8 kSecretKey[] = {
45 0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b,
46 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c
49 // The key ID for all encrypted files.
50 const uint8 kKeyId[] = {
51 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
52 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35
55 const int kAppendWholeFile = -1;
57 // Constants for the Media Source config change tests.
58 const int kAppendTimeSec = 1;
59 const int kAppendTimeMs = kAppendTimeSec * 1000;
60 const int k320WebMFileDurationMs = 2737;
61 const int k640WebMFileDurationMs = 2763;
62 const int kOpusEndTrimmingWebMFileDurationMs = 2771;
63 const int kVP9WebMFileDurationMs = 2735;
64 const int kVP8AWebMFileDurationMs = 2700;
66 #if defined(USE_PROPRIETARY_CODECS)
67 const int k640IsoFileDurationMs = 2737;
68 const int k640IsoCencFileDurationMs = 2736;
69 const int k1280IsoFileDurationMs = 2736;
70 const int k1280IsoAVC3FileDurationMs = 2735;
71 #endif // defined(USE_PROPRIETARY_CODECS)
73 // Note: Tests using this class only exercise the DecryptingDemuxerStream path.
74 // They do not exercise the Decrypting{Audio|Video}Decoder path.
75 class FakeEncryptedMedia {
76 public:
77 // Defines the behavior of the "app" that responds to EME events.
78 class AppBase {
79 public:
80 virtual ~AppBase() {}
82 virtual void OnSessionCreated(uint32 session_id,
83 const std::string& web_session_id) = 0;
85 virtual void OnSessionMessage(uint32 session_id,
86 const std::vector<uint8>& message,
87 const std::string& destination_url) = 0;
89 virtual void OnSessionReady(uint32 session_id) = 0;
91 virtual void OnSessionClosed(uint32 session_id) = 0;
93 // Errors are not expected unless overridden.
94 virtual void OnSessionError(uint32 session_id,
95 MediaKeys::KeyError error_code,
96 uint32 system_code) {
97 FAIL() << "Unexpected Key Error";
100 virtual void NeedKey(const std::string& type,
101 const std::vector<uint8>& init_data,
102 AesDecryptor* decryptor) = 0;
105 FakeEncryptedMedia(AppBase* app)
106 : decryptor_(base::Bind(&FakeEncryptedMedia::OnSessionCreated,
107 base::Unretained(this)),
108 base::Bind(&FakeEncryptedMedia::OnSessionMessage,
109 base::Unretained(this)),
110 base::Bind(&FakeEncryptedMedia::OnSessionReady,
111 base::Unretained(this)),
112 base::Bind(&FakeEncryptedMedia::OnSessionClosed,
113 base::Unretained(this)),
114 base::Bind(&FakeEncryptedMedia::OnSessionError,
115 base::Unretained(this))),
116 app_(app) {}
118 AesDecryptor* decryptor() {
119 return &decryptor_;
122 // Callbacks for firing session events. Delegate to |app_|.
123 void OnSessionCreated(uint32 session_id, const std::string& web_session_id) {
124 app_->OnSessionCreated(session_id, web_session_id);
127 void OnSessionMessage(uint32 session_id,
128 const std::vector<uint8>& message,
129 const std::string& destination_url) {
130 app_->OnSessionMessage(session_id, message, destination_url);
133 void OnSessionReady(uint32 session_id) {
134 app_->OnSessionReady(session_id);
137 void OnSessionClosed(uint32 session_id) {
138 app_->OnSessionClosed(session_id);
141 void OnSessionError(uint32 session_id,
142 MediaKeys::KeyError error_code,
143 uint32 system_code) {
144 app_->OnSessionError(session_id, error_code, system_code);
147 void NeedKey(const std::string& type,
148 const std::vector<uint8>& init_data) {
149 app_->NeedKey(type, init_data, &decryptor_);
152 private:
153 AesDecryptor decryptor_;
154 scoped_ptr<AppBase> app_;
157 // Provides |kSecretKey| in response to needkey.
158 class KeyProvidingApp : public FakeEncryptedMedia::AppBase {
159 public:
160 KeyProvidingApp() : current_session_id_(0) {}
162 virtual void OnSessionCreated(uint32 session_id,
163 const std::string& web_session_id) OVERRIDE {
164 EXPECT_GT(session_id, 0u);
165 EXPECT_FALSE(web_session_id.empty());
168 virtual void OnSessionMessage(uint32 session_id,
169 const std::vector<uint8>& message,
170 const std::string& default_url) OVERRIDE {
171 EXPECT_GT(session_id, 0u);
172 EXPECT_FALSE(message.empty());
174 current_session_id_ = session_id;
177 virtual void OnSessionReady(uint32 session_id) OVERRIDE {
178 EXPECT_GT(session_id, 0u);
181 virtual void OnSessionClosed(uint32 session_id) OVERRIDE {
182 EXPECT_GT(session_id, 0u);
185 virtual void NeedKey(const std::string& type,
186 const std::vector<uint8>& init_data,
187 AesDecryptor* decryptor) OVERRIDE {
188 if (current_session_id_ == 0u) {
189 EXPECT_TRUE(
190 decryptor->CreateSession(12, type, kInitData, arraysize(kInitData)));
193 EXPECT_EQ(current_session_id_, 12u);
195 // Clear Key really needs the key ID in |init_data|. For WebM, they are the
196 // same, but this is not the case for ISO CENC. Therefore, provide the
197 // correct key ID.
198 const uint8* key_id = init_data.empty() ? NULL : &init_data[0];
199 size_t key_id_length = init_data.size();
200 if (type == kMP4AudioType || type == kMP4VideoType) {
201 key_id = kKeyId;
202 key_id_length = arraysize(kKeyId);
205 // Convert key into a JSON structure and then add it.
206 std::string jwk = GenerateJWKSet(
207 kSecretKey, arraysize(kSecretKey), key_id, key_id_length);
208 decryptor->UpdateSession(current_session_id_,
209 reinterpret_cast<const uint8*>(jwk.data()),
210 jwk.size());
213 uint32 current_session_id_;
216 // Ignores needkey and does not perform a license request
217 class NoResponseApp : public FakeEncryptedMedia::AppBase {
218 public:
219 virtual void OnSessionCreated(uint32 session_id,
220 const std::string& web_session_id) OVERRIDE {
221 EXPECT_GT(session_id, 0u);
222 EXPECT_FALSE(web_session_id.empty());
225 virtual void OnSessionMessage(uint32 session_id,
226 const std::vector<uint8>& message,
227 const std::string& default_url) OVERRIDE {
228 EXPECT_GT(session_id, 0u);
229 EXPECT_FALSE(message.empty());
230 FAIL() << "Unexpected KeyMessage";
233 virtual void OnSessionReady(uint32 session_id) OVERRIDE {
234 EXPECT_GT(session_id, 0u);
235 FAIL() << "Unexpected Ready";
238 virtual void OnSessionClosed(uint32 session_id) OVERRIDE {
239 EXPECT_GT(session_id, 0u);
240 FAIL() << "Unexpected Closed";
243 virtual void NeedKey(const std::string& type,
244 const std::vector<uint8>& init_data,
245 AesDecryptor* decryptor) OVERRIDE {
249 // Helper class that emulates calls made on the ChunkDemuxer by the
250 // Media Source API.
251 class MockMediaSource {
252 public:
253 MockMediaSource(const std::string& filename, const std::string& mimetype,
254 int initial_append_size)
255 : file_path_(GetTestDataFilePath(filename)),
256 current_position_(0),
257 initial_append_size_(initial_append_size),
258 mimetype_(mimetype),
259 chunk_demuxer_(new ChunkDemuxer(
260 base::Bind(&MockMediaSource::DemuxerOpened,
261 base::Unretained(this)),
262 base::Bind(&MockMediaSource::DemuxerNeedKey,
263 base::Unretained(this)),
264 LogCB())),
265 owned_chunk_demuxer_(chunk_demuxer_) {
267 file_data_ = ReadTestDataFile(filename);
269 if (initial_append_size_ == kAppendWholeFile)
270 initial_append_size_ = file_data_->data_size();
272 DCHECK_GT(initial_append_size_, 0);
273 DCHECK_LE(initial_append_size_, file_data_->data_size());
276 virtual ~MockMediaSource() {}
278 scoped_ptr<Demuxer> GetDemuxer() { return owned_chunk_demuxer_.Pass(); }
280 void set_need_key_cb(const Demuxer::NeedKeyCB& need_key_cb) {
281 need_key_cb_ = need_key_cb;
284 void Seek(base::TimeDelta seek_time, int new_position, int seek_append_size) {
285 chunk_demuxer_->StartWaitingForSeek(seek_time);
287 chunk_demuxer_->Abort(kSourceId);
289 DCHECK_GE(new_position, 0);
290 DCHECK_LT(new_position, file_data_->data_size());
291 current_position_ = new_position;
293 AppendData(seek_append_size);
296 void AppendData(int size) {
297 DCHECK(chunk_demuxer_);
298 DCHECK_LT(current_position_, file_data_->data_size());
299 DCHECK_LE(current_position_ + size, file_data_->data_size());
301 // TODO(wolenetz): Test timestamp offset updating once "sequence" append
302 // mode processing is implemented. See http://crbug.com/249422.
303 chunk_demuxer_->AppendData(
304 kSourceId, file_data_->data() + current_position_, size, NULL);
305 current_position_ += size;
308 void AppendAtTime(const base::TimeDelta& timestampOffset,
309 const uint8* pData, int size) {
310 CHECK(chunk_demuxer_->SetTimestampOffset(kSourceId, timestampOffset));
311 chunk_demuxer_->AppendData(kSourceId, pData, size, NULL);
312 CHECK(chunk_demuxer_->SetTimestampOffset(kSourceId, base::TimeDelta()));
315 void EndOfStream() {
316 chunk_demuxer_->MarkEndOfStream(PIPELINE_OK);
319 void Abort() {
320 if (!chunk_demuxer_)
321 return;
322 chunk_demuxer_->Shutdown();
323 chunk_demuxer_ = NULL;
326 void DemuxerOpened() {
327 base::MessageLoop::current()->PostTask(
328 FROM_HERE, base::Bind(&MockMediaSource::DemuxerOpenedTask,
329 base::Unretained(this)));
332 void DemuxerOpenedTask() {
333 // This code assumes that |mimetype_| is one of the following forms.
334 // 1. audio/mpeg
335 // 2. video/webm;codec="vorbis,vp8".
336 size_t semicolon = mimetype_.find(";");
337 std::string type = mimetype_;
338 std::vector<std::string> codecs;
339 if (semicolon != std::string::npos) {
340 type = mimetype_.substr(0, semicolon);
341 size_t codecs_param_start = mimetype_.find("codecs=\"", semicolon);
343 CHECK_NE(codecs_param_start, std::string::npos);
345 codecs_param_start += 8; // Skip over the codecs=".
347 size_t codecs_param_end = mimetype_.find("\"", codecs_param_start);
349 CHECK_NE(codecs_param_end, std::string::npos);
351 std::string codecs_param =
352 mimetype_.substr(codecs_param_start,
353 codecs_param_end - codecs_param_start);
354 Tokenize(codecs_param, ",", &codecs);
357 CHECK_EQ(chunk_demuxer_->AddId(kSourceId, type, codecs), ChunkDemuxer::kOk);
358 AppendData(initial_append_size_);
361 void DemuxerNeedKey(const std::string& type,
362 const std::vector<uint8>& init_data) {
363 DCHECK(!init_data.empty());
364 CHECK(!need_key_cb_.is_null());
365 need_key_cb_.Run(type, init_data);
368 private:
369 base::FilePath file_path_;
370 scoped_refptr<DecoderBuffer> file_data_;
371 int current_position_;
372 int initial_append_size_;
373 std::string mimetype_;
374 ChunkDemuxer* chunk_demuxer_;
375 scoped_ptr<Demuxer> owned_chunk_demuxer_;
376 Demuxer::NeedKeyCB need_key_cb_;
379 class PipelineIntegrationTest
380 : public testing::Test,
381 public PipelineIntegrationTestBase {
382 public:
383 void StartPipelineWithMediaSource(MockMediaSource* source) {
384 EXPECT_CALL(*this, OnBufferingState(Pipeline::kHaveMetadata))
385 .Times(AtMost(1));
386 EXPECT_CALL(*this, OnBufferingState(Pipeline::kPrerollCompleted))
387 .Times(AtMost(1));
388 pipeline_->Start(
389 CreateFilterCollection(source->GetDemuxer(), NULL),
390 base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)),
391 base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)),
392 QuitOnStatusCB(PIPELINE_OK),
393 base::Bind(&PipelineIntegrationTest::OnBufferingState,
394 base::Unretained(this)),
395 base::Closure());
397 message_loop_.Run();
400 void StartHashedPipelineWithMediaSource(MockMediaSource* source) {
401 hashing_enabled_ = true;
402 StartPipelineWithMediaSource(source);
405 void StartPipelineWithEncryptedMedia(
406 MockMediaSource* source,
407 FakeEncryptedMedia* encrypted_media) {
408 EXPECT_CALL(*this, OnBufferingState(Pipeline::kHaveMetadata))
409 .Times(AtMost(1));
410 EXPECT_CALL(*this, OnBufferingState(Pipeline::kPrerollCompleted))
411 .Times(AtMost(1));
412 pipeline_->Start(
413 CreateFilterCollection(source->GetDemuxer(),
414 encrypted_media->decryptor()),
415 base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)),
416 base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)),
417 QuitOnStatusCB(PIPELINE_OK),
418 base::Bind(&PipelineIntegrationTest::OnBufferingState,
419 base::Unretained(this)),
420 base::Closure());
422 source->set_need_key_cb(base::Bind(&FakeEncryptedMedia::NeedKey,
423 base::Unretained(encrypted_media)));
425 message_loop_.Run();
428 // Verifies that seeking works properly for ChunkDemuxer when the
429 // seek happens while there is a pending read on the ChunkDemuxer
430 // and no data is available.
431 bool TestSeekDuringRead(const std::string& filename,
432 const std::string& mimetype,
433 int initial_append_size,
434 base::TimeDelta start_seek_time,
435 base::TimeDelta seek_time,
436 int seek_file_position,
437 int seek_append_size) {
438 MockMediaSource source(filename, mimetype, initial_append_size);
439 StartPipelineWithMediaSource(&source);
441 if (pipeline_status_ != PIPELINE_OK)
442 return false;
444 Play();
445 if (!WaitUntilCurrentTimeIsAfter(start_seek_time))
446 return false;
448 source.Seek(seek_time, seek_file_position, seek_append_size);
449 if (!Seek(seek_time))
450 return false;
452 source.EndOfStream();
454 source.Abort();
455 Stop();
456 return true;
460 TEST_F(PipelineIntegrationTest, BasicPlayback) {
461 ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240.webm"), PIPELINE_OK));
463 Play();
465 ASSERT_TRUE(WaitUntilOnEnded());
468 TEST_F(PipelineIntegrationTest, BasicPlaybackHashed) {
469 ASSERT_TRUE(Start(
470 GetTestDataFilePath("bear-320x240.webm"), PIPELINE_OK, kHashed));
472 Play();
474 ASSERT_TRUE(WaitUntilOnEnded());
476 EXPECT_EQ("f0be120a90a811506777c99a2cdf7cc1", GetVideoHash());
477 EXPECT_EQ("-3.59,-2.06,-0.43,2.15,0.77,-0.95,", GetAudioHash());
480 TEST_F(PipelineIntegrationTest, F32PlaybackHashed) {
481 ASSERT_TRUE(
482 Start(GetTestDataFilePath("sfx_f32le.wav"), PIPELINE_OK, kHashed));
483 Play();
484 ASSERT_TRUE(WaitUntilOnEnded());
485 EXPECT_EQ(std::string(kNullVideoHash), GetVideoHash());
486 EXPECT_EQ("3.03,2.86,2.99,3.31,3.57,4.06,", GetAudioHash());
489 TEST_F(PipelineIntegrationTest, BasicPlaybackEncrypted) {
490 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
491 set_need_key_cb(base::Bind(&FakeEncryptedMedia::NeedKey,
492 base::Unretained(&encrypted_media)));
494 ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240-av_enc-av.webm"),
495 encrypted_media.decryptor()));
497 Play();
499 ASSERT_TRUE(WaitUntilOnEnded());
500 Stop();
503 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource) {
504 MockMediaSource source("bear-320x240.webm", kWebM, 219229);
505 StartPipelineWithMediaSource(&source);
506 source.EndOfStream();
508 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
509 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
510 EXPECT_EQ(k320WebMFileDurationMs,
511 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
513 Play();
515 ASSERT_TRUE(WaitUntilOnEnded());
516 source.Abort();
517 Stop();
520 // TODO(fgalligan): Enable after new vp9 files are landed.
521 // http://crbug.com/259116
522 TEST_F(PipelineIntegrationTest,
523 DISABLED_BasicPlayback_MediaSource_VideoOnly_VP9_WebM) {
524 MockMediaSource source("bear-vp9.webm", kWebMVP9, 32393);
525 StartPipelineWithMediaSource(&source);
526 source.EndOfStream();
528 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
529 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
530 EXPECT_EQ(kVP9WebMFileDurationMs,
531 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
533 Play();
535 ASSERT_TRUE(WaitUntilOnEnded());
536 source.Abort();
537 Stop();
540 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_VP8A_WebM) {
541 EXPECT_CALL(*this, OnSetOpaque(false)).Times(AnyNumber());
542 MockMediaSource source("bear-vp8a.webm", kVideoOnlyWebM, kAppendWholeFile);
543 StartPipelineWithMediaSource(&source);
544 source.EndOfStream();
546 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
547 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
548 EXPECT_EQ(kVP8AWebMFileDurationMs,
549 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
551 Play();
553 ASSERT_TRUE(WaitUntilOnEnded());
554 source.Abort();
555 Stop();
558 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_Opus_WebM) {
559 EXPECT_CALL(*this, OnSetOpaque(false)).Times(AnyNumber());
560 MockMediaSource source("bear-opus-end-trimming.webm", kOpusAudioOnlyWebM,
561 kAppendWholeFile);
562 StartPipelineWithMediaSource(&source);
563 source.EndOfStream();
565 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
566 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
567 EXPECT_EQ(kOpusEndTrimmingWebMFileDurationMs,
568 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
569 Play();
571 ASSERT_TRUE(WaitUntilOnEnded());
572 source.Abort();
573 Stop();
576 // Flaky. http://crbug.com/304776
577 TEST_F(PipelineIntegrationTest, DISABLED_MediaSource_Opus_Seeking_WebM) {
578 EXPECT_CALL(*this, OnSetOpaque(false)).Times(AnyNumber());
579 MockMediaSource source("bear-opus-end-trimming.webm", kOpusAudioOnlyWebM,
580 kAppendWholeFile);
581 StartHashedPipelineWithMediaSource(&source);
584 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
585 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
586 EXPECT_EQ(kOpusEndTrimmingWebMFileDurationMs,
587 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
589 base::TimeDelta start_seek_time = base::TimeDelta::FromMilliseconds(1000);
590 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(2000);
592 Play();
593 ASSERT_TRUE(WaitUntilCurrentTimeIsAfter(start_seek_time));
594 source.Seek(seek_time, 0x1D5, 34017);
595 source.EndOfStream();
596 ASSERT_TRUE(Seek(seek_time));
598 ASSERT_TRUE(WaitUntilOnEnded());
600 EXPECT_EQ("0.76,0.20,-0.82,-0.58,-1.29,-0.29,", GetAudioHash());
602 source.Abort();
603 Stop();
606 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_WebM) {
607 MockMediaSource source("bear-320x240-16x9-aspect.webm", kWebM,
608 kAppendWholeFile);
609 StartPipelineWithMediaSource(&source);
611 scoped_refptr<DecoderBuffer> second_file =
612 ReadTestDataFile("bear-640x360.webm");
614 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
615 second_file->data(), second_file->data_size());
617 source.EndOfStream();
619 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
620 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
621 EXPECT_EQ(kAppendTimeMs + k640WebMFileDurationMs,
622 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
624 Play();
626 EXPECT_TRUE(WaitUntilOnEnded());
627 source.Abort();
628 Stop();
631 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_Encrypted_WebM) {
632 MockMediaSource source("bear-320x240-16x9-aspect-av_enc-av.webm", kWebM,
633 kAppendWholeFile);
634 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
635 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
637 scoped_refptr<DecoderBuffer> second_file =
638 ReadTestDataFile("bear-640x360-av_enc-av.webm");
640 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
641 second_file->data(), second_file->data_size());
643 source.EndOfStream();
645 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
646 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
647 EXPECT_EQ(kAppendTimeMs + k640WebMFileDurationMs,
648 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
650 Play();
652 EXPECT_TRUE(WaitUntilOnEnded());
653 source.Abort();
654 Stop();
657 // Config changes from encrypted to clear are not currently supported.
658 TEST_F(PipelineIntegrationTest,
659 MediaSource_ConfigChange_ClearThenEncrypted_WebM) {
660 MockMediaSource source("bear-320x240-16x9-aspect.webm", kWebM,
661 kAppendWholeFile);
662 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
663 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
665 scoped_refptr<DecoderBuffer> second_file =
666 ReadTestDataFile("bear-640x360-av_enc-av.webm");
668 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
669 second_file->data(), second_file->data_size());
671 source.EndOfStream();
673 message_loop_.Run();
674 EXPECT_EQ(PIPELINE_ERROR_DECODE, pipeline_status_);
676 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
677 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
678 // The second video was not added, so its time has not been added.
679 EXPECT_EQ(k320WebMFileDurationMs,
680 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
682 Play();
684 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
685 source.Abort();
688 // Config changes from clear to encrypted are not currently supported.
689 TEST_F(PipelineIntegrationTest,
690 MediaSource_ConfigChange_EncryptedThenClear_WebM) {
691 MockMediaSource source("bear-320x240-16x9-aspect-av_enc-av.webm", kWebM,
692 kAppendWholeFile);
693 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
694 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
696 scoped_refptr<DecoderBuffer> second_file =
697 ReadTestDataFile("bear-640x360.webm");
699 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
700 second_file->data(), second_file->data_size());
702 source.EndOfStream();
704 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
705 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
706 // The second video was not added, so its time has not been added.
707 EXPECT_EQ(k320WebMFileDurationMs,
708 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
710 Play();
712 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
713 source.Abort();
716 #if defined(USE_PROPRIETARY_CODECS)
717 TEST_F(PipelineIntegrationTest, MediaSource_MP3) {
718 MockMediaSource source("sfx.mp3", kMP3, kAppendWholeFile);
719 StartPipelineWithMediaSource(&source);
720 source.EndOfStream();
722 Play();
724 EXPECT_TRUE(WaitUntilOnEnded());
728 TEST_F(PipelineIntegrationTest, MediaSource_MP3_Icecast) {
729 MockMediaSource source("icy_sfx.mp3", kMP3, kAppendWholeFile);
730 StartPipelineWithMediaSource(&source);
731 source.EndOfStream();
733 Play();
735 EXPECT_TRUE(WaitUntilOnEnded());
738 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_MP4) {
739 MockMediaSource source("bear-640x360-av_frag.mp4", kMP4, kAppendWholeFile);
740 StartPipelineWithMediaSource(&source);
742 scoped_refptr<DecoderBuffer> second_file =
743 ReadTestDataFile("bear-1280x720-av_frag.mp4");
745 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
746 second_file->data(), second_file->data_size());
748 source.EndOfStream();
750 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
751 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
752 EXPECT_EQ(kAppendTimeMs + k1280IsoFileDurationMs,
753 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
755 Play();
757 EXPECT_TRUE(WaitUntilOnEnded());
758 source.Abort();
759 Stop();
762 TEST_F(PipelineIntegrationTest,
763 MediaSource_ConfigChange_Encrypted_MP4_CENC_VideoOnly) {
764 MockMediaSource source("bear-640x360-v_frag-cenc.mp4",
765 kMP4Video, kAppendWholeFile);
766 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
767 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
769 scoped_refptr<DecoderBuffer> second_file =
770 ReadTestDataFile("bear-1280x720-v_frag-cenc.mp4");
772 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
773 second_file->data(), second_file->data_size());
775 source.EndOfStream();
777 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
778 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
779 EXPECT_EQ(kAppendTimeMs + k1280IsoFileDurationMs,
780 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
782 Play();
784 EXPECT_TRUE(WaitUntilOnEnded());
785 source.Abort();
786 Stop();
789 // Config changes from clear to encrypted are not currently supported.
790 // TODO(ddorwin): Figure out why this CHECKs in AppendAtTime().
791 TEST_F(PipelineIntegrationTest,
792 DISABLED_MediaSource_ConfigChange_ClearThenEncrypted_MP4_CENC) {
793 MockMediaSource source("bear-640x360-av_frag.mp4", kMP4Video,
794 kAppendWholeFile);
795 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
796 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
798 scoped_refptr<DecoderBuffer> second_file =
799 ReadTestDataFile("bear-1280x720-v_frag-cenc.mp4");
801 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
802 second_file->data(), second_file->data_size());
804 source.EndOfStream();
806 message_loop_.Run();
807 EXPECT_EQ(PIPELINE_ERROR_DECODE, pipeline_status_);
809 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
810 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
811 // The second video was not added, so its time has not been added.
812 EXPECT_EQ(k640IsoFileDurationMs,
813 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
815 Play();
817 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
818 source.Abort();
821 // Config changes from encrypted to clear are not currently supported.
822 TEST_F(PipelineIntegrationTest,
823 MediaSource_ConfigChange_EncryptedThenClear_MP4_CENC) {
824 MockMediaSource source("bear-640x360-v_frag-cenc.mp4",
825 kMP4Video, kAppendWholeFile);
826 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
827 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
829 scoped_refptr<DecoderBuffer> second_file =
830 ReadTestDataFile("bear-1280x720-av_frag.mp4");
832 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
833 second_file->data(), second_file->data_size());
835 source.EndOfStream();
837 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
838 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
839 // The second video was not added, so its time has not been added.
840 EXPECT_EQ(k640IsoCencFileDurationMs,
841 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
843 Play();
845 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
846 source.Abort();
849 // Verify files which change configuration midstream fail gracefully.
850 TEST_F(PipelineIntegrationTest, MidStreamConfigChangesFail) {
851 ASSERT_TRUE(Start(
852 GetTestDataFilePath("midstream_config_change.mp3"), PIPELINE_OK));
853 Play();
854 ASSERT_EQ(WaitUntilEndedOrError(), PIPELINE_ERROR_DECODE);
857 #endif
859 TEST_F(PipelineIntegrationTest, BasicPlayback_16x9AspectRatio) {
860 ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240-16x9-aspect.webm"),
861 PIPELINE_OK));
862 Play();
863 ASSERT_TRUE(WaitUntilOnEnded());
866 TEST_F(PipelineIntegrationTest, EncryptedPlayback_WebM) {
867 MockMediaSource source("bear-320x240-av_enc-av.webm", kWebM, 219816);
868 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
869 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
871 source.EndOfStream();
872 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
874 Play();
876 ASSERT_TRUE(WaitUntilOnEnded());
877 source.Abort();
878 Stop();
881 TEST_F(PipelineIntegrationTest, EncryptedPlayback_ClearStart_WebM) {
882 MockMediaSource source("bear-320x240-av_enc-av_clear-1s.webm",
883 kWebM, kAppendWholeFile);
884 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
885 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
887 source.EndOfStream();
888 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
890 Play();
892 ASSERT_TRUE(WaitUntilOnEnded());
893 source.Abort();
894 Stop();
897 TEST_F(PipelineIntegrationTest, EncryptedPlayback_NoEncryptedFrames_WebM) {
898 MockMediaSource source("bear-320x240-av_enc-av_clear-all.webm",
899 kWebM, kAppendWholeFile);
900 FakeEncryptedMedia encrypted_media(new NoResponseApp());
901 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
903 source.EndOfStream();
904 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
906 Play();
908 ASSERT_TRUE(WaitUntilOnEnded());
909 source.Abort();
910 Stop();
913 #if defined(USE_PROPRIETARY_CODECS)
914 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_VideoOnly) {
915 MockMediaSource source("bear-1280x720-v_frag-cenc.mp4",
916 kMP4Video, kAppendWholeFile);
917 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
918 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
920 source.EndOfStream();
921 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
923 Play();
925 ASSERT_TRUE(WaitUntilOnEnded());
926 source.Abort();
927 Stop();
930 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_AudioOnly) {
931 MockMediaSource source("bear-1280x720-a_frag-cenc.mp4",
932 kMP4Audio, kAppendWholeFile);
933 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
934 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
936 source.EndOfStream();
937 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
939 Play();
941 ASSERT_TRUE(WaitUntilOnEnded());
942 source.Abort();
943 Stop();
946 TEST_F(PipelineIntegrationTest,
947 EncryptedPlayback_NoEncryptedFrames_MP4_CENC_VideoOnly) {
948 MockMediaSource source("bear-1280x720-v_frag-cenc_clear-all.mp4",
949 kMP4Video, kAppendWholeFile);
950 FakeEncryptedMedia encrypted_media(new NoResponseApp());
951 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
953 source.EndOfStream();
954 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
956 Play();
958 ASSERT_TRUE(WaitUntilOnEnded());
959 source.Abort();
960 Stop();
963 TEST_F(PipelineIntegrationTest,
964 EncryptedPlayback_NoEncryptedFrames_MP4_CENC_AudioOnly) {
965 MockMediaSource source("bear-1280x720-a_frag-cenc_clear-all.mp4",
966 kMP4Audio, kAppendWholeFile);
967 FakeEncryptedMedia encrypted_media(new NoResponseApp());
968 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
970 source.EndOfStream();
971 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
973 Play();
975 ASSERT_TRUE(WaitUntilOnEnded());
976 source.Abort();
977 Stop();
980 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_VideoOnly_MP4_AVC3) {
981 MockMediaSource source("bear-1280x720-v_frag-avc3.mp4", kMP4VideoAVC3,
982 kAppendWholeFile);
983 StartPipelineWithMediaSource(&source);
984 source.EndOfStream();
986 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
987 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
988 EXPECT_EQ(k1280IsoAVC3FileDurationMs,
989 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
991 Play();
993 ASSERT_TRUE(WaitUntilOnEnded());
994 source.Abort();
995 Stop();
998 #endif
1000 // TODO(acolwell): Fix flakiness http://crbug.com/117921
1001 TEST_F(PipelineIntegrationTest, DISABLED_SeekWhilePaused) {
1002 ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240.webm"), PIPELINE_OK));
1004 base::TimeDelta duration(pipeline_->GetMediaDuration());
1005 base::TimeDelta start_seek_time(duration / 4);
1006 base::TimeDelta seek_time(duration * 3 / 4);
1008 Play();
1009 ASSERT_TRUE(WaitUntilCurrentTimeIsAfter(start_seek_time));
1010 Pause();
1011 ASSERT_TRUE(Seek(seek_time));
1012 EXPECT_EQ(pipeline_->GetMediaTime(), seek_time);
1013 Play();
1014 ASSERT_TRUE(WaitUntilOnEnded());
1016 // Make sure seeking after reaching the end works as expected.
1017 Pause();
1018 ASSERT_TRUE(Seek(seek_time));
1019 EXPECT_EQ(pipeline_->GetMediaTime(), seek_time);
1020 Play();
1021 ASSERT_TRUE(WaitUntilOnEnded());
1024 // TODO(acolwell): Fix flakiness http://crbug.com/117921
1025 TEST_F(PipelineIntegrationTest, DISABLED_SeekWhilePlaying) {
1026 ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240.webm"), PIPELINE_OK));
1028 base::TimeDelta duration(pipeline_->GetMediaDuration());
1029 base::TimeDelta start_seek_time(duration / 4);
1030 base::TimeDelta seek_time(duration * 3 / 4);
1032 Play();
1033 ASSERT_TRUE(WaitUntilCurrentTimeIsAfter(start_seek_time));
1034 ASSERT_TRUE(Seek(seek_time));
1035 EXPECT_GE(pipeline_->GetMediaTime(), seek_time);
1036 ASSERT_TRUE(WaitUntilOnEnded());
1038 // Make sure seeking after reaching the end works as expected.
1039 ASSERT_TRUE(Seek(seek_time));
1040 EXPECT_GE(pipeline_->GetMediaTime(), seek_time);
1041 ASSERT_TRUE(WaitUntilOnEnded());
1044 // Verify audio decoder & renderer can handle aborted demuxer reads.
1045 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_AudioOnly) {
1046 ASSERT_TRUE(TestSeekDuringRead("bear-320x240-audio-only.webm", kAudioOnlyWebM,
1047 8192,
1048 base::TimeDelta::FromMilliseconds(464),
1049 base::TimeDelta::FromMilliseconds(617),
1050 0x10CA, 19730));
1053 // Verify video decoder & renderer can handle aborted demuxer reads.
1054 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_VideoOnly) {
1055 ASSERT_TRUE(TestSeekDuringRead("bear-320x240-video-only.webm", kVideoOnlyWebM,
1056 32768,
1057 base::TimeDelta::FromMilliseconds(200),
1058 base::TimeDelta::FromMilliseconds(1668),
1059 0x1C896, 65536));
1062 // Verify that Opus audio in WebM containers can be played back.
1063 TEST_F(PipelineIntegrationTest, BasicPlayback_AudioOnly_Opus_WebM) {
1064 ASSERT_TRUE(Start(GetTestDataFilePath("bear-opus-end-trimming.webm"),
1065 PIPELINE_OK));
1066 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1067 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1068 EXPECT_EQ(kOpusEndTrimmingWebMFileDurationMs,
1069 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1070 Play();
1071 ASSERT_TRUE(WaitUntilOnEnded());
1074 // Verify that VP9 video in WebM containers can be played back.
1075 // TODO(fgalligan): Enable after new vp9 files are landed.
1076 // http://crbug.com/259116
1077 TEST_F(PipelineIntegrationTest, DISABLED_BasicPlayback_VideoOnly_VP9_WebM) {
1078 ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp9.webm"),
1079 PIPELINE_OK));
1080 Play();
1081 ASSERT_TRUE(WaitUntilOnEnded());
1084 // Verify that VP9 video and Opus audio in the same WebM container can be played
1085 // back.
1086 // TODO(fgalligan): Enable after new vp9 files are landed.
1087 // http://crbug.com/259116
1088 TEST_F(PipelineIntegrationTest, DISABLED_BasicPlayback_VP9_Opus_WebM) {
1089 ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp9-opus.webm"),
1090 PIPELINE_OK));
1091 Play();
1092 ASSERT_TRUE(WaitUntilOnEnded());
1095 // Verify that VP8 video with alpha channel can be played back.
1096 TEST_F(PipelineIntegrationTest, BasicPlayback_VP8A_WebM) {
1097 EXPECT_CALL(*this, OnSetOpaque(false)).Times(AnyNumber());
1098 ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp8a.webm"),
1099 PIPELINE_OK));
1100 Play();
1101 ASSERT_TRUE(WaitUntilOnEnded());
1102 EXPECT_EQ(last_video_frame_format_, VideoFrame::YV12A);
1105 // Verify that VP8A video with odd width/height can be played back.
1106 TEST_F(PipelineIntegrationTest, BasicPlayback_VP8A_Odd_WebM) {
1107 EXPECT_CALL(*this, OnSetOpaque(false)).Times(AnyNumber());
1108 ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp8a-odd-dimensions.webm"),
1109 PIPELINE_OK));
1110 Play();
1111 ASSERT_TRUE(WaitUntilOnEnded());
1112 EXPECT_EQ(last_video_frame_format_, VideoFrame::YV12A);
1115 // Verify that VP8 video with inband text track can be played back.
1116 TEST_F(PipelineIntegrationTest,
1117 BasicPlayback_VP8_WebVTT_WebM) {
1118 ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp8-webvtt.webm"),
1119 PIPELINE_OK));
1120 Play();
1121 ASSERT_TRUE(WaitUntilOnEnded());
1124 } // namespace media