gn: 'platform_impl' should be a group instead of component (since it has no code...
[chromium-blink-merge.git] / media / test / pipeline_integration_test.cc
blob1e8911920da0be035fa3ffbdbda7756251487487
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 "base/bind.h"
6 #include "base/command_line.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/stl_util.h"
9 #include "base/strings/string_util.h"
10 #include "build/build_config.h"
11 #include "media/base/cdm_callback_promise.h"
12 #include "media/base/cdm_context.h"
13 #include "media/base/cdm_key_information.h"
14 #include "media/base/decoder_buffer.h"
15 #include "media/base/media.h"
16 #include "media/base/media_keys.h"
17 #include "media/base/media_switches.h"
18 #include "media/base/test_data_util.h"
19 #include "media/cdm/aes_decryptor.h"
20 #include "media/cdm/json_web_key.h"
21 #include "media/filters/chunk_demuxer.h"
22 #include "media/renderers/renderer_impl.h"
23 #include "media/test/pipeline_integration_test_base.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "url/gurl.h"
27 #if defined(MOJO_RENDERER)
28 #include "media/mojo/services/mojo_renderer_impl.h"
29 #include "mojo/application/public/cpp/application_impl.h"
30 #include "mojo/application/public/cpp/application_test_base.h"
31 #include "mojo/application/public/cpp/connect.h"
33 // TODO(dalecurtis): The mojo renderer is in another process, so we have no way
34 // currently to get hashes for video and audio samples. This also means that
35 // real audio plays out for each test.
36 #define EXPECT_HASH_EQ(a, b)
37 #define EXPECT_VIDEO_FORMAT_EQ(a, b)
39 // TODO(xhwang): EME support is not complete for the mojo renderer, so all
40 // encrypted tests are currently disabled.
41 #define DISABLE_EME_TESTS 1
43 // TODO(xhwang,dalecurtis): Text tracks are not currently supported by the mojo
44 // renderer.
45 #define DISABLE_TEXT_TRACK_TESTS 1
46 #else
47 #define EXPECT_HASH_EQ(a, b) EXPECT_EQ(a, b)
48 #define EXPECT_VIDEO_FORMAT_EQ(a, b) EXPECT_EQ(a, b)
49 #endif
51 using testing::_;
52 using testing::AnyNumber;
53 using testing::AtLeast;
54 using testing::AtMost;
55 using testing::SaveArg;
57 namespace media {
59 const char kSourceId[] = "SourceId";
61 const char kWebM[] = "video/webm; codecs=\"vp8,vorbis\"";
62 const char kWebMVP9[] = "video/webm; codecs=\"vp9\"";
63 const char kAudioOnlyWebM[] = "video/webm; codecs=\"vorbis\"";
64 const char kOpusAudioOnlyWebM[] = "video/webm; codecs=\"opus\"";
65 const char kVideoOnlyWebM[] = "video/webm; codecs=\"vp8\"";
66 #if defined(USE_PROPRIETARY_CODECS)
67 const char kADTS[] = "audio/aac";
68 const char kMP4[] = "video/mp4; codecs=\"avc1.4D4041,mp4a.40.2\"";
69 const char kMP4VideoAVC3[] = "video/mp4; codecs=\"avc3.64001f\"";
70 #if !defined(DISABLE_EME_TESTS)
71 const char kMP4Video[] = "video/mp4; codecs=\"avc1.4D4041\"";
72 const char kMP4Audio[] = "audio/mp4; codecs=\"mp4a.40.2\"";
73 #endif // !defined(DISABLE_EME_TESTS)
74 const char kMP3[] = "audio/mpeg";
75 #endif // defined(USE_PROPRIETARY_CODECS)
77 // Key used to encrypt test files.
78 const uint8 kSecretKey[] = {
79 0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b,
80 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c
83 // The key ID for all encrypted files.
84 const uint8 kKeyId[] = {
85 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
86 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35
89 const int kAppendWholeFile = -1;
91 // Constants for the Media Source config change tests.
92 const int kAppendTimeSec = 1;
93 const int kAppendTimeMs = kAppendTimeSec * 1000;
94 const int k320WebMFileDurationMs = 2736;
95 #if !defined(DISABLE_EME_TESTS)
96 const int k320EncWebMFileDurationMs = 2737;
97 #endif // !defined(DISABLE_EME_TESTS)
98 const int k640WebMFileDurationMs = 2749;
99 const int kOpusEndTrimmingWebMFileDurationMs = 2741;
100 const int kVP9WebMFileDurationMs = 2736;
101 const int kVP8AWebMFileDurationMs = 2734;
103 #if defined(USE_PROPRIETARY_CODECS)
104 #if !defined(DISABLE_EME_TESTS)
105 const int k640IsoFileDurationMs = 2737;
106 const int k640IsoCencFileDurationMs = 2736;
107 #endif // !defined(DISABLE_EME_TESTS)
108 const int k1280IsoFileDurationMs = 2736;
109 const int k1280IsoAVC3FileDurationMs = 2736;
110 #endif // defined(USE_PROPRIETARY_CODECS)
112 // Return a timeline offset for bear-320x240-live.webm.
113 static base::Time kLiveTimelineOffset() {
114 // The file contians the following UTC timeline offset:
115 // 2012-11-10 12:34:56.789123456
116 // Since base::Time only has a resolution of microseconds,
117 // construct a base::Time for 2012-11-10 12:34:56.789123.
118 base::Time::Exploded exploded_time;
119 exploded_time.year = 2012;
120 exploded_time.month = 11;
121 exploded_time.day_of_month = 10;
122 exploded_time.hour = 12;
123 exploded_time.minute = 34;
124 exploded_time.second = 56;
125 exploded_time.millisecond = 789;
126 base::Time timeline_offset = base::Time::FromUTCExploded(exploded_time);
128 timeline_offset += base::TimeDelta::FromMicroseconds(123);
130 return timeline_offset;
133 // FFmpeg only supports time a resolution of seconds so this
134 // helper function truncates a base::Time to seconds resolution.
135 static base::Time TruncateToFFmpegTimeResolution(base::Time t) {
136 base::Time::Exploded exploded_time;
137 t.UTCExplode(&exploded_time);
138 exploded_time.millisecond = 0;
140 return base::Time::FromUTCExploded(exploded_time);
143 // Note: Tests using this class only exercise the DecryptingDemuxerStream path.
144 // They do not exercise the Decrypting{Audio|Video}Decoder path.
145 class FakeEncryptedMedia {
146 public:
147 // Defines the behavior of the "app" that responds to EME events.
148 class AppBase {
149 public:
150 virtual ~AppBase() {}
152 virtual void OnSessionMessage(const std::string& session_id,
153 MediaKeys::MessageType message_type,
154 const std::vector<uint8>& message,
155 const GURL& legacy_destination_url) = 0;
157 virtual void OnSessionClosed(const std::string& session_id) = 0;
159 virtual void OnSessionKeysChange(const std::string& session_id,
160 bool has_additional_usable_key,
161 CdmKeysInfo keys_info) = 0;
163 // Errors are not expected unless overridden.
164 virtual void OnLegacySessionError(const std::string& session_id,
165 const std::string& error_name,
166 uint32 system_code,
167 const std::string& error_message) {
168 FAIL() << "Unexpected Key Error";
171 virtual void OnEncryptedMediaInitData(EmeInitDataType init_data_type,
172 const std::vector<uint8>& init_data,
173 AesDecryptor* decryptor) = 0;
176 FakeEncryptedMedia(AppBase* app)
177 : decryptor_(GURL::EmptyGURL(),
178 base::Bind(&FakeEncryptedMedia::OnSessionMessage,
179 base::Unretained(this)),
180 base::Bind(&FakeEncryptedMedia::OnSessionClosed,
181 base::Unretained(this)),
182 base::Bind(&FakeEncryptedMedia::OnSessionKeysChange,
183 base::Unretained(this))),
184 cdm_context_(&decryptor_),
185 app_(app) {}
187 CdmContext* GetCdmContext() { return &cdm_context_; }
189 // Callbacks for firing session events. Delegate to |app_|.
190 void OnSessionMessage(const std::string& session_id,
191 MediaKeys::MessageType message_type,
192 const std::vector<uint8>& message,
193 const GURL& legacy_destination_url) {
194 app_->OnSessionMessage(session_id, message_type, message,
195 legacy_destination_url);
198 void OnSessionClosed(const std::string& session_id) {
199 app_->OnSessionClosed(session_id);
202 void OnSessionKeysChange(const std::string& session_id,
203 bool has_additional_usable_key,
204 CdmKeysInfo keys_info) {
205 app_->OnSessionKeysChange(session_id, has_additional_usable_key,
206 keys_info.Pass());
209 void OnLegacySessionError(const std::string& session_id,
210 const std::string& error_name,
211 uint32 system_code,
212 const std::string& error_message) {
213 app_->OnLegacySessionError(session_id, error_name, system_code,
214 error_message);
217 void OnEncryptedMediaInitData(EmeInitDataType init_data_type,
218 const std::vector<uint8>& init_data) {
219 app_->OnEncryptedMediaInitData(init_data_type, init_data, &decryptor_);
222 private:
223 class TestCdmContext : public CdmContext {
224 public:
225 TestCdmContext(Decryptor* decryptor) : decryptor_(decryptor) {}
227 Decryptor* GetDecryptor() final { return decryptor_; }
228 int GetCdmId() const final { return kInvalidCdmId; }
230 private:
231 Decryptor* decryptor_;
234 AesDecryptor decryptor_;
235 TestCdmContext cdm_context_;
236 scoped_ptr<AppBase> app_;
239 enum PromiseResult { RESOLVED, REJECTED };
241 // Provides |kSecretKey| in response to needkey.
242 class KeyProvidingApp : public FakeEncryptedMedia::AppBase {
243 public:
244 KeyProvidingApp() {}
246 void OnResolveWithSession(PromiseResult expected,
247 const std::string& session_id) {
248 EXPECT_EQ(expected, RESOLVED);
249 EXPECT_GT(session_id.length(), 0ul);
250 current_session_id_ = session_id;
253 void OnResolve(PromiseResult expected) {
254 EXPECT_EQ(expected, RESOLVED);
257 void OnReject(PromiseResult expected,
258 media::MediaKeys::Exception exception_code,
259 uint32 system_code,
260 const std::string& error_message) {
261 EXPECT_EQ(expected, REJECTED) << error_message;
264 scoped_ptr<SimpleCdmPromise> CreatePromise(PromiseResult expected) {
265 scoped_ptr<media::SimpleCdmPromise> promise(new media::CdmCallbackPromise<>(
266 base::Bind(
267 &KeyProvidingApp::OnResolve, base::Unretained(this), expected),
268 base::Bind(
269 &KeyProvidingApp::OnReject, base::Unretained(this), expected)));
270 return promise.Pass();
273 scoped_ptr<NewSessionCdmPromise> CreateSessionPromise(
274 PromiseResult expected) {
275 scoped_ptr<media::NewSessionCdmPromise> promise(
276 new media::CdmCallbackPromise<std::string>(
277 base::Bind(&KeyProvidingApp::OnResolveWithSession,
278 base::Unretained(this),
279 expected),
280 base::Bind(
281 &KeyProvidingApp::OnReject, base::Unretained(this), expected)));
282 return promise.Pass();
285 void OnSessionMessage(const std::string& session_id,
286 MediaKeys::MessageType message_type,
287 const std::vector<uint8>& message,
288 const GURL& legacy_destination_url) override {
289 EXPECT_FALSE(session_id.empty());
290 EXPECT_FALSE(message.empty());
291 EXPECT_EQ(current_session_id_, session_id);
294 void OnSessionClosed(const std::string& session_id) override {
295 EXPECT_EQ(current_session_id_, session_id);
298 void OnSessionKeysChange(const std::string& session_id,
299 bool has_additional_usable_key,
300 CdmKeysInfo keys_info) override {
301 EXPECT_EQ(current_session_id_, session_id);
302 EXPECT_EQ(has_additional_usable_key, true);
305 void OnEncryptedMediaInitData(EmeInitDataType init_data_type,
306 const std::vector<uint8>& init_data,
307 AesDecryptor* decryptor) override {
308 // Since only 1 session is created, skip the request if the |init_data|
309 // has been seen before (no need to add the same key again).
310 if (init_data == prev_init_data_)
311 return;
312 prev_init_data_ = init_data;
314 if (current_session_id_.empty()) {
315 if (init_data_type == EmeInitDataType::CENC) {
316 // Since the 'cenc' files are not created with proper 'pssh' boxes,
317 // simply pretend that this is a webm file and pass the expected
318 // key ID as the init_data.
319 // http://crbug.com/460308
320 decryptor->CreateSessionAndGenerateRequest(
321 MediaKeys::TEMPORARY_SESSION, EmeInitDataType::WEBM,
322 std::vector<uint8>(kKeyId, kKeyId + arraysize(kKeyId)),
323 CreateSessionPromise(RESOLVED));
324 } else {
325 decryptor->CreateSessionAndGenerateRequest(
326 MediaKeys::TEMPORARY_SESSION, init_data_type, init_data,
327 CreateSessionPromise(RESOLVED));
329 EXPECT_FALSE(current_session_id_.empty());
332 // Clear Key really needs the key ID from |init_data|. For WebM, they are
333 // the same, but this is not the case for ISO CENC (key ID embedded in a
334 // 'pssh' box). Therefore, provide the correct key ID.
335 const uint8* key_id = vector_as_array(&init_data);
336 size_t key_id_length = init_data.size();
337 if (init_data_type == EmeInitDataType::CENC) {
338 key_id = kKeyId;
339 key_id_length = arraysize(kKeyId);
342 // Convert key into a JSON structure and then add it.
343 std::string jwk = GenerateJWKSet(
344 kSecretKey, arraysize(kSecretKey), key_id, key_id_length);
345 decryptor->UpdateSession(current_session_id_,
346 std::vector<uint8>(jwk.begin(), jwk.end()),
347 CreatePromise(RESOLVED));
350 std::string current_session_id_;
351 std::vector<uint8> prev_init_data_;
354 class RotatingKeyProvidingApp : public KeyProvidingApp {
355 public:
356 RotatingKeyProvidingApp() : num_distint_need_key_calls_(0) {}
357 ~RotatingKeyProvidingApp() override {
358 // Expect that OnEncryptedMediaInitData is fired multiple times with
359 // different |init_data|.
360 EXPECT_GT(num_distint_need_key_calls_, 1u);
363 void OnEncryptedMediaInitData(EmeInitDataType init_data_type,
364 const std::vector<uint8>& init_data,
365 AesDecryptor* decryptor) override {
366 // Skip the request if the |init_data| has been seen.
367 if (init_data == prev_init_data_)
368 return;
369 prev_init_data_ = init_data;
370 ++num_distint_need_key_calls_;
372 std::vector<uint8> key_id;
373 std::vector<uint8> key;
374 EXPECT_TRUE(GetKeyAndKeyId(init_data, &key, &key_id));
376 if (init_data_type == EmeInitDataType::CENC) {
377 // Since the 'cenc' files are not created with proper 'pssh' boxes,
378 // simply pretend that this is a webm file and pass the expected
379 // key ID as the init_data.
380 // http://crbug.com/460308
381 decryptor->CreateSessionAndGenerateRequest(
382 MediaKeys::TEMPORARY_SESSION, EmeInitDataType::WEBM, key_id,
383 CreateSessionPromise(RESOLVED));
384 } else {
385 decryptor->CreateSessionAndGenerateRequest(
386 MediaKeys::TEMPORARY_SESSION, init_data_type, init_data,
387 CreateSessionPromise(RESOLVED));
390 // Convert key into a JSON structure and then add it.
391 std::string jwk = GenerateJWKSet(vector_as_array(&key),
392 key.size(),
393 vector_as_array(&key_id),
394 key_id.size());
395 decryptor->UpdateSession(current_session_id_,
396 std::vector<uint8>(jwk.begin(), jwk.end()),
397 CreatePromise(RESOLVED));
400 private:
401 bool GetKeyAndKeyId(std::vector<uint8> init_data,
402 std::vector<uint8>* key,
403 std::vector<uint8>* key_id) {
404 // For WebM, init_data is key_id; for ISO CENC, init_data should contain
405 // the key_id. We assume key_id is in the end of init_data here (that is
406 // only a reasonable assumption for WebM and clear key ISO CENC).
407 DCHECK_GE(init_data.size(), arraysize(kKeyId));
408 std::vector<uint8> key_id_from_init_data(
409 init_data.end() - arraysize(kKeyId), init_data.end());
411 key->assign(kSecretKey, kSecretKey + arraysize(kSecretKey));
412 key_id->assign(kKeyId, kKeyId + arraysize(kKeyId));
414 // The Key and KeyId for this testing key provider are created by left
415 // rotating kSecretKey and kKeyId. Note that this implementation is only
416 // intended for testing purpose. The actual key rotation algorithm can be
417 // much more complicated.
418 // Find out the rotating position from |key_id_from_init_data| and apply on
419 // |key|.
420 for (size_t pos = 0; pos < arraysize(kKeyId); ++pos) {
421 std::rotate(key_id->begin(), key_id->begin() + pos, key_id->end());
422 if (*key_id == key_id_from_init_data) {
423 std::rotate(key->begin(), key->begin() + pos, key->end());
424 return true;
427 return false;
430 std::vector<uint8> prev_init_data_;
431 uint32 num_distint_need_key_calls_;
434 // Ignores needkey and does not perform a license request
435 class NoResponseApp : public FakeEncryptedMedia::AppBase {
436 public:
437 void OnSessionMessage(const std::string& session_id,
438 MediaKeys::MessageType message_type,
439 const std::vector<uint8>& message,
440 const GURL& legacy_destination_url) override {
441 EXPECT_FALSE(session_id.empty());
442 EXPECT_FALSE(message.empty());
443 FAIL() << "Unexpected Message";
446 void OnSessionClosed(const std::string& session_id) override {
447 EXPECT_FALSE(session_id.empty());
448 FAIL() << "Unexpected Closed";
451 void OnSessionKeysChange(const std::string& session_id,
452 bool has_additional_usable_key,
453 CdmKeysInfo keys_info) override {
454 EXPECT_FALSE(session_id.empty());
455 EXPECT_EQ(has_additional_usable_key, true);
458 void OnEncryptedMediaInitData(EmeInitDataType init_data_type,
459 const std::vector<uint8>& init_data,
460 AesDecryptor* decryptor) override {}
463 // Helper class that emulates calls made on the ChunkDemuxer by the
464 // Media Source API.
465 class MockMediaSource {
466 public:
467 MockMediaSource(const std::string& filename,
468 const std::string& mimetype,
469 int initial_append_size)
470 : current_position_(0),
471 initial_append_size_(initial_append_size),
472 mimetype_(mimetype),
473 chunk_demuxer_(new ChunkDemuxer(
474 base::Bind(&MockMediaSource::DemuxerOpened, base::Unretained(this)),
475 base::Bind(&MockMediaSource::OnEncryptedMediaInitData,
476 base::Unretained(this)),
477 LogCB(),
478 scoped_refptr<MediaLog>(new MediaLog()),
479 true)),
480 owned_chunk_demuxer_(chunk_demuxer_) {
481 file_data_ = ReadTestDataFile(filename);
483 if (initial_append_size_ == kAppendWholeFile)
484 initial_append_size_ = file_data_->data_size();
486 DCHECK_GT(initial_append_size_, 0);
487 DCHECK_LE(initial_append_size_, file_data_->data_size());
490 virtual ~MockMediaSource() {}
492 scoped_ptr<Demuxer> GetDemuxer() { return owned_chunk_demuxer_.Pass(); }
494 void set_encrypted_media_init_data_cb(
495 const Demuxer::EncryptedMediaInitDataCB& encrypted_media_init_data_cb) {
496 encrypted_media_init_data_cb_ = encrypted_media_init_data_cb;
499 void Seek(base::TimeDelta seek_time, int new_position, int seek_append_size) {
500 chunk_demuxer_->StartWaitingForSeek(seek_time);
502 chunk_demuxer_->Abort(
503 kSourceId,
504 base::TimeDelta(), kInfiniteDuration(), &last_timestamp_offset_);
506 DCHECK_GE(new_position, 0);
507 DCHECK_LT(new_position, file_data_->data_size());
508 current_position_ = new_position;
510 AppendData(seek_append_size);
513 void AppendData(int size) {
514 DCHECK(chunk_demuxer_);
515 DCHECK_LT(current_position_, file_data_->data_size());
516 DCHECK_LE(current_position_ + size, file_data_->data_size());
518 chunk_demuxer_->AppendData(
519 kSourceId, file_data_->data() + current_position_, size,
520 base::TimeDelta(), kInfiniteDuration(), &last_timestamp_offset_,
521 base::Bind(&MockMediaSource::InitSegmentReceived,
522 base::Unretained(this)));
523 current_position_ += size;
526 void AppendAtTime(base::TimeDelta timestamp_offset,
527 const uint8* pData,
528 int size) {
529 CHECK(!chunk_demuxer_->IsParsingMediaSegment(kSourceId));
530 chunk_demuxer_->AppendData(kSourceId, pData, size,
531 base::TimeDelta(), kInfiniteDuration(),
532 &timestamp_offset,
533 base::Bind(&MockMediaSource::InitSegmentReceived,
534 base::Unretained(this)));
535 last_timestamp_offset_ = timestamp_offset;
538 void AppendAtTimeWithWindow(base::TimeDelta timestamp_offset,
539 base::TimeDelta append_window_start,
540 base::TimeDelta append_window_end,
541 const uint8* pData,
542 int size) {
543 CHECK(!chunk_demuxer_->IsParsingMediaSegment(kSourceId));
544 chunk_demuxer_->AppendData(kSourceId,
545 pData,
546 size,
547 append_window_start,
548 append_window_end,
549 &timestamp_offset,
550 base::Bind(&MockMediaSource::InitSegmentReceived,
551 base::Unretained(this)));
552 last_timestamp_offset_ = timestamp_offset;
555 void EndOfStream() {
556 chunk_demuxer_->MarkEndOfStream(PIPELINE_OK);
559 void Abort() {
560 if (!chunk_demuxer_)
561 return;
562 chunk_demuxer_->Shutdown();
563 chunk_demuxer_ = NULL;
566 void DemuxerOpened() {
567 base::MessageLoop::current()->PostTask(
568 FROM_HERE, base::Bind(&MockMediaSource::DemuxerOpenedTask,
569 base::Unretained(this)));
572 void DemuxerOpenedTask() {
573 // This code assumes that |mimetype_| is one of the following forms.
574 // 1. audio/mpeg
575 // 2. video/webm;codec="vorbis,vp8".
576 size_t semicolon = mimetype_.find(";");
577 std::string type = mimetype_;
578 std::vector<std::string> codecs;
579 if (semicolon != std::string::npos) {
580 type = mimetype_.substr(0, semicolon);
581 size_t codecs_param_start = mimetype_.find("codecs=\"", semicolon);
583 CHECK_NE(codecs_param_start, std::string::npos);
585 codecs_param_start += 8; // Skip over the codecs=".
587 size_t codecs_param_end = mimetype_.find("\"", codecs_param_start);
589 CHECK_NE(codecs_param_end, std::string::npos);
591 std::string codecs_param =
592 mimetype_.substr(codecs_param_start,
593 codecs_param_end - codecs_param_start);
594 Tokenize(codecs_param, ",", &codecs);
597 CHECK_EQ(chunk_demuxer_->AddId(kSourceId, type, codecs), ChunkDemuxer::kOk);
599 AppendData(initial_append_size_);
602 void OnEncryptedMediaInitData(EmeInitDataType init_data_type,
603 const std::vector<uint8>& init_data) {
604 DCHECK(!init_data.empty());
605 CHECK(!encrypted_media_init_data_cb_.is_null());
606 encrypted_media_init_data_cb_.Run(init_data_type, init_data);
609 base::TimeDelta last_timestamp_offset() const {
610 return last_timestamp_offset_;
613 MOCK_METHOD0(InitSegmentReceived, void(void));
615 private:
616 scoped_refptr<DecoderBuffer> file_data_;
617 int current_position_;
618 int initial_append_size_;
619 std::string mimetype_;
620 ChunkDemuxer* chunk_demuxer_;
621 scoped_ptr<Demuxer> owned_chunk_demuxer_;
622 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb_;
623 base::TimeDelta last_timestamp_offset_;
626 #if defined(MOJO_RENDERER)
627 class PipelineIntegrationTestHost : public mojo::test::ApplicationTestBase,
628 public PipelineIntegrationTestBase {
629 public:
630 bool ShouldCreateDefaultRunLoop() override { return false; }
632 void SetUp() override {
633 ApplicationTestBase::SetUp();
634 InitializeMediaLibrary();
637 protected:
638 scoped_ptr<Renderer> CreateRenderer() override {
639 mojo::URLRequestPtr request(mojo::URLRequest::New());
640 request->url = mojo::String::From("mojo:media");
641 mojo::ServiceProvider* service_provider =
642 application_impl()
643 ->ConnectToApplication(request.Pass())
644 ->GetServiceProvider();
646 mojo::MediaRendererPtr mojo_media_renderer;
647 mojo::ConnectToService(service_provider, &mojo_media_renderer);
648 return make_scoped_ptr(new MojoRendererImpl(message_loop_.task_runner(),
649 mojo_media_renderer.Pass()));
652 #else
653 class PipelineIntegrationTestHost : public testing::Test,
654 public PipelineIntegrationTestBase {};
655 #endif
657 class PipelineIntegrationTest : public PipelineIntegrationTestHost {
658 public:
659 void StartPipelineWithMediaSource(MockMediaSource* source) {
660 EXPECT_CALL(*source, InitSegmentReceived()).Times(AtLeast(1));
661 EXPECT_CALL(*this, OnMetadata(_))
662 .Times(AtMost(1))
663 .WillRepeatedly(SaveArg<0>(&metadata_));
664 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH))
665 .Times(AnyNumber());
666 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_NOTHING))
667 .Times(AnyNumber());
669 // Encrypted content not used, so this is never called.
670 EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0);
672 demuxer_ = source->GetDemuxer().Pass();
673 pipeline_->Start(
674 demuxer_.get(), CreateRenderer(),
675 base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)),
676 base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)),
677 base::Bind(&PipelineIntegrationTest::OnStatusCallback,
678 base::Unretained(this)),
679 base::Bind(&PipelineIntegrationTest::OnMetadata,
680 base::Unretained(this)),
681 base::Bind(&PipelineIntegrationTest::OnBufferingStateChanged,
682 base::Unretained(this)),
683 base::Closure(), base::Bind(&PipelineIntegrationTest::OnAddTextTrack,
684 base::Unretained(this)),
685 base::Bind(&PipelineIntegrationTest::OnWaitingForDecryptionKey,
686 base::Unretained(this)));
687 message_loop_.Run();
688 EXPECT_EQ(PIPELINE_OK, pipeline_status_);
691 void StartHashedPipelineWithMediaSource(MockMediaSource* source) {
692 hashing_enabled_ = true;
693 StartPipelineWithMediaSource(source);
696 void StartPipelineWithEncryptedMedia(
697 MockMediaSource* source,
698 FakeEncryptedMedia* encrypted_media) {
699 EXPECT_CALL(*source, InitSegmentReceived()).Times(AtLeast(1));
700 EXPECT_CALL(*this, OnMetadata(_))
701 .Times(AtMost(1))
702 .WillRepeatedly(SaveArg<0>(&metadata_));
703 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH))
704 .Times(AnyNumber());
705 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_NOTHING))
706 .Times(AnyNumber());
707 EXPECT_CALL(*this, DecryptorAttached(true));
709 // Encrypted content used but keys provided in advance, so this is
710 // never called.
711 EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0);
713 demuxer_ = source->GetDemuxer().Pass();
715 pipeline_->SetCdm(encrypted_media->GetCdmContext(),
716 base::Bind(&PipelineIntegrationTest::DecryptorAttached,
717 base::Unretained(this)));
719 pipeline_->Start(
720 demuxer_.get(), CreateRenderer(),
721 base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)),
722 base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)),
723 base::Bind(&PipelineIntegrationTest::OnStatusCallback,
724 base::Unretained(this)),
725 base::Bind(&PipelineIntegrationTest::OnMetadata,
726 base::Unretained(this)),
727 base::Bind(&PipelineIntegrationTest::OnBufferingStateChanged,
728 base::Unretained(this)),
729 base::Closure(), base::Bind(&PipelineIntegrationTest::OnAddTextTrack,
730 base::Unretained(this)),
731 base::Bind(&PipelineIntegrationTest::OnWaitingForDecryptionKey,
732 base::Unretained(this)));
734 source->set_encrypted_media_init_data_cb(
735 base::Bind(&FakeEncryptedMedia::OnEncryptedMediaInitData,
736 base::Unretained(encrypted_media)));
738 message_loop_.Run();
739 EXPECT_EQ(PIPELINE_OK, pipeline_status_);
742 // Verifies that seeking works properly for ChunkDemuxer when the
743 // seek happens while there is a pending read on the ChunkDemuxer
744 // and no data is available.
745 bool TestSeekDuringRead(const std::string& filename,
746 const std::string& mimetype,
747 int initial_append_size,
748 base::TimeDelta start_seek_time,
749 base::TimeDelta seek_time,
750 int seek_file_position,
751 int seek_append_size) {
752 MockMediaSource source(filename, mimetype, initial_append_size);
753 StartPipelineWithMediaSource(&source);
755 if (pipeline_status_ != PIPELINE_OK)
756 return false;
758 Play();
759 if (!WaitUntilCurrentTimeIsAfter(start_seek_time))
760 return false;
762 source.Seek(seek_time, seek_file_position, seek_append_size);
763 if (!Seek(seek_time))
764 return false;
766 source.EndOfStream();
768 source.Abort();
769 Stop();
770 return true;
774 TEST_F(PipelineIntegrationTest, BasicPlayback) {
775 ASSERT_EQ(PIPELINE_OK, Start("bear-320x240.webm"));
777 Play();
779 ASSERT_TRUE(WaitUntilOnEnded());
782 TEST_F(PipelineIntegrationTest, BasicPlaybackOpusOgg) {
783 ASSERT_EQ(PIPELINE_OK, Start("bear-opus.ogg"));
785 Play();
787 ASSERT_TRUE(WaitUntilOnEnded());
790 TEST_F(PipelineIntegrationTest, BasicPlaybackHashed) {
791 ASSERT_EQ(PIPELINE_OK, Start("bear-320x240.webm", kHashed));
793 Play();
795 ASSERT_TRUE(WaitUntilOnEnded());
797 EXPECT_HASH_EQ("f0be120a90a811506777c99a2cdf7cc1", GetVideoHash());
798 EXPECT_HASH_EQ("-3.59,-2.06,-0.43,2.15,0.77,-0.95,", GetAudioHash());
799 EXPECT_TRUE(demuxer_->GetTimelineOffset().is_null());
802 TEST_F(PipelineIntegrationTest, BasicPlaybackLive) {
803 ASSERT_EQ(PIPELINE_OK, Start("bear-320x240-live.webm", kHashed));
805 Play();
807 ASSERT_TRUE(WaitUntilOnEnded());
809 EXPECT_HASH_EQ("f0be120a90a811506777c99a2cdf7cc1", GetVideoHash());
810 EXPECT_HASH_EQ("-3.59,-2.06,-0.43,2.15,0.77,-0.95,", GetAudioHash());
812 // TODO: Fix FFmpeg code to return higher resolution time values so
813 // we don't have to truncate our expectations here.
814 EXPECT_EQ(TruncateToFFmpegTimeResolution(kLiveTimelineOffset()),
815 demuxer_->GetTimelineOffset());
818 TEST_F(PipelineIntegrationTest, F32PlaybackHashed) {
819 ASSERT_EQ(PIPELINE_OK, Start("sfx_f32le.wav", kHashed));
820 Play();
821 ASSERT_TRUE(WaitUntilOnEnded());
822 EXPECT_HASH_EQ(std::string(kNullVideoHash), GetVideoHash());
823 EXPECT_HASH_EQ("3.03,2.86,2.99,3.31,3.57,4.06,", GetAudioHash());
826 #if !defined(DISABLE_EME_TESTS)
827 TEST_F(PipelineIntegrationTest, BasicPlaybackEncrypted) {
828 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
829 set_encrypted_media_init_data_cb(
830 base::Bind(&FakeEncryptedMedia::OnEncryptedMediaInitData,
831 base::Unretained(&encrypted_media)));
833 ASSERT_EQ(PIPELINE_OK, Start("bear-320x240-av_enc-av.webm",
834 encrypted_media.GetCdmContext()));
836 Play();
838 ASSERT_TRUE(WaitUntilOnEnded());
839 Stop();
841 #endif // !defined(DISABLE_EME_TESTS)
843 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource) {
844 MockMediaSource source("bear-320x240.webm", kWebM, 219229);
845 StartPipelineWithMediaSource(&source);
846 source.EndOfStream();
848 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
849 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
850 EXPECT_EQ(k320WebMFileDurationMs,
851 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
853 Play();
855 ASSERT_TRUE(WaitUntilOnEnded());
857 EXPECT_TRUE(demuxer_->GetTimelineOffset().is_null());
858 source.Abort();
859 Stop();
862 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_Live) {
863 MockMediaSource source("bear-320x240-live.webm", kWebM, 219221);
864 StartPipelineWithMediaSource(&source);
865 source.EndOfStream();
867 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
868 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
869 EXPECT_EQ(k320WebMFileDurationMs,
870 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
872 Play();
874 ASSERT_TRUE(WaitUntilOnEnded());
876 EXPECT_EQ(kLiveTimelineOffset(),
877 demuxer_->GetTimelineOffset());
878 source.Abort();
879 Stop();
882 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_VP9_WebM) {
883 MockMediaSource source("bear-vp9.webm", kWebMVP9, 67504);
884 StartPipelineWithMediaSource(&source);
885 source.EndOfStream();
887 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
888 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
889 EXPECT_EQ(kVP9WebMFileDurationMs,
890 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
892 Play();
894 ASSERT_TRUE(WaitUntilOnEnded());
895 source.Abort();
896 Stop();
899 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_VP8A_WebM) {
900 MockMediaSource source("bear-vp8a.webm", kVideoOnlyWebM, kAppendWholeFile);
901 StartPipelineWithMediaSource(&source);
902 source.EndOfStream();
904 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
905 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
906 EXPECT_EQ(kVP8AWebMFileDurationMs,
907 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
909 Play();
911 ASSERT_TRUE(WaitUntilOnEnded());
912 source.Abort();
913 Stop();
916 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_Opus_WebM) {
917 MockMediaSource source("bear-opus-end-trimming.webm", kOpusAudioOnlyWebM,
918 kAppendWholeFile);
919 StartPipelineWithMediaSource(&source);
920 source.EndOfStream();
922 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
923 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
924 EXPECT_EQ(kOpusEndTrimmingWebMFileDurationMs,
925 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
926 Play();
928 ASSERT_TRUE(WaitUntilOnEnded());
929 source.Abort();
930 Stop();
933 // Flaky. http://crbug.com/304776
934 TEST_F(PipelineIntegrationTest, DISABLED_MediaSource_Opus_Seeking_WebM) {
935 MockMediaSource source("bear-opus-end-trimming.webm", kOpusAudioOnlyWebM,
936 kAppendWholeFile);
937 StartHashedPipelineWithMediaSource(&source);
939 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
940 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
941 EXPECT_EQ(kOpusEndTrimmingWebMFileDurationMs,
942 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
944 base::TimeDelta start_seek_time = base::TimeDelta::FromMilliseconds(1000);
945 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(2000);
947 Play();
948 ASSERT_TRUE(WaitUntilCurrentTimeIsAfter(start_seek_time));
949 source.Seek(seek_time, 0x1D5, 34017);
950 source.EndOfStream();
951 ASSERT_TRUE(Seek(seek_time));
953 ASSERT_TRUE(WaitUntilOnEnded());
955 EXPECT_HASH_EQ("0.76,0.20,-0.82,-0.58,-1.29,-0.29,", GetAudioHash());
957 source.Abort();
958 Stop();
961 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_WebM) {
962 MockMediaSource source("bear-320x240-16x9-aspect.webm", kWebM,
963 kAppendWholeFile);
964 StartPipelineWithMediaSource(&source);
966 scoped_refptr<DecoderBuffer> second_file =
967 ReadTestDataFile("bear-640x360.webm");
969 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
970 second_file->data(), second_file->data_size());
972 source.EndOfStream();
974 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
975 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
976 EXPECT_EQ(kAppendTimeMs + k640WebMFileDurationMs,
977 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
979 Play();
981 EXPECT_TRUE(WaitUntilOnEnded());
982 source.Abort();
983 Stop();
986 #if !defined(DISABLE_EME_TESTS)
987 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_Encrypted_WebM) {
988 MockMediaSource source("bear-320x240-16x9-aspect-av_enc-av.webm", kWebM,
989 kAppendWholeFile);
990 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
991 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
993 scoped_refptr<DecoderBuffer> second_file =
994 ReadTestDataFile("bear-640x360-av_enc-av.webm");
996 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
997 second_file->data(), second_file->data_size());
999 source.EndOfStream();
1001 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1002 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1003 EXPECT_EQ(kAppendTimeMs + k640WebMFileDurationMs,
1004 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1006 Play();
1008 EXPECT_TRUE(WaitUntilOnEnded());
1009 source.Abort();
1010 Stop();
1013 // Config changes from encrypted to clear are not currently supported.
1014 TEST_F(PipelineIntegrationTest,
1015 MediaSource_ConfigChange_ClearThenEncrypted_WebM) {
1016 MockMediaSource source("bear-320x240-16x9-aspect.webm", kWebM,
1017 kAppendWholeFile);
1018 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1019 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1021 scoped_refptr<DecoderBuffer> second_file =
1022 ReadTestDataFile("bear-640x360-av_enc-av.webm");
1024 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1025 second_file->data(), second_file->data_size());
1027 source.EndOfStream();
1029 message_loop_.Run();
1030 EXPECT_EQ(PIPELINE_ERROR_DECODE, pipeline_status_);
1032 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1033 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1034 // The second video was not added, so its time has not been added.
1035 EXPECT_EQ(k320WebMFileDurationMs,
1036 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1038 Play();
1040 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
1041 source.Abort();
1044 // Config changes from clear to encrypted are not currently supported.
1045 TEST_F(PipelineIntegrationTest,
1046 MediaSource_ConfigChange_EncryptedThenClear_WebM) {
1047 MockMediaSource source("bear-320x240-16x9-aspect-av_enc-av.webm", kWebM,
1048 kAppendWholeFile);
1049 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1050 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1052 scoped_refptr<DecoderBuffer> second_file =
1053 ReadTestDataFile("bear-640x360.webm");
1055 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1056 second_file->data(), second_file->data_size());
1058 source.EndOfStream();
1060 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1061 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1062 // The second video was not added, so its time has not been added.
1063 EXPECT_EQ(k320EncWebMFileDurationMs,
1064 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1066 Play();
1068 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
1069 source.Abort();
1071 #endif // !defined(DISABLE_EME_TESTS)
1073 #if defined(USE_PROPRIETARY_CODECS)
1074 TEST_F(PipelineIntegrationTest, MediaSource_ADTS) {
1075 MockMediaSource source("sfx.adts", kADTS, kAppendWholeFile);
1076 StartPipelineWithMediaSource(&source);
1077 source.EndOfStream();
1079 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1080 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1081 EXPECT_EQ(325, pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1083 Play();
1085 EXPECT_TRUE(WaitUntilOnEnded());
1088 TEST_F(PipelineIntegrationTest, MediaSource_ADTS_TimestampOffset) {
1089 MockMediaSource source("sfx.adts", kADTS, kAppendWholeFile);
1090 StartHashedPipelineWithMediaSource(&source);
1091 EXPECT_EQ(325, source.last_timestamp_offset().InMilliseconds());
1093 // Trim off multiple frames off the beginning of the segment which will cause
1094 // the first decoded frame to be incorrect if preroll isn't implemented.
1095 const base::TimeDelta adts_preroll_duration =
1096 base::TimeDelta::FromSecondsD(2.5 * 1024 / 44100);
1097 const base::TimeDelta append_time =
1098 source.last_timestamp_offset() - adts_preroll_duration;
1100 scoped_refptr<DecoderBuffer> second_file = ReadTestDataFile("sfx.adts");
1101 source.AppendAtTimeWithWindow(append_time,
1102 append_time + adts_preroll_duration,
1103 kInfiniteDuration(),
1104 second_file->data(),
1105 second_file->data_size());
1106 source.EndOfStream();
1108 EXPECT_EQ(592, source.last_timestamp_offset().InMilliseconds());
1109 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1110 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1111 EXPECT_EQ(592, pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1113 Play();
1115 EXPECT_TRUE(WaitUntilOnEnded());
1117 // Verify preroll is stripped.
1118 EXPECT_HASH_EQ("-0.06,0.97,-0.90,-0.70,-0.53,-0.34,", GetAudioHash());
1121 TEST_F(PipelineIntegrationTest, BasicPlaybackHashed_MP3) {
1122 ASSERT_EQ(PIPELINE_OK, Start("sfx.mp3", kHashed));
1124 Play();
1126 ASSERT_TRUE(WaitUntilOnEnded());
1128 // Verify codec delay and preroll are stripped.
1129 EXPECT_HASH_EQ("1.30,2.72,4.56,5.08,3.74,2.03,", GetAudioHash());
1132 TEST_F(PipelineIntegrationTest, MediaSource_MP3) {
1133 MockMediaSource source("sfx.mp3", kMP3, kAppendWholeFile);
1134 StartHashedPipelineWithMediaSource(&source);
1135 source.EndOfStream();
1137 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1138 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1139 EXPECT_EQ(313, pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1141 Play();
1143 EXPECT_TRUE(WaitUntilOnEnded());
1145 // Verify that codec delay was stripped.
1146 EXPECT_HASH_EQ("1.01,2.71,4.18,4.32,3.04,1.12,", GetAudioHash());
1149 TEST_F(PipelineIntegrationTest, MediaSource_MP3_TimestampOffset) {
1150 MockMediaSource source("sfx.mp3", kMP3, kAppendWholeFile);
1151 StartPipelineWithMediaSource(&source);
1152 EXPECT_EQ(313, source.last_timestamp_offset().InMilliseconds());
1154 // There are 576 silent frames at the start of this mp3. The second append
1155 // should trim them off.
1156 const base::TimeDelta mp3_preroll_duration =
1157 base::TimeDelta::FromSecondsD(576.0 / 44100);
1158 const base::TimeDelta append_time =
1159 source.last_timestamp_offset() - mp3_preroll_duration;
1161 scoped_refptr<DecoderBuffer> second_file = ReadTestDataFile("sfx.mp3");
1162 source.AppendAtTimeWithWindow(append_time,
1163 append_time + mp3_preroll_duration,
1164 kInfiniteDuration(),
1165 second_file->data(),
1166 second_file->data_size());
1167 source.EndOfStream();
1169 EXPECT_EQ(613, source.last_timestamp_offset().InMilliseconds());
1170 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1171 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1172 EXPECT_EQ(613, pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1174 Play();
1176 EXPECT_TRUE(WaitUntilOnEnded());
1179 TEST_F(PipelineIntegrationTest, MediaSource_MP3_Icecast) {
1180 MockMediaSource source("icy_sfx.mp3", kMP3, kAppendWholeFile);
1181 StartPipelineWithMediaSource(&source);
1182 source.EndOfStream();
1184 Play();
1186 EXPECT_TRUE(WaitUntilOnEnded());
1189 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_MP4) {
1190 MockMediaSource source("bear-640x360-av_frag.mp4", kMP4, kAppendWholeFile);
1191 StartPipelineWithMediaSource(&source);
1193 scoped_refptr<DecoderBuffer> second_file =
1194 ReadTestDataFile("bear-1280x720-av_frag.mp4");
1196 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1197 second_file->data(), second_file->data_size());
1199 source.EndOfStream();
1201 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1202 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1203 EXPECT_EQ(kAppendTimeMs + k1280IsoFileDurationMs,
1204 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1206 Play();
1208 EXPECT_TRUE(WaitUntilOnEnded());
1209 source.Abort();
1210 Stop();
1213 #if !defined(DISABLE_EME_TESTS)
1214 TEST_F(PipelineIntegrationTest,
1215 MediaSource_ConfigChange_Encrypted_MP4_CENC_VideoOnly) {
1216 MockMediaSource source("bear-640x360-v_frag-cenc.mp4", kMP4Video,
1217 kAppendWholeFile);
1218 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1219 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1221 scoped_refptr<DecoderBuffer> second_file =
1222 ReadTestDataFile("bear-1280x720-v_frag-cenc.mp4");
1224 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1225 second_file->data(), second_file->data_size());
1227 source.EndOfStream();
1229 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1230 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1231 EXPECT_EQ(kAppendTimeMs + k1280IsoFileDurationMs,
1232 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1234 Play();
1236 EXPECT_TRUE(WaitUntilOnEnded());
1237 source.Abort();
1238 Stop();
1241 TEST_F(PipelineIntegrationTest,
1242 MediaSource_ConfigChange_Encrypted_MP4_CENC_KeyRotation_VideoOnly) {
1243 MockMediaSource source("bear-640x360-v_frag-cenc-key_rotation.mp4", kMP4Video,
1244 kAppendWholeFile);
1245 FakeEncryptedMedia encrypted_media(new RotatingKeyProvidingApp());
1246 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1248 scoped_refptr<DecoderBuffer> second_file =
1249 ReadTestDataFile("bear-1280x720-v_frag-cenc-key_rotation.mp4");
1251 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1252 second_file->data(), second_file->data_size());
1254 source.EndOfStream();
1256 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1257 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1258 EXPECT_EQ(kAppendTimeMs + k1280IsoFileDurationMs,
1259 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1261 Play();
1263 EXPECT_TRUE(WaitUntilOnEnded());
1264 source.Abort();
1265 Stop();
1268 // Config changes from clear to encrypted are not currently supported.
1269 // TODO(ddorwin): Figure out why this CHECKs in AppendAtTime().
1270 TEST_F(PipelineIntegrationTest,
1271 DISABLED_MediaSource_ConfigChange_ClearThenEncrypted_MP4_CENC) {
1272 MockMediaSource source("bear-640x360-av_frag.mp4", kMP4Video,
1273 kAppendWholeFile);
1274 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1275 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1277 scoped_refptr<DecoderBuffer> second_file =
1278 ReadTestDataFile("bear-1280x720-v_frag-cenc.mp4");
1280 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1281 second_file->data(), second_file->data_size());
1283 source.EndOfStream();
1285 message_loop_.Run();
1286 EXPECT_EQ(PIPELINE_ERROR_DECODE, pipeline_status_);
1288 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1289 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1290 // The second video was not added, so its time has not been added.
1291 EXPECT_EQ(k640IsoFileDurationMs,
1292 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1294 Play();
1296 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
1297 source.Abort();
1300 // Config changes from encrypted to clear are not currently supported.
1301 TEST_F(PipelineIntegrationTest,
1302 MediaSource_ConfigChange_EncryptedThenClear_MP4_CENC) {
1303 MockMediaSource source("bear-640x360-v_frag-cenc.mp4", kMP4Video,
1304 kAppendWholeFile);
1305 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1306 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1308 scoped_refptr<DecoderBuffer> second_file =
1309 ReadTestDataFile("bear-1280x720-av_frag.mp4");
1311 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1312 second_file->data(), second_file->data_size());
1314 source.EndOfStream();
1316 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1317 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1318 // The second video was not added, so its time has not been added.
1319 EXPECT_EQ(k640IsoCencFileDurationMs,
1320 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1322 Play();
1324 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
1325 source.Abort();
1327 #endif // !defined(DISABLE_EME_TESTS)
1329 // Verify files which change configuration midstream fail gracefully.
1330 TEST_F(PipelineIntegrationTest, MidStreamConfigChangesFail) {
1331 ASSERT_EQ(PIPELINE_OK, Start("midstream_config_change.mp3"));
1332 Play();
1333 ASSERT_EQ(WaitUntilEndedOrError(), PIPELINE_ERROR_DECODE);
1336 #endif
1338 TEST_F(PipelineIntegrationTest, BasicPlayback_16x9AspectRatio) {
1339 ASSERT_EQ(PIPELINE_OK, Start("bear-320x240-16x9-aspect.webm"));
1340 Play();
1341 ASSERT_TRUE(WaitUntilOnEnded());
1344 #if !defined(DISABLE_EME_TESTS)
1345 TEST_F(PipelineIntegrationTest, EncryptedPlayback_WebM) {
1346 MockMediaSource source("bear-320x240-av_enc-av.webm", kWebM, 219816);
1347 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1348 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1350 source.EndOfStream();
1351 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1353 Play();
1355 ASSERT_TRUE(WaitUntilOnEnded());
1356 source.Abort();
1357 Stop();
1360 TEST_F(PipelineIntegrationTest, EncryptedPlayback_ClearStart_WebM) {
1361 MockMediaSource source("bear-320x240-av_enc-av_clear-1s.webm", kWebM,
1362 kAppendWholeFile);
1363 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1364 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1366 source.EndOfStream();
1367 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1369 Play();
1371 ASSERT_TRUE(WaitUntilOnEnded());
1372 source.Abort();
1373 Stop();
1376 TEST_F(PipelineIntegrationTest, EncryptedPlayback_NoEncryptedFrames_WebM) {
1377 MockMediaSource source("bear-320x240-av_enc-av_clear-all.webm", kWebM,
1378 kAppendWholeFile);
1379 FakeEncryptedMedia encrypted_media(new NoResponseApp());
1380 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1382 source.EndOfStream();
1383 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1385 Play();
1387 ASSERT_TRUE(WaitUntilOnEnded());
1388 source.Abort();
1389 Stop();
1391 #endif // !defined(DISABLE_EME_TESTS)
1393 #if defined(USE_PROPRIETARY_CODECS)
1394 #if !defined(DISABLE_EME_TESTS)
1395 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_VideoOnly) {
1396 MockMediaSource source("bear-1280x720-v_frag-cenc.mp4", kMP4Video,
1397 kAppendWholeFile);
1398 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1399 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1401 source.EndOfStream();
1402 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1404 Play();
1406 ASSERT_TRUE(WaitUntilOnEnded());
1407 source.Abort();
1408 Stop();
1411 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_AudioOnly) {
1412 MockMediaSource source("bear-1280x720-a_frag-cenc.mp4", kMP4Audio,
1413 kAppendWholeFile);
1414 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1415 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1417 source.EndOfStream();
1418 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1420 Play();
1422 ASSERT_TRUE(WaitUntilOnEnded());
1423 source.Abort();
1424 Stop();
1427 TEST_F(PipelineIntegrationTest,
1428 EncryptedPlayback_NoEncryptedFrames_MP4_CENC_VideoOnly) {
1429 MockMediaSource source("bear-1280x720-v_frag-cenc_clear-all.mp4", kMP4Video,
1430 kAppendWholeFile);
1431 FakeEncryptedMedia encrypted_media(new NoResponseApp());
1432 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1434 source.EndOfStream();
1435 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1437 Play();
1439 ASSERT_TRUE(WaitUntilOnEnded());
1440 source.Abort();
1441 Stop();
1444 TEST_F(PipelineIntegrationTest,
1445 EncryptedPlayback_NoEncryptedFrames_MP4_CENC_AudioOnly) {
1446 MockMediaSource source("bear-1280x720-a_frag-cenc_clear-all.mp4", kMP4Audio,
1447 kAppendWholeFile);
1448 FakeEncryptedMedia encrypted_media(new NoResponseApp());
1449 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1451 source.EndOfStream();
1452 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1454 Play();
1456 ASSERT_TRUE(WaitUntilOnEnded());
1457 source.Abort();
1458 Stop();
1461 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_KeyRotation_Video) {
1462 MockMediaSource source("bear-1280x720-v_frag-cenc-key_rotation.mp4",
1463 kMP4Video, kAppendWholeFile);
1464 FakeEncryptedMedia encrypted_media(new RotatingKeyProvidingApp());
1465 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1467 source.EndOfStream();
1468 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1470 Play();
1472 ASSERT_TRUE(WaitUntilOnEnded());
1473 source.Abort();
1474 Stop();
1477 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_KeyRotation_Audio) {
1478 MockMediaSource source("bear-1280x720-a_frag-cenc-key_rotation.mp4",
1479 kMP4Audio, kAppendWholeFile);
1480 FakeEncryptedMedia encrypted_media(new RotatingKeyProvidingApp());
1481 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1483 source.EndOfStream();
1484 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1486 Play();
1488 ASSERT_TRUE(WaitUntilOnEnded());
1489 source.Abort();
1490 Stop();
1492 #endif // !defined(DISABLE_EME_TESTS)
1494 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_VideoOnly_MP4_AVC3) {
1495 MockMediaSource source("bear-1280x720-v_frag-avc3.mp4", kMP4VideoAVC3,
1496 kAppendWholeFile);
1497 StartPipelineWithMediaSource(&source);
1498 source.EndOfStream();
1500 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1501 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1502 EXPECT_EQ(k1280IsoAVC3FileDurationMs,
1503 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1505 Play();
1507 ASSERT_TRUE(WaitUntilOnEnded());
1508 source.Abort();
1509 Stop();
1511 #endif // defined(USE_PROPRIETARY_CODECS)
1513 TEST_F(PipelineIntegrationTest, SeekWhilePaused) {
1514 ASSERT_EQ(PIPELINE_OK, Start("bear-320x240.webm"));
1516 base::TimeDelta duration(pipeline_->GetMediaDuration());
1517 base::TimeDelta start_seek_time(duration / 4);
1518 base::TimeDelta seek_time(duration * 3 / 4);
1520 Play();
1521 ASSERT_TRUE(WaitUntilCurrentTimeIsAfter(start_seek_time));
1522 Pause();
1523 ASSERT_TRUE(Seek(seek_time));
1524 EXPECT_EQ(seek_time, pipeline_->GetMediaTime());
1525 Play();
1526 ASSERT_TRUE(WaitUntilOnEnded());
1528 // Make sure seeking after reaching the end works as expected.
1529 Pause();
1530 ASSERT_TRUE(Seek(seek_time));
1531 EXPECT_EQ(seek_time, pipeline_->GetMediaTime());
1532 Play();
1533 ASSERT_TRUE(WaitUntilOnEnded());
1536 TEST_F(PipelineIntegrationTest, SeekWhilePlaying) {
1537 ASSERT_EQ(PIPELINE_OK, Start("bear-320x240.webm"));
1539 base::TimeDelta duration(pipeline_->GetMediaDuration());
1540 base::TimeDelta start_seek_time(duration / 4);
1541 base::TimeDelta seek_time(duration * 3 / 4);
1543 Play();
1544 ASSERT_TRUE(WaitUntilCurrentTimeIsAfter(start_seek_time));
1545 ASSERT_TRUE(Seek(seek_time));
1546 EXPECT_GE(pipeline_->GetMediaTime(), seek_time);
1547 ASSERT_TRUE(WaitUntilOnEnded());
1549 // Make sure seeking after reaching the end works as expected.
1550 ASSERT_TRUE(Seek(seek_time));
1551 EXPECT_GE(pipeline_->GetMediaTime(), seek_time);
1552 ASSERT_TRUE(WaitUntilOnEnded());
1555 #if defined(USE_PROPRIETARY_CODECS)
1556 TEST_F(PipelineIntegrationTest, Rotated_Metadata_0) {
1557 ASSERT_EQ(PIPELINE_OK, Start("bear_rotate_0.mp4"));
1558 ASSERT_EQ(VIDEO_ROTATION_0, metadata_.video_rotation);
1561 TEST_F(PipelineIntegrationTest, Rotated_Metadata_90) {
1562 ASSERT_EQ(PIPELINE_OK, Start("bear_rotate_90.mp4"));
1563 ASSERT_EQ(VIDEO_ROTATION_90, metadata_.video_rotation);
1566 TEST_F(PipelineIntegrationTest, Rotated_Metadata_180) {
1567 ASSERT_EQ(PIPELINE_OK, Start("bear_rotate_180.mp4"));
1568 ASSERT_EQ(VIDEO_ROTATION_180, metadata_.video_rotation);
1571 TEST_F(PipelineIntegrationTest, Rotated_Metadata_270) {
1572 ASSERT_EQ(PIPELINE_OK, Start("bear_rotate_270.mp4"));
1573 ASSERT_EQ(VIDEO_ROTATION_270, metadata_.video_rotation);
1575 #endif
1577 // Verify audio decoder & renderer can handle aborted demuxer reads.
1578 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_AudioOnly) {
1579 ASSERT_TRUE(TestSeekDuringRead("bear-320x240-audio-only.webm", kAudioOnlyWebM,
1580 16384,
1581 base::TimeDelta::FromMilliseconds(464),
1582 base::TimeDelta::FromMilliseconds(617),
1583 0x10CA, 19730));
1586 // Verify video decoder & renderer can handle aborted demuxer reads.
1587 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_VideoOnly) {
1588 ASSERT_TRUE(TestSeekDuringRead("bear-320x240-video-only.webm", kVideoOnlyWebM,
1589 32768,
1590 base::TimeDelta::FromMilliseconds(167),
1591 base::TimeDelta::FromMilliseconds(1668),
1592 0x1C896, 65536));
1595 // Verify that Opus audio in WebM containers can be played back.
1596 TEST_F(PipelineIntegrationTest, BasicPlayback_AudioOnly_Opus_WebM) {
1597 ASSERT_EQ(PIPELINE_OK, Start("bear-opus-end-trimming.webm"));
1598 Play();
1599 ASSERT_TRUE(WaitUntilOnEnded());
1602 // Verify that VP9 video in WebM containers can be played back.
1603 TEST_F(PipelineIntegrationTest, BasicPlayback_VideoOnly_VP9_WebM) {
1604 ASSERT_EQ(PIPELINE_OK, Start("bear-vp9.webm"));
1605 Play();
1606 ASSERT_TRUE(WaitUntilOnEnded());
1609 // Verify that VP9 video and Opus audio in the same WebM container can be played
1610 // back.
1611 TEST_F(PipelineIntegrationTest, BasicPlayback_VP9_Opus_WebM) {
1612 ASSERT_EQ(PIPELINE_OK, Start("bear-vp9-opus.webm"));
1613 Play();
1614 ASSERT_TRUE(WaitUntilOnEnded());
1617 // Verify that VP8 video with alpha channel can be played back.
1618 TEST_F(PipelineIntegrationTest, BasicPlayback_VP8A_WebM) {
1619 ASSERT_EQ(PIPELINE_OK, Start("bear-vp8a.webm"));
1620 Play();
1621 ASSERT_TRUE(WaitUntilOnEnded());
1622 EXPECT_VIDEO_FORMAT_EQ(last_video_frame_format_, VideoFrame::YV12A);
1625 // Verify that VP8A video with odd width/height can be played back.
1626 TEST_F(PipelineIntegrationTest, BasicPlayback_VP8A_Odd_WebM) {
1627 ASSERT_EQ(PIPELINE_OK, Start("bear-vp8a-odd-dimensions.webm"));
1628 Play();
1629 ASSERT_TRUE(WaitUntilOnEnded());
1630 EXPECT_VIDEO_FORMAT_EQ(last_video_frame_format_, VideoFrame::YV12A);
1633 // Verify that VP9 video with odd width/height can be played back.
1634 TEST_F(PipelineIntegrationTest, BasicPlayback_VP9_Odd_WebM) {
1635 ASSERT_EQ(PIPELINE_OK, Start("bear-vp9-odd-dimensions.webm"));
1636 Play();
1637 ASSERT_TRUE(WaitUntilOnEnded());
1640 #if !defined(DISABLE_TEXT_TRACK_TESTS)
1641 // Verify that VP8 video with inband text track can be played back.
1642 TEST_F(PipelineIntegrationTest, BasicPlayback_VP8_WebVTT_WebM) {
1643 EXPECT_CALL(*this, OnAddTextTrack(_, _));
1644 ASSERT_EQ(PIPELINE_OK, Start("bear-vp8-webvtt.webm"));
1645 Play();
1646 ASSERT_TRUE(WaitUntilOnEnded());
1648 #endif // !defined(DISABLE_TEXT_TRACK_TESTS)
1650 // Verify that VP9 video with 4:4:4 subsampling can be played back.
1651 TEST_F(PipelineIntegrationTest, P444_VP9_WebM) {
1652 ASSERT_EQ(PIPELINE_OK, Start("bear-320x240-P444.webm"));
1653 Play();
1654 ASSERT_TRUE(WaitUntilOnEnded());
1655 EXPECT_VIDEO_FORMAT_EQ(last_video_frame_format_, VideoFrame::YV24);
1658 // Verify that frames of VP9 video in the BT.709 color space have the YV12HD
1659 // format.
1660 TEST_F(PipelineIntegrationTest, BT709_VP9_WebM) {
1661 ASSERT_EQ(PIPELINE_OK, Start("bear-vp9-bt709.webm"));
1662 Play();
1663 ASSERT_TRUE(WaitUntilOnEnded());
1664 EXPECT_VIDEO_FORMAT_EQ(last_video_frame_format_, VideoFrame::YV12);
1665 EXPECT_EQ(last_video_frame_color_space_, VideoFrame::COLOR_SPACE_HD_REC709);
1668 // Verify that videos with an odd frame size playback successfully.
1669 TEST_F(PipelineIntegrationTest, BasicPlayback_OddVideoSize) {
1670 ASSERT_EQ(PIPELINE_OK, Start("butterfly-853x480.webm"));
1671 Play();
1672 ASSERT_TRUE(WaitUntilOnEnded());
1675 // Verify that OPUS audio in a webm which reports a 44.1kHz sample rate plays
1676 // correctly at 48kHz
1677 TEST_F(PipelineIntegrationTest, BasicPlayback_Opus441kHz) {
1678 ASSERT_EQ(PIPELINE_OK, Start("sfx-opus-441.webm"));
1679 Play();
1680 ASSERT_TRUE(WaitUntilOnEnded());
1681 EXPECT_EQ(48000,
1682 demuxer_->GetStream(DemuxerStream::AUDIO)
1683 ->audio_decoder_config()
1684 .samples_per_second());
1687 // Same as above but using MediaSource.
1688 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_Opus441kHz) {
1689 MockMediaSource source(
1690 "sfx-opus-441.webm", kOpusAudioOnlyWebM, kAppendWholeFile);
1691 StartPipelineWithMediaSource(&source);
1692 source.EndOfStream();
1693 Play();
1694 ASSERT_TRUE(WaitUntilOnEnded());
1695 source.Abort();
1696 Stop();
1697 EXPECT_EQ(48000,
1698 demuxer_->GetStream(DemuxerStream::AUDIO)
1699 ->audio_decoder_config()
1700 .samples_per_second());
1703 // Ensures audio-only playback with missing or negative timestamps works. Tests
1704 // the common live-streaming case for chained ogg. See http://crbug.com/396864.
1705 TEST_F(PipelineIntegrationTest, BasicPlaybackChainedOgg) {
1706 ASSERT_EQ(PIPELINE_OK, Start("double-sfx.ogg"));
1707 Play();
1708 ASSERT_TRUE(WaitUntilOnEnded());
1709 ASSERT_EQ(base::TimeDelta(), demuxer_->GetStartTime());
1712 // Ensures audio-video playback with missing or negative timestamps fails softly
1713 // instead of crashing. See http://crbug.com/396864.
1714 TEST_F(PipelineIntegrationTest, BasicPlaybackChainedOggVideo) {
1715 ASSERT_EQ(PIPELINE_OK, Start("double-bear.ogv"));
1716 Play();
1717 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
1718 ASSERT_EQ(base::TimeDelta(), demuxer_->GetStartTime());
1721 // Tests that we signal ended even when audio runs longer than video track.
1722 TEST_F(PipelineIntegrationTest, BasicPlaybackAudioLongerThanVideo) {
1723 ASSERT_EQ(PIPELINE_OK, Start("bear_audio_longer_than_video.ogv"));
1724 // Audio track is 2000ms. Video track is 1001ms. Duration should be higher
1725 // of the two.
1726 EXPECT_EQ(2000, pipeline_->GetMediaDuration().InMilliseconds());
1727 Play();
1728 ASSERT_TRUE(WaitUntilOnEnded());
1731 // Tests that we signal ended even when audio runs shorter than video track.
1732 TEST_F(PipelineIntegrationTest, BasicPlaybackAudioShorterThanVideo) {
1733 ASSERT_EQ(PIPELINE_OK, Start("bear_audio_shorter_than_video.ogv"));
1734 // Audio track is 500ms. Video track is 1001ms. Duration should be higher of
1735 // the two.
1736 EXPECT_EQ(1001, pipeline_->GetMediaDuration().InMilliseconds());
1737 Play();
1738 ASSERT_TRUE(WaitUntilOnEnded());
1741 TEST_F(PipelineIntegrationTest, BasicPlaybackPositiveStartTime) {
1742 ASSERT_EQ(PIPELINE_OK, Start("nonzero-start-time.webm"));
1743 Play();
1744 ASSERT_TRUE(WaitUntilOnEnded());
1745 ASSERT_EQ(base::TimeDelta::FromMicroseconds(396000),
1746 demuxer_->GetStartTime());
1749 } // namespace media