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"
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/cdm_promise.h"
13 #include "media/base/decoder_buffer.h"
14 #include "media/base/media_keys.h"
15 #include "media/base/media_switches.h"
16 #include "media/base/test_data_util.h"
17 #include "media/cdm/aes_decryptor.h"
18 #include "media/cdm/json_web_key.h"
19 #include "media/filters/chunk_demuxer.h"
22 using testing::AnyNumber;
23 using testing::AtMost;
24 using testing::SaveArg;
28 const char kSourceId[] = "SourceId";
29 const uint8 kInitData[] = { 0x69, 0x6e, 0x69, 0x74 };
31 const char kWebM[] = "video/webm; codecs=\"vp8,vorbis\"";
32 const char kWebMVP9[] = "video/webm; codecs=\"vp9\"";
33 const char kAudioOnlyWebM[] = "video/webm; codecs=\"vorbis\"";
34 const char kOpusAudioOnlyWebM[] = "video/webm; codecs=\"opus\"";
35 const char kVideoOnlyWebM[] = "video/webm; codecs=\"vp8\"";
36 const char kMP4VideoType[] = "video/mp4";
37 const char kMP4AudioType[] = "audio/mp4";
38 #if defined(USE_PROPRIETARY_CODECS)
39 const char kADTS[] = "audio/aac";
40 const char kMP4[] = "video/mp4; codecs=\"avc1.4D4041,mp4a.40.2\"";
41 const char kMP4Video[] = "video/mp4; codecs=\"avc1.4D4041\"";
42 const char kMP4VideoAVC3[] = "video/mp4; codecs=\"avc3.64001f\"";
43 const char kMP4Audio[] = "audio/mp4; codecs=\"mp4a.40.2\"";
44 const char kMP3[] = "audio/mpeg";
45 #endif // defined(USE_PROPRIETARY_CODECS)
47 // Key used to encrypt test files.
48 const uint8 kSecretKey[] = {
49 0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b,
50 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c
53 // The key ID for all encrypted files.
54 const uint8 kKeyId[] = {
55 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
56 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35
59 const int kAppendWholeFile = -1;
61 // Constants for the Media Source config change tests.
62 const int kAppendTimeSec = 1;
63 const int kAppendTimeMs = kAppendTimeSec * 1000;
64 const int k320WebMFileDurationMs = 2736;
65 const int k640WebMFileDurationMs = 2749;
66 const int kOpusEndTrimmingWebMFileDurationMs = 2741;
67 const int kVP9WebMFileDurationMs = 2736;
68 const int kVP8AWebMFileDurationMs = 2733;
70 #if defined(USE_PROPRIETARY_CODECS)
71 const int k640IsoFileDurationMs = 2737;
72 const int k640IsoCencFileDurationMs = 2736;
73 const int k1280IsoFileDurationMs = 2736;
74 const int k1280IsoAVC3FileDurationMs = 2736;
75 #endif // defined(USE_PROPRIETARY_CODECS)
77 // Return a timeline offset for bear-320x240-live.webm.
78 static base::Time kLiveTimelineOffset() {
79 // The file contians the following UTC timeline offset:
80 // 2012-11-10 12:34:56.789123456
81 // Since base::Time only has a resolution of microseconds,
82 // construct a base::Time for 2012-11-10 12:34:56.789123.
83 base::Time::Exploded exploded_time;
84 exploded_time.year = 2012;
85 exploded_time.month = 11;
86 exploded_time.day_of_month = 10;
87 exploded_time.hour = 12;
88 exploded_time.minute = 34;
89 exploded_time.second = 56;
90 exploded_time.millisecond = 789;
91 base::Time timeline_offset = base::Time::FromUTCExploded(exploded_time);
93 timeline_offset += base::TimeDelta::FromMicroseconds(123);
95 return timeline_offset;
98 // FFmpeg only supports time a resolution of seconds so this
99 // helper function truncates a base::Time to seconds resolution.
100 static base::Time TruncateToFFmpegTimeResolution(base::Time t) {
101 base::Time::Exploded exploded_time;
102 t.UTCExplode(&exploded_time);
103 exploded_time.millisecond = 0;
105 return base::Time::FromUTCExploded(exploded_time);
108 // Note: Tests using this class only exercise the DecryptingDemuxerStream path.
109 // They do not exercise the Decrypting{Audio|Video}Decoder path.
110 class FakeEncryptedMedia {
112 // Defines the behavior of the "app" that responds to EME events.
115 virtual ~AppBase() {}
117 virtual void OnSessionMessage(const std::string& web_session_id,
118 const std::vector<uint8>& message,
119 const GURL& destination_url) = 0;
121 virtual void OnSessionReady(const std::string& web_session_id) = 0;
123 virtual void OnSessionClosed(const std::string& web_session_id) = 0;
125 // Errors are not expected unless overridden.
126 virtual void OnSessionError(const std::string& web_session_id,
127 const std::string& error_name,
129 const std::string& error_message) {
130 FAIL() << "Unexpected Key Error";
133 virtual void NeedKey(const std::string& type,
134 const std::vector<uint8>& init_data,
135 AesDecryptor* decryptor) = 0;
138 FakeEncryptedMedia(AppBase* app)
139 : decryptor_(base::Bind(&FakeEncryptedMedia::OnSessionMessage,
140 base::Unretained(this)),
141 base::Bind(&FakeEncryptedMedia::OnSessionClosed,
142 base::Unretained(this))),
145 AesDecryptor* decryptor() {
149 // Callbacks for firing session events. Delegate to |app_|.
150 void OnSessionMessage(const std::string& web_session_id,
151 const std::vector<uint8>& message,
152 const GURL& destination_url) {
153 app_->OnSessionMessage(web_session_id, message, destination_url);
156 void OnSessionReady(const std::string& web_session_id) {
157 app_->OnSessionReady(web_session_id);
160 void OnSessionClosed(const std::string& web_session_id) {
161 app_->OnSessionClosed(web_session_id);
164 void OnSessionError(const std::string& web_session_id,
165 const std::string& error_name,
167 const std::string& error_message) {
168 app_->OnSessionError(
169 web_session_id, error_name, system_code, error_message);
172 void NeedKey(const std::string& type,
173 const std::vector<uint8>& init_data) {
174 app_->NeedKey(type, init_data, &decryptor_);
178 AesDecryptor decryptor_;
179 scoped_ptr<AppBase> app_;
182 enum PromiseResult { RESOLVED, REJECTED };
184 // Provides |kSecretKey| in response to needkey.
185 class KeyProvidingApp : public FakeEncryptedMedia::AppBase {
189 void OnResolveWithSession(PromiseResult expected,
190 const std::string& web_session_id) {
191 EXPECT_EQ(expected, RESOLVED);
192 EXPECT_GT(web_session_id.length(), 0ul);
193 current_session_id_ = web_session_id;
196 void OnResolve(PromiseResult expected) {
197 EXPECT_EQ(expected, RESOLVED);
200 void OnReject(PromiseResult expected,
201 media::MediaKeys::Exception exception_code,
203 const std::string& error_message) {
204 EXPECT_EQ(expected, REJECTED);
207 scoped_ptr<SimpleCdmPromise> CreatePromise(PromiseResult expected) {
208 scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise(
210 &KeyProvidingApp::OnResolve, base::Unretained(this), expected),
212 &KeyProvidingApp::OnReject, base::Unretained(this), expected)));
213 return promise.Pass();
216 scoped_ptr<NewSessionCdmPromise> CreateSessionPromise(
217 PromiseResult expected) {
218 scoped_ptr<media::NewSessionCdmPromise> promise(
219 new media::NewSessionCdmPromise(
220 base::Bind(&KeyProvidingApp::OnResolveWithSession,
221 base::Unretained(this),
224 &KeyProvidingApp::OnReject, base::Unretained(this), expected)));
225 return promise.Pass();
228 virtual void OnSessionMessage(const std::string& web_session_id,
229 const std::vector<uint8>& message,
230 const GURL& destination_url) OVERRIDE {
231 EXPECT_FALSE(web_session_id.empty());
232 EXPECT_FALSE(message.empty());
233 EXPECT_EQ(current_session_id_, web_session_id);
236 virtual void OnSessionReady(const std::string& web_session_id) OVERRIDE {
237 EXPECT_EQ(current_session_id_, web_session_id);
240 virtual void OnSessionClosed(const std::string& web_session_id) OVERRIDE {
241 EXPECT_EQ(current_session_id_, web_session_id);
244 virtual void NeedKey(const std::string& type,
245 const std::vector<uint8>& init_data,
246 AesDecryptor* decryptor) OVERRIDE {
247 if (current_session_id_.empty()) {
248 decryptor->CreateSession(type,
250 arraysize(kInitData),
251 MediaKeys::TEMPORARY_SESSION,
252 CreateSessionPromise(RESOLVED));
253 EXPECT_FALSE(current_session_id_.empty());
256 // Clear Key really needs the key ID in |init_data|. For WebM, they are the
257 // same, but this is not the case for ISO CENC. Therefore, provide the
259 const uint8* key_id = init_data.empty() ? NULL : &init_data[0];
260 size_t key_id_length = init_data.size();
261 if (type == kMP4AudioType || type == kMP4VideoType) {
263 key_id_length = arraysize(kKeyId);
266 // Convert key into a JSON structure and then add it.
267 std::string jwk = GenerateJWKSet(
268 kSecretKey, arraysize(kSecretKey), key_id, key_id_length);
269 decryptor->UpdateSession(current_session_id_,
270 reinterpret_cast<const uint8*>(jwk.data()),
272 CreatePromise(RESOLVED));
275 std::string current_session_id_;
278 class RotatingKeyProvidingApp : public KeyProvidingApp {
280 RotatingKeyProvidingApp() : num_distint_need_key_calls_(0) {}
281 virtual ~RotatingKeyProvidingApp() {
282 // Expect that NeedKey is fired multiple times with different |init_data|.
283 EXPECT_GT(num_distint_need_key_calls_, 1u);
286 virtual void NeedKey(const std::string& type,
287 const std::vector<uint8>& init_data,
288 AesDecryptor* decryptor) OVERRIDE {
289 // Skip the request if the |init_data| has been seen.
290 if (init_data == prev_init_data_)
292 prev_init_data_ = init_data;
293 ++num_distint_need_key_calls_;
295 decryptor->CreateSession(type,
296 vector_as_array(&init_data),
298 MediaKeys::TEMPORARY_SESSION,
299 CreateSessionPromise(RESOLVED));
301 std::vector<uint8> key_id;
302 std::vector<uint8> key;
303 EXPECT_TRUE(GetKeyAndKeyId(init_data, &key, &key_id));
305 // Convert key into a JSON structure and then add it.
306 std::string jwk = GenerateJWKSet(vector_as_array(&key),
308 vector_as_array(&key_id),
310 decryptor->UpdateSession(current_session_id_,
311 reinterpret_cast<const uint8*>(jwk.data()),
313 CreatePromise(RESOLVED));
317 bool GetKeyAndKeyId(std::vector<uint8> init_data,
318 std::vector<uint8>* key,
319 std::vector<uint8>* key_id) {
320 // For WebM, init_data is key_id; for ISO CENC, init_data should contain
321 // the key_id. We assume key_id is in the end of init_data here (that is
322 // only a reasonable assumption for WebM and clear key ISO CENC).
323 DCHECK_GE(init_data.size(), arraysize(kKeyId));
324 std::vector<uint8> key_id_from_init_data(
325 init_data.end() - arraysize(kKeyId), init_data.end());
327 key->assign(kSecretKey, kSecretKey + arraysize(kSecretKey));
328 key_id->assign(kKeyId, kKeyId + arraysize(kKeyId));
330 // The Key and KeyId for this testing key provider are created by left
331 // rotating kSecretKey and kKeyId. Note that this implementation is only
332 // intended for testing purpose. The actual key rotation algorithm can be
333 // much more complicated.
334 // Find out the rotating position from |key_id_from_init_data| and apply on
336 for (size_t pos = 0; pos < arraysize(kKeyId); ++pos) {
337 std::rotate(key_id->begin(), key_id->begin() + pos, key_id->end());
338 if (*key_id == key_id_from_init_data) {
339 std::rotate(key->begin(), key->begin() + pos, key->end());
346 std::vector<uint8> prev_init_data_;
347 uint32 num_distint_need_key_calls_;
350 // Ignores needkey and does not perform a license request
351 class NoResponseApp : public FakeEncryptedMedia::AppBase {
353 virtual void OnSessionMessage(const std::string& web_session_id,
354 const std::vector<uint8>& message,
355 const GURL& default_url) OVERRIDE {
356 EXPECT_FALSE(web_session_id.empty());
357 EXPECT_FALSE(message.empty());
358 FAIL() << "Unexpected Message";
361 virtual void OnSessionReady(const std::string& web_session_id) OVERRIDE {
362 EXPECT_FALSE(web_session_id.empty());
363 FAIL() << "Unexpected Ready";
366 virtual void OnSessionClosed(const std::string& web_session_id) OVERRIDE {
367 EXPECT_FALSE(web_session_id.empty());
368 FAIL() << "Unexpected Closed";
371 virtual void NeedKey(const std::string& type,
372 const std::vector<uint8>& init_data,
373 AesDecryptor* decryptor) OVERRIDE {
377 // Helper class that emulates calls made on the ChunkDemuxer by the
379 class MockMediaSource {
381 MockMediaSource(const std::string& filename,
382 const std::string& mimetype,
383 int initial_append_size)
384 : file_path_(GetTestDataFilePath(filename)),
385 current_position_(0),
386 initial_append_size_(initial_append_size),
388 chunk_demuxer_(new ChunkDemuxer(
389 base::Bind(&MockMediaSource::DemuxerOpened, base::Unretained(this)),
390 base::Bind(&MockMediaSource::DemuxerNeedKey,
391 base::Unretained(this)),
394 owned_chunk_demuxer_(chunk_demuxer_) {
396 file_data_ = ReadTestDataFile(filename);
398 if (initial_append_size_ == kAppendWholeFile)
399 initial_append_size_ = file_data_->data_size();
401 DCHECK_GT(initial_append_size_, 0);
402 DCHECK_LE(initial_append_size_, file_data_->data_size());
405 virtual ~MockMediaSource() {}
407 scoped_ptr<Demuxer> GetDemuxer() { return owned_chunk_demuxer_.Pass(); }
409 void set_need_key_cb(const Demuxer::NeedKeyCB& need_key_cb) {
410 need_key_cb_ = need_key_cb;
413 void Seek(base::TimeDelta seek_time, int new_position, int seek_append_size) {
414 chunk_demuxer_->StartWaitingForSeek(seek_time);
416 chunk_demuxer_->Abort(
418 base::TimeDelta(), kInfiniteDuration(), &last_timestamp_offset_);
420 DCHECK_GE(new_position, 0);
421 DCHECK_LT(new_position, file_data_->data_size());
422 current_position_ = new_position;
424 AppendData(seek_append_size);
427 void AppendData(int size) {
428 DCHECK(chunk_demuxer_);
429 DCHECK_LT(current_position_, file_data_->data_size());
430 DCHECK_LE(current_position_ + size, file_data_->data_size());
432 chunk_demuxer_->AppendData(
433 kSourceId, file_data_->data() + current_position_, size,
434 base::TimeDelta(), kInfiniteDuration(), &last_timestamp_offset_);
435 current_position_ += size;
438 void AppendAtTime(base::TimeDelta timestamp_offset,
441 CHECK(!chunk_demuxer_->IsParsingMediaSegment(kSourceId));
442 chunk_demuxer_->AppendData(kSourceId, pData, size,
443 base::TimeDelta(), kInfiniteDuration(),
445 last_timestamp_offset_ = timestamp_offset;
448 void AppendAtTimeWithWindow(base::TimeDelta timestamp_offset,
449 base::TimeDelta append_window_start,
450 base::TimeDelta append_window_end,
453 CHECK(!chunk_demuxer_->IsParsingMediaSegment(kSourceId));
454 chunk_demuxer_->AppendData(kSourceId,
460 last_timestamp_offset_ = timestamp_offset;
464 chunk_demuxer_->MarkEndOfStream(PIPELINE_OK);
470 chunk_demuxer_->Shutdown();
471 chunk_demuxer_ = NULL;
474 void DemuxerOpened() {
475 base::MessageLoop::current()->PostTask(
476 FROM_HERE, base::Bind(&MockMediaSource::DemuxerOpenedTask,
477 base::Unretained(this)));
480 void DemuxerOpenedTask() {
481 // This code assumes that |mimetype_| is one of the following forms.
483 // 2. video/webm;codec="vorbis,vp8".
484 size_t semicolon = mimetype_.find(";");
485 std::string type = mimetype_;
486 std::vector<std::string> codecs;
487 if (semicolon != std::string::npos) {
488 type = mimetype_.substr(0, semicolon);
489 size_t codecs_param_start = mimetype_.find("codecs=\"", semicolon);
491 CHECK_NE(codecs_param_start, std::string::npos);
493 codecs_param_start += 8; // Skip over the codecs=".
495 size_t codecs_param_end = mimetype_.find("\"", codecs_param_start);
497 CHECK_NE(codecs_param_end, std::string::npos);
499 std::string codecs_param =
500 mimetype_.substr(codecs_param_start,
501 codecs_param_end - codecs_param_start);
502 Tokenize(codecs_param, ",", &codecs);
505 CHECK_EQ(chunk_demuxer_->AddId(kSourceId, type, codecs), ChunkDemuxer::kOk);
507 AppendData(initial_append_size_);
510 void DemuxerNeedKey(const std::string& type,
511 const std::vector<uint8>& init_data) {
512 DCHECK(!init_data.empty());
513 CHECK(!need_key_cb_.is_null());
514 need_key_cb_.Run(type, init_data);
517 base::TimeDelta last_timestamp_offset() const {
518 return last_timestamp_offset_;
522 base::FilePath file_path_;
523 scoped_refptr<DecoderBuffer> file_data_;
524 int current_position_;
525 int initial_append_size_;
526 std::string mimetype_;
527 ChunkDemuxer* chunk_demuxer_;
528 scoped_ptr<Demuxer> owned_chunk_demuxer_;
529 Demuxer::NeedKeyCB need_key_cb_;
530 base::TimeDelta last_timestamp_offset_;
533 class PipelineIntegrationTest
534 : public testing::Test,
535 public PipelineIntegrationTestBase {
537 void StartPipelineWithMediaSource(MockMediaSource* source) {
538 EXPECT_CALL(*this, OnMetadata(_))
540 .WillRepeatedly(SaveArg<0>(&metadata_));
541 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH))
544 CreateFilterCollection(source->GetDemuxer(), NULL),
545 base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)),
546 base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)),
547 QuitOnStatusCB(PIPELINE_OK),
548 base::Bind(&PipelineIntegrationTest::OnMetadata,
549 base::Unretained(this)),
550 base::Bind(&PipelineIntegrationTest::OnBufferingStateChanged,
551 base::Unretained(this)),
557 void StartHashedPipelineWithMediaSource(MockMediaSource* source) {
558 hashing_enabled_ = true;
559 StartPipelineWithMediaSource(source);
562 void StartPipelineWithEncryptedMedia(
563 MockMediaSource* source,
564 FakeEncryptedMedia* encrypted_media) {
565 EXPECT_CALL(*this, OnMetadata(_))
567 .WillRepeatedly(SaveArg<0>(&metadata_));
568 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH))
571 CreateFilterCollection(source->GetDemuxer(),
572 encrypted_media->decryptor()),
573 base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)),
574 base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)),
575 QuitOnStatusCB(PIPELINE_OK),
576 base::Bind(&PipelineIntegrationTest::OnMetadata,
577 base::Unretained(this)),
578 base::Bind(&PipelineIntegrationTest::OnBufferingStateChanged,
579 base::Unretained(this)),
582 source->set_need_key_cb(base::Bind(&FakeEncryptedMedia::NeedKey,
583 base::Unretained(encrypted_media)));
588 // Verifies that seeking works properly for ChunkDemuxer when the
589 // seek happens while there is a pending read on the ChunkDemuxer
590 // and no data is available.
591 bool TestSeekDuringRead(const std::string& filename,
592 const std::string& mimetype,
593 int initial_append_size,
594 base::TimeDelta start_seek_time,
595 base::TimeDelta seek_time,
596 int seek_file_position,
597 int seek_append_size) {
598 MockMediaSource source(filename, mimetype, initial_append_size);
599 StartPipelineWithMediaSource(&source);
601 if (pipeline_status_ != PIPELINE_OK)
605 if (!WaitUntilCurrentTimeIsAfter(start_seek_time))
608 source.Seek(seek_time, seek_file_position, seek_append_size);
609 if (!Seek(seek_time))
612 source.EndOfStream();
620 TEST_F(PipelineIntegrationTest, BasicPlayback) {
621 ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240.webm"), PIPELINE_OK));
625 ASSERT_TRUE(WaitUntilOnEnded());
628 TEST_F(PipelineIntegrationTest, BasicPlaybackOpusOgg) {
629 ASSERT_TRUE(Start(GetTestDataFilePath("bear-opus.ogg"), PIPELINE_OK));
633 ASSERT_TRUE(WaitUntilOnEnded());
636 TEST_F(PipelineIntegrationTest, BasicPlaybackHashed) {
638 GetTestDataFilePath("bear-320x240.webm"), PIPELINE_OK, kHashed));
642 ASSERT_TRUE(WaitUntilOnEnded());
644 EXPECT_EQ("f0be120a90a811506777c99a2cdf7cc1", GetVideoHash());
645 EXPECT_EQ("-3.59,-2.06,-0.43,2.15,0.77,-0.95,", GetAudioHash());
646 EXPECT_TRUE(demuxer_->GetTimelineOffset().is_null());
649 TEST_F(PipelineIntegrationTest, BasicPlaybackLive) {
651 GetTestDataFilePath("bear-320x240-live.webm"), PIPELINE_OK, kHashed));
655 ASSERT_TRUE(WaitUntilOnEnded());
657 EXPECT_EQ("f0be120a90a811506777c99a2cdf7cc1", GetVideoHash());
658 EXPECT_EQ("-3.59,-2.06,-0.43,2.15,0.77,-0.95,", GetAudioHash());
660 // TODO: Fix FFmpeg code to return higher resolution time values so
661 // we don't have to truncate our expectations here.
662 EXPECT_EQ(TruncateToFFmpegTimeResolution(kLiveTimelineOffset()),
663 demuxer_->GetTimelineOffset());
666 TEST_F(PipelineIntegrationTest, F32PlaybackHashed) {
668 Start(GetTestDataFilePath("sfx_f32le.wav"), PIPELINE_OK, kHashed));
670 ASSERT_TRUE(WaitUntilOnEnded());
671 EXPECT_EQ(std::string(kNullVideoHash), GetVideoHash());
672 EXPECT_EQ("3.03,2.86,2.99,3.31,3.57,4.06,", GetAudioHash());
675 TEST_F(PipelineIntegrationTest, BasicPlaybackEncrypted) {
676 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
677 set_need_key_cb(base::Bind(&FakeEncryptedMedia::NeedKey,
678 base::Unretained(&encrypted_media)));
680 ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240-av_enc-av.webm"),
681 encrypted_media.decryptor()));
685 ASSERT_TRUE(WaitUntilOnEnded());
689 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource) {
690 MockMediaSource source("bear-320x240.webm", kWebM, 219229);
691 StartPipelineWithMediaSource(&source);
692 source.EndOfStream();
694 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
695 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
696 EXPECT_EQ(k320WebMFileDurationMs,
697 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
701 ASSERT_TRUE(WaitUntilOnEnded());
703 EXPECT_TRUE(demuxer_->GetTimelineOffset().is_null());
708 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_Live) {
709 MockMediaSource source("bear-320x240-live.webm", kWebM, 219221);
710 StartPipelineWithMediaSource(&source);
711 source.EndOfStream();
713 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
714 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
715 EXPECT_EQ(k320WebMFileDurationMs,
716 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
720 ASSERT_TRUE(WaitUntilOnEnded());
722 EXPECT_EQ(kLiveTimelineOffset(),
723 demuxer_->GetTimelineOffset());
728 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_VP9_WebM) {
729 MockMediaSource source("bear-vp9.webm", kWebMVP9, 67504);
730 StartPipelineWithMediaSource(&source);
731 source.EndOfStream();
733 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
734 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
735 EXPECT_EQ(kVP9WebMFileDurationMs,
736 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
740 ASSERT_TRUE(WaitUntilOnEnded());
745 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_VP8A_WebM) {
746 MockMediaSource source("bear-vp8a.webm", kVideoOnlyWebM, kAppendWholeFile);
747 StartPipelineWithMediaSource(&source);
748 source.EndOfStream();
750 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
751 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
752 EXPECT_EQ(kVP8AWebMFileDurationMs,
753 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
757 ASSERT_TRUE(WaitUntilOnEnded());
762 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_Opus_WebM) {
763 MockMediaSource source("bear-opus-end-trimming.webm", kOpusAudioOnlyWebM,
765 StartPipelineWithMediaSource(&source);
766 source.EndOfStream();
768 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
769 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
770 EXPECT_EQ(kOpusEndTrimmingWebMFileDurationMs,
771 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
774 ASSERT_TRUE(WaitUntilOnEnded());
779 // Flaky. http://crbug.com/304776
780 TEST_F(PipelineIntegrationTest, DISABLED_MediaSource_Opus_Seeking_WebM) {
781 MockMediaSource source("bear-opus-end-trimming.webm", kOpusAudioOnlyWebM,
783 StartHashedPipelineWithMediaSource(&source);
785 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
786 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
787 EXPECT_EQ(kOpusEndTrimmingWebMFileDurationMs,
788 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
790 base::TimeDelta start_seek_time = base::TimeDelta::FromMilliseconds(1000);
791 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(2000);
794 ASSERT_TRUE(WaitUntilCurrentTimeIsAfter(start_seek_time));
795 source.Seek(seek_time, 0x1D5, 34017);
796 source.EndOfStream();
797 ASSERT_TRUE(Seek(seek_time));
799 ASSERT_TRUE(WaitUntilOnEnded());
801 EXPECT_EQ("0.76,0.20,-0.82,-0.58,-1.29,-0.29,", GetAudioHash());
807 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_WebM) {
808 MockMediaSource source("bear-320x240-16x9-aspect.webm", kWebM,
810 StartPipelineWithMediaSource(&source);
812 scoped_refptr<DecoderBuffer> second_file =
813 ReadTestDataFile("bear-640x360.webm");
815 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
816 second_file->data(), second_file->data_size());
818 source.EndOfStream();
820 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
821 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
822 EXPECT_EQ(kAppendTimeMs + k640WebMFileDurationMs,
823 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
827 EXPECT_TRUE(WaitUntilOnEnded());
832 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_Encrypted_WebM) {
833 MockMediaSource source("bear-320x240-16x9-aspect-av_enc-av.webm", kWebM,
835 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
836 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
838 scoped_refptr<DecoderBuffer> second_file =
839 ReadTestDataFile("bear-640x360-av_enc-av.webm");
841 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
842 second_file->data(), second_file->data_size());
844 source.EndOfStream();
846 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
847 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
848 EXPECT_EQ(kAppendTimeMs + k640WebMFileDurationMs,
849 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
853 EXPECT_TRUE(WaitUntilOnEnded());
858 // Config changes from encrypted to clear are not currently supported.
859 TEST_F(PipelineIntegrationTest,
860 MediaSource_ConfigChange_ClearThenEncrypted_WebM) {
861 MockMediaSource source("bear-320x240-16x9-aspect.webm", kWebM,
863 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
864 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
866 scoped_refptr<DecoderBuffer> second_file =
867 ReadTestDataFile("bear-640x360-av_enc-av.webm");
869 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
870 second_file->data(), second_file->data_size());
872 source.EndOfStream();
875 EXPECT_EQ(PIPELINE_ERROR_DECODE, pipeline_status_);
877 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
878 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
879 // The second video was not added, so its time has not been added.
880 EXPECT_EQ(k320WebMFileDurationMs,
881 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
885 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
889 // Config changes from clear to encrypted are not currently supported.
890 TEST_F(PipelineIntegrationTest,
891 MediaSource_ConfigChange_EncryptedThenClear_WebM) {
892 MockMediaSource source("bear-320x240-16x9-aspect-av_enc-av.webm", kWebM,
894 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
895 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
897 scoped_refptr<DecoderBuffer> second_file =
898 ReadTestDataFile("bear-640x360.webm");
900 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
901 second_file->data(), second_file->data_size());
903 source.EndOfStream();
905 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
906 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
907 // The second video was not added, so its time has not been added.
908 EXPECT_EQ(k320WebMFileDurationMs,
909 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
913 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
917 #if defined(USE_PROPRIETARY_CODECS)
918 TEST_F(PipelineIntegrationTest, MediaSource_ADTS) {
919 MockMediaSource source("sfx.adts", kADTS, kAppendWholeFile);
920 StartPipelineWithMediaSource(&source);
921 source.EndOfStream();
923 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
924 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
925 EXPECT_EQ(325, pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
929 EXPECT_TRUE(WaitUntilOnEnded());
932 TEST_F(PipelineIntegrationTest, MediaSource_ADTS_TimestampOffset) {
933 MockMediaSource source("sfx.adts", kADTS, kAppendWholeFile);
934 StartHashedPipelineWithMediaSource(&source);
935 EXPECT_EQ(325, source.last_timestamp_offset().InMilliseconds());
937 // Trim off multiple frames off the beginning of the segment which will cause
938 // the first decoded frame to be incorrect if preroll isn't implemented.
939 const base::TimeDelta adts_preroll_duration =
940 base::TimeDelta::FromSecondsD(2.5 * 1024 / 44100);
941 const base::TimeDelta append_time =
942 source.last_timestamp_offset() - adts_preroll_duration;
944 scoped_refptr<DecoderBuffer> second_file = ReadTestDataFile("sfx.adts");
945 source.AppendAtTimeWithWindow(append_time,
946 append_time + adts_preroll_duration,
949 second_file->data_size());
950 source.EndOfStream();
952 EXPECT_EQ(592, source.last_timestamp_offset().InMilliseconds());
953 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
954 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
955 EXPECT_EQ(592, pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
959 EXPECT_TRUE(WaitUntilOnEnded());
961 // Verify preroll is stripped.
962 EXPECT_EQ("-0.06,0.97,-0.90,-0.70,-0.53,-0.34,", GetAudioHash());
965 TEST_F(PipelineIntegrationTest, BasicPlaybackHashed_MP3) {
966 ASSERT_TRUE(Start(GetTestDataFilePath("sfx.mp3"), PIPELINE_OK, kHashed));
970 ASSERT_TRUE(WaitUntilOnEnded());
972 // Verify codec delay and preroll are stripped.
973 EXPECT_EQ("3.05,2.87,3.00,3.32,3.58,4.08,", GetAudioHash());
976 TEST_F(PipelineIntegrationTest, MediaSource_MP3) {
977 MockMediaSource source("sfx.mp3", kMP3, kAppendWholeFile);
978 StartHashedPipelineWithMediaSource(&source);
979 source.EndOfStream();
981 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
982 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
983 EXPECT_EQ(313, pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
987 EXPECT_TRUE(WaitUntilOnEnded());
989 // Verify that codec delay was stripped.
990 EXPECT_EQ("1.01,2.71,4.18,4.32,3.04,1.12,", GetAudioHash());
993 TEST_F(PipelineIntegrationTest, MediaSource_MP3_TimestampOffset) {
994 MockMediaSource source("sfx.mp3", kMP3, kAppendWholeFile);
995 StartPipelineWithMediaSource(&source);
996 EXPECT_EQ(313, source.last_timestamp_offset().InMilliseconds());
998 // There are 576 silent frames at the start of this mp3. The second append
999 // should trim them off.
1000 const base::TimeDelta mp3_preroll_duration =
1001 base::TimeDelta::FromSecondsD(576.0 / 44100);
1002 const base::TimeDelta append_time =
1003 source.last_timestamp_offset() - mp3_preroll_duration;
1005 scoped_refptr<DecoderBuffer> second_file = ReadTestDataFile("sfx.mp3");
1006 source.AppendAtTimeWithWindow(append_time,
1007 append_time + mp3_preroll_duration,
1008 kInfiniteDuration(),
1009 second_file->data(),
1010 second_file->data_size());
1011 source.EndOfStream();
1013 EXPECT_EQ(613, source.last_timestamp_offset().InMilliseconds());
1014 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1015 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1016 EXPECT_EQ(613, pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1020 EXPECT_TRUE(WaitUntilOnEnded());
1023 TEST_F(PipelineIntegrationTest, MediaSource_MP3_Icecast) {
1024 MockMediaSource source("icy_sfx.mp3", kMP3, kAppendWholeFile);
1025 StartPipelineWithMediaSource(&source);
1026 source.EndOfStream();
1030 EXPECT_TRUE(WaitUntilOnEnded());
1033 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_MP4) {
1034 MockMediaSource source("bear-640x360-av_frag.mp4", kMP4, kAppendWholeFile);
1035 StartPipelineWithMediaSource(&source);
1037 scoped_refptr<DecoderBuffer> second_file =
1038 ReadTestDataFile("bear-1280x720-av_frag.mp4");
1040 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1041 second_file->data(), second_file->data_size());
1043 source.EndOfStream();
1045 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1046 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1047 EXPECT_EQ(kAppendTimeMs + k1280IsoFileDurationMs,
1048 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1052 EXPECT_TRUE(WaitUntilOnEnded());
1057 TEST_F(PipelineIntegrationTest,
1058 MediaSource_ConfigChange_Encrypted_MP4_CENC_VideoOnly) {
1059 MockMediaSource source("bear-640x360-v_frag-cenc.mp4", kMP4Video,
1061 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1062 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1064 scoped_refptr<DecoderBuffer> second_file =
1065 ReadTestDataFile("bear-1280x720-v_frag-cenc.mp4");
1067 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1068 second_file->data(), second_file->data_size());
1070 source.EndOfStream();
1072 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1073 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1074 EXPECT_EQ(kAppendTimeMs + k1280IsoFileDurationMs,
1075 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1079 EXPECT_TRUE(WaitUntilOnEnded());
1084 TEST_F(PipelineIntegrationTest,
1085 MediaSource_ConfigChange_Encrypted_MP4_CENC_KeyRotation_VideoOnly) {
1086 MockMediaSource source("bear-640x360-v_frag-cenc-key_rotation.mp4", kMP4Video,
1088 FakeEncryptedMedia encrypted_media(new RotatingKeyProvidingApp());
1089 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1091 scoped_refptr<DecoderBuffer> second_file =
1092 ReadTestDataFile("bear-1280x720-v_frag-cenc-key_rotation.mp4");
1094 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1095 second_file->data(), second_file->data_size());
1097 source.EndOfStream();
1099 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1100 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1101 EXPECT_EQ(kAppendTimeMs + k1280IsoFileDurationMs,
1102 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1106 EXPECT_TRUE(WaitUntilOnEnded());
1111 // Config changes from clear to encrypted are not currently supported.
1112 // TODO(ddorwin): Figure out why this CHECKs in AppendAtTime().
1113 TEST_F(PipelineIntegrationTest,
1114 DISABLED_MediaSource_ConfigChange_ClearThenEncrypted_MP4_CENC) {
1115 MockMediaSource source("bear-640x360-av_frag.mp4", kMP4Video,
1117 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1118 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1120 scoped_refptr<DecoderBuffer> second_file =
1121 ReadTestDataFile("bear-1280x720-v_frag-cenc.mp4");
1123 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1124 second_file->data(), second_file->data_size());
1126 source.EndOfStream();
1128 message_loop_.Run();
1129 EXPECT_EQ(PIPELINE_ERROR_DECODE, pipeline_status_);
1131 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1132 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1133 // The second video was not added, so its time has not been added.
1134 EXPECT_EQ(k640IsoFileDurationMs,
1135 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1139 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
1143 // Config changes from encrypted to clear are not currently supported.
1144 TEST_F(PipelineIntegrationTest,
1145 MediaSource_ConfigChange_EncryptedThenClear_MP4_CENC) {
1146 MockMediaSource source("bear-640x360-v_frag-cenc.mp4", kMP4Video,
1148 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1149 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1151 scoped_refptr<DecoderBuffer> second_file =
1152 ReadTestDataFile("bear-1280x720-av_frag.mp4");
1154 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1155 second_file->data(), second_file->data_size());
1157 source.EndOfStream();
1159 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1160 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1161 // The second video was not added, so its time has not been added.
1162 EXPECT_EQ(k640IsoCencFileDurationMs,
1163 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1167 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
1171 // Verify files which change configuration midstream fail gracefully.
1172 TEST_F(PipelineIntegrationTest, MidStreamConfigChangesFail) {
1174 GetTestDataFilePath("midstream_config_change.mp3"), PIPELINE_OK));
1176 ASSERT_EQ(WaitUntilEndedOrError(), PIPELINE_ERROR_DECODE);
1181 TEST_F(PipelineIntegrationTest, BasicPlayback_16x9AspectRatio) {
1182 ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240-16x9-aspect.webm"),
1185 ASSERT_TRUE(WaitUntilOnEnded());
1188 TEST_F(PipelineIntegrationTest, EncryptedPlayback_WebM) {
1189 MockMediaSource source("bear-320x240-av_enc-av.webm", kWebM, 219816);
1190 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1191 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1193 source.EndOfStream();
1194 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1198 ASSERT_TRUE(WaitUntilOnEnded());
1203 TEST_F(PipelineIntegrationTest, EncryptedPlayback_ClearStart_WebM) {
1204 MockMediaSource source("bear-320x240-av_enc-av_clear-1s.webm", kWebM,
1206 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1207 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1209 source.EndOfStream();
1210 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1214 ASSERT_TRUE(WaitUntilOnEnded());
1219 TEST_F(PipelineIntegrationTest, EncryptedPlayback_NoEncryptedFrames_WebM) {
1220 MockMediaSource source("bear-320x240-av_enc-av_clear-all.webm", kWebM,
1222 FakeEncryptedMedia encrypted_media(new NoResponseApp());
1223 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1225 source.EndOfStream();
1226 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1230 ASSERT_TRUE(WaitUntilOnEnded());
1235 #if defined(USE_PROPRIETARY_CODECS)
1236 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_VideoOnly) {
1237 MockMediaSource source("bear-1280x720-v_frag-cenc.mp4", kMP4Video,
1239 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1240 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1242 source.EndOfStream();
1243 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1247 ASSERT_TRUE(WaitUntilOnEnded());
1252 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_AudioOnly) {
1253 MockMediaSource source("bear-1280x720-a_frag-cenc.mp4", kMP4Audio,
1255 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1256 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1258 source.EndOfStream();
1259 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1263 ASSERT_TRUE(WaitUntilOnEnded());
1268 TEST_F(PipelineIntegrationTest,
1269 EncryptedPlayback_NoEncryptedFrames_MP4_CENC_VideoOnly) {
1270 MockMediaSource source("bear-1280x720-v_frag-cenc_clear-all.mp4", kMP4Video,
1272 FakeEncryptedMedia encrypted_media(new NoResponseApp());
1273 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1275 source.EndOfStream();
1276 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1280 ASSERT_TRUE(WaitUntilOnEnded());
1285 TEST_F(PipelineIntegrationTest,
1286 EncryptedPlayback_NoEncryptedFrames_MP4_CENC_AudioOnly) {
1287 MockMediaSource source("bear-1280x720-a_frag-cenc_clear-all.mp4", kMP4Audio,
1289 FakeEncryptedMedia encrypted_media(new NoResponseApp());
1290 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1292 source.EndOfStream();
1293 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1297 ASSERT_TRUE(WaitUntilOnEnded());
1302 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_VideoOnly_MP4_AVC3) {
1303 MockMediaSource source("bear-1280x720-v_frag-avc3.mp4", kMP4VideoAVC3,
1305 StartPipelineWithMediaSource(&source);
1306 source.EndOfStream();
1308 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1309 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1310 EXPECT_EQ(k1280IsoAVC3FileDurationMs,
1311 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1315 ASSERT_TRUE(WaitUntilOnEnded());
1320 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_KeyRotation_Video) {
1321 MockMediaSource source("bear-1280x720-v_frag-cenc-key_rotation.mp4",
1322 kMP4Video, kAppendWholeFile);
1323 FakeEncryptedMedia encrypted_media(new RotatingKeyProvidingApp());
1324 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1326 source.EndOfStream();
1327 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1331 ASSERT_TRUE(WaitUntilOnEnded());
1336 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_KeyRotation_Audio) {
1337 MockMediaSource source("bear-1280x720-a_frag-cenc-key_rotation.mp4",
1338 kMP4Audio, kAppendWholeFile);
1339 FakeEncryptedMedia encrypted_media(new RotatingKeyProvidingApp());
1340 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1342 source.EndOfStream();
1343 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1347 ASSERT_TRUE(WaitUntilOnEnded());
1353 // TODO(acolwell): Fix flakiness http://crbug.com/117921
1354 TEST_F(PipelineIntegrationTest, DISABLED_SeekWhilePaused) {
1355 ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240.webm"), PIPELINE_OK));
1357 base::TimeDelta duration(pipeline_->GetMediaDuration());
1358 base::TimeDelta start_seek_time(duration / 4);
1359 base::TimeDelta seek_time(duration * 3 / 4);
1362 ASSERT_TRUE(WaitUntilCurrentTimeIsAfter(start_seek_time));
1364 ASSERT_TRUE(Seek(seek_time));
1365 EXPECT_EQ(pipeline_->GetMediaTime(), seek_time);
1367 ASSERT_TRUE(WaitUntilOnEnded());
1369 // Make sure seeking after reaching the end works as expected.
1371 ASSERT_TRUE(Seek(seek_time));
1372 EXPECT_EQ(pipeline_->GetMediaTime(), seek_time);
1374 ASSERT_TRUE(WaitUntilOnEnded());
1377 // TODO(acolwell): Fix flakiness http://crbug.com/117921
1378 TEST_F(PipelineIntegrationTest, DISABLED_SeekWhilePlaying) {
1379 ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240.webm"), PIPELINE_OK));
1381 base::TimeDelta duration(pipeline_->GetMediaDuration());
1382 base::TimeDelta start_seek_time(duration / 4);
1383 base::TimeDelta seek_time(duration * 3 / 4);
1386 ASSERT_TRUE(WaitUntilCurrentTimeIsAfter(start_seek_time));
1387 ASSERT_TRUE(Seek(seek_time));
1388 EXPECT_GE(pipeline_->GetMediaTime(), seek_time);
1389 ASSERT_TRUE(WaitUntilOnEnded());
1391 // Make sure seeking after reaching the end works as expected.
1392 ASSERT_TRUE(Seek(seek_time));
1393 EXPECT_GE(pipeline_->GetMediaTime(), seek_time);
1394 ASSERT_TRUE(WaitUntilOnEnded());
1397 #if defined(USE_PROPRIETARY_CODECS)
1398 TEST_F(PipelineIntegrationTest, Rotated_Metadata_0) {
1399 ASSERT_TRUE(Start(GetTestDataFilePath("bear_rotate_0.mp4"), PIPELINE_OK));
1400 ASSERT_EQ(VIDEO_ROTATION_0, metadata_.video_rotation);
1403 TEST_F(PipelineIntegrationTest, Rotated_Metadata_90) {
1404 ASSERT_TRUE(Start(GetTestDataFilePath("bear_rotate_90.mp4"), PIPELINE_OK));
1405 ASSERT_EQ(VIDEO_ROTATION_90, metadata_.video_rotation);
1408 TEST_F(PipelineIntegrationTest, Rotated_Metadata_180) {
1409 ASSERT_TRUE(Start(GetTestDataFilePath("bear_rotate_180.mp4"), PIPELINE_OK));
1410 ASSERT_EQ(VIDEO_ROTATION_180, metadata_.video_rotation);
1413 TEST_F(PipelineIntegrationTest, Rotated_Metadata_270) {
1414 ASSERT_TRUE(Start(GetTestDataFilePath("bear_rotate_270.mp4"), PIPELINE_OK));
1415 ASSERT_EQ(VIDEO_ROTATION_270, metadata_.video_rotation);
1419 // Verify audio decoder & renderer can handle aborted demuxer reads.
1420 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_AudioOnly) {
1421 ASSERT_TRUE(TestSeekDuringRead("bear-320x240-audio-only.webm", kAudioOnlyWebM,
1423 base::TimeDelta::FromMilliseconds(464),
1424 base::TimeDelta::FromMilliseconds(617),
1428 // Verify video decoder & renderer can handle aborted demuxer reads.
1429 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_VideoOnly) {
1430 ASSERT_TRUE(TestSeekDuringRead("bear-320x240-video-only.webm", kVideoOnlyWebM,
1432 base::TimeDelta::FromMilliseconds(167),
1433 base::TimeDelta::FromMilliseconds(1668),
1437 // Verify that Opus audio in WebM containers can be played back.
1438 TEST_F(PipelineIntegrationTest, BasicPlayback_AudioOnly_Opus_WebM) {
1439 ASSERT_TRUE(Start(GetTestDataFilePath("bear-opus-end-trimming.webm"),
1442 ASSERT_TRUE(WaitUntilOnEnded());
1445 // Verify that VP9 video in WebM containers can be played back.
1446 TEST_F(PipelineIntegrationTest, BasicPlayback_VideoOnly_VP9_WebM) {
1447 ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp9.webm"),
1450 ASSERT_TRUE(WaitUntilOnEnded());
1453 // Verify that VP9 video and Opus audio in the same WebM container can be played
1455 TEST_F(PipelineIntegrationTest, BasicPlayback_VP9_Opus_WebM) {
1456 ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp9-opus.webm"),
1459 ASSERT_TRUE(WaitUntilOnEnded());
1462 // Verify that VP8 video with alpha channel can be played back.
1463 TEST_F(PipelineIntegrationTest, BasicPlayback_VP8A_WebM) {
1464 ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp8a.webm"),
1467 ASSERT_TRUE(WaitUntilOnEnded());
1468 EXPECT_EQ(last_video_frame_format_, VideoFrame::YV12A);
1471 // Verify that VP8A video with odd width/height can be played back.
1472 TEST_F(PipelineIntegrationTest, BasicPlayback_VP8A_Odd_WebM) {
1473 ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp8a-odd-dimensions.webm"),
1476 ASSERT_TRUE(WaitUntilOnEnded());
1477 EXPECT_EQ(last_video_frame_format_, VideoFrame::YV12A);
1480 // Verify that VP9 video with odd width/height can be played back.
1481 TEST_F(PipelineIntegrationTest, BasicPlayback_VP9_Odd_WebM) {
1482 ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp9-odd-dimensions.webm"),
1485 ASSERT_TRUE(WaitUntilOnEnded());
1488 // Verify that VP8 video with inband text track can be played back.
1489 TEST_F(PipelineIntegrationTest,
1490 BasicPlayback_VP8_WebVTT_WebM) {
1491 ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp8-webvtt.webm"),
1494 ASSERT_TRUE(WaitUntilOnEnded());
1497 // Verify that VP9 video with 4:4:4 subsampling can be played back.
1498 TEST_F(PipelineIntegrationTest, P444_VP9_WebM) {
1499 ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240-P444.webm"),
1502 ASSERT_TRUE(WaitUntilOnEnded());
1503 EXPECT_EQ(last_video_frame_format_, VideoFrame::YV24);
1506 // Verify that videos with an odd frame size playback successfully.
1507 TEST_F(PipelineIntegrationTest, BasicPlayback_OddVideoSize) {
1508 ASSERT_TRUE(Start(GetTestDataFilePath("butterfly-853x480.webm"),
1511 ASSERT_TRUE(WaitUntilOnEnded());
1514 // Verify that OPUS audio in a webm which reports a 44.1kHz sample rate plays
1515 // correctly at 48kHz
1516 TEST_F(PipelineIntegrationTest, BasicPlayback_Opus441kHz) {
1517 ASSERT_TRUE(Start(GetTestDataFilePath("sfx-opus-441.webm"), PIPELINE_OK));
1519 ASSERT_TRUE(WaitUntilOnEnded());
1521 demuxer_->GetStream(DemuxerStream::AUDIO)
1522 ->audio_decoder_config()
1523 .samples_per_second());
1526 // Same as above but using MediaSource.
1527 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_Opus441kHz) {
1528 MockMediaSource source(
1529 "sfx-opus-441.webm", kOpusAudioOnlyWebM, kAppendWholeFile);
1530 StartPipelineWithMediaSource(&source);
1531 source.EndOfStream();
1533 ASSERT_TRUE(WaitUntilOnEnded());
1537 demuxer_->GetStream(DemuxerStream::AUDIO)
1538 ->audio_decoder_config()
1539 .samples_per_second());
1542 // Ensures audio-only playback with missing or negative timestamps works. Tests
1543 // the common live-streaming case for chained ogg. See http://crbug.com/396864.
1544 TEST_F(PipelineIntegrationTest, BasicPlaybackChainedOgg) {
1545 ASSERT_TRUE(Start(GetTestDataFilePath("double-sfx.ogg"), PIPELINE_OK));
1547 ASSERT_TRUE(WaitUntilOnEnded());
1548 ASSERT_EQ(base::TimeDelta(), demuxer_->GetStartTime());
1551 // Ensures audio-video playback with missing or negative timestamps fails softly
1552 // instead of crashing. See http://crbug.com/396864.
1553 TEST_F(PipelineIntegrationTest, BasicPlaybackChainedOggVideo) {
1554 ASSERT_TRUE(Start(GetTestDataFilePath("double-bear.ogv"), PIPELINE_OK));
1556 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
1557 ASSERT_EQ(base::TimeDelta(), demuxer_->GetStartTime());
1560 TEST_F(PipelineIntegrationTest, BasicPlaybackPositiveStartTime) {
1562 Start(GetTestDataFilePath("nonzero-start-time.webm"), PIPELINE_OK));
1564 ASSERT_TRUE(WaitUntilOnEnded());
1565 ASSERT_EQ(base::TimeDelta::FromMicroseconds(396000),
1566 demuxer_->GetStartTime());
1569 } // namespace media