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.
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"
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
49 #define DISABLE_TEXT_TRACK_TESTS 1
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)
57 using testing::AnyNumber
;
58 using testing::AtLeast
;
59 using testing::AtMost
;
60 using testing::SaveArg
;
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,";
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)
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
{
173 // Defines the behavior of the "app" that responds to EME events.
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_
),
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
,
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
,
244 void OnEncryptedMediaInitData(EmeInitDataType init_data_type
,
245 const std::vector
<uint8_t>& init_data
) {
246 app_
->OnEncryptedMediaInitData(init_data_type
, init_data
, &decryptor_
);
250 class TestCdmContext
: public CdmContext
{
252 TestCdmContext(Decryptor
* decryptor
) : decryptor_(decryptor
) {}
254 Decryptor
* GetDecryptor() final
{ return decryptor_
; }
255 int GetCdmId() const final
{ return kInvalidCdmId
; }
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
{
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
<>(
294 &KeyProvidingApp::OnResolve
, base::Unretained(this), expected
),
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),
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());
326 std::string error_message
;
327 EXPECT_TRUE(ExtractKeyIdsFromKeyIdsInitData(message_string
, &key_ids
,
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.
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_
)
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
));
382 std::string current_session_id_
;
383 std::vector
<uint8_t> prev_init_data_
;
386 class RotatingKeyProvidingApp
: public KeyProvidingApp
{
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_
)
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());
429 uint32_t num_distinct_need_key_calls_
;
432 // Ignores needkey and does not perform a license request
433 class NoResponseApp
: public FakeEncryptedMedia::AppBase
{
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
464 class MockMediaSource
{
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
),
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()),
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(
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
,
531 CHECK(!chunk_demuxer_
->IsParsingMediaSegment(kSourceId
));
532 chunk_demuxer_
->AppendData(kSourceId
, pData
, size
,
533 base::TimeDelta(), kInfiniteDuration(),
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
,
545 CHECK(!chunk_demuxer_
->IsParsingMediaSegment(kSourceId
));
546 chunk_demuxer_
->AppendData(kSourceId
,
552 base::Bind(&MockMediaSource::InitSegmentReceived
,
553 base::Unretained(this)));
554 last_timestamp_offset_
= timestamp_offset
;
558 chunk_demuxer_
->MarkEndOfStream(PIPELINE_OK
);
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.
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));
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
{
633 bool ShouldCreateDefaultRunLoop() override
{ return false; }
635 void SetUp() override
{
636 ApplicationTestBase::SetUp();
637 InitializeMediaLibrary();
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
=
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()));
659 interfaces::ServiceFactoryPtr media_service_factory_
;
662 class PipelineIntegrationTestHost
: public testing::Test
,
663 public PipelineIntegrationTestBase
{};
666 class PipelineIntegrationTest
: public PipelineIntegrationTestHost
{
668 void StartPipelineWithMediaSource(MockMediaSource
* source
) {
669 EXPECT_CALL(*source
, InitSegmentReceived()).Times(AtLeast(1));
670 EXPECT_CALL(*this, OnMetadata(_
))
672 .WillRepeatedly(SaveArg
<0>(&metadata_
));
673 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH
))
675 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_NOTHING
))
678 // Encrypted content not used, so this is never called.
679 EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0);
681 demuxer_
= source
->GetDemuxer().Pass();
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)));
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(_
))
717 .WillRepeatedly(SaveArg
<0>(&metadata_
));
718 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH
))
720 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_NOTHING
))
722 EXPECT_CALL(*this, DecryptorAttached(true));
724 // Encrypted content used but keys provided in advance, so this is
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)));
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
)));
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
)
774 if (!WaitUntilCurrentTimeIsAfter(start_seek_time
))
777 source
.Seek(seek_time
, seek_file_position
, seek_append_size
);
778 if (!Seek(seek_time
))
781 source
.EndOfStream();
789 TEST_F(PipelineIntegrationTest
, BasicPlayback
) {
790 ASSERT_EQ(PIPELINE_OK
, Start("bear-320x240.webm"));
794 ASSERT_TRUE(WaitUntilOnEnded());
797 TEST_F(PipelineIntegrationTest
, BasicPlaybackOpusOgg
) {
798 ASSERT_EQ(PIPELINE_OK
, Start("bear-opus.ogg"));
802 ASSERT_TRUE(WaitUntilOnEnded());
805 TEST_F(PipelineIntegrationTest
, BasicPlaybackHashed
) {
806 ASSERT_EQ(PIPELINE_OK
, Start("bear-320x240.webm", kHashed
));
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
));
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)));
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)));
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
));
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)));
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)));
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
,
867 StartHashedClocklessPipelineWithMediaSource(&source
);
868 source
.EndOfStream();
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
));
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
));
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
));
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
));
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()));
933 ASSERT_TRUE(WaitUntilOnEnded());
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());
950 ASSERT_TRUE(WaitUntilOnEnded());
952 EXPECT_TRUE(demuxer_
->GetTimelineOffset().is_null());
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());
969 ASSERT_TRUE(WaitUntilOnEnded());
971 EXPECT_EQ(kLiveTimelineOffset(),
972 demuxer_
->GetTimelineOffset());
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());
989 ASSERT_TRUE(WaitUntilOnEnded());
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());
1006 ASSERT_TRUE(WaitUntilOnEnded());
1011 TEST_F(PipelineIntegrationTest
, BasicPlayback_MediaSource_Opus_WebM
) {
1012 MockMediaSource
source("bear-opus-end-trimming.webm", kOpusAudioOnlyWebM
,
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());
1023 ASSERT_TRUE(WaitUntilOnEnded());
1028 // Flaky. http://crbug.com/304776
1029 TEST_F(PipelineIntegrationTest
, DISABLED_MediaSource_Opus_Seeking_WebM
) {
1030 MockMediaSource
source("bear-opus-end-trimming.webm", kOpusAudioOnlyWebM
,
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);
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());
1056 TEST_F(PipelineIntegrationTest
, MediaSource_ConfigChange_WebM
) {
1057 MockMediaSource
source("bear-320x240-16x9-aspect.webm", kWebM
,
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());
1076 EXPECT_TRUE(WaitUntilOnEnded());
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
,
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());
1103 EXPECT_TRUE(WaitUntilOnEnded());
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
,
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());
1135 EXPECT_EQ(PIPELINE_ERROR_DECODE
, WaitUntilEndedOrError());
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
,
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());
1163 EXPECT_EQ(PIPELINE_ERROR_DECODE
, WaitUntilEndedOrError());
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());
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());
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
));
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());
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());
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();
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());
1303 EXPECT_TRUE(WaitUntilOnEnded());
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
,
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());
1331 EXPECT_TRUE(WaitUntilOnEnded());
1336 TEST_F(PipelineIntegrationTest
,
1337 MediaSource_ConfigChange_Encrypted_MP4_CENC_KeyRotation_VideoOnly
) {
1338 MockMediaSource
source("bear-640x360-v_frag-cenc-key_rotation.mp4", kMP4Video
,
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());
1358 EXPECT_TRUE(WaitUntilOnEnded());
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
,
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());
1391 EXPECT_EQ(PIPELINE_ERROR_DECODE
, WaitUntilEndedOrError());
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
,
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());
1419 EXPECT_EQ(PIPELINE_ERROR_DECODE
, WaitUntilEndedOrError());
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"));
1428 ASSERT_EQ(WaitUntilEndedOrError(), PIPELINE_ERROR_DECODE
);
1433 TEST_F(PipelineIntegrationTest
, BasicPlayback_16x9AspectRatio
) {
1434 ASSERT_EQ(PIPELINE_OK
, Start("bear-320x240-16x9-aspect.webm"));
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_
);
1450 ASSERT_TRUE(WaitUntilOnEnded());
1455 TEST_F(PipelineIntegrationTest
, EncryptedPlayback_ClearStart_WebM
) {
1456 MockMediaSource
source("bear-320x240-av_enc-av_clear-1s.webm", kWebM
,
1458 FakeEncryptedMedia
encrypted_media(new KeyProvidingApp());
1459 StartPipelineWithEncryptedMedia(&source
, &encrypted_media
);
1461 source
.EndOfStream();
1462 ASSERT_EQ(PIPELINE_OK
, pipeline_status_
);
1466 ASSERT_TRUE(WaitUntilOnEnded());
1471 TEST_F(PipelineIntegrationTest
, EncryptedPlayback_NoEncryptedFrames_WebM
) {
1472 MockMediaSource
source("bear-320x240-av_enc-av_clear-all.webm", kWebM
,
1474 FakeEncryptedMedia
encrypted_media(new NoResponseApp());
1475 StartPipelineWithEncryptedMedia(&source
, &encrypted_media
);
1477 source
.EndOfStream();
1478 ASSERT_EQ(PIPELINE_OK
, pipeline_status_
);
1482 ASSERT_TRUE(WaitUntilOnEnded());
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
,
1493 FakeEncryptedMedia
encrypted_media(new KeyProvidingApp());
1494 StartPipelineWithEncryptedMedia(&source
, &encrypted_media
);
1496 source
.EndOfStream();
1497 ASSERT_EQ(PIPELINE_OK
, pipeline_status_
);
1501 ASSERT_TRUE(WaitUntilOnEnded());
1506 TEST_F(PipelineIntegrationTest
, EncryptedPlayback_MP4_CENC_AudioOnly
) {
1507 MockMediaSource
source("bear-1280x720-a_frag-cenc.mp4", kMP4Audio
,
1509 FakeEncryptedMedia
encrypted_media(new KeyProvidingApp());
1510 StartPipelineWithEncryptedMedia(&source
, &encrypted_media
);
1512 source
.EndOfStream();
1513 ASSERT_EQ(PIPELINE_OK
, pipeline_status_
);
1517 ASSERT_TRUE(WaitUntilOnEnded());
1522 TEST_F(PipelineIntegrationTest
,
1523 EncryptedPlayback_NoEncryptedFrames_MP4_CENC_VideoOnly
) {
1524 MockMediaSource
source("bear-1280x720-v_frag-cenc_clear-all.mp4", kMP4Video
,
1526 FakeEncryptedMedia
encrypted_media(new NoResponseApp());
1527 StartPipelineWithEncryptedMedia(&source
, &encrypted_media
);
1529 source
.EndOfStream();
1530 ASSERT_EQ(PIPELINE_OK
, pipeline_status_
);
1534 ASSERT_TRUE(WaitUntilOnEnded());
1539 TEST_F(PipelineIntegrationTest
,
1540 EncryptedPlayback_NoEncryptedFrames_MP4_CENC_AudioOnly
) {
1541 MockMediaSource
source("bear-1280x720-a_frag-cenc_clear-all.mp4", kMP4Audio
,
1543 FakeEncryptedMedia
encrypted_media(new NoResponseApp());
1544 StartPipelineWithEncryptedMedia(&source
, &encrypted_media
);
1546 source
.EndOfStream();
1547 ASSERT_EQ(PIPELINE_OK
, pipeline_status_
);
1551 ASSERT_TRUE(WaitUntilOnEnded());
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_
);
1567 ASSERT_TRUE(WaitUntilOnEnded());
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_
);
1583 ASSERT_TRUE(WaitUntilOnEnded());
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
,
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());
1602 ASSERT_TRUE(WaitUntilOnEnded());
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);
1616 ASSERT_TRUE(WaitUntilCurrentTimeIsAfter(start_seek_time
));
1618 ASSERT_TRUE(Seek(seek_time
));
1619 EXPECT_EQ(seek_time
, pipeline_
->GetMediaTime());
1621 ASSERT_TRUE(WaitUntilOnEnded());
1623 // Make sure seeking after reaching the end works as expected.
1625 ASSERT_TRUE(Seek(seek_time
));
1626 EXPECT_EQ(seek_time
, pipeline_
->GetMediaTime());
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);
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
);
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
,
1676 base::TimeDelta::FromMilliseconds(464),
1677 base::TimeDelta::FromMilliseconds(617),
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
,
1685 base::TimeDelta::FromMilliseconds(167),
1686 base::TimeDelta::FromMilliseconds(1668),
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"));
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"));
1701 ASSERT_TRUE(WaitUntilOnEnded());
1704 // Verify that VP9 video and Opus audio in the same WebM container can be played
1706 TEST_F(PipelineIntegrationTest
, BasicPlayback_VP9_Opus_WebM
) {
1707 ASSERT_EQ(PIPELINE_OK
, Start("bear-vp9-opus.webm"));
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"));
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"));
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"));
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"));
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"));
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
1755 TEST_F(PipelineIntegrationTest
, BT709_VP9_WebM
) {
1756 ASSERT_EQ(PIPELINE_OK
, Start("bear-vp9-bt709.webm"));
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"));
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"));
1775 ASSERT_TRUE(WaitUntilOnEnded());
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();
1789 ASSERT_TRUE(WaitUntilOnEnded());
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"));
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"));
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
1821 EXPECT_EQ(2000, pipeline_
->GetMediaDuration().InMilliseconds());
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
1831 EXPECT_EQ(1001, pipeline_
->GetMediaDuration().InMilliseconds());
1833 ASSERT_TRUE(WaitUntilOnEnded());
1836 TEST_F(PipelineIntegrationTest
, BasicPlaybackPositiveStartTime
) {
1837 ASSERT_EQ(PIPELINE_OK
, Start("nonzero-start-time.webm"));
1839 ASSERT_TRUE(WaitUntilOnEnded());
1840 ASSERT_EQ(base::TimeDelta::FromMicroseconds(396000),
1841 demuxer_
->GetStartTime());
1844 } // namespace media