Upstream version 10.38.220.0
[platform/framework/web/crosswalk.git] / src / media / filters / pipeline_integration_test.cc
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.
4
5 #include "media/filters/pipeline_integration_test_base.h"
6
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/strings/string_util.h"
11 #include "build/build_config.h"
12 #include "media/base/cdm_promise.h"
13 #include "media/base/decoder_buffer.h"
14 #include "media/base/media_keys.h"
15 #include "media/base/media_switches.h"
16 #include "media/base/test_data_util.h"
17 #include "media/cdm/aes_decryptor.h"
18 #include "media/cdm/json_web_key.h"
19 #include "media/filters/chunk_demuxer.h"
20
21 using testing::_;
22 using testing::AnyNumber;
23 using testing::AtMost;
24 using testing::SaveArg;
25
26 namespace media {
27
28 const char kSourceId[] = "SourceId";
29 const uint8 kInitData[] = { 0x69, 0x6e, 0x69, 0x74 };
30
31 const char kWebM[] = "video/webm; codecs=\"vp8,vorbis\"";
32 const char kWebMVP9[] = "video/webm; codecs=\"vp9\"";
33 const char kAudioOnlyWebM[] = "video/webm; codecs=\"vorbis\"";
34 const char kOpusAudioOnlyWebM[] = "video/webm; codecs=\"opus\"";
35 const char kVideoOnlyWebM[] = "video/webm; codecs=\"vp8\"";
36 const char kMP4VideoType[] = "video/mp4";
37 const char kMP4AudioType[] = "audio/mp4";
38 #if defined(USE_PROPRIETARY_CODECS)
39 const char kADTS[] = "audio/aac";
40 const char kMP4[] = "video/mp4; codecs=\"avc1.4D4041,mp4a.40.2\"";
41 const char kMP4Video[] = "video/mp4; codecs=\"avc1.4D4041\"";
42 const char kMP4VideoAVC3[] = "video/mp4; codecs=\"avc3.64001f\"";
43 const char kMP4Audio[] = "audio/mp4; codecs=\"mp4a.40.2\"";
44 const char kMP3[] = "audio/mpeg";
45 #endif  // defined(USE_PROPRIETARY_CODECS)
46
47 // Key used to encrypt test files.
48 const uint8 kSecretKey[] = {
49   0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b,
50   0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c
51 };
52
53 // The key ID for all encrypted files.
54 const uint8 kKeyId[] = {
55   0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
56   0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35
57 };
58
59 const int kAppendWholeFile = -1;
60
61 // Constants for the Media Source config change tests.
62 const int kAppendTimeSec = 1;
63 const int kAppendTimeMs = kAppendTimeSec * 1000;
64 const int k320WebMFileDurationMs = 2736;
65 const int k640WebMFileDurationMs = 2749;
66 const int kOpusEndTrimmingWebMFileDurationMs = 2741;
67 const int kVP9WebMFileDurationMs = 2736;
68 const int kVP8AWebMFileDurationMs = 2733;
69
70 #if defined(USE_PROPRIETARY_CODECS)
71 const int k640IsoFileDurationMs = 2737;
72 const int k640IsoCencFileDurationMs = 2736;
73 const int k1280IsoFileDurationMs = 2736;
74 const int k1280IsoAVC3FileDurationMs = 2736;
75 #endif  // defined(USE_PROPRIETARY_CODECS)
76
77 // Return a timeline offset for bear-320x240-live.webm.
78 static base::Time kLiveTimelineOffset() {
79   // The file contians the following UTC timeline offset:
80   // 2012-11-10 12:34:56.789123456
81   // Since base::Time only has a resolution of microseconds,
82   // construct a base::Time for 2012-11-10 12:34:56.789123.
83   base::Time::Exploded exploded_time;
84   exploded_time.year = 2012;
85   exploded_time.month = 11;
86   exploded_time.day_of_month = 10;
87   exploded_time.hour = 12;
88   exploded_time.minute = 34;
89   exploded_time.second = 56;
90   exploded_time.millisecond = 789;
91   base::Time timeline_offset = base::Time::FromUTCExploded(exploded_time);
92
93   timeline_offset += base::TimeDelta::FromMicroseconds(123);
94
95   return timeline_offset;
96 }
97
98 // FFmpeg only supports time a resolution of seconds so this
99 // helper function truncates a base::Time to seconds resolution.
100 static base::Time TruncateToFFmpegTimeResolution(base::Time t) {
101   base::Time::Exploded exploded_time;
102   t.UTCExplode(&exploded_time);
103   exploded_time.millisecond = 0;
104
105   return base::Time::FromUTCExploded(exploded_time);
106 }
107
108 // Note: Tests using this class only exercise the DecryptingDemuxerStream path.
109 // They do not exercise the Decrypting{Audio|Video}Decoder path.
110 class FakeEncryptedMedia {
111  public:
112   // Defines the behavior of the "app" that responds to EME events.
113   class AppBase {
114    public:
115     virtual ~AppBase() {}
116
117     virtual void OnSessionMessage(const std::string& web_session_id,
118                                   const std::vector<uint8>& message,
119                                   const GURL& destination_url) = 0;
120
121     virtual void OnSessionReady(const std::string& web_session_id) = 0;
122
123     virtual void OnSessionClosed(const std::string& web_session_id) = 0;
124
125     // Errors are not expected unless overridden.
126     virtual void OnSessionError(const std::string& web_session_id,
127                                 const std::string& error_name,
128                                 uint32 system_code,
129                                 const std::string& error_message) {
130       FAIL() << "Unexpected Key Error";
131     }
132
133     virtual void NeedKey(const std::string& type,
134                          const std::vector<uint8>& init_data,
135                          AesDecryptor* decryptor) = 0;
136   };
137
138   FakeEncryptedMedia(AppBase* app)
139       : decryptor_(base::Bind(&FakeEncryptedMedia::OnSessionMessage,
140                               base::Unretained(this)),
141                    base::Bind(&FakeEncryptedMedia::OnSessionClosed,
142                               base::Unretained(this))),
143         app_(app) {}
144
145   AesDecryptor* decryptor() {
146     return &decryptor_;
147   }
148
149   // Callbacks for firing session events. Delegate to |app_|.
150   void OnSessionMessage(const std::string& web_session_id,
151                         const std::vector<uint8>& message,
152                         const GURL& destination_url) {
153     app_->OnSessionMessage(web_session_id, message, destination_url);
154   }
155
156   void OnSessionReady(const std::string& web_session_id) {
157     app_->OnSessionReady(web_session_id);
158   }
159
160   void OnSessionClosed(const std::string& web_session_id) {
161     app_->OnSessionClosed(web_session_id);
162   }
163
164   void OnSessionError(const std::string& web_session_id,
165                       const std::string& error_name,
166                       uint32 system_code,
167                       const std::string& error_message) {
168     app_->OnSessionError(
169         web_session_id, error_name, system_code, error_message);
170   }
171
172   void NeedKey(const std::string& type,
173                const std::vector<uint8>& init_data) {
174     app_->NeedKey(type, init_data, &decryptor_);
175   }
176
177  private:
178   AesDecryptor decryptor_;
179   scoped_ptr<AppBase> app_;
180 };
181
182 enum PromiseResult { RESOLVED, REJECTED };
183
184 // Provides |kSecretKey| in response to needkey.
185 class KeyProvidingApp : public FakeEncryptedMedia::AppBase {
186  public:
187   KeyProvidingApp() {}
188
189   void OnResolveWithSession(PromiseResult expected,
190                             const std::string& web_session_id) {
191     EXPECT_EQ(expected, RESOLVED);
192     EXPECT_GT(web_session_id.length(), 0ul);
193     current_session_id_ = web_session_id;
194   }
195
196   void OnResolve(PromiseResult expected) {
197     EXPECT_EQ(expected, RESOLVED);
198   }
199
200   void OnReject(PromiseResult expected,
201                 media::MediaKeys::Exception exception_code,
202                 uint32 system_code,
203                 const std::string& error_message) {
204     EXPECT_EQ(expected, REJECTED);
205   }
206
207   scoped_ptr<SimpleCdmPromise> CreatePromise(PromiseResult expected) {
208     scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise(
209         base::Bind(
210             &KeyProvidingApp::OnResolve, base::Unretained(this), expected),
211         base::Bind(
212             &KeyProvidingApp::OnReject, base::Unretained(this), expected)));
213     return promise.Pass();
214   }
215
216   scoped_ptr<NewSessionCdmPromise> CreateSessionPromise(
217       PromiseResult expected) {
218     scoped_ptr<media::NewSessionCdmPromise> promise(
219         new media::NewSessionCdmPromise(
220             base::Bind(&KeyProvidingApp::OnResolveWithSession,
221                        base::Unretained(this),
222                        expected),
223             base::Bind(
224                 &KeyProvidingApp::OnReject, base::Unretained(this), expected)));
225     return promise.Pass();
226   }
227
228   virtual void OnSessionMessage(const std::string& web_session_id,
229                                 const std::vector<uint8>& message,
230                                 const GURL& destination_url) OVERRIDE {
231     EXPECT_FALSE(web_session_id.empty());
232     EXPECT_FALSE(message.empty());
233     EXPECT_EQ(current_session_id_, web_session_id);
234   }
235
236   virtual void OnSessionReady(const std::string& web_session_id) OVERRIDE {
237     EXPECT_EQ(current_session_id_, web_session_id);
238   }
239
240   virtual void OnSessionClosed(const std::string& web_session_id) OVERRIDE {
241     EXPECT_EQ(current_session_id_, web_session_id);
242   }
243
244   virtual void NeedKey(const std::string& type,
245                        const std::vector<uint8>& init_data,
246                        AesDecryptor* decryptor) OVERRIDE {
247     if (current_session_id_.empty()) {
248       decryptor->CreateSession(type,
249                                kInitData,
250                                arraysize(kInitData),
251                                MediaKeys::TEMPORARY_SESSION,
252                                CreateSessionPromise(RESOLVED));
253       EXPECT_FALSE(current_session_id_.empty());
254     }
255
256     // Clear Key really needs the key ID in |init_data|. For WebM, they are the
257     // same, but this is not the case for ISO CENC. Therefore, provide the
258     // correct key ID.
259     const uint8* key_id = init_data.empty() ? NULL : &init_data[0];
260     size_t key_id_length = init_data.size();
261     if (type == kMP4AudioType || type == kMP4VideoType) {
262       key_id = kKeyId;
263       key_id_length = arraysize(kKeyId);
264     }
265
266     // Convert key into a JSON structure and then add it.
267     std::string jwk = GenerateJWKSet(
268         kSecretKey, arraysize(kSecretKey), key_id, key_id_length);
269     decryptor->UpdateSession(current_session_id_,
270                              reinterpret_cast<const uint8*>(jwk.data()),
271                              jwk.size(),
272                              CreatePromise(RESOLVED));
273   }
274
275   std::string current_session_id_;
276 };
277
278 class RotatingKeyProvidingApp : public KeyProvidingApp {
279  public:
280   RotatingKeyProvidingApp() : num_distint_need_key_calls_(0) {}
281   virtual ~RotatingKeyProvidingApp() {
282     // Expect that NeedKey is fired multiple times with different |init_data|.
283     EXPECT_GT(num_distint_need_key_calls_, 1u);
284   }
285
286   virtual void NeedKey(const std::string& type,
287                        const std::vector<uint8>& init_data,
288                        AesDecryptor* decryptor) OVERRIDE {
289     // Skip the request if the |init_data| has been seen.
290     if (init_data == prev_init_data_)
291       return;
292     prev_init_data_ = init_data;
293     ++num_distint_need_key_calls_;
294
295     decryptor->CreateSession(type,
296                              vector_as_array(&init_data),
297                              init_data.size(),
298                              MediaKeys::TEMPORARY_SESSION,
299                              CreateSessionPromise(RESOLVED));
300
301     std::vector<uint8> key_id;
302     std::vector<uint8> key;
303     EXPECT_TRUE(GetKeyAndKeyId(init_data, &key, &key_id));
304
305     // Convert key into a JSON structure and then add it.
306     std::string jwk = GenerateJWKSet(vector_as_array(&key),
307                                      key.size(),
308                                      vector_as_array(&key_id),
309                                      key_id.size());
310     decryptor->UpdateSession(current_session_id_,
311                              reinterpret_cast<const uint8*>(jwk.data()),
312                              jwk.size(),
313                              CreatePromise(RESOLVED));
314   }
315
316  private:
317   bool GetKeyAndKeyId(std::vector<uint8> init_data,
318                       std::vector<uint8>* key,
319                       std::vector<uint8>* key_id) {
320     // For WebM, init_data is key_id; for ISO CENC, init_data should contain
321     // the key_id. We assume key_id is in the end of init_data here (that is
322     // only a reasonable assumption for WebM and clear key ISO CENC).
323     DCHECK_GE(init_data.size(), arraysize(kKeyId));
324     std::vector<uint8> key_id_from_init_data(
325         init_data.end() - arraysize(kKeyId), init_data.end());
326
327     key->assign(kSecretKey, kSecretKey + arraysize(kSecretKey));
328     key_id->assign(kKeyId, kKeyId + arraysize(kKeyId));
329
330     // The Key and KeyId for this testing key provider are created by left
331     // rotating kSecretKey and kKeyId. Note that this implementation is only
332     // intended for testing purpose. The actual key rotation algorithm can be
333     // much more complicated.
334     // Find out the rotating position from |key_id_from_init_data| and apply on
335     // |key|.
336     for (size_t pos = 0; pos < arraysize(kKeyId); ++pos) {
337       std::rotate(key_id->begin(), key_id->begin() + pos, key_id->end());
338       if (*key_id == key_id_from_init_data) {
339         std::rotate(key->begin(), key->begin() + pos, key->end());
340         return true;
341       }
342     }
343     return false;
344   }
345
346   std::vector<uint8> prev_init_data_;
347   uint32 num_distint_need_key_calls_;
348 };
349
350 // Ignores needkey and does not perform a license request
351 class NoResponseApp : public FakeEncryptedMedia::AppBase {
352  public:
353   virtual void OnSessionMessage(const std::string& web_session_id,
354                                 const std::vector<uint8>& message,
355                                 const GURL& default_url) OVERRIDE {
356     EXPECT_FALSE(web_session_id.empty());
357     EXPECT_FALSE(message.empty());
358     FAIL() << "Unexpected Message";
359   }
360
361   virtual void OnSessionReady(const std::string& web_session_id) OVERRIDE {
362     EXPECT_FALSE(web_session_id.empty());
363     FAIL() << "Unexpected Ready";
364   }
365
366   virtual void OnSessionClosed(const std::string& web_session_id) OVERRIDE {
367     EXPECT_FALSE(web_session_id.empty());
368     FAIL() << "Unexpected Closed";
369   }
370
371   virtual void NeedKey(const std::string& type,
372                        const std::vector<uint8>& init_data,
373                        AesDecryptor* decryptor) OVERRIDE {
374   }
375 };
376
377 // Helper class that emulates calls made on the ChunkDemuxer by the
378 // Media Source API.
379 class MockMediaSource {
380  public:
381   MockMediaSource(const std::string& filename,
382                   const std::string& mimetype,
383                   int initial_append_size)
384       : file_path_(GetTestDataFilePath(filename)),
385         current_position_(0),
386         initial_append_size_(initial_append_size),
387         mimetype_(mimetype),
388         chunk_demuxer_(new ChunkDemuxer(
389             base::Bind(&MockMediaSource::DemuxerOpened, base::Unretained(this)),
390             base::Bind(&MockMediaSource::DemuxerNeedKey,
391                        base::Unretained(this)),
392             LogCB(),
393             true)),
394         owned_chunk_demuxer_(chunk_demuxer_) {
395
396     file_data_ = ReadTestDataFile(filename);
397
398     if (initial_append_size_ == kAppendWholeFile)
399       initial_append_size_ = file_data_->data_size();
400
401     DCHECK_GT(initial_append_size_, 0);
402     DCHECK_LE(initial_append_size_, file_data_->data_size());
403   }
404
405   virtual ~MockMediaSource() {}
406
407   scoped_ptr<Demuxer> GetDemuxer() { return owned_chunk_demuxer_.Pass(); }
408
409   void set_need_key_cb(const Demuxer::NeedKeyCB& need_key_cb) {
410     need_key_cb_ = need_key_cb;
411   }
412
413   void Seek(base::TimeDelta seek_time, int new_position, int seek_append_size) {
414     chunk_demuxer_->StartWaitingForSeek(seek_time);
415
416     chunk_demuxer_->Abort(
417         kSourceId,
418         base::TimeDelta(), kInfiniteDuration(), &last_timestamp_offset_);
419
420     DCHECK_GE(new_position, 0);
421     DCHECK_LT(new_position, file_data_->data_size());
422     current_position_ = new_position;
423
424     AppendData(seek_append_size);
425   }
426
427   void AppendData(int size) {
428     DCHECK(chunk_demuxer_);
429     DCHECK_LT(current_position_, file_data_->data_size());
430     DCHECK_LE(current_position_ + size, file_data_->data_size());
431
432     chunk_demuxer_->AppendData(
433         kSourceId, file_data_->data() + current_position_, size,
434         base::TimeDelta(), kInfiniteDuration(), &last_timestamp_offset_);
435     current_position_ += size;
436   }
437
438   void AppendAtTime(base::TimeDelta timestamp_offset,
439                     const uint8* pData,
440                     int size) {
441     CHECK(!chunk_demuxer_->IsParsingMediaSegment(kSourceId));
442     chunk_demuxer_->AppendData(kSourceId, pData, size,
443                                base::TimeDelta(), kInfiniteDuration(),
444                                &timestamp_offset);
445     last_timestamp_offset_ = timestamp_offset;
446   }
447
448   void AppendAtTimeWithWindow(base::TimeDelta timestamp_offset,
449                               base::TimeDelta append_window_start,
450                               base::TimeDelta append_window_end,
451                               const uint8* pData,
452                               int size) {
453     CHECK(!chunk_demuxer_->IsParsingMediaSegment(kSourceId));
454     chunk_demuxer_->AppendData(kSourceId,
455                                pData,
456                                size,
457                                append_window_start,
458                                append_window_end,
459                                &timestamp_offset);
460     last_timestamp_offset_ = timestamp_offset;
461   }
462
463   void EndOfStream() {
464     chunk_demuxer_->MarkEndOfStream(PIPELINE_OK);
465   }
466
467   void Abort() {
468     if (!chunk_demuxer_)
469       return;
470     chunk_demuxer_->Shutdown();
471     chunk_demuxer_ = NULL;
472   }
473
474   void DemuxerOpened() {
475     base::MessageLoop::current()->PostTask(
476         FROM_HERE, base::Bind(&MockMediaSource::DemuxerOpenedTask,
477                               base::Unretained(this)));
478   }
479
480   void DemuxerOpenedTask() {
481     // This code assumes that |mimetype_| is one of the following forms.
482     // 1. audio/mpeg
483     // 2. video/webm;codec="vorbis,vp8".
484     size_t semicolon = mimetype_.find(";");
485     std::string type = mimetype_;
486     std::vector<std::string> codecs;
487     if (semicolon != std::string::npos) {
488       type = mimetype_.substr(0, semicolon);
489       size_t codecs_param_start = mimetype_.find("codecs=\"", semicolon);
490
491       CHECK_NE(codecs_param_start, std::string::npos);
492
493       codecs_param_start += 8; // Skip over the codecs=".
494
495       size_t codecs_param_end = mimetype_.find("\"", codecs_param_start);
496
497       CHECK_NE(codecs_param_end, std::string::npos);
498
499       std::string codecs_param =
500           mimetype_.substr(codecs_param_start,
501                            codecs_param_end - codecs_param_start);
502       Tokenize(codecs_param, ",", &codecs);
503     }
504
505     CHECK_EQ(chunk_demuxer_->AddId(kSourceId, type, codecs), ChunkDemuxer::kOk);
506
507     AppendData(initial_append_size_);
508   }
509
510   void DemuxerNeedKey(const std::string& type,
511                       const std::vector<uint8>& init_data) {
512     DCHECK(!init_data.empty());
513     CHECK(!need_key_cb_.is_null());
514     need_key_cb_.Run(type, init_data);
515   }
516
517   base::TimeDelta last_timestamp_offset() const {
518     return last_timestamp_offset_;
519   }
520
521  private:
522   base::FilePath file_path_;
523   scoped_refptr<DecoderBuffer> file_data_;
524   int current_position_;
525   int initial_append_size_;
526   std::string mimetype_;
527   ChunkDemuxer* chunk_demuxer_;
528   scoped_ptr<Demuxer> owned_chunk_demuxer_;
529   Demuxer::NeedKeyCB need_key_cb_;
530   base::TimeDelta last_timestamp_offset_;
531 };
532
533 class PipelineIntegrationTest
534     : public testing::Test,
535       public PipelineIntegrationTestBase {
536  public:
537   void StartPipelineWithMediaSource(MockMediaSource* source) {
538     EXPECT_CALL(*this, OnMetadata(_))
539         .Times(AtMost(1))
540         .WillRepeatedly(SaveArg<0>(&metadata_));
541     EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH))
542         .Times(AtMost(1));
543     pipeline_->Start(
544         CreateFilterCollection(source->GetDemuxer(), NULL),
545         base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)),
546         base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)),
547         QuitOnStatusCB(PIPELINE_OK),
548         base::Bind(&PipelineIntegrationTest::OnMetadata,
549                    base::Unretained(this)),
550         base::Bind(&PipelineIntegrationTest::OnBufferingStateChanged,
551                    base::Unretained(this)),
552         base::Closure());
553
554     message_loop_.Run();
555   }
556
557   void StartHashedPipelineWithMediaSource(MockMediaSource* source) {
558     hashing_enabled_ = true;
559     StartPipelineWithMediaSource(source);
560   }
561
562   void StartPipelineWithEncryptedMedia(
563       MockMediaSource* source,
564       FakeEncryptedMedia* encrypted_media) {
565     EXPECT_CALL(*this, OnMetadata(_))
566         .Times(AtMost(1))
567         .WillRepeatedly(SaveArg<0>(&metadata_));
568     EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH))
569         .Times(AtMost(1));
570     pipeline_->Start(
571         CreateFilterCollection(source->GetDemuxer(),
572                                encrypted_media->decryptor()),
573         base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)),
574         base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)),
575         QuitOnStatusCB(PIPELINE_OK),
576         base::Bind(&PipelineIntegrationTest::OnMetadata,
577                    base::Unretained(this)),
578         base::Bind(&PipelineIntegrationTest::OnBufferingStateChanged,
579                    base::Unretained(this)),
580         base::Closure());
581
582     source->set_need_key_cb(base::Bind(&FakeEncryptedMedia::NeedKey,
583                                        base::Unretained(encrypted_media)));
584
585     message_loop_.Run();
586   }
587
588   // Verifies that seeking works properly for ChunkDemuxer when the
589   // seek happens while there is a pending read on the ChunkDemuxer
590   // and no data is available.
591   bool TestSeekDuringRead(const std::string& filename,
592                           const std::string& mimetype,
593                           int initial_append_size,
594                           base::TimeDelta start_seek_time,
595                           base::TimeDelta seek_time,
596                           int seek_file_position,
597                           int seek_append_size) {
598     MockMediaSource source(filename, mimetype, initial_append_size);
599     StartPipelineWithMediaSource(&source);
600
601     if (pipeline_status_ != PIPELINE_OK)
602       return false;
603
604     Play();
605     if (!WaitUntilCurrentTimeIsAfter(start_seek_time))
606       return false;
607
608     source.Seek(seek_time, seek_file_position, seek_append_size);
609     if (!Seek(seek_time))
610       return false;
611
612     source.EndOfStream();
613
614     source.Abort();
615     Stop();
616     return true;
617   }
618 };
619
620 TEST_F(PipelineIntegrationTest, BasicPlayback) {
621   ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240.webm"), PIPELINE_OK));
622
623   Play();
624
625   ASSERT_TRUE(WaitUntilOnEnded());
626 }
627
628 TEST_F(PipelineIntegrationTest, BasicPlaybackOpusOgg) {
629   ASSERT_TRUE(Start(GetTestDataFilePath("bear-opus.ogg"), PIPELINE_OK));
630
631   Play();
632
633   ASSERT_TRUE(WaitUntilOnEnded());
634 }
635
636 TEST_F(PipelineIntegrationTest, BasicPlaybackHashed) {
637   ASSERT_TRUE(Start(
638       GetTestDataFilePath("bear-320x240.webm"), PIPELINE_OK, kHashed));
639
640   Play();
641
642   ASSERT_TRUE(WaitUntilOnEnded());
643
644   EXPECT_EQ("f0be120a90a811506777c99a2cdf7cc1", GetVideoHash());
645   EXPECT_EQ("-3.59,-2.06,-0.43,2.15,0.77,-0.95,", GetAudioHash());
646   EXPECT_TRUE(demuxer_->GetTimelineOffset().is_null());
647 }
648
649 TEST_F(PipelineIntegrationTest, BasicPlaybackLive) {
650   ASSERT_TRUE(Start(
651       GetTestDataFilePath("bear-320x240-live.webm"), PIPELINE_OK, kHashed));
652
653   Play();
654
655   ASSERT_TRUE(WaitUntilOnEnded());
656
657   EXPECT_EQ("f0be120a90a811506777c99a2cdf7cc1", GetVideoHash());
658   EXPECT_EQ("-3.59,-2.06,-0.43,2.15,0.77,-0.95,", GetAudioHash());
659
660   // TODO: Fix FFmpeg code to return higher resolution time values so
661   // we don't have to truncate our expectations here.
662   EXPECT_EQ(TruncateToFFmpegTimeResolution(kLiveTimelineOffset()),
663             demuxer_->GetTimelineOffset());
664 }
665
666 TEST_F(PipelineIntegrationTest, F32PlaybackHashed) {
667   ASSERT_TRUE(
668       Start(GetTestDataFilePath("sfx_f32le.wav"), PIPELINE_OK, kHashed));
669   Play();
670   ASSERT_TRUE(WaitUntilOnEnded());
671   EXPECT_EQ(std::string(kNullVideoHash), GetVideoHash());
672   EXPECT_EQ("3.03,2.86,2.99,3.31,3.57,4.06,", GetAudioHash());
673 }
674
675 TEST_F(PipelineIntegrationTest, BasicPlaybackEncrypted) {
676   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
677   set_need_key_cb(base::Bind(&FakeEncryptedMedia::NeedKey,
678                              base::Unretained(&encrypted_media)));
679
680   ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240-av_enc-av.webm"),
681                     encrypted_media.decryptor()));
682
683   Play();
684
685   ASSERT_TRUE(WaitUntilOnEnded());
686   Stop();
687 }
688
689 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource) {
690   MockMediaSource source("bear-320x240.webm", kWebM, 219229);
691   StartPipelineWithMediaSource(&source);
692   source.EndOfStream();
693
694   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
695   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
696   EXPECT_EQ(k320WebMFileDurationMs,
697             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
698
699   Play();
700
701   ASSERT_TRUE(WaitUntilOnEnded());
702
703   EXPECT_TRUE(demuxer_->GetTimelineOffset().is_null());
704   source.Abort();
705   Stop();
706 }
707
708 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_Live) {
709   MockMediaSource source("bear-320x240-live.webm", kWebM, 219221);
710   StartPipelineWithMediaSource(&source);
711   source.EndOfStream();
712
713   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
714   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
715   EXPECT_EQ(k320WebMFileDurationMs,
716             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
717
718   Play();
719
720   ASSERT_TRUE(WaitUntilOnEnded());
721
722   EXPECT_EQ(kLiveTimelineOffset(),
723             demuxer_->GetTimelineOffset());
724   source.Abort();
725   Stop();
726 }
727
728 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_VP9_WebM) {
729   MockMediaSource source("bear-vp9.webm", kWebMVP9, 67504);
730   StartPipelineWithMediaSource(&source);
731   source.EndOfStream();
732
733   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
734   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
735   EXPECT_EQ(kVP9WebMFileDurationMs,
736             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
737
738   Play();
739
740   ASSERT_TRUE(WaitUntilOnEnded());
741   source.Abort();
742   Stop();
743 }
744
745 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_VP8A_WebM) {
746   MockMediaSource source("bear-vp8a.webm", kVideoOnlyWebM, kAppendWholeFile);
747   StartPipelineWithMediaSource(&source);
748   source.EndOfStream();
749
750   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
751   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
752   EXPECT_EQ(kVP8AWebMFileDurationMs,
753             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
754
755   Play();
756
757   ASSERT_TRUE(WaitUntilOnEnded());
758   source.Abort();
759   Stop();
760 }
761
762 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_Opus_WebM) {
763   MockMediaSource source("bear-opus-end-trimming.webm", kOpusAudioOnlyWebM,
764                          kAppendWholeFile);
765   StartPipelineWithMediaSource(&source);
766   source.EndOfStream();
767
768   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
769   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
770   EXPECT_EQ(kOpusEndTrimmingWebMFileDurationMs,
771             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
772   Play();
773
774   ASSERT_TRUE(WaitUntilOnEnded());
775   source.Abort();
776   Stop();
777 }
778
779 // Flaky. http://crbug.com/304776
780 TEST_F(PipelineIntegrationTest, DISABLED_MediaSource_Opus_Seeking_WebM) {
781   MockMediaSource source("bear-opus-end-trimming.webm", kOpusAudioOnlyWebM,
782                          kAppendWholeFile);
783   StartHashedPipelineWithMediaSource(&source);
784
785   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
786   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
787   EXPECT_EQ(kOpusEndTrimmingWebMFileDurationMs,
788             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
789
790   base::TimeDelta start_seek_time = base::TimeDelta::FromMilliseconds(1000);
791   base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(2000);
792
793   Play();
794   ASSERT_TRUE(WaitUntilCurrentTimeIsAfter(start_seek_time));
795   source.Seek(seek_time, 0x1D5, 34017);
796   source.EndOfStream();
797   ASSERT_TRUE(Seek(seek_time));
798
799   ASSERT_TRUE(WaitUntilOnEnded());
800
801   EXPECT_EQ("0.76,0.20,-0.82,-0.58,-1.29,-0.29,", GetAudioHash());
802
803   source.Abort();
804   Stop();
805 }
806
807 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_WebM) {
808   MockMediaSource source("bear-320x240-16x9-aspect.webm", kWebM,
809                          kAppendWholeFile);
810   StartPipelineWithMediaSource(&source);
811
812   scoped_refptr<DecoderBuffer> second_file =
813       ReadTestDataFile("bear-640x360.webm");
814
815   source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
816                       second_file->data(), second_file->data_size());
817
818   source.EndOfStream();
819
820   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
821   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
822   EXPECT_EQ(kAppendTimeMs + k640WebMFileDurationMs,
823             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
824
825   Play();
826
827   EXPECT_TRUE(WaitUntilOnEnded());
828   source.Abort();
829   Stop();
830 }
831
832 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_Encrypted_WebM) {
833   MockMediaSource source("bear-320x240-16x9-aspect-av_enc-av.webm", kWebM,
834                          kAppendWholeFile);
835   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
836   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
837
838   scoped_refptr<DecoderBuffer> second_file =
839       ReadTestDataFile("bear-640x360-av_enc-av.webm");
840
841   source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
842                       second_file->data(), second_file->data_size());
843
844   source.EndOfStream();
845
846   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
847   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
848   EXPECT_EQ(kAppendTimeMs + k640WebMFileDurationMs,
849             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
850
851   Play();
852
853   EXPECT_TRUE(WaitUntilOnEnded());
854   source.Abort();
855   Stop();
856 }
857
858 // Config changes from encrypted to clear are not currently supported.
859 TEST_F(PipelineIntegrationTest,
860        MediaSource_ConfigChange_ClearThenEncrypted_WebM) {
861   MockMediaSource source("bear-320x240-16x9-aspect.webm", kWebM,
862                          kAppendWholeFile);
863   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
864   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
865
866   scoped_refptr<DecoderBuffer> second_file =
867       ReadTestDataFile("bear-640x360-av_enc-av.webm");
868
869   source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
870                       second_file->data(), second_file->data_size());
871
872   source.EndOfStream();
873
874   message_loop_.Run();
875   EXPECT_EQ(PIPELINE_ERROR_DECODE, pipeline_status_);
876
877   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
878   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
879   // The second video was not added, so its time has not been added.
880   EXPECT_EQ(k320WebMFileDurationMs,
881             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
882
883   Play();
884
885   EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
886   source.Abort();
887 }
888
889 // Config changes from clear to encrypted are not currently supported.
890 TEST_F(PipelineIntegrationTest,
891        MediaSource_ConfigChange_EncryptedThenClear_WebM) {
892   MockMediaSource source("bear-320x240-16x9-aspect-av_enc-av.webm", kWebM,
893                          kAppendWholeFile);
894   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
895   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
896
897   scoped_refptr<DecoderBuffer> second_file =
898       ReadTestDataFile("bear-640x360.webm");
899
900   source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
901                       second_file->data(), second_file->data_size());
902
903   source.EndOfStream();
904
905   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
906   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
907   // The second video was not added, so its time has not been added.
908   EXPECT_EQ(k320WebMFileDurationMs,
909             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
910
911   Play();
912
913   EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
914   source.Abort();
915 }
916
917 #if defined(USE_PROPRIETARY_CODECS)
918 TEST_F(PipelineIntegrationTest, MediaSource_ADTS) {
919   MockMediaSource source("sfx.adts", kADTS, kAppendWholeFile);
920   StartPipelineWithMediaSource(&source);
921   source.EndOfStream();
922
923   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
924   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
925   EXPECT_EQ(325, pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
926
927   Play();
928
929   EXPECT_TRUE(WaitUntilOnEnded());
930 }
931
932 TEST_F(PipelineIntegrationTest, MediaSource_ADTS_TimestampOffset) {
933   MockMediaSource source("sfx.adts", kADTS, kAppendWholeFile);
934   StartHashedPipelineWithMediaSource(&source);
935   EXPECT_EQ(325, source.last_timestamp_offset().InMilliseconds());
936
937   // Trim off multiple frames off the beginning of the segment which will cause
938   // the first decoded frame to be incorrect if preroll isn't implemented.
939   const base::TimeDelta adts_preroll_duration =
940       base::TimeDelta::FromSecondsD(2.5 * 1024 / 44100);
941   const base::TimeDelta append_time =
942       source.last_timestamp_offset() - adts_preroll_duration;
943
944   scoped_refptr<DecoderBuffer> second_file = ReadTestDataFile("sfx.adts");
945   source.AppendAtTimeWithWindow(append_time,
946                                 append_time + adts_preroll_duration,
947                                 kInfiniteDuration(),
948                                 second_file->data(),
949                                 second_file->data_size());
950   source.EndOfStream();
951
952   EXPECT_EQ(592, source.last_timestamp_offset().InMilliseconds());
953   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
954   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
955   EXPECT_EQ(592, pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
956
957   Play();
958
959   EXPECT_TRUE(WaitUntilOnEnded());
960
961   // Verify preroll is stripped.
962   EXPECT_EQ("-0.06,0.97,-0.90,-0.70,-0.53,-0.34,", GetAudioHash());
963 }
964
965 TEST_F(PipelineIntegrationTest, BasicPlaybackHashed_MP3) {
966   ASSERT_TRUE(Start(GetTestDataFilePath("sfx.mp3"), PIPELINE_OK, kHashed));
967
968   Play();
969
970   ASSERT_TRUE(WaitUntilOnEnded());
971
972   // Verify codec delay and preroll are stripped.
973   EXPECT_EQ("3.05,2.87,3.00,3.32,3.58,4.08,", GetAudioHash());
974 }
975
976 TEST_F(PipelineIntegrationTest, MediaSource_MP3) {
977   MockMediaSource source("sfx.mp3", kMP3, kAppendWholeFile);
978   StartHashedPipelineWithMediaSource(&source);
979   source.EndOfStream();
980
981   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
982   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
983   EXPECT_EQ(313, pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
984
985   Play();
986
987   EXPECT_TRUE(WaitUntilOnEnded());
988
989   // Verify that codec delay was stripped.
990   EXPECT_EQ("1.01,2.71,4.18,4.32,3.04,1.12,", GetAudioHash());
991 }
992
993 TEST_F(PipelineIntegrationTest, MediaSource_MP3_TimestampOffset) {
994   MockMediaSource source("sfx.mp3", kMP3, kAppendWholeFile);
995   StartPipelineWithMediaSource(&source);
996   EXPECT_EQ(313, source.last_timestamp_offset().InMilliseconds());
997
998   // There are 576 silent frames at the start of this mp3.  The second append
999   // should trim them off.
1000   const base::TimeDelta mp3_preroll_duration =
1001       base::TimeDelta::FromSecondsD(576.0 / 44100);
1002   const base::TimeDelta append_time =
1003       source.last_timestamp_offset() - mp3_preroll_duration;
1004
1005   scoped_refptr<DecoderBuffer> second_file = ReadTestDataFile("sfx.mp3");
1006   source.AppendAtTimeWithWindow(append_time,
1007                                 append_time + mp3_preroll_duration,
1008                                 kInfiniteDuration(),
1009                                 second_file->data(),
1010                                 second_file->data_size());
1011   source.EndOfStream();
1012
1013   EXPECT_EQ(613, source.last_timestamp_offset().InMilliseconds());
1014   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1015   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1016   EXPECT_EQ(613, pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1017
1018   Play();
1019
1020   EXPECT_TRUE(WaitUntilOnEnded());
1021 }
1022
1023 TEST_F(PipelineIntegrationTest, MediaSource_MP3_Icecast) {
1024   MockMediaSource source("icy_sfx.mp3", kMP3, kAppendWholeFile);
1025   StartPipelineWithMediaSource(&source);
1026   source.EndOfStream();
1027
1028   Play();
1029
1030   EXPECT_TRUE(WaitUntilOnEnded());
1031 }
1032
1033 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_MP4) {
1034   MockMediaSource source("bear-640x360-av_frag.mp4", kMP4, kAppendWholeFile);
1035   StartPipelineWithMediaSource(&source);
1036
1037   scoped_refptr<DecoderBuffer> second_file =
1038       ReadTestDataFile("bear-1280x720-av_frag.mp4");
1039
1040   source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1041                       second_file->data(), second_file->data_size());
1042
1043   source.EndOfStream();
1044
1045   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1046   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1047   EXPECT_EQ(kAppendTimeMs + k1280IsoFileDurationMs,
1048             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1049
1050   Play();
1051
1052   EXPECT_TRUE(WaitUntilOnEnded());
1053   source.Abort();
1054   Stop();
1055 }
1056
1057 TEST_F(PipelineIntegrationTest,
1058        MediaSource_ConfigChange_Encrypted_MP4_CENC_VideoOnly) {
1059   MockMediaSource source("bear-640x360-v_frag-cenc.mp4", kMP4Video,
1060                          kAppendWholeFile);
1061   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1062   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1063
1064   scoped_refptr<DecoderBuffer> second_file =
1065       ReadTestDataFile("bear-1280x720-v_frag-cenc.mp4");
1066
1067   source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1068                       second_file->data(), second_file->data_size());
1069
1070   source.EndOfStream();
1071
1072   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1073   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1074   EXPECT_EQ(kAppendTimeMs + k1280IsoFileDurationMs,
1075             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1076
1077   Play();
1078
1079   EXPECT_TRUE(WaitUntilOnEnded());
1080   source.Abort();
1081   Stop();
1082 }
1083
1084 TEST_F(PipelineIntegrationTest,
1085        MediaSource_ConfigChange_Encrypted_MP4_CENC_KeyRotation_VideoOnly) {
1086   MockMediaSource source("bear-640x360-v_frag-cenc-key_rotation.mp4", kMP4Video,
1087                          kAppendWholeFile);
1088   FakeEncryptedMedia encrypted_media(new RotatingKeyProvidingApp());
1089   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1090
1091   scoped_refptr<DecoderBuffer> second_file =
1092       ReadTestDataFile("bear-1280x720-v_frag-cenc-key_rotation.mp4");
1093
1094   source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1095                       second_file->data(), second_file->data_size());
1096
1097   source.EndOfStream();
1098
1099   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1100   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1101   EXPECT_EQ(kAppendTimeMs + k1280IsoFileDurationMs,
1102             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1103
1104   Play();
1105
1106   EXPECT_TRUE(WaitUntilOnEnded());
1107   source.Abort();
1108   Stop();
1109 }
1110
1111 // Config changes from clear to encrypted are not currently supported.
1112 // TODO(ddorwin): Figure out why this CHECKs in AppendAtTime().
1113 TEST_F(PipelineIntegrationTest,
1114        DISABLED_MediaSource_ConfigChange_ClearThenEncrypted_MP4_CENC) {
1115   MockMediaSource source("bear-640x360-av_frag.mp4", kMP4Video,
1116                          kAppendWholeFile);
1117   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1118   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1119
1120   scoped_refptr<DecoderBuffer> second_file =
1121       ReadTestDataFile("bear-1280x720-v_frag-cenc.mp4");
1122
1123   source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1124                       second_file->data(), second_file->data_size());
1125
1126   source.EndOfStream();
1127
1128   message_loop_.Run();
1129   EXPECT_EQ(PIPELINE_ERROR_DECODE, pipeline_status_);
1130
1131   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1132   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1133   // The second video was not added, so its time has not been added.
1134   EXPECT_EQ(k640IsoFileDurationMs,
1135             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1136
1137   Play();
1138
1139   EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
1140   source.Abort();
1141 }
1142
1143 // Config changes from encrypted to clear are not currently supported.
1144 TEST_F(PipelineIntegrationTest,
1145        MediaSource_ConfigChange_EncryptedThenClear_MP4_CENC) {
1146   MockMediaSource source("bear-640x360-v_frag-cenc.mp4", kMP4Video,
1147                          kAppendWholeFile);
1148   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1149   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1150
1151   scoped_refptr<DecoderBuffer> second_file =
1152       ReadTestDataFile("bear-1280x720-av_frag.mp4");
1153
1154   source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
1155                       second_file->data(), second_file->data_size());
1156
1157   source.EndOfStream();
1158
1159   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1160   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1161   // The second video was not added, so its time has not been added.
1162   EXPECT_EQ(k640IsoCencFileDurationMs,
1163             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1164
1165   Play();
1166
1167   EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
1168   source.Abort();
1169 }
1170
1171 // Verify files which change configuration midstream fail gracefully.
1172 TEST_F(PipelineIntegrationTest, MidStreamConfigChangesFail) {
1173   ASSERT_TRUE(Start(
1174       GetTestDataFilePath("midstream_config_change.mp3"), PIPELINE_OK));
1175   Play();
1176   ASSERT_EQ(WaitUntilEndedOrError(), PIPELINE_ERROR_DECODE);
1177 }
1178
1179 #endif
1180
1181 TEST_F(PipelineIntegrationTest, BasicPlayback_16x9AspectRatio) {
1182   ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240-16x9-aspect.webm"),
1183                     PIPELINE_OK));
1184   Play();
1185   ASSERT_TRUE(WaitUntilOnEnded());
1186 }
1187
1188 TEST_F(PipelineIntegrationTest, EncryptedPlayback_WebM) {
1189   MockMediaSource source("bear-320x240-av_enc-av.webm", kWebM, 219816);
1190   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1191   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1192
1193   source.EndOfStream();
1194   ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1195
1196   Play();
1197
1198   ASSERT_TRUE(WaitUntilOnEnded());
1199   source.Abort();
1200   Stop();
1201 }
1202
1203 TEST_F(PipelineIntegrationTest, EncryptedPlayback_ClearStart_WebM) {
1204   MockMediaSource source("bear-320x240-av_enc-av_clear-1s.webm", kWebM,
1205                          kAppendWholeFile);
1206   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1207   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1208
1209   source.EndOfStream();
1210   ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1211
1212   Play();
1213
1214   ASSERT_TRUE(WaitUntilOnEnded());
1215   source.Abort();
1216   Stop();
1217 }
1218
1219 TEST_F(PipelineIntegrationTest, EncryptedPlayback_NoEncryptedFrames_WebM) {
1220   MockMediaSource source("bear-320x240-av_enc-av_clear-all.webm", kWebM,
1221                          kAppendWholeFile);
1222   FakeEncryptedMedia encrypted_media(new NoResponseApp());
1223   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1224
1225   source.EndOfStream();
1226   ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1227
1228   Play();
1229
1230   ASSERT_TRUE(WaitUntilOnEnded());
1231   source.Abort();
1232   Stop();
1233 }
1234
1235 #if defined(USE_PROPRIETARY_CODECS)
1236 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_VideoOnly) {
1237   MockMediaSource source("bear-1280x720-v_frag-cenc.mp4", kMP4Video,
1238                          kAppendWholeFile);
1239   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1240   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1241
1242   source.EndOfStream();
1243   ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1244
1245   Play();
1246
1247   ASSERT_TRUE(WaitUntilOnEnded());
1248   source.Abort();
1249   Stop();
1250 }
1251
1252 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_AudioOnly) {
1253   MockMediaSource source("bear-1280x720-a_frag-cenc.mp4", kMP4Audio,
1254                          kAppendWholeFile);
1255   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
1256   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1257
1258   source.EndOfStream();
1259   ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1260
1261   Play();
1262
1263   ASSERT_TRUE(WaitUntilOnEnded());
1264   source.Abort();
1265   Stop();
1266 }
1267
1268 TEST_F(PipelineIntegrationTest,
1269        EncryptedPlayback_NoEncryptedFrames_MP4_CENC_VideoOnly) {
1270   MockMediaSource source("bear-1280x720-v_frag-cenc_clear-all.mp4", kMP4Video,
1271                          kAppendWholeFile);
1272   FakeEncryptedMedia encrypted_media(new NoResponseApp());
1273   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1274
1275   source.EndOfStream();
1276   ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1277
1278   Play();
1279
1280   ASSERT_TRUE(WaitUntilOnEnded());
1281   source.Abort();
1282   Stop();
1283 }
1284
1285 TEST_F(PipelineIntegrationTest,
1286        EncryptedPlayback_NoEncryptedFrames_MP4_CENC_AudioOnly) {
1287   MockMediaSource source("bear-1280x720-a_frag-cenc_clear-all.mp4", kMP4Audio,
1288                          kAppendWholeFile);
1289   FakeEncryptedMedia encrypted_media(new NoResponseApp());
1290   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1291
1292   source.EndOfStream();
1293   ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1294
1295   Play();
1296
1297   ASSERT_TRUE(WaitUntilOnEnded());
1298   source.Abort();
1299   Stop();
1300 }
1301
1302 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_VideoOnly_MP4_AVC3) {
1303   MockMediaSource source("bear-1280x720-v_frag-avc3.mp4", kMP4VideoAVC3,
1304                          kAppendWholeFile);
1305   StartPipelineWithMediaSource(&source);
1306   source.EndOfStream();
1307
1308   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
1309   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
1310   EXPECT_EQ(k1280IsoAVC3FileDurationMs,
1311             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
1312
1313   Play();
1314
1315   ASSERT_TRUE(WaitUntilOnEnded());
1316   source.Abort();
1317   Stop();
1318 }
1319
1320 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_KeyRotation_Video) {
1321   MockMediaSource source("bear-1280x720-v_frag-cenc-key_rotation.mp4",
1322                          kMP4Video, kAppendWholeFile);
1323   FakeEncryptedMedia encrypted_media(new RotatingKeyProvidingApp());
1324   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1325
1326   source.EndOfStream();
1327   ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1328
1329   Play();
1330
1331   ASSERT_TRUE(WaitUntilOnEnded());
1332   source.Abort();
1333   Stop();
1334 }
1335
1336 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_KeyRotation_Audio) {
1337   MockMediaSource source("bear-1280x720-a_frag-cenc-key_rotation.mp4",
1338                          kMP4Audio, kAppendWholeFile);
1339   FakeEncryptedMedia encrypted_media(new RotatingKeyProvidingApp());
1340   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
1341
1342   source.EndOfStream();
1343   ASSERT_EQ(PIPELINE_OK, pipeline_status_);
1344
1345   Play();
1346
1347   ASSERT_TRUE(WaitUntilOnEnded());
1348   source.Abort();
1349   Stop();
1350 }
1351 #endif
1352
1353 // TODO(acolwell): Fix flakiness http://crbug.com/117921
1354 TEST_F(PipelineIntegrationTest, DISABLED_SeekWhilePaused) {
1355   ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240.webm"), PIPELINE_OK));
1356
1357   base::TimeDelta duration(pipeline_->GetMediaDuration());
1358   base::TimeDelta start_seek_time(duration / 4);
1359   base::TimeDelta seek_time(duration * 3 / 4);
1360
1361   Play();
1362   ASSERT_TRUE(WaitUntilCurrentTimeIsAfter(start_seek_time));
1363   Pause();
1364   ASSERT_TRUE(Seek(seek_time));
1365   EXPECT_EQ(pipeline_->GetMediaTime(), seek_time);
1366   Play();
1367   ASSERT_TRUE(WaitUntilOnEnded());
1368
1369   // Make sure seeking after reaching the end works as expected.
1370   Pause();
1371   ASSERT_TRUE(Seek(seek_time));
1372   EXPECT_EQ(pipeline_->GetMediaTime(), seek_time);
1373   Play();
1374   ASSERT_TRUE(WaitUntilOnEnded());
1375 }
1376
1377 // TODO(acolwell): Fix flakiness http://crbug.com/117921
1378 TEST_F(PipelineIntegrationTest, DISABLED_SeekWhilePlaying) {
1379   ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240.webm"), PIPELINE_OK));
1380
1381   base::TimeDelta duration(pipeline_->GetMediaDuration());
1382   base::TimeDelta start_seek_time(duration / 4);
1383   base::TimeDelta seek_time(duration * 3 / 4);
1384
1385   Play();
1386   ASSERT_TRUE(WaitUntilCurrentTimeIsAfter(start_seek_time));
1387   ASSERT_TRUE(Seek(seek_time));
1388   EXPECT_GE(pipeline_->GetMediaTime(), seek_time);
1389   ASSERT_TRUE(WaitUntilOnEnded());
1390
1391   // Make sure seeking after reaching the end works as expected.
1392   ASSERT_TRUE(Seek(seek_time));
1393   EXPECT_GE(pipeline_->GetMediaTime(), seek_time);
1394   ASSERT_TRUE(WaitUntilOnEnded());
1395 }
1396
1397 #if defined(USE_PROPRIETARY_CODECS)
1398 TEST_F(PipelineIntegrationTest, Rotated_Metadata_0) {
1399   ASSERT_TRUE(Start(GetTestDataFilePath("bear_rotate_0.mp4"), PIPELINE_OK));
1400   ASSERT_EQ(VIDEO_ROTATION_0, metadata_.video_rotation);
1401 }
1402
1403 TEST_F(PipelineIntegrationTest, Rotated_Metadata_90) {
1404   ASSERT_TRUE(Start(GetTestDataFilePath("bear_rotate_90.mp4"), PIPELINE_OK));
1405   ASSERT_EQ(VIDEO_ROTATION_90, metadata_.video_rotation);
1406 }
1407
1408 TEST_F(PipelineIntegrationTest, Rotated_Metadata_180) {
1409   ASSERT_TRUE(Start(GetTestDataFilePath("bear_rotate_180.mp4"), PIPELINE_OK));
1410   ASSERT_EQ(VIDEO_ROTATION_180, metadata_.video_rotation);
1411 }
1412
1413 TEST_F(PipelineIntegrationTest, Rotated_Metadata_270) {
1414   ASSERT_TRUE(Start(GetTestDataFilePath("bear_rotate_270.mp4"), PIPELINE_OK));
1415   ASSERT_EQ(VIDEO_ROTATION_270, metadata_.video_rotation);
1416 }
1417 #endif
1418
1419 // Verify audio decoder & renderer can handle aborted demuxer reads.
1420 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_AudioOnly) {
1421   ASSERT_TRUE(TestSeekDuringRead("bear-320x240-audio-only.webm", kAudioOnlyWebM,
1422                                  8192,
1423                                  base::TimeDelta::FromMilliseconds(464),
1424                                  base::TimeDelta::FromMilliseconds(617),
1425                                  0x10CA, 19730));
1426 }
1427
1428 // Verify video decoder & renderer can handle aborted demuxer reads.
1429 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_VideoOnly) {
1430   ASSERT_TRUE(TestSeekDuringRead("bear-320x240-video-only.webm", kVideoOnlyWebM,
1431                                  32768,
1432                                  base::TimeDelta::FromMilliseconds(167),
1433                                  base::TimeDelta::FromMilliseconds(1668),
1434                                  0x1C896, 65536));
1435 }
1436
1437 // Verify that Opus audio in WebM containers can be played back.
1438 TEST_F(PipelineIntegrationTest, BasicPlayback_AudioOnly_Opus_WebM) {
1439   ASSERT_TRUE(Start(GetTestDataFilePath("bear-opus-end-trimming.webm"),
1440                     PIPELINE_OK));
1441   Play();
1442   ASSERT_TRUE(WaitUntilOnEnded());
1443 }
1444
1445 // Verify that VP9 video in WebM containers can be played back.
1446 TEST_F(PipelineIntegrationTest, BasicPlayback_VideoOnly_VP9_WebM) {
1447   ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp9.webm"),
1448                     PIPELINE_OK));
1449   Play();
1450   ASSERT_TRUE(WaitUntilOnEnded());
1451 }
1452
1453 // Verify that VP9 video and Opus audio in the same WebM container can be played
1454 // back.
1455 TEST_F(PipelineIntegrationTest, BasicPlayback_VP9_Opus_WebM) {
1456   ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp9-opus.webm"),
1457                     PIPELINE_OK));
1458   Play();
1459   ASSERT_TRUE(WaitUntilOnEnded());
1460 }
1461
1462 // Verify that VP8 video with alpha channel can be played back.
1463 TEST_F(PipelineIntegrationTest, BasicPlayback_VP8A_WebM) {
1464   ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp8a.webm"),
1465                     PIPELINE_OK));
1466   Play();
1467   ASSERT_TRUE(WaitUntilOnEnded());
1468   EXPECT_EQ(last_video_frame_format_, VideoFrame::YV12A);
1469 }
1470
1471 // Verify that VP8A video with odd width/height can be played back.
1472 TEST_F(PipelineIntegrationTest, BasicPlayback_VP8A_Odd_WebM) {
1473   ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp8a-odd-dimensions.webm"),
1474                     PIPELINE_OK));
1475   Play();
1476   ASSERT_TRUE(WaitUntilOnEnded());
1477   EXPECT_EQ(last_video_frame_format_, VideoFrame::YV12A);
1478 }
1479
1480 // Verify that VP9 video with odd width/height can be played back.
1481 TEST_F(PipelineIntegrationTest, BasicPlayback_VP9_Odd_WebM) {
1482   ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp9-odd-dimensions.webm"),
1483                     PIPELINE_OK));
1484   Play();
1485   ASSERT_TRUE(WaitUntilOnEnded());
1486 }
1487
1488 // Verify that VP8 video with inband text track can be played back.
1489 TEST_F(PipelineIntegrationTest,
1490        BasicPlayback_VP8_WebVTT_WebM) {
1491   ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp8-webvtt.webm"),
1492                     PIPELINE_OK));
1493   Play();
1494   ASSERT_TRUE(WaitUntilOnEnded());
1495 }
1496
1497 // Verify that VP9 video with 4:4:4 subsampling can be played back.
1498 TEST_F(PipelineIntegrationTest, P444_VP9_WebM) {
1499   ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240-P444.webm"),
1500                     PIPELINE_OK));
1501   Play();
1502   ASSERT_TRUE(WaitUntilOnEnded());
1503   EXPECT_EQ(last_video_frame_format_, VideoFrame::YV24);
1504 }
1505
1506 // Verify that videos with an odd frame size playback successfully.
1507 TEST_F(PipelineIntegrationTest, BasicPlayback_OddVideoSize) {
1508   ASSERT_TRUE(Start(GetTestDataFilePath("butterfly-853x480.webm"),
1509                     PIPELINE_OK));
1510   Play();
1511   ASSERT_TRUE(WaitUntilOnEnded());
1512 }
1513
1514 // Verify that OPUS audio in a webm which reports a 44.1kHz sample rate plays
1515 // correctly at 48kHz
1516 TEST_F(PipelineIntegrationTest, BasicPlayback_Opus441kHz) {
1517   ASSERT_TRUE(Start(GetTestDataFilePath("sfx-opus-441.webm"), PIPELINE_OK));
1518   Play();
1519   ASSERT_TRUE(WaitUntilOnEnded());
1520   EXPECT_EQ(48000,
1521             demuxer_->GetStream(DemuxerStream::AUDIO)
1522                 ->audio_decoder_config()
1523                 .samples_per_second());
1524 }
1525
1526 // Same as above but using MediaSource.
1527 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_Opus441kHz) {
1528   MockMediaSource source(
1529       "sfx-opus-441.webm", kOpusAudioOnlyWebM, kAppendWholeFile);
1530   StartPipelineWithMediaSource(&source);
1531   source.EndOfStream();
1532   Play();
1533   ASSERT_TRUE(WaitUntilOnEnded());
1534   source.Abort();
1535   Stop();
1536   EXPECT_EQ(48000,
1537             demuxer_->GetStream(DemuxerStream::AUDIO)
1538                 ->audio_decoder_config()
1539                 .samples_per_second());
1540 }
1541
1542 // Ensures audio-only playback with missing or negative timestamps works.  Tests
1543 // the common live-streaming case for chained ogg.  See http://crbug.com/396864.
1544 TEST_F(PipelineIntegrationTest, BasicPlaybackChainedOgg) {
1545   ASSERT_TRUE(Start(GetTestDataFilePath("double-sfx.ogg"), PIPELINE_OK));
1546   Play();
1547   ASSERT_TRUE(WaitUntilOnEnded());
1548   ASSERT_EQ(base::TimeDelta(), demuxer_->GetStartTime());
1549 }
1550
1551 // Ensures audio-video playback with missing or negative timestamps fails softly
1552 // instead of crashing.  See http://crbug.com/396864.
1553 TEST_F(PipelineIntegrationTest, BasicPlaybackChainedOggVideo) {
1554   ASSERT_TRUE(Start(GetTestDataFilePath("double-bear.ogv"), PIPELINE_OK));
1555   Play();
1556   EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
1557   ASSERT_EQ(base::TimeDelta(), demuxer_->GetStartTime());
1558 }
1559
1560 TEST_F(PipelineIntegrationTest, BasicPlaybackPositiveStartTime) {
1561   ASSERT_TRUE(
1562       Start(GetTestDataFilePath("nonzero-start-time.webm"), PIPELINE_OK));
1563   Play();
1564   ASSERT_TRUE(WaitUntilOnEnded());
1565   ASSERT_EQ(base::TimeDelta::FromMicroseconds(396000),
1566             demuxer_->GetStartTime());
1567 }
1568
1569 }  // namespace media