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