Infobar material design refresh: bg color
[chromium-blink-merge.git] / media / test / pipeline_integration_test.cc
blobdd339778c0a57f2f7309fa20c23ac8f2d3ddd0f8
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_split.h"
10 #include "base/strings/string_util.h"
11 #include "build/build_config.h"
12 #include "media/base/cdm_callback_promise.h"
13 #include "media/base/cdm_context.h"
14 #include "media/base/cdm_key_information.h"
15 #include "media/base/decoder_buffer.h"
16 #include "media/base/media.h"
17 #include "media/base/media_keys.h"
18 #include "media/base/media_switches.h"
19 #include "media/base/test_data_util.h"
20 #include "media/cdm/aes_decryptor.h"
21 #include "media/cdm/json_web_key.h"
22 #include "media/filters/chunk_demuxer.h"
23 #include "media/renderers/renderer_impl.h"
24 #include "media/test/pipeline_integration_test_base.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "url/gurl.h"
28 #if defined(MOJO_RENDERER)
29 #include "media/mojo/interfaces/renderer.mojom.h"
30 #include "media/mojo/interfaces/service_factory.mojom.h"
31 #include "media/mojo/services/mojo_renderer_impl.h"
32 #include "mojo/application/public/cpp/application_impl.h"
33 #include "mojo/application/public/cpp/application_test_base.h"
34 #include "mojo/application/public/cpp/connect.h"
36 // TODO(dalecurtis): The mojo renderer is in another process, so we have no way
37 // currently to get hashes for video and audio samples. This also means that
38 // real audio plays out for each test.
39 #define EXPECT_HASH_EQ(a, b)
40 #define EXPECT_VIDEO_FORMAT_EQ(a, b)
41 #define EXPECT_COLOR_SPACE_EQ(a, b)
43 // TODO(xhwang): EME support is not complete for the mojo renderer, so all
44 // encrypted tests are currently disabled.
45 #define DISABLE_EME_TESTS 1
47 // TODO(xhwang,dalecurtis): Text tracks are not currently supported by the mojo
48 // renderer.
49 #define DISABLE_TEXT_TRACK_TESTS 1
50 #else
51 #define EXPECT_HASH_EQ(a, b) EXPECT_EQ(a, b)
52 #define EXPECT_VIDEO_FORMAT_EQ(a, b) EXPECT_EQ(a, b)
53 #define EXPECT_COLOR_SPACE_EQ(a, b) EXPECT_EQ(a, b)
54 #endif
56 using testing::_;
57 using testing::AnyNumber;
58 using testing::AtLeast;
59 using testing::AtMost;
60 using testing::SaveArg;
62 namespace media {
64 const char kSourceId[] = "SourceId";
66 const char kWebM[] = "video/webm; codecs=\"vp8,vorbis\"";
67 const char kWebMVP9[] = "video/webm; codecs=\"vp9\"";
68 const char kAudioOnlyWebM[] = "video/webm; codecs=\"vorbis\"";
69 const char kOpusAudioOnlyWebM[] = "video/webm; codecs=\"opus\"";
70 const char kVideoOnlyWebM[] = "video/webm; codecs=\"vp8\"";
71 #if defined(USE_PROPRIETARY_CODECS)
72 const char kADTS[] = "audio/aac";
73 const char kMP4[] = "video/mp4; codecs=\"avc1.4D4041,mp4a.40.2\"";
74 const char kMP4VideoAVC3[] = "video/mp4; codecs=\"avc3.64001f\"";
75 #if !defined(DISABLE_EME_TESTS)
76 const char kMP4Video[] = "video/mp4; codecs=\"avc1.4D4041\"";
77 const char kMP4Audio[] = "audio/mp4; codecs=\"mp4a.40.2\"";
78 #endif // !defined(DISABLE_EME_TESTS)
79 const char kMP3[] = "audio/mpeg";
80 #endif // defined(USE_PROPRIETARY_CODECS)
82 // Key used to encrypt test files.
83 const uint8_t kSecretKey[] = {
84 0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b,
85 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c
88 // The key ID for all encrypted files.
89 const uint8_t kKeyId[] = {
90 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
91 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35
94 const int kAppendWholeFile = -1;
96 // Constants for the Media Source config change tests.
97 const int kAppendTimeSec = 1;
98 const int kAppendTimeMs = kAppendTimeSec * 1000;
99 const int k320WebMFileDurationMs = 2736;
100 #if !defined(DISABLE_EME_TESTS)
101 const int k320EncWebMFileDurationMs = 2737;
102 #endif // !defined(DISABLE_EME_TESTS)
103 const int k640WebMFileDurationMs = 2749;
104 const int kOpusEndTrimmingWebMFileDurationMs = 2741;
105 const int kVP9WebMFileDurationMs = 2736;
106 const int kVP8AWebMFileDurationMs = 2734;
108 #if !defined(MOJO_RENDERER)
109 #if defined(OPUS_FIXED_POINT)
110 static const char kOpusEndTrimmingHash_1[] =
111 "-4.57,-5.68,-6.54,-6.29,-4.35,-3.59,";
112 static const char kOpusEndTrimmingHash_2[] =
113 "-11.93,-11.12,-8.27,-7.10,-7.84,-10.00,";
114 static const char kOpusEndTrimmingHash_3[] =
115 "-13.32,-14.38,-13.70,-11.69,-10.20,-10.48,";
116 #else
117 // Hash for a full playthrough of "opus-trimming-test.(webm|ogg)".
118 static const char kOpusEndTrimmingHash_1[] =
119 "-4.56,-5.65,-6.51,-6.29,-4.36,-3.59,";
120 // The above hash, plus an additional playthrough starting from T=1s.
121 static const char kOpusEndTrimmingHash_2[] =
122 "-11.89,-11.09,-8.25,-7.11,-7.84,-9.97,";
123 // The above hash, plus an additional playthrough starting from T=6.36s.
124 static const char kOpusEndTrimmingHash_3[] =
125 "-13.28,-14.35,-13.67,-11.68,-10.18,-10.46,";
126 #endif // defined(OPUS_FIXED_POINT)
127 #endif
129 #if defined(USE_PROPRIETARY_CODECS)
130 #if !defined(DISABLE_EME_TESTS)
131 const int k640IsoFileDurationMs = 2737;
132 const int k640IsoCencFileDurationMs = 2736;
133 #endif // !defined(DISABLE_EME_TESTS)
134 const int k1280IsoFileDurationMs = 2736;
135 const int k1280IsoAVC3FileDurationMs = 2736;
136 #endif // defined(USE_PROPRIETARY_CODECS)
138 // Return a timeline offset for bear-320x240-live.webm.
139 static base::Time kLiveTimelineOffset() {
140 // The file contians the following UTC timeline offset:
141 // 2012-11-10 12:34:56.789123456
142 // Since base::Time only has a resolution of microseconds,
143 // construct a base::Time for 2012-11-10 12:34:56.789123.
144 base::Time::Exploded exploded_time;
145 exploded_time.year = 2012;
146 exploded_time.month = 11;
147 exploded_time.day_of_month = 10;
148 exploded_time.hour = 12;
149 exploded_time.minute = 34;
150 exploded_time.second = 56;
151 exploded_time.millisecond = 789;
152 base::Time timeline_offset = base::Time::FromUTCExploded(exploded_time);
154 timeline_offset += base::TimeDelta::FromMicroseconds(123);
156 return timeline_offset;
159 // FFmpeg only supports time a resolution of seconds so this
160 // helper function truncates a base::Time to seconds resolution.
161 static base::Time TruncateToFFmpegTimeResolution(base::Time t) {
162 base::Time::Exploded exploded_time;
163 t.UTCExplode(&exploded_time);
164 exploded_time.millisecond = 0;
166 return base::Time::FromUTCExploded(exploded_time);
169 // Note: Tests using this class only exercise the DecryptingDemuxerStream path.
170 // They do not exercise the Decrypting{Audio|Video}Decoder path.
171 class FakeEncryptedMedia {
172 public:
173 // Defines the behavior of the "app" that responds to EME events.
174 class AppBase {
175 public:
176 virtual ~AppBase() {}
178 virtual void OnSessionMessage(const std::string& session_id,
179 MediaKeys::MessageType message_type,
180 const std::vector<uint8_t>& message,
181 const GURL& legacy_destination_url,
182 AesDecryptor* decryptor) = 0;
184 virtual void OnSessionClosed(const std::string& session_id) = 0;
186 virtual void OnSessionKeysChange(const std::string& session_id,
187 bool has_additional_usable_key,
188 CdmKeysInfo keys_info) = 0;
190 // Errors are not expected unless overridden.
191 virtual void OnLegacySessionError(const std::string& session_id,
192 const std::string& error_name,
193 uint32_t system_code,
194 const std::string& error_message) {
195 FAIL() << "Unexpected Key Error";
198 virtual void OnEncryptedMediaInitData(EmeInitDataType init_data_type,
199 const std::vector<uint8_t>& init_data,
200 AesDecryptor* decryptor) = 0;
203 FakeEncryptedMedia(AppBase* app)
204 : decryptor_(GURL::EmptyGURL(),
205 base::Bind(&FakeEncryptedMedia::OnSessionMessage,
206 base::Unretained(this)),
207 base::Bind(&FakeEncryptedMedia::OnSessionClosed,
208 base::Unretained(this)),
209 base::Bind(&FakeEncryptedMedia::OnSessionKeysChange,
210 base::Unretained(this))),
211 cdm_context_(&decryptor_),
212 app_(app) {}
214 CdmContext* GetCdmContext() { return &cdm_context_; }
216 // Callbacks for firing session events. Delegate to |app_|.
217 void OnSessionMessage(const std::string& session_id,
218 MediaKeys::MessageType message_type,
219 const std::vector<uint8_t>& message,
220 const GURL& legacy_destination_url) {
221 app_->OnSessionMessage(session_id, message_type, message,
222 legacy_destination_url, &decryptor_);
225 void OnSessionClosed(const std::string& session_id) {
226 app_->OnSessionClosed(session_id);
229 void OnSessionKeysChange(const std::string& session_id,
230 bool has_additional_usable_key,
231 CdmKeysInfo keys_info) {
232 app_->OnSessionKeysChange(session_id, has_additional_usable_key,
233 keys_info.Pass());
236 void OnLegacySessionError(const std::string& session_id,
237 const std::string& error_name,
238 uint32_t system_code,
239 const std::string& error_message) {
240 app_->OnLegacySessionError(session_id, error_name, system_code,
241 error_message);
244 void OnEncryptedMediaInitData(EmeInitDataType init_data_type,
245 const std::vector<uint8_t>& init_data) {
246 app_->OnEncryptedMediaInitData(init_data_type, init_data, &decryptor_);
249 private:
250 class TestCdmContext : public CdmContext {
251 public:
252 TestCdmContext(Decryptor* decryptor) : decryptor_(decryptor) {}
254 Decryptor* GetDecryptor() final { return decryptor_; }
255 int GetCdmId() const final { return kInvalidCdmId; }
257 private:
258 Decryptor* decryptor_;
261 AesDecryptor decryptor_;
262 TestCdmContext cdm_context_;
263 scoped_ptr<AppBase> app_;
266 enum PromiseResult { RESOLVED, REJECTED };
268 // Provides |kSecretKey| in response to needkey.
269 class KeyProvidingApp : public FakeEncryptedMedia::AppBase {
270 public:
271 KeyProvidingApp() {}
273 void OnResolveWithSession(PromiseResult expected,
274 const std::string& session_id) {
275 EXPECT_EQ(expected, RESOLVED);
276 EXPECT_GT(session_id.length(), 0ul);
277 current_session_id_ = session_id;
280 void OnResolve(PromiseResult expected) {
281 EXPECT_EQ(expected, RESOLVED);
284 void OnReject(PromiseResult expected,
285 media::MediaKeys::Exception exception_code,
286 uint32_t system_code,
287 const std::string& error_message) {
288 EXPECT_EQ(expected, REJECTED) << error_message;
291 scoped_ptr<SimpleCdmPromise> CreatePromise(PromiseResult expected) {
292 scoped_ptr<media::SimpleCdmPromise> promise(new media::CdmCallbackPromise<>(
293 base::Bind(
294 &KeyProvidingApp::OnResolve, base::Unretained(this), expected),
295 base::Bind(
296 &KeyProvidingApp::OnReject, base::Unretained(this), expected)));
297 return promise.Pass();
300 scoped_ptr<NewSessionCdmPromise> CreateSessionPromise(
301 PromiseResult expected) {
302 scoped_ptr<media::NewSessionCdmPromise> promise(
303 new media::CdmCallbackPromise<std::string>(
304 base::Bind(&KeyProvidingApp::OnResolveWithSession,
305 base::Unretained(this),
306 expected),
307 base::Bind(
308 &KeyProvidingApp::OnReject, base::Unretained(this), expected)));
309 return promise.Pass();
312 void OnSessionMessage(const std::string& session_id,
313 MediaKeys::MessageType message_type,
314 const std::vector<uint8_t>& message,
315 const GURL& legacy_destination_url,
316 AesDecryptor* decryptor) override {
317 EXPECT_FALSE(session_id.empty());
318 EXPECT_FALSE(message.empty());
319 EXPECT_EQ(current_session_id_, session_id);
320 EXPECT_EQ(MediaKeys::MessageType::LICENSE_REQUEST, message_type);
322 // Extract the key ID from |message|. For Clear Key this is a JSON object
323 // containing a set of "kids". There should only be 1 key ID in |message|.
324 std::string message_string(message.begin(), message.end());
325 KeyIdList key_ids;
326 std::string error_message;
327 EXPECT_TRUE(ExtractKeyIdsFromKeyIdsInitData(message_string, &key_ids,
328 &error_message))
329 << error_message;
330 EXPECT_EQ(1u, key_ids.size());
332 // Determine the key that matches the key ID |key_ids[0]|.
333 std::vector<uint8_t> key;
334 EXPECT_TRUE(LookupKey(key_ids[0], &key));
336 // Update the session with the key ID and key.
337 std::string jwk =
338 GenerateJWKSet(vector_as_array(&key), key.size(),
339 vector_as_array(&key_ids[0]), key_ids[0].size());
340 decryptor->UpdateSession(session_id,
341 std::vector<uint8_t>(jwk.begin(), jwk.end()),
342 CreatePromise(RESOLVED));
345 void OnSessionClosed(const std::string& session_id) override {
346 EXPECT_EQ(current_session_id_, session_id);
349 void OnSessionKeysChange(const std::string& session_id,
350 bool has_additional_usable_key,
351 CdmKeysInfo keys_info) override {
352 EXPECT_EQ(current_session_id_, session_id);
353 EXPECT_EQ(has_additional_usable_key, true);
356 void OnEncryptedMediaInitData(EmeInitDataType init_data_type,
357 const std::vector<uint8_t>& init_data,
358 AesDecryptor* decryptor) override {
359 // Since only 1 session is created, skip the request if the |init_data|
360 // has been seen before (no need to add the same key again).
361 if (init_data == prev_init_data_)
362 return;
363 prev_init_data_ = init_data;
365 if (current_session_id_.empty()) {
366 decryptor->CreateSessionAndGenerateRequest(
367 MediaKeys::TEMPORARY_SESSION, init_data_type, init_data,
368 CreateSessionPromise(RESOLVED));
369 EXPECT_FALSE(current_session_id_.empty());
373 virtual bool LookupKey(const std::vector<uint8_t>& key_id,
374 std::vector<uint8_t>* key) {
375 // As there is no key rotation, the key ID provided should be |kKeyId|
376 // which uses |kSecretKey| as the key.
377 EXPECT_EQ(std::vector<uint8_t>(kKeyId, kKeyId + arraysize(kKeyId)), key_id);
378 key->assign(kSecretKey, kSecretKey + arraysize(kSecretKey));
379 return true;
382 std::string current_session_id_;
383 std::vector<uint8_t> prev_init_data_;
386 class RotatingKeyProvidingApp : public KeyProvidingApp {
387 public:
388 RotatingKeyProvidingApp() : num_distinct_need_key_calls_(0) {}
389 ~RotatingKeyProvidingApp() override {
390 // Expect that OnEncryptedMediaInitData is fired multiple times with
391 // different |init_data|.
392 EXPECT_GT(num_distinct_need_key_calls_, 1u);
395 void OnEncryptedMediaInitData(EmeInitDataType init_data_type,
396 const std::vector<uint8_t>& init_data,
397 AesDecryptor* decryptor) override {
398 // Skip the request if the |init_data| has been seen.
399 if (init_data == prev_init_data_)
400 return;
401 prev_init_data_ = init_data;
402 ++num_distinct_need_key_calls_;
404 decryptor->CreateSessionAndGenerateRequest(MediaKeys::TEMPORARY_SESSION,
405 init_data_type, init_data,
406 CreateSessionPromise(RESOLVED));
409 bool LookupKey(const std::vector<uint8_t>& key_id,
410 std::vector<uint8_t>* key) override {
411 // The Key and KeyId for this testing key provider are created by left
412 // rotating |kSecretKey| and |kKeyId|. Note that this implementation is
413 // only intended for testing purpose. The actual key rotation algorithm
414 // can be much more complicated.
415 // Find out the rotating position from |starting_key_id| and apply on |key|.
416 std::vector<uint8_t> starting_key_id(kKeyId, kKeyId + arraysize(kKeyId));
417 for (size_t pos = 0; pos < starting_key_id.size(); ++pos) {
418 std::rotate(starting_key_id.begin(), starting_key_id.begin() + pos,
419 starting_key_id.end());
420 if (key_id == starting_key_id) {
421 key->assign(kSecretKey, kSecretKey + arraysize(kSecretKey));
422 std::rotate(key->begin(), key->begin() + pos, key->end());
423 return true;
426 return false;
429 uint32_t num_distinct_need_key_calls_;
432 // Ignores needkey and does not perform a license request
433 class NoResponseApp : public FakeEncryptedMedia::AppBase {
434 public:
435 void OnSessionMessage(const std::string& session_id,
436 MediaKeys::MessageType message_type,
437 const std::vector<uint8_t>& message,
438 const GURL& legacy_destination_url,
439 AesDecryptor* decryptor) override {
440 EXPECT_FALSE(session_id.empty());
441 EXPECT_FALSE(message.empty());
442 FAIL() << "Unexpected Message";
445 void OnSessionClosed(const std::string& session_id) override {
446 EXPECT_FALSE(session_id.empty());
447 FAIL() << "Unexpected Closed";
450 void OnSessionKeysChange(const std::string& session_id,
451 bool has_additional_usable_key,
452 CdmKeysInfo keys_info) override {
453 EXPECT_FALSE(session_id.empty());
454 EXPECT_EQ(has_additional_usable_key, true);
457 void OnEncryptedMediaInitData(EmeInitDataType init_data_type,
458 const std::vector<uint8_t>& init_data,
459 AesDecryptor* decryptor) override {}
462 // Helper class that emulates calls made on the ChunkDemuxer by the
463 // Media Source API.
464 class MockMediaSource {
465 public:
466 MockMediaSource(const std::string& filename,
467 const std::string& mimetype,
468 int initial_append_size)
469 : current_position_(0),
470 initial_append_size_(initial_append_size),
471 mimetype_(mimetype),
472 chunk_demuxer_(new ChunkDemuxer(
473 base::Bind(&MockMediaSource::DemuxerOpened, base::Unretained(this)),
474 base::Bind(&MockMediaSource::OnEncryptedMediaInitData,
475 base::Unretained(this)),
476 scoped_refptr<MediaLog>(new MediaLog()),
477 true)),
478 owned_chunk_demuxer_(chunk_demuxer_) {
479 file_data_ = ReadTestDataFile(filename);
481 if (initial_append_size_ == kAppendWholeFile)
482 initial_append_size_ = file_data_->data_size();
484 DCHECK_GT(initial_append_size_, 0);
485 DCHECK_LE(initial_append_size_, file_data_->data_size());
488 virtual ~MockMediaSource() {}
490 scoped_ptr<Demuxer> GetDemuxer() { return owned_chunk_demuxer_.Pass(); }
492 void set_encrypted_media_init_data_cb(
493 const Demuxer::EncryptedMediaInitDataCB& encrypted_media_init_data_cb) {
494 encrypted_media_init_data_cb_ = encrypted_media_init_data_cb;
497 void Seek(base::TimeDelta seek_time, int new_position, int seek_append_size) {
498 chunk_demuxer_->StartWaitingForSeek(seek_time);
500 chunk_demuxer_->Abort(
501 kSourceId,
502 base::TimeDelta(), kInfiniteDuration(), &last_timestamp_offset_);
504 DCHECK_GE(new_position, 0);
505 DCHECK_LT(new_position, file_data_->data_size());
506 current_position_ = new_position;
508 AppendData(seek_append_size);
511 void Seek(base::TimeDelta seek_time) {
512 chunk_demuxer_->StartWaitingForSeek(seek_time);
515 void AppendData(int size) {
516 DCHECK(chunk_demuxer_);
517 DCHECK_LT(current_position_, file_data_->data_size());
518 DCHECK_LE(current_position_ + size, file_data_->data_size());
520 chunk_demuxer_->AppendData(
521 kSourceId, file_data_->data() + current_position_, size,
522 base::TimeDelta(), kInfiniteDuration(), &last_timestamp_offset_,
523 base::Bind(&MockMediaSource::InitSegmentReceived,
524 base::Unretained(this)));
525 current_position_ += size;
528 void AppendAtTime(base::TimeDelta timestamp_offset,
529 const uint8_t* pData,
530 int size) {
531 CHECK(!chunk_demuxer_->IsParsingMediaSegment(kSourceId));
532 chunk_demuxer_->AppendData(kSourceId, pData, size,
533 base::TimeDelta(), kInfiniteDuration(),
534 &timestamp_offset,
535 base::Bind(&MockMediaSource::InitSegmentReceived,
536 base::Unretained(this)));
537 last_timestamp_offset_ = timestamp_offset;
540 void AppendAtTimeWithWindow(base::TimeDelta timestamp_offset,
541 base::TimeDelta append_window_start,
542 base::TimeDelta append_window_end,
543 const uint8_t* pData,
544 int size) {
545 CHECK(!chunk_demuxer_->IsParsingMediaSegment(kSourceId));
546 chunk_demuxer_->AppendData(kSourceId,
547 pData,
548 size,
549 append_window_start,
550 append_window_end,
551 &timestamp_offset,
552 base::Bind(&MockMediaSource::InitSegmentReceived,
553 base::Unretained(this)));
554 last_timestamp_offset_ = timestamp_offset;
557 void EndOfStream() {
558 chunk_demuxer_->MarkEndOfStream(PIPELINE_OK);
561 void Abort() {
562 if (!chunk_demuxer_)
563 return;
564 chunk_demuxer_->Shutdown();
565 chunk_demuxer_ = NULL;
568 void DemuxerOpened() {
569 base::MessageLoop::current()->PostTask(
570 FROM_HERE, base::Bind(&MockMediaSource::DemuxerOpenedTask,
571 base::Unretained(this)));
574 void DemuxerOpenedTask() {
575 // This code assumes that |mimetype_| is one of the following forms.
576 // 1. audio/mpeg
577 // 2. video/webm;codec="vorbis,vp8".
578 size_t semicolon = mimetype_.find(";");
579 std::string type = mimetype_;
580 std::vector<std::string> codecs;
581 if (semicolon != std::string::npos) {
582 type = mimetype_.substr(0, semicolon);
583 size_t codecs_param_start = mimetype_.find("codecs=\"", semicolon);
585 CHECK_NE(codecs_param_start, std::string::npos);
587 codecs_param_start += 8; // Skip over the codecs=".
589 size_t codecs_param_end = mimetype_.find("\"", codecs_param_start);
591 CHECK_NE(codecs_param_end, std::string::npos);
593 std::string codecs_param =
594 mimetype_.substr(codecs_param_start,
595 codecs_param_end - codecs_param_start);
596 codecs = base::SplitString(
597 codecs_param, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
600 CHECK_EQ(chunk_demuxer_->AddId(kSourceId, type, codecs), ChunkDemuxer::kOk);
602 AppendData(initial_append_size_);
605 void OnEncryptedMediaInitData(EmeInitDataType init_data_type,
606 const std::vector<uint8_t>& init_data) {
607 DCHECK(!init_data.empty());
608 CHECK(!encrypted_media_init_data_cb_.is_null());
609 encrypted_media_init_data_cb_.Run(init_data_type, init_data);
612 base::TimeDelta last_timestamp_offset() const {
613 return last_timestamp_offset_;
616 MOCK_METHOD0(InitSegmentReceived, void(void));
618 private:
619 scoped_refptr<DecoderBuffer> file_data_;
620 int current_position_;
621 int initial_append_size_;
622 std::string mimetype_;
623 ChunkDemuxer* chunk_demuxer_;
624 scoped_ptr<Demuxer> owned_chunk_demuxer_;
625 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb_;
626 base::TimeDelta last_timestamp_offset_;
629 #if defined(MOJO_RENDERER)
630 class PipelineIntegrationTestHost : public mojo::test::ApplicationTestBase,
631 public PipelineIntegrationTestBase {
632 public:
633 bool ShouldCreateDefaultRunLoop() override { return false; }
635 void SetUp() override {
636 ApplicationTestBase::SetUp();
637 InitializeMediaLibrary();
640 protected:
641 scoped_ptr<Renderer> CreateRenderer() override {
642 mojo::URLRequestPtr request(mojo::URLRequest::New());
643 request->url = mojo::String::From("mojo:media");
644 mojo::ServiceProvider* service_provider =
645 application_impl()
646 ->ConnectToApplication(request.Pass())
647 ->GetServiceProvider();
649 mojo::ConnectToService(service_provider, &media_service_factory_);
651 interfaces::RendererPtr mojo_renderer;
652 media_service_factory_->CreateRenderer(mojo::GetProxy(&mojo_renderer));
654 return make_scoped_ptr(new MojoRendererImpl(message_loop_.task_runner(),
655 mojo_renderer.Pass()));
658 private:
659 interfaces::ServiceFactoryPtr media_service_factory_;
661 #else
662 class PipelineIntegrationTestHost : public testing::Test,
663 public PipelineIntegrationTestBase {};
664 #endif
666 class PipelineIntegrationTest : public PipelineIntegrationTestHost {
667 public:
668 void StartPipelineWithMediaSource(MockMediaSource* source) {
669 EXPECT_CALL(*source, InitSegmentReceived()).Times(AtLeast(1));
670 EXPECT_CALL(*this, OnMetadata(_))
671 .Times(AtMost(1))
672 .WillRepeatedly(SaveArg<0>(&metadata_));
673 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH))
674 .Times(AnyNumber());
675 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_NOTHING))
676 .Times(AnyNumber());
678 // Encrypted content not used, so this is never called.
679 EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0);
681 demuxer_ = source->GetDemuxer().Pass();
682 pipeline_->Start(
683 demuxer_.get(), CreateRenderer(),
684 base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)),
685 base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)),
686 base::Bind(&PipelineIntegrationTest::OnStatusCallback,
687 base::Unretained(this)),
688 base::Bind(&PipelineIntegrationTest::OnMetadata,
689 base::Unretained(this)),
690 base::Bind(&PipelineIntegrationTest::OnBufferingStateChanged,
691 base::Unretained(this)),
692 base::Closure(), base::Bind(&PipelineIntegrationTest::OnAddTextTrack,
693 base::Unretained(this)),
694 base::Bind(&PipelineIntegrationTest::OnWaitingForDecryptionKey,
695 base::Unretained(this)));
696 message_loop_.Run();
697 EXPECT_EQ(PIPELINE_OK, pipeline_status_);
700 void StartHashedPipelineWithMediaSource(MockMediaSource* source) {
701 hashing_enabled_ = true;
702 StartPipelineWithMediaSource(source);
705 void StartHashedClocklessPipelineWithMediaSource(MockMediaSource* source) {
706 hashing_enabled_ = true;
707 clockless_playback_ = true;
708 StartPipelineWithMediaSource(source);
711 void StartPipelineWithEncryptedMedia(
712 MockMediaSource* source,
713 FakeEncryptedMedia* encrypted_media) {
714 EXPECT_CALL(*source, InitSegmentReceived()).Times(AtLeast(1));
715 EXPECT_CALL(*this, OnMetadata(_))
716 .Times(AtMost(1))
717 .WillRepeatedly(SaveArg<0>(&metadata_));
718 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH))
719 .Times(AnyNumber());
720 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_NOTHING))
721 .Times(AnyNumber());
722 EXPECT_CALL(*this, DecryptorAttached(true));
724 // Encrypted content used but keys provided in advance, so this is
725 // never called.
726 EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0);
728 demuxer_ = source->GetDemuxer().Pass();
730 pipeline_->SetCdm(encrypted_media->GetCdmContext(),
731 base::Bind(&PipelineIntegrationTest::DecryptorAttached,
732 base::Unretained(this)));
734 pipeline_->Start(
735 demuxer_.get(), CreateRenderer(),
736 base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)),
737 base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)),
738 base::Bind(&PipelineIntegrationTest::OnStatusCallback,
739 base::Unretained(this)),
740 base::Bind(&PipelineIntegrationTest::OnMetadata,
741 base::Unretained(this)),
742 base::Bind(&PipelineIntegrationTest::OnBufferingStateChanged,
743 base::Unretained(this)),
744 base::Closure(), base::Bind(&PipelineIntegrationTest::OnAddTextTrack,
745 base::Unretained(this)),
746 base::Bind(&PipelineIntegrationTest::OnWaitingForDecryptionKey,
747 base::Unretained(this)));
749 source->set_encrypted_media_init_data_cb(
750 base::Bind(&FakeEncryptedMedia::OnEncryptedMediaInitData,
751 base::Unretained(encrypted_media)));
753 message_loop_.Run();
754 EXPECT_EQ(PIPELINE_OK, pipeline_status_);
757 // Verifies that seeking works properly for ChunkDemuxer when the
758 // seek happens while there is a pending read on the ChunkDemuxer
759 // and no data is available.
760 bool TestSeekDuringRead(const std::string& filename,
761 const std::string& mimetype,
762 int initial_append_size,
763 base::TimeDelta start_seek_time,
764 base::TimeDelta seek_time,
765 int seek_file_position,
766 int seek_append_size) {
767 MockMediaSource source(filename, mimetype, initial_append_size);
768 StartPipelineWithMediaSource(&source);
770 if (pipeline_status_ != PIPELINE_OK)
771 return false;
773 Play();
774 if (!WaitUntilCurrentTimeIsAfter(start_seek_time))
775 return false;
777 source.Seek(seek_time, seek_file_position, seek_append_size);
778 if (!Seek(seek_time))
779 return false;
781 source.EndOfStream();
783 source.Abort();
784 Stop();
785 return true;
789 TEST_F(PipelineIntegrationTest, BasicPlayback) {
790 ASSERT_EQ(PIPELINE_OK, Start("bear-320x240.webm"));
792 Play();
794 ASSERT_TRUE(WaitUntilOnEnded());
797 TEST_F(PipelineIntegrationTest, BasicPlaybackOpusOgg) {
798 ASSERT_EQ(PIPELINE_OK, Start("bear-opus.ogg"));
800 Play();
802 ASSERT_TRUE(WaitUntilOnEnded());
805 TEST_F(PipelineIntegrationTest, BasicPlaybackHashed) {
806 ASSERT_EQ(PIPELINE_OK, Start("bear-320x240.webm", kHashed));
808 Play();
810 ASSERT_TRUE(WaitUntilOnEnded());
812 EXPECT_HASH_EQ("f0be120a90a811506777c99a2cdf7cc1", GetVideoHash());
813 EXPECT_HASH_EQ("-3.59,-2.06,-0.43,2.15,0.77,-0.95,", GetAudioHash());
814 EXPECT_TRUE(demuxer_->GetTimelineOffset().is_null());
817 TEST_F(PipelineIntegrationTest, BasicPlaybackOpusOggTrimmingHashed) {
818 ASSERT_EQ(PIPELINE_OK,
819 Start("opus-trimming-test.webm", kHashed | kClockless));
821 Play();
823 ASSERT_TRUE(WaitUntilOnEnded());
824 EXPECT_HASH_EQ(kOpusEndTrimmingHash_1, GetAudioHash());
826 // Seek within the pre-skip section, this should not cause a beep.
827 ASSERT_TRUE(Seek(base::TimeDelta::FromSeconds(1)));
828 Play();
829 ASSERT_TRUE(WaitUntilOnEnded());
830 EXPECT_HASH_EQ(kOpusEndTrimmingHash_2, GetAudioHash());
832 // Seek somewhere outside of the pre-skip / end-trim section, demxuer should
833 // correctly preroll enough to accurately decode this segment.
834 ASSERT_TRUE(Seek(base::TimeDelta::FromMilliseconds(6360)));
835 Play();
836 ASSERT_TRUE(WaitUntilOnEnded());
837 EXPECT_HASH_EQ(kOpusEndTrimmingHash_3, GetAudioHash());
840 TEST_F(PipelineIntegrationTest, BasicPlaybackOpusWebmTrimmingHashed) {
841 ASSERT_EQ(PIPELINE_OK,
842 Start("opus-trimming-test.webm", kHashed | kClockless));
844 Play();
846 ASSERT_TRUE(WaitUntilOnEnded());
847 EXPECT_HASH_EQ(kOpusEndTrimmingHash_1, GetAudioHash());
849 // Seek within the pre-skip section, this should not cause a beep.
850 ASSERT_TRUE(Seek(base::TimeDelta::FromSeconds(1)));
851 Play();
852 ASSERT_TRUE(WaitUntilOnEnded());
853 EXPECT_HASH_EQ(kOpusEndTrimmingHash_2, GetAudioHash());
855 // Seek somewhere outside of the pre-skip / end-trim section, demxuer should
856 // correctly preroll enough to accurately decode this segment.
857 ASSERT_TRUE(Seek(base::TimeDelta::FromMilliseconds(6360)));
858 Play();
859 ASSERT_TRUE(WaitUntilOnEnded());
860 EXPECT_HASH_EQ(kOpusEndTrimmingHash_3, GetAudioHash());
863 TEST_F(PipelineIntegrationTest,
864 BasicPlaybackOpusWebmTrimmingHashed_MediaSource) {
865 MockMediaSource source("opus-trimming-test.webm", kOpusAudioOnlyWebM,
866 kAppendWholeFile);
867 StartHashedClocklessPipelineWithMediaSource(&source);
868 source.EndOfStream();
870 Play();
872 ASSERT_TRUE(WaitUntilOnEnded());
873 EXPECT_HASH_EQ(kOpusEndTrimmingHash_1, GetAudioHash());
875 // Seek within the pre-skip section, this should not cause a beep.
876 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(1);
877 source.Seek(seek_time);
878 ASSERT_TRUE(Seek(seek_time));
879 Play();
880 ASSERT_TRUE(WaitUntilOnEnded());
881 EXPECT_HASH_EQ(kOpusEndTrimmingHash_2, GetAudioHash());
883 // Seek somewhere outside of the pre-skip / end-trim section, demuxer should
884 // correctly preroll enough to accurately decode this segment.
885 seek_time = base::TimeDelta::FromMilliseconds(6360);
886 source.Seek(seek_time);
887 ASSERT_TRUE(Seek(seek_time));
888 Play();
889 ASSERT_TRUE(WaitUntilOnEnded());
890 EXPECT_HASH_EQ(kOpusEndTrimmingHash_3, GetAudioHash());
893 // TODO(dalecurtis): Add an opus test file which FFmpeg and ChunkDemuxer will
894 // both seek the same in and shows the difference of preroll.
895 // http://crbug.com/509894
897 TEST_F(PipelineIntegrationTest, BasicPlaybackLive) {
898 ASSERT_EQ(PIPELINE_OK, Start("bear-320x240-live.webm", kHashed));
900 Play();
902 ASSERT_TRUE(WaitUntilOnEnded());
904 EXPECT_HASH_EQ("f0be120a90a811506777c99a2cdf7cc1", GetVideoHash());
905 EXPECT_HASH_EQ("-3.59,-2.06,-0.43,2.15,0.77,-0.95,", GetAudioHash());
907 // TODO: Fix FFmpeg code to return higher resolution time values so
908 // we don't have to truncate our expectations here.
909 EXPECT_EQ(TruncateToFFmpegTimeResolution(kLiveTimelineOffset()),
910 demuxer_->GetTimelineOffset());
913 TEST_F(PipelineIntegrationTest, F32PlaybackHashed) {
914 ASSERT_EQ(PIPELINE_OK, Start("sfx_f32le.wav", kHashed));
915 Play();
916 ASSERT_TRUE(WaitUntilOnEnded());
917 EXPECT_HASH_EQ(std::string(kNullVideoHash), GetVideoHash());
918 EXPECT_HASH_EQ("3.03,2.86,2.99,3.31,3.57,4.06,", GetAudioHash());
921 #if !defined(DISABLE_EME_TESTS)
922 TEST_F(PipelineIntegrationTest, BasicPlaybackEncrypted) {
923 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
924 set_encrypted_media_init_data_cb(
925 base::Bind(&FakeEncryptedMedia::OnEncryptedMediaInitData,
926 base::Unretained(&encrypted_media)));
928 ASSERT_EQ(PIPELINE_OK, Start("bear-320x240-av_enc-av.webm",
929 encrypted_media.GetCdmContext()));
931 Play();
933 ASSERT_TRUE(WaitUntilOnEnded());
934 Stop();
936 #endif // !defined(DISABLE_EME_TESTS)
938 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource) {
939 MockMediaSource source("bear-320x240.webm", kWebM, 219229);
940 StartPipelineWithMediaSource(&source);
941 source.EndOfStream();
943 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
944 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
945 EXPECT_EQ(k320WebMFileDurationMs,
946 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
948 Play();
950 ASSERT_TRUE(WaitUntilOnEnded());
952 EXPECT_TRUE(demuxer_->GetTimelineOffset().is_null());
953 source.Abort();
954 Stop();
957 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_Live) {
958 MockMediaSource source("bear-320x240-live.webm", kWebM, 219221);
959 StartPipelineWithMediaSource(&source);
960 source.EndOfStream();
962 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
963 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
964 EXPECT_EQ(k320WebMFileDurationMs,
965 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
967 Play();
969 ASSERT_TRUE(WaitUntilOnEnded());
971 EXPECT_EQ(kLiveTimelineOffset(),
972 demuxer_->GetTimelineOffset());
973 source.Abort();
974 Stop();
977 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_VP9_WebM) {
978 MockMediaSource source("bear-vp9.webm", kWebMVP9, 67504);
979 StartPipelineWithMediaSource(&source);
980 source.EndOfStream();
982 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
983 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
984 EXPECT_EQ(kVP9WebMFileDurationMs,
985 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
987 Play();
989 ASSERT_TRUE(WaitUntilOnEnded());
990 source.Abort();
991 Stop();
994 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_VP8A_WebM) {
995 MockMediaSource source("bear-vp8a.webm", kVideoOnlyWebM, kAppendWholeFile);
996 StartPipelineWithMediaSource(&source);
997 source.EndOfStream();
999 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1000 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1001 EXPECT_EQ(kVP8AWebMFileDurationMs,
1002 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1004 Play();
1006 ASSERT_TRUE(WaitUntilOnEnded());
1007 source.Abort();
1008 Stop();
1011 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_Opus_WebM) {
1012 MockMediaSource source("bear-opus-end-trimming.webm", kOpusAudioOnlyWebM,
1013 kAppendWholeFile);
1014 StartPipelineWithMediaSource(&source);
1015 source.EndOfStream();
1017 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1018 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1019 EXPECT_EQ(kOpusEndTrimmingWebMFileDurationMs,
1020 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1021 Play();
1023 ASSERT_TRUE(WaitUntilOnEnded());
1024 source.Abort();
1025 Stop();
1028 // Flaky. http://crbug.com/304776
1029 TEST_F(PipelineIntegrationTest, DISABLED_MediaSource_Opus_Seeking_WebM) {
1030 MockMediaSource source("bear-opus-end-trimming.webm", kOpusAudioOnlyWebM,
1031 kAppendWholeFile);
1032 StartHashedPipelineWithMediaSource(&source);
1034 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1035 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1036 EXPECT_EQ(kOpusEndTrimmingWebMFileDurationMs,
1037 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1039 base::TimeDelta start_seek_time = base::TimeDelta::FromMilliseconds(1000);
1040 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(2000);
1042 Play();
1043 ASSERT_TRUE(WaitUntilCurrentTimeIsAfter(start_seek_time));
1044 source.Seek(seek_time, 0x1D5, 34017);
1045 source.EndOfStream();
1046 ASSERT_TRUE(Seek(seek_time));
1048 ASSERT_TRUE(WaitUntilOnEnded());
1050 EXPECT_HASH_EQ("0.76,0.20,-0.82,-0.58,-1.29,-0.29,", GetAudioHash());
1052 source.Abort();
1053 Stop();
1056 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_WebM) {
1057 MockMediaSource source("bear-320x240-16x9-aspect.webm", kWebM,
1058 kAppendWholeFile);
1059 StartPipelineWithMediaSource(&source);
1061 scoped_refptr<DecoderBuffer> second_file =
1062 ReadTestDataFile("bear-640x360.webm");
1064 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1065 second_file->data(), second_file->data_size());
1067 source.EndOfStream();
1069 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1070 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1071 EXPECT_EQ(kAppendTimeMs + k640WebMFileDurationMs,
1072 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1074 Play();
1076 EXPECT_TRUE(WaitUntilOnEnded());
1077 source.Abort();
1078 Stop();
1081 #if !defined(DISABLE_EME_TESTS)
1082 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_Encrypted_WebM) {
1083 MockMediaSource source("bear-320x240-16x9-aspect-av_enc-av.webm", kWebM,
1084 kAppendWholeFile);
1085 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1086 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1088 scoped_refptr<DecoderBuffer> second_file =
1089 ReadTestDataFile("bear-640x360-av_enc-av.webm");
1091 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1092 second_file->data(), second_file->data_size());
1094 source.EndOfStream();
1096 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1097 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1098 EXPECT_EQ(kAppendTimeMs + k640WebMFileDurationMs,
1099 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1101 Play();
1103 EXPECT_TRUE(WaitUntilOnEnded());
1104 source.Abort();
1105 Stop();
1108 // Config changes from encrypted to clear are not currently supported.
1109 TEST_F(PipelineIntegrationTest,
1110 MediaSource_ConfigChange_ClearThenEncrypted_WebM) {
1111 MockMediaSource source("bear-320x240-16x9-aspect.webm", kWebM,
1112 kAppendWholeFile);
1113 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1114 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1116 scoped_refptr<DecoderBuffer> second_file =
1117 ReadTestDataFile("bear-640x360-av_enc-av.webm");
1119 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1120 second_file->data(), second_file->data_size());
1122 source.EndOfStream();
1124 message_loop_.Run();
1125 EXPECT_EQ(PIPELINE_ERROR_DECODE, pipeline_status_);
1127 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1128 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1129 // The second video was not added, so its time has not been added.
1130 EXPECT_EQ(k320WebMFileDurationMs,
1131 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1133 Play();
1135 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
1136 source.Abort();
1139 // Config changes from clear to encrypted are not currently supported.
1140 TEST_F(PipelineIntegrationTest,
1141 MediaSource_ConfigChange_EncryptedThenClear_WebM) {
1142 MockMediaSource source("bear-320x240-16x9-aspect-av_enc-av.webm", kWebM,
1143 kAppendWholeFile);
1144 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1145 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1147 scoped_refptr<DecoderBuffer> second_file =
1148 ReadTestDataFile("bear-640x360.webm");
1150 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1151 second_file->data(), second_file->data_size());
1153 source.EndOfStream();
1155 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1156 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1157 // The second video was not added, so its time has not been added.
1158 EXPECT_EQ(k320EncWebMFileDurationMs,
1159 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1161 Play();
1163 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
1164 source.Abort();
1166 #endif // !defined(DISABLE_EME_TESTS)
1168 #if defined(USE_PROPRIETARY_CODECS)
1169 TEST_F(PipelineIntegrationTest, MediaSource_ADTS) {
1170 MockMediaSource source("sfx.adts", kADTS, kAppendWholeFile);
1171 StartPipelineWithMediaSource(&source);
1172 source.EndOfStream();
1174 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1175 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1176 EXPECT_EQ(325, pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1178 Play();
1180 EXPECT_TRUE(WaitUntilOnEnded());
1183 TEST_F(PipelineIntegrationTest, MediaSource_ADTS_TimestampOffset) {
1184 MockMediaSource source("sfx.adts", kADTS, kAppendWholeFile);
1185 StartHashedPipelineWithMediaSource(&source);
1186 EXPECT_EQ(325, source.last_timestamp_offset().InMilliseconds());
1188 // Trim off multiple frames off the beginning of the segment which will cause
1189 // the first decoded frame to be incorrect if preroll isn't implemented.
1190 const base::TimeDelta adts_preroll_duration =
1191 base::TimeDelta::FromSecondsD(2.5 * 1024 / 44100);
1192 const base::TimeDelta append_time =
1193 source.last_timestamp_offset() - adts_preroll_duration;
1195 scoped_refptr<DecoderBuffer> second_file = ReadTestDataFile("sfx.adts");
1196 source.AppendAtTimeWithWindow(append_time,
1197 append_time + adts_preroll_duration,
1198 kInfiniteDuration(),
1199 second_file->data(),
1200 second_file->data_size());
1201 source.EndOfStream();
1203 EXPECT_EQ(592, source.last_timestamp_offset().InMilliseconds());
1204 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1205 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1206 EXPECT_EQ(592, pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1208 Play();
1210 EXPECT_TRUE(WaitUntilOnEnded());
1212 // Verify preroll is stripped.
1213 EXPECT_HASH_EQ("-0.06,0.97,-0.90,-0.70,-0.53,-0.34,", GetAudioHash());
1216 TEST_F(PipelineIntegrationTest, BasicPlaybackHashed_MP3) {
1217 ASSERT_EQ(PIPELINE_OK, Start("sfx.mp3", kHashed));
1219 Play();
1221 ASSERT_TRUE(WaitUntilOnEnded());
1223 // Verify codec delay and preroll are stripped.
1224 EXPECT_HASH_EQ("1.30,2.72,4.56,5.08,3.74,2.03,", GetAudioHash());
1227 TEST_F(PipelineIntegrationTest, MediaSource_MP3) {
1228 MockMediaSource source("sfx.mp3", kMP3, kAppendWholeFile);
1229 StartHashedPipelineWithMediaSource(&source);
1230 source.EndOfStream();
1232 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1233 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1234 EXPECT_EQ(313, pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1236 Play();
1238 EXPECT_TRUE(WaitUntilOnEnded());
1240 // Verify that codec delay was stripped.
1241 EXPECT_HASH_EQ("1.01,2.71,4.18,4.32,3.04,1.12,", GetAudioHash());
1244 TEST_F(PipelineIntegrationTest, MediaSource_MP3_TimestampOffset) {
1245 MockMediaSource source("sfx.mp3", kMP3, kAppendWholeFile);
1246 StartPipelineWithMediaSource(&source);
1247 EXPECT_EQ(313, source.last_timestamp_offset().InMilliseconds());
1249 // There are 576 silent frames at the start of this mp3. The second append
1250 // should trim them off.
1251 const base::TimeDelta mp3_preroll_duration =
1252 base::TimeDelta::FromSecondsD(576.0 / 44100);
1253 const base::TimeDelta append_time =
1254 source.last_timestamp_offset() - mp3_preroll_duration;
1256 scoped_refptr<DecoderBuffer> second_file = ReadTestDataFile("sfx.mp3");
1257 source.AppendAtTimeWithWindow(append_time,
1258 append_time + mp3_preroll_duration,
1259 kInfiniteDuration(),
1260 second_file->data(),
1261 second_file->data_size());
1262 source.EndOfStream();
1264 EXPECT_EQ(613, source.last_timestamp_offset().InMilliseconds());
1265 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1266 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1267 EXPECT_EQ(613, pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1269 Play();
1271 EXPECT_TRUE(WaitUntilOnEnded());
1274 TEST_F(PipelineIntegrationTest, MediaSource_MP3_Icecast) {
1275 MockMediaSource source("icy_sfx.mp3", kMP3, kAppendWholeFile);
1276 StartPipelineWithMediaSource(&source);
1277 source.EndOfStream();
1279 Play();
1281 EXPECT_TRUE(WaitUntilOnEnded());
1284 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_MP4) {
1285 MockMediaSource source("bear-640x360-av_frag.mp4", kMP4, kAppendWholeFile);
1286 StartPipelineWithMediaSource(&source);
1288 scoped_refptr<DecoderBuffer> second_file =
1289 ReadTestDataFile("bear-1280x720-av_frag.mp4");
1291 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1292 second_file->data(), second_file->data_size());
1294 source.EndOfStream();
1296 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1297 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1298 EXPECT_EQ(kAppendTimeMs + k1280IsoFileDurationMs,
1299 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1301 Play();
1303 EXPECT_TRUE(WaitUntilOnEnded());
1304 source.Abort();
1305 Stop();
1308 #if !defined(DISABLE_EME_TESTS)
1309 TEST_F(PipelineIntegrationTest,
1310 MediaSource_ConfigChange_Encrypted_MP4_CENC_VideoOnly) {
1311 MockMediaSource source("bear-640x360-v_frag-cenc.mp4", kMP4Video,
1312 kAppendWholeFile);
1313 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1314 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1316 scoped_refptr<DecoderBuffer> second_file =
1317 ReadTestDataFile("bear-1280x720-v_frag-cenc.mp4");
1319 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1320 second_file->data(), second_file->data_size());
1322 source.EndOfStream();
1324 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1325 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1326 EXPECT_EQ(kAppendTimeMs + k1280IsoFileDurationMs,
1327 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1329 Play();
1331 EXPECT_TRUE(WaitUntilOnEnded());
1332 source.Abort();
1333 Stop();
1336 TEST_F(PipelineIntegrationTest,
1337 MediaSource_ConfigChange_Encrypted_MP4_CENC_KeyRotation_VideoOnly) {
1338 MockMediaSource source("bear-640x360-v_frag-cenc-key_rotation.mp4", kMP4Video,
1339 kAppendWholeFile);
1340 FakeEncryptedMedia encrypted_media(new RotatingKeyProvidingApp());
1341 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1343 scoped_refptr<DecoderBuffer> second_file =
1344 ReadTestDataFile("bear-1280x720-v_frag-cenc-key_rotation.mp4");
1346 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1347 second_file->data(), second_file->data_size());
1349 source.EndOfStream();
1351 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1352 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1353 EXPECT_EQ(kAppendTimeMs + k1280IsoFileDurationMs,
1354 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1356 Play();
1358 EXPECT_TRUE(WaitUntilOnEnded());
1359 source.Abort();
1360 Stop();
1363 // Config changes from clear to encrypted are not currently supported.
1364 // TODO(ddorwin): Figure out why this CHECKs in AppendAtTime().
1365 TEST_F(PipelineIntegrationTest,
1366 DISABLED_MediaSource_ConfigChange_ClearThenEncrypted_MP4_CENC) {
1367 MockMediaSource source("bear-640x360-av_frag.mp4", kMP4Video,
1368 kAppendWholeFile);
1369 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1370 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1372 scoped_refptr<DecoderBuffer> second_file =
1373 ReadTestDataFile("bear-1280x720-v_frag-cenc.mp4");
1375 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1376 second_file->data(), second_file->data_size());
1378 source.EndOfStream();
1380 message_loop_.Run();
1381 EXPECT_EQ(PIPELINE_ERROR_DECODE, pipeline_status_);
1383 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1384 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1385 // The second video was not added, so its time has not been added.
1386 EXPECT_EQ(k640IsoFileDurationMs,
1387 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1389 Play();
1391 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
1392 source.Abort();
1395 // Config changes from encrypted to clear are not currently supported.
1396 TEST_F(PipelineIntegrationTest,
1397 MediaSource_ConfigChange_EncryptedThenClear_MP4_CENC) {
1398 MockMediaSource source("bear-640x360-v_frag-cenc.mp4", kMP4Video,
1399 kAppendWholeFile);
1400 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1401 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1403 scoped_refptr<DecoderBuffer> second_file =
1404 ReadTestDataFile("bear-1280x720-av_frag.mp4");
1406 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1407 second_file->data(), second_file->data_size());
1409 source.EndOfStream();
1411 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1412 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1413 // The second video was not added, so its time has not been added.
1414 EXPECT_EQ(k640IsoCencFileDurationMs,
1415 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1417 Play();
1419 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
1420 source.Abort();
1422 #endif // !defined(DISABLE_EME_TESTS)
1424 // Verify files which change configuration midstream fail gracefully.
1425 TEST_F(PipelineIntegrationTest, MidStreamConfigChangesFail) {
1426 ASSERT_EQ(PIPELINE_OK, Start("midstream_config_change.mp3"));
1427 Play();
1428 ASSERT_EQ(WaitUntilEndedOrError(), PIPELINE_ERROR_DECODE);
1431 #endif
1433 TEST_F(PipelineIntegrationTest, BasicPlayback_16x9AspectRatio) {
1434 ASSERT_EQ(PIPELINE_OK, Start("bear-320x240-16x9-aspect.webm"));
1435 Play();
1436 ASSERT_TRUE(WaitUntilOnEnded());
1439 #if !defined(DISABLE_EME_TESTS)
1440 TEST_F(PipelineIntegrationTest, EncryptedPlayback_WebM) {
1441 MockMediaSource source("bear-320x240-av_enc-av.webm", kWebM, 219816);
1442 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1443 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1445 source.EndOfStream();
1446 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1448 Play();
1450 ASSERT_TRUE(WaitUntilOnEnded());
1451 source.Abort();
1452 Stop();
1455 TEST_F(PipelineIntegrationTest, EncryptedPlayback_ClearStart_WebM) {
1456 MockMediaSource source("bear-320x240-av_enc-av_clear-1s.webm", kWebM,
1457 kAppendWholeFile);
1458 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1459 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1461 source.EndOfStream();
1462 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1464 Play();
1466 ASSERT_TRUE(WaitUntilOnEnded());
1467 source.Abort();
1468 Stop();
1471 TEST_F(PipelineIntegrationTest, EncryptedPlayback_NoEncryptedFrames_WebM) {
1472 MockMediaSource source("bear-320x240-av_enc-av_clear-all.webm", kWebM,
1473 kAppendWholeFile);
1474 FakeEncryptedMedia encrypted_media(new NoResponseApp());
1475 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1477 source.EndOfStream();
1478 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1480 Play();
1482 ASSERT_TRUE(WaitUntilOnEnded());
1483 source.Abort();
1484 Stop();
1486 #endif // !defined(DISABLE_EME_TESTS)
1488 #if defined(USE_PROPRIETARY_CODECS)
1489 #if !defined(DISABLE_EME_TESTS)
1490 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_VideoOnly) {
1491 MockMediaSource source("bear-1280x720-v_frag-cenc.mp4", kMP4Video,
1492 kAppendWholeFile);
1493 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1494 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1496 source.EndOfStream();
1497 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1499 Play();
1501 ASSERT_TRUE(WaitUntilOnEnded());
1502 source.Abort();
1503 Stop();
1506 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_AudioOnly) {
1507 MockMediaSource source("bear-1280x720-a_frag-cenc.mp4", kMP4Audio,
1508 kAppendWholeFile);
1509 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1510 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1512 source.EndOfStream();
1513 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1515 Play();
1517 ASSERT_TRUE(WaitUntilOnEnded());
1518 source.Abort();
1519 Stop();
1522 TEST_F(PipelineIntegrationTest,
1523 EncryptedPlayback_NoEncryptedFrames_MP4_CENC_VideoOnly) {
1524 MockMediaSource source("bear-1280x720-v_frag-cenc_clear-all.mp4", kMP4Video,
1525 kAppendWholeFile);
1526 FakeEncryptedMedia encrypted_media(new NoResponseApp());
1527 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1529 source.EndOfStream();
1530 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1532 Play();
1534 ASSERT_TRUE(WaitUntilOnEnded());
1535 source.Abort();
1536 Stop();
1539 TEST_F(PipelineIntegrationTest,
1540 EncryptedPlayback_NoEncryptedFrames_MP4_CENC_AudioOnly) {
1541 MockMediaSource source("bear-1280x720-a_frag-cenc_clear-all.mp4", kMP4Audio,
1542 kAppendWholeFile);
1543 FakeEncryptedMedia encrypted_media(new NoResponseApp());
1544 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1546 source.EndOfStream();
1547 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1549 Play();
1551 ASSERT_TRUE(WaitUntilOnEnded());
1552 source.Abort();
1553 Stop();
1556 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_KeyRotation_Video) {
1557 MockMediaSource source("bear-1280x720-v_frag-cenc-key_rotation.mp4",
1558 kMP4Video, kAppendWholeFile);
1559 FakeEncryptedMedia encrypted_media(new RotatingKeyProvidingApp());
1560 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1562 source.EndOfStream();
1563 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1565 Play();
1567 ASSERT_TRUE(WaitUntilOnEnded());
1568 source.Abort();
1569 Stop();
1572 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_KeyRotation_Audio) {
1573 MockMediaSource source("bear-1280x720-a_frag-cenc-key_rotation.mp4",
1574 kMP4Audio, kAppendWholeFile);
1575 FakeEncryptedMedia encrypted_media(new RotatingKeyProvidingApp());
1576 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1578 source.EndOfStream();
1579 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1581 Play();
1583 ASSERT_TRUE(WaitUntilOnEnded());
1584 source.Abort();
1585 Stop();
1587 #endif // !defined(DISABLE_EME_TESTS)
1589 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_VideoOnly_MP4_AVC3) {
1590 MockMediaSource source("bear-1280x720-v_frag-avc3.mp4", kMP4VideoAVC3,
1591 kAppendWholeFile);
1592 StartPipelineWithMediaSource(&source);
1593 source.EndOfStream();
1595 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1596 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1597 EXPECT_EQ(k1280IsoAVC3FileDurationMs,
1598 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1600 Play();
1602 ASSERT_TRUE(WaitUntilOnEnded());
1603 source.Abort();
1604 Stop();
1606 #endif // defined(USE_PROPRIETARY_CODECS)
1608 TEST_F(PipelineIntegrationTest, SeekWhilePaused) {
1609 ASSERT_EQ(PIPELINE_OK, Start("bear-320x240.webm"));
1611 base::TimeDelta duration(pipeline_->GetMediaDuration());
1612 base::TimeDelta start_seek_time(duration / 4);
1613 base::TimeDelta seek_time(duration * 3 / 4);
1615 Play();
1616 ASSERT_TRUE(WaitUntilCurrentTimeIsAfter(start_seek_time));
1617 Pause();
1618 ASSERT_TRUE(Seek(seek_time));
1619 EXPECT_EQ(seek_time, pipeline_->GetMediaTime());
1620 Play();
1621 ASSERT_TRUE(WaitUntilOnEnded());
1623 // Make sure seeking after reaching the end works as expected.
1624 Pause();
1625 ASSERT_TRUE(Seek(seek_time));
1626 EXPECT_EQ(seek_time, pipeline_->GetMediaTime());
1627 Play();
1628 ASSERT_TRUE(WaitUntilOnEnded());
1631 TEST_F(PipelineIntegrationTest, SeekWhilePlaying) {
1632 ASSERT_EQ(PIPELINE_OK, Start("bear-320x240.webm"));
1634 base::TimeDelta duration(pipeline_->GetMediaDuration());
1635 base::TimeDelta start_seek_time(duration / 4);
1636 base::TimeDelta seek_time(duration * 3 / 4);
1638 Play();
1639 ASSERT_TRUE(WaitUntilCurrentTimeIsAfter(start_seek_time));
1640 ASSERT_TRUE(Seek(seek_time));
1641 EXPECT_GE(pipeline_->GetMediaTime(), seek_time);
1642 ASSERT_TRUE(WaitUntilOnEnded());
1644 // Make sure seeking after reaching the end works as expected.
1645 ASSERT_TRUE(Seek(seek_time));
1646 EXPECT_GE(pipeline_->GetMediaTime(), seek_time);
1647 ASSERT_TRUE(WaitUntilOnEnded());
1650 #if defined(USE_PROPRIETARY_CODECS)
1651 TEST_F(PipelineIntegrationTest, Rotated_Metadata_0) {
1652 ASSERT_EQ(PIPELINE_OK, Start("bear_rotate_0.mp4"));
1653 ASSERT_EQ(VIDEO_ROTATION_0, metadata_.video_rotation);
1656 TEST_F(PipelineIntegrationTest, Rotated_Metadata_90) {
1657 ASSERT_EQ(PIPELINE_OK, Start("bear_rotate_90.mp4"));
1658 ASSERT_EQ(VIDEO_ROTATION_90, metadata_.video_rotation);
1661 TEST_F(PipelineIntegrationTest, Rotated_Metadata_180) {
1662 ASSERT_EQ(PIPELINE_OK, Start("bear_rotate_180.mp4"));
1663 ASSERT_EQ(VIDEO_ROTATION_180, metadata_.video_rotation);
1666 TEST_F(PipelineIntegrationTest, Rotated_Metadata_270) {
1667 ASSERT_EQ(PIPELINE_OK, Start("bear_rotate_270.mp4"));
1668 ASSERT_EQ(VIDEO_ROTATION_270, metadata_.video_rotation);
1670 #endif
1672 // Verify audio decoder & renderer can handle aborted demuxer reads.
1673 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_AudioOnly) {
1674 ASSERT_TRUE(TestSeekDuringRead("bear-320x240-audio-only.webm", kAudioOnlyWebM,
1675 16384,
1676 base::TimeDelta::FromMilliseconds(464),
1677 base::TimeDelta::FromMilliseconds(617),
1678 0x10CA, 19730));
1681 // Verify video decoder & renderer can handle aborted demuxer reads.
1682 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_VideoOnly) {
1683 ASSERT_TRUE(TestSeekDuringRead("bear-320x240-video-only.webm", kVideoOnlyWebM,
1684 32768,
1685 base::TimeDelta::FromMilliseconds(167),
1686 base::TimeDelta::FromMilliseconds(1668),
1687 0x1C896, 65536));
1690 // Verify that Opus audio in WebM containers can be played back.
1691 TEST_F(PipelineIntegrationTest, BasicPlayback_AudioOnly_Opus_WebM) {
1692 ASSERT_EQ(PIPELINE_OK, Start("bear-opus-end-trimming.webm"));
1693 Play();
1694 ASSERT_TRUE(WaitUntilOnEnded());
1697 // Verify that VP9 video in WebM containers can be played back.
1698 TEST_F(PipelineIntegrationTest, BasicPlayback_VideoOnly_VP9_WebM) {
1699 ASSERT_EQ(PIPELINE_OK, Start("bear-vp9.webm"));
1700 Play();
1701 ASSERT_TRUE(WaitUntilOnEnded());
1704 // Verify that VP9 video and Opus audio in the same WebM container can be played
1705 // back.
1706 TEST_F(PipelineIntegrationTest, BasicPlayback_VP9_Opus_WebM) {
1707 ASSERT_EQ(PIPELINE_OK, Start("bear-vp9-opus.webm"));
1708 Play();
1709 ASSERT_TRUE(WaitUntilOnEnded());
1712 // Verify that VP8 video with alpha channel can be played back.
1713 TEST_F(PipelineIntegrationTest, BasicPlayback_VP8A_WebM) {
1714 ASSERT_EQ(PIPELINE_OK, Start("bear-vp8a.webm"));
1715 Play();
1716 ASSERT_TRUE(WaitUntilOnEnded());
1717 EXPECT_VIDEO_FORMAT_EQ(last_video_frame_format_, PIXEL_FORMAT_YV12A);
1720 // Verify that VP8A video with odd width/height can be played back.
1721 TEST_F(PipelineIntegrationTest, BasicPlayback_VP8A_Odd_WebM) {
1722 ASSERT_EQ(PIPELINE_OK, Start("bear-vp8a-odd-dimensions.webm"));
1723 Play();
1724 ASSERT_TRUE(WaitUntilOnEnded());
1725 EXPECT_VIDEO_FORMAT_EQ(last_video_frame_format_, PIXEL_FORMAT_YV12A);
1728 // Verify that VP9 video with odd width/height can be played back.
1729 TEST_F(PipelineIntegrationTest, BasicPlayback_VP9_Odd_WebM) {
1730 ASSERT_EQ(PIPELINE_OK, Start("bear-vp9-odd-dimensions.webm"));
1731 Play();
1732 ASSERT_TRUE(WaitUntilOnEnded());
1735 #if !defined(DISABLE_TEXT_TRACK_TESTS)
1736 // Verify that VP8 video with inband text track can be played back.
1737 TEST_F(PipelineIntegrationTest, BasicPlayback_VP8_WebVTT_WebM) {
1738 EXPECT_CALL(*this, OnAddTextTrack(_, _));
1739 ASSERT_EQ(PIPELINE_OK, Start("bear-vp8-webvtt.webm"));
1740 Play();
1741 ASSERT_TRUE(WaitUntilOnEnded());
1743 #endif // !defined(DISABLE_TEXT_TRACK_TESTS)
1745 // Verify that VP9 video with 4:4:4 subsampling can be played back.
1746 TEST_F(PipelineIntegrationTest, P444_VP9_WebM) {
1747 ASSERT_EQ(PIPELINE_OK, Start("bear-320x240-P444.webm"));
1748 Play();
1749 ASSERT_TRUE(WaitUntilOnEnded());
1750 EXPECT_VIDEO_FORMAT_EQ(last_video_frame_format_, PIXEL_FORMAT_YV24);
1753 // Verify that frames of VP9 video in the BT.709 color space have the YV12HD
1754 // format.
1755 TEST_F(PipelineIntegrationTest, BT709_VP9_WebM) {
1756 ASSERT_EQ(PIPELINE_OK, Start("bear-vp9-bt709.webm"));
1757 Play();
1758 ASSERT_TRUE(WaitUntilOnEnded());
1759 EXPECT_VIDEO_FORMAT_EQ(last_video_frame_format_, PIXEL_FORMAT_YV12);
1760 EXPECT_COLOR_SPACE_EQ(last_video_frame_color_space_, COLOR_SPACE_HD_REC709);
1763 // Verify that videos with an odd frame size playback successfully.
1764 TEST_F(PipelineIntegrationTest, BasicPlayback_OddVideoSize) {
1765 ASSERT_EQ(PIPELINE_OK, Start("butterfly-853x480.webm"));
1766 Play();
1767 ASSERT_TRUE(WaitUntilOnEnded());
1770 // Verify that OPUS audio in a webm which reports a 44.1kHz sample rate plays
1771 // correctly at 48kHz
1772 TEST_F(PipelineIntegrationTest, BasicPlayback_Opus441kHz) {
1773 ASSERT_EQ(PIPELINE_OK, Start("sfx-opus-441.webm"));
1774 Play();
1775 ASSERT_TRUE(WaitUntilOnEnded());
1776 EXPECT_EQ(48000,
1777 demuxer_->GetStream(DemuxerStream::AUDIO)
1778 ->audio_decoder_config()
1779 .samples_per_second());
1782 // Same as above but using MediaSource.
1783 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_Opus441kHz) {
1784 MockMediaSource source(
1785 "sfx-opus-441.webm", kOpusAudioOnlyWebM, kAppendWholeFile);
1786 StartPipelineWithMediaSource(&source);
1787 source.EndOfStream();
1788 Play();
1789 ASSERT_TRUE(WaitUntilOnEnded());
1790 source.Abort();
1791 Stop();
1792 EXPECT_EQ(48000,
1793 demuxer_->GetStream(DemuxerStream::AUDIO)
1794 ->audio_decoder_config()
1795 .samples_per_second());
1798 // Ensures audio-only playback with missing or negative timestamps works. Tests
1799 // the common live-streaming case for chained ogg. See http://crbug.com/396864.
1800 TEST_F(PipelineIntegrationTest, BasicPlaybackChainedOgg) {
1801 ASSERT_EQ(PIPELINE_OK, Start("double-sfx.ogg"));
1802 Play();
1803 ASSERT_TRUE(WaitUntilOnEnded());
1804 ASSERT_EQ(base::TimeDelta(), demuxer_->GetStartTime());
1807 // Ensures audio-video playback with missing or negative timestamps fails softly
1808 // instead of crashing. See http://crbug.com/396864.
1809 TEST_F(PipelineIntegrationTest, BasicPlaybackChainedOggVideo) {
1810 ASSERT_EQ(PIPELINE_OK, Start("double-bear.ogv"));
1811 Play();
1812 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
1813 ASSERT_EQ(base::TimeDelta(), demuxer_->GetStartTime());
1816 // Tests that we signal ended even when audio runs longer than video track.
1817 TEST_F(PipelineIntegrationTest, BasicPlaybackAudioLongerThanVideo) {
1818 ASSERT_EQ(PIPELINE_OK, Start("bear_audio_longer_than_video.ogv"));
1819 // Audio track is 2000ms. Video track is 1001ms. Duration should be higher
1820 // of the two.
1821 EXPECT_EQ(2000, pipeline_->GetMediaDuration().InMilliseconds());
1822 Play();
1823 ASSERT_TRUE(WaitUntilOnEnded());
1826 // Tests that we signal ended even when audio runs shorter than video track.
1827 TEST_F(PipelineIntegrationTest, BasicPlaybackAudioShorterThanVideo) {
1828 ASSERT_EQ(PIPELINE_OK, Start("bear_audio_shorter_than_video.ogv"));
1829 // Audio track is 500ms. Video track is 1001ms. Duration should be higher of
1830 // the two.
1831 EXPECT_EQ(1001, pipeline_->GetMediaDuration().InMilliseconds());
1832 Play();
1833 ASSERT_TRUE(WaitUntilOnEnded());
1836 TEST_F(PipelineIntegrationTest, BasicPlaybackPositiveStartTime) {
1837 ASSERT_EQ(PIPELINE_OK, Start("nonzero-start-time.webm"));
1838 Play();
1839 ASSERT_TRUE(WaitUntilOnEnded());
1840 ASSERT_EQ(base::TimeDelta::FromMicroseconds(396000),
1841 demuxer_->GetStartTime());
1844 } // namespace media