Home | History | Annotate | Download | only in filters
      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(_)).Times(AtMost(1))
    539         .WillRepeatedly(SaveArg<0>(&metadata_));
    540     EXPECT_CALL(*this, OnPrerollCompleted()).Times(AtMost(1));
    541     pipeline_->Start(
    542         CreateFilterCollection(source->GetDemuxer(), NULL),
    543         base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)),
    544         base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)),
    545         QuitOnStatusCB(PIPELINE_OK),
    546         base::Bind(&PipelineIntegrationTest::OnMetadata,
    547                    base::Unretained(this)),
    548         base::Bind(&PipelineIntegrationTest::OnPrerollCompleted,
    549                    base::Unretained(this)),
    550         base::Closure());
    551 
    552     message_loop_.Run();
    553   }
    554 
    555   void StartHashedPipelineWithMediaSource(MockMediaSource* source) {
    556     hashing_enabled_ = true;
    557     StartPipelineWithMediaSource(source);
    558   }
    559 
    560   void StartPipelineWithEncryptedMedia(
    561       MockMediaSource* source,
    562       FakeEncryptedMedia* encrypted_media) {
    563     EXPECT_CALL(*this, OnMetadata(_)).Times(AtMost(1))
    564         .WillRepeatedly(SaveArg<0>(&metadata_));
    565     EXPECT_CALL(*this, OnPrerollCompleted()).Times(AtMost(1));
    566     pipeline_->Start(
    567         CreateFilterCollection(source->GetDemuxer(),
    568                                encrypted_media->decryptor()),
    569         base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)),
    570         base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)),
    571         QuitOnStatusCB(PIPELINE_OK),
    572         base::Bind(&PipelineIntegrationTest::OnMetadata,
    573                    base::Unretained(this)),
    574         base::Bind(&PipelineIntegrationTest::OnPrerollCompleted,
    575                    base::Unretained(this)),
    576         base::Closure());
    577 
    578     source->set_need_key_cb(base::Bind(&FakeEncryptedMedia::NeedKey,
    579                                        base::Unretained(encrypted_media)));
    580 
    581     message_loop_.Run();
    582   }
    583 
    584   // Verifies that seeking works properly for ChunkDemuxer when the
    585   // seek happens while there is a pending read on the ChunkDemuxer
    586   // and no data is available.
    587   bool TestSeekDuringRead(const std::string& filename,
    588                           const std::string& mimetype,
    589                           int initial_append_size,
    590                           base::TimeDelta start_seek_time,
    591                           base::TimeDelta seek_time,
    592                           int seek_file_position,
    593                           int seek_append_size) {
    594     MockMediaSource source(filename, mimetype, initial_append_size);
    595     StartPipelineWithMediaSource(&source);
    596 
    597     if (pipeline_status_ != PIPELINE_OK)
    598       return false;
    599 
    600     Play();
    601     if (!WaitUntilCurrentTimeIsAfter(start_seek_time))
    602       return false;
    603 
    604     source.Seek(seek_time, seek_file_position, seek_append_size);
    605     if (!Seek(seek_time))
    606       return false;
    607 
    608     source.EndOfStream();
    609 
    610     source.Abort();
    611     Stop();
    612     return true;
    613   }
    614 };
    615 
    616 TEST_F(PipelineIntegrationTest, BasicPlayback) {
    617   ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240.webm"), PIPELINE_OK));
    618 
    619   Play();
    620 
    621   ASSERT_TRUE(WaitUntilOnEnded());
    622 }
    623 
    624 TEST_F(PipelineIntegrationTest, BasicPlaybackOpusOgg) {
    625   ASSERT_TRUE(Start(GetTestDataFilePath("bear-opus.ogg"), PIPELINE_OK));
    626 
    627   Play();
    628 
    629   ASSERT_TRUE(WaitUntilOnEnded());
    630 }
    631 
    632 TEST_F(PipelineIntegrationTest, BasicPlaybackHashed) {
    633   ASSERT_TRUE(Start(
    634       GetTestDataFilePath("bear-320x240.webm"), PIPELINE_OK, kHashed));
    635 
    636   Play();
    637 
    638   ASSERT_TRUE(WaitUntilOnEnded());
    639 
    640   EXPECT_EQ("f0be120a90a811506777c99a2cdf7cc1", GetVideoHash());
    641   EXPECT_EQ("-3.59,-2.06,-0.43,2.15,0.77,-0.95,", GetAudioHash());
    642   EXPECT_TRUE(demuxer_->GetTimelineOffset().is_null());
    643 }
    644 
    645 TEST_F(PipelineIntegrationTest, BasicPlaybackLive) {
    646   ASSERT_TRUE(Start(
    647       GetTestDataFilePath("bear-320x240-live.webm"), PIPELINE_OK, kHashed));
    648 
    649   Play();
    650 
    651   ASSERT_TRUE(WaitUntilOnEnded());
    652 
    653   EXPECT_EQ("f0be120a90a811506777c99a2cdf7cc1", GetVideoHash());
    654   EXPECT_EQ("-3.59,-2.06,-0.43,2.15,0.77,-0.95,", GetAudioHash());
    655 
    656   // TODO: Fix FFmpeg code to return higher resolution time values so
    657   // we don't have to truncate our expectations here.
    658   EXPECT_EQ(TruncateToFFmpegTimeResolution(kLiveTimelineOffset()),
    659             demuxer_->GetTimelineOffset());
    660 }
    661 
    662 TEST_F(PipelineIntegrationTest, F32PlaybackHashed) {
    663   ASSERT_TRUE(
    664       Start(GetTestDataFilePath("sfx_f32le.wav"), PIPELINE_OK, kHashed));
    665   Play();
    666   ASSERT_TRUE(WaitUntilOnEnded());
    667   EXPECT_EQ(std::string(kNullVideoHash), GetVideoHash());
    668   EXPECT_EQ("3.03,2.86,2.99,3.31,3.57,4.06,", GetAudioHash());
    669 }
    670 
    671 TEST_F(PipelineIntegrationTest, BasicPlaybackEncrypted) {
    672   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
    673   set_need_key_cb(base::Bind(&FakeEncryptedMedia::NeedKey,
    674                              base::Unretained(&encrypted_media)));
    675 
    676   ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240-av_enc-av.webm"),
    677                     encrypted_media.decryptor()));
    678 
    679   Play();
    680 
    681   ASSERT_TRUE(WaitUntilOnEnded());
    682   Stop();
    683 }
    684 
    685 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource) {
    686   MockMediaSource source("bear-320x240.webm", kWebM, 219229);
    687   StartPipelineWithMediaSource(&source);
    688   source.EndOfStream();
    689 
    690   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
    691   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
    692   EXPECT_EQ(k320WebMFileDurationMs,
    693             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
    694 
    695   Play();
    696 
    697   ASSERT_TRUE(WaitUntilOnEnded());
    698 
    699   EXPECT_TRUE(demuxer_->GetTimelineOffset().is_null());
    700   source.Abort();
    701   Stop();
    702 }
    703 
    704 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_Live) {
    705   MockMediaSource source("bear-320x240-live.webm", kWebM, 219221);
    706   StartPipelineWithMediaSource(&source);
    707   source.EndOfStream();
    708 
    709   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
    710   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
    711   EXPECT_EQ(k320WebMFileDurationMs,
    712             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
    713 
    714   Play();
    715 
    716   ASSERT_TRUE(WaitUntilOnEnded());
    717 
    718   EXPECT_EQ(kLiveTimelineOffset(),
    719             demuxer_->GetTimelineOffset());
    720   source.Abort();
    721   Stop();
    722 }
    723 
    724 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_VP9_WebM) {
    725   MockMediaSource source("bear-vp9.webm", kWebMVP9, 67504);
    726   StartPipelineWithMediaSource(&source);
    727   source.EndOfStream();
    728 
    729   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
    730   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
    731   EXPECT_EQ(kVP9WebMFileDurationMs,
    732             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
    733 
    734   Play();
    735 
    736   ASSERT_TRUE(WaitUntilOnEnded());
    737   source.Abort();
    738   Stop();
    739 }
    740 
    741 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_VP8A_WebM) {
    742   MockMediaSource source("bear-vp8a.webm", kVideoOnlyWebM, kAppendWholeFile);
    743   StartPipelineWithMediaSource(&source);
    744   source.EndOfStream();
    745 
    746   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
    747   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
    748   EXPECT_EQ(kVP8AWebMFileDurationMs,
    749             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
    750 
    751   Play();
    752 
    753   ASSERT_TRUE(WaitUntilOnEnded());
    754   source.Abort();
    755   Stop();
    756 }
    757 
    758 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_Opus_WebM) {
    759   MockMediaSource source("bear-opus-end-trimming.webm", kOpusAudioOnlyWebM,
    760                          kAppendWholeFile);
    761   StartPipelineWithMediaSource(&source);
    762   source.EndOfStream();
    763 
    764   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
    765   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
    766   EXPECT_EQ(kOpusEndTrimmingWebMFileDurationMs,
    767             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
    768   Play();
    769 
    770   ASSERT_TRUE(WaitUntilOnEnded());
    771   source.Abort();
    772   Stop();
    773 }
    774 
    775 // Flaky. http://crbug.com/304776
    776 TEST_F(PipelineIntegrationTest, DISABLED_MediaSource_Opus_Seeking_WebM) {
    777   MockMediaSource source("bear-opus-end-trimming.webm", kOpusAudioOnlyWebM,
    778                          kAppendWholeFile);
    779   StartHashedPipelineWithMediaSource(&source);
    780 
    781   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
    782   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
    783   EXPECT_EQ(kOpusEndTrimmingWebMFileDurationMs,
    784             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
    785 
    786   base::TimeDelta start_seek_time = base::TimeDelta::FromMilliseconds(1000);
    787   base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(2000);
    788 
    789   Play();
    790   ASSERT_TRUE(WaitUntilCurrentTimeIsAfter(start_seek_time));
    791   source.Seek(seek_time, 0x1D5, 34017);
    792   source.EndOfStream();
    793   ASSERT_TRUE(Seek(seek_time));
    794 
    795   ASSERT_TRUE(WaitUntilOnEnded());
    796 
    797   EXPECT_EQ("0.76,0.20,-0.82,-0.58,-1.29,-0.29,", GetAudioHash());
    798 
    799   source.Abort();
    800   Stop();
    801 }
    802 
    803 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_WebM) {
    804   MockMediaSource source("bear-320x240-16x9-aspect.webm", kWebM,
    805                          kAppendWholeFile);
    806   StartPipelineWithMediaSource(&source);
    807 
    808   scoped_refptr<DecoderBuffer> second_file =
    809       ReadTestDataFile("bear-640x360.webm");
    810 
    811   source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
    812                       second_file->data(), second_file->data_size());
    813 
    814   source.EndOfStream();
    815 
    816   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
    817   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
    818   EXPECT_EQ(kAppendTimeMs + k640WebMFileDurationMs,
    819             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
    820 
    821   Play();
    822 
    823   EXPECT_TRUE(WaitUntilOnEnded());
    824   source.Abort();
    825   Stop();
    826 }
    827 
    828 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_Encrypted_WebM) {
    829   MockMediaSource source("bear-320x240-16x9-aspect-av_enc-av.webm", kWebM,
    830                          kAppendWholeFile);
    831   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
    832   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
    833 
    834   scoped_refptr<DecoderBuffer> second_file =
    835       ReadTestDataFile("bear-640x360-av_enc-av.webm");
    836 
    837   source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
    838                       second_file->data(), second_file->data_size());
    839 
    840   source.EndOfStream();
    841 
    842   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
    843   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
    844   EXPECT_EQ(kAppendTimeMs + k640WebMFileDurationMs,
    845             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
    846 
    847   Play();
    848 
    849   EXPECT_TRUE(WaitUntilOnEnded());
    850   source.Abort();
    851   Stop();
    852 }
    853 
    854 // Config changes from encrypted to clear are not currently supported.
    855 TEST_F(PipelineIntegrationTest,
    856        MediaSource_ConfigChange_ClearThenEncrypted_WebM) {
    857   MockMediaSource source("bear-320x240-16x9-aspect.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   message_loop_.Run();
    871   EXPECT_EQ(PIPELINE_ERROR_DECODE, pipeline_status_);
    872 
    873   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
    874   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
    875   // The second video was not added, so its time has not been added.
    876   EXPECT_EQ(k320WebMFileDurationMs,
    877             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
    878 
    879   Play();
    880 
    881   EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
    882   source.Abort();
    883 }
    884 
    885 // Config changes from clear to encrypted are not currently supported.
    886 TEST_F(PipelineIntegrationTest,
    887        MediaSource_ConfigChange_EncryptedThenClear_WebM) {
    888   MockMediaSource source("bear-320x240-16x9-aspect-av_enc-av.webm", kWebM,
    889                          kAppendWholeFile);
    890   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
    891   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
    892 
    893   scoped_refptr<DecoderBuffer> second_file =
    894       ReadTestDataFile("bear-640x360.webm");
    895 
    896   source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
    897                       second_file->data(), second_file->data_size());
    898 
    899   source.EndOfStream();
    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 #if defined(USE_PROPRIETARY_CODECS)
    914 TEST_F(PipelineIntegrationTest, MediaSource_ADTS) {
    915   MockMediaSource source("sfx.adts", kADTS, kAppendWholeFile);
    916   StartPipelineWithMediaSource(&source);
    917   source.EndOfStream();
    918 
    919   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
    920   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
    921   EXPECT_EQ(325, pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
    922 
    923   Play();
    924 
    925   EXPECT_TRUE(WaitUntilOnEnded());
    926 }
    927 
    928 TEST_F(PipelineIntegrationTest, MediaSource_ADTS_TimestampOffset) {
    929   MockMediaSource source("sfx.adts", kADTS, kAppendWholeFile);
    930   StartHashedPipelineWithMediaSource(&source);
    931   EXPECT_EQ(325, source.last_timestamp_offset().InMilliseconds());
    932 
    933   // Trim off multiple frames off the beginning of the segment which will cause
    934   // the first decoded frame to be incorrect if preroll isn't implemented.
    935   const base::TimeDelta adts_preroll_duration =
    936       base::TimeDelta::FromSecondsD(2.5 * 1024 / 44100);
    937   const base::TimeDelta append_time =
    938       source.last_timestamp_offset() - adts_preroll_duration;
    939 
    940   scoped_refptr<DecoderBuffer> second_file = ReadTestDataFile("sfx.adts");
    941   source.AppendAtTimeWithWindow(append_time,
    942                                 append_time + adts_preroll_duration,
    943                                 kInfiniteDuration(),
    944                                 second_file->data(),
    945                                 second_file->data_size());
    946   source.EndOfStream();
    947 
    948   EXPECT_EQ(592, source.last_timestamp_offset().InMilliseconds());
    949   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
    950   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
    951   EXPECT_EQ(592, pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
    952 
    953   Play();
    954 
    955   EXPECT_TRUE(WaitUntilOnEnded());
    956 
    957   // Verify preroll is stripped.
    958   EXPECT_EQ("-0.06,0.97,-0.90,-0.70,-0.53,-0.34,", GetAudioHash());
    959 }
    960 
    961 TEST_F(PipelineIntegrationTest, BasicPlaybackHashed_MP3) {
    962   ASSERT_TRUE(Start(GetTestDataFilePath("sfx.mp3"), PIPELINE_OK, kHashed));
    963 
    964   Play();
    965 
    966   ASSERT_TRUE(WaitUntilOnEnded());
    967 
    968   // Verify codec delay and preroll are stripped.
    969   EXPECT_EQ("3.05,2.87,3.00,3.32,3.58,4.08,", GetAudioHash());
    970 }
    971 
    972 TEST_F(PipelineIntegrationTest, MediaSource_MP3) {
    973   MockMediaSource source("sfx.mp3", kMP3, kAppendWholeFile);
    974   StartHashedPipelineWithMediaSource(&source);
    975   source.EndOfStream();
    976 
    977   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
    978   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
    979   EXPECT_EQ(313, pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
    980 
    981   Play();
    982 
    983   EXPECT_TRUE(WaitUntilOnEnded());
    984 
    985   // Verify that codec delay was stripped.
    986   EXPECT_EQ("1.01,2.71,4.18,4.32,3.04,1.12,", GetAudioHash());
    987 }
    988 
    989 TEST_F(PipelineIntegrationTest, MediaSource_MP3_TimestampOffset) {
    990   MockMediaSource source("sfx.mp3", kMP3, kAppendWholeFile);
    991   StartPipelineWithMediaSource(&source);
    992   EXPECT_EQ(313, source.last_timestamp_offset().InMilliseconds());
    993 
    994   // There are 576 silent frames at the start of this mp3.  The second append
    995   // should trim them off.
    996   const base::TimeDelta mp3_preroll_duration =
    997       base::TimeDelta::FromSecondsD(576.0 / 44100);
    998   const base::TimeDelta append_time =
    999       source.last_timestamp_offset() - mp3_preroll_duration;
   1000 
   1001   scoped_refptr<DecoderBuffer> second_file = ReadTestDataFile("sfx.mp3");
   1002   source.AppendAtTimeWithWindow(append_time,
   1003                                 append_time + mp3_preroll_duration,
   1004                                 kInfiniteDuration(),
   1005                                 second_file->data(),
   1006                                 second_file->data_size());
   1007   source.EndOfStream();
   1008 
   1009   EXPECT_EQ(613, source.last_timestamp_offset().InMilliseconds());
   1010   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
   1011   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
   1012   EXPECT_EQ(613, pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
   1013 
   1014   Play();
   1015 
   1016   EXPECT_TRUE(WaitUntilOnEnded());
   1017 }
   1018 
   1019 TEST_F(PipelineIntegrationTest, MediaSource_MP3_Icecast) {
   1020   MockMediaSource source("icy_sfx.mp3", kMP3, kAppendWholeFile);
   1021   StartPipelineWithMediaSource(&source);
   1022   source.EndOfStream();
   1023 
   1024   Play();
   1025 
   1026   EXPECT_TRUE(WaitUntilOnEnded());
   1027 }
   1028 
   1029 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_MP4) {
   1030   MockMediaSource source("bear-640x360-av_frag.mp4", kMP4, kAppendWholeFile);
   1031   StartPipelineWithMediaSource(&source);
   1032 
   1033   scoped_refptr<DecoderBuffer> second_file =
   1034       ReadTestDataFile("bear-1280x720-av_frag.mp4");
   1035 
   1036   source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
   1037                       second_file->data(), second_file->data_size());
   1038 
   1039   source.EndOfStream();
   1040 
   1041   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
   1042   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
   1043   EXPECT_EQ(kAppendTimeMs + k1280IsoFileDurationMs,
   1044             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
   1045 
   1046   Play();
   1047 
   1048   EXPECT_TRUE(WaitUntilOnEnded());
   1049   source.Abort();
   1050   Stop();
   1051 }
   1052 
   1053 TEST_F(PipelineIntegrationTest,
   1054        MediaSource_ConfigChange_Encrypted_MP4_CENC_VideoOnly) {
   1055   MockMediaSource source("bear-640x360-v_frag-cenc.mp4", kMP4Video,
   1056                          kAppendWholeFile);
   1057   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
   1058   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
   1059 
   1060   scoped_refptr<DecoderBuffer> second_file =
   1061       ReadTestDataFile("bear-1280x720-v_frag-cenc.mp4");
   1062 
   1063   source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
   1064                       second_file->data(), second_file->data_size());
   1065 
   1066   source.EndOfStream();
   1067 
   1068   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
   1069   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
   1070   EXPECT_EQ(kAppendTimeMs + k1280IsoFileDurationMs,
   1071             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
   1072 
   1073   Play();
   1074 
   1075   EXPECT_TRUE(WaitUntilOnEnded());
   1076   source.Abort();
   1077   Stop();
   1078 }
   1079 
   1080 TEST_F(PipelineIntegrationTest,
   1081        MediaSource_ConfigChange_Encrypted_MP4_CENC_KeyRotation_VideoOnly) {
   1082   MockMediaSource source("bear-640x360-v_frag-cenc-key_rotation.mp4", kMP4Video,
   1083                          kAppendWholeFile);
   1084   FakeEncryptedMedia encrypted_media(new RotatingKeyProvidingApp());
   1085   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
   1086 
   1087   scoped_refptr<DecoderBuffer> second_file =
   1088       ReadTestDataFile("bear-1280x720-v_frag-cenc-key_rotation.mp4");
   1089 
   1090   source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
   1091                       second_file->data(), second_file->data_size());
   1092 
   1093   source.EndOfStream();
   1094 
   1095   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
   1096   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
   1097   EXPECT_EQ(kAppendTimeMs + k1280IsoFileDurationMs,
   1098             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
   1099 
   1100   Play();
   1101 
   1102   EXPECT_TRUE(WaitUntilOnEnded());
   1103   source.Abort();
   1104   Stop();
   1105 }
   1106 
   1107 // Config changes from clear to encrypted are not currently supported.
   1108 // TODO(ddorwin): Figure out why this CHECKs in AppendAtTime().
   1109 TEST_F(PipelineIntegrationTest,
   1110        DISABLED_MediaSource_ConfigChange_ClearThenEncrypted_MP4_CENC) {
   1111   MockMediaSource source("bear-640x360-av_frag.mp4", kMP4Video,
   1112                          kAppendWholeFile);
   1113   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
   1114   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
   1115 
   1116   scoped_refptr<DecoderBuffer> second_file =
   1117       ReadTestDataFile("bear-1280x720-v_frag-cenc.mp4");
   1118 
   1119   source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
   1120                       second_file->data(), second_file->data_size());
   1121 
   1122   source.EndOfStream();
   1123 
   1124   message_loop_.Run();
   1125   EXPECT_EQ(PIPELINE_ERROR_DECODE, pipeline_status_);
   1126 
   1127   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
   1128   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
   1129   // The second video was not added, so its time has not been added.
   1130   EXPECT_EQ(k640IsoFileDurationMs,
   1131             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
   1132 
   1133   Play();
   1134 
   1135   EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
   1136   source.Abort();
   1137 }
   1138 
   1139 // Config changes from encrypted to clear are not currently supported.
   1140 TEST_F(PipelineIntegrationTest,
   1141        MediaSource_ConfigChange_EncryptedThenClear_MP4_CENC) {
   1142   MockMediaSource source("bear-640x360-v_frag-cenc.mp4", kMP4Video,
   1143                          kAppendWholeFile);
   1144   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
   1145   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
   1146 
   1147   scoped_refptr<DecoderBuffer> second_file =
   1148       ReadTestDataFile("bear-1280x720-av_frag.mp4");
   1149 
   1150   source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
   1151                       second_file->data(), second_file->data_size());
   1152 
   1153   source.EndOfStream();
   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(k640IsoCencFileDurationMs,
   1159             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
   1160 
   1161   Play();
   1162 
   1163   EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
   1164   source.Abort();
   1165 }
   1166 
   1167 // Verify files which change configuration midstream fail gracefully.
   1168 TEST_F(PipelineIntegrationTest, MidStreamConfigChangesFail) {
   1169   ASSERT_TRUE(Start(
   1170       GetTestDataFilePath("midstream_config_change.mp3"), PIPELINE_OK));
   1171   Play();
   1172   ASSERT_EQ(WaitUntilEndedOrError(), PIPELINE_ERROR_DECODE);
   1173 }
   1174 
   1175 #endif
   1176 
   1177 TEST_F(PipelineIntegrationTest, BasicPlayback_16x9AspectRatio) {
   1178   ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240-16x9-aspect.webm"),
   1179                     PIPELINE_OK));
   1180   Play();
   1181   ASSERT_TRUE(WaitUntilOnEnded());
   1182 }
   1183 
   1184 TEST_F(PipelineIntegrationTest, EncryptedPlayback_WebM) {
   1185   MockMediaSource source("bear-320x240-av_enc-av.webm", kWebM, 219816);
   1186   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
   1187   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
   1188 
   1189   source.EndOfStream();
   1190   ASSERT_EQ(PIPELINE_OK, pipeline_status_);
   1191 
   1192   Play();
   1193 
   1194   ASSERT_TRUE(WaitUntilOnEnded());
   1195   source.Abort();
   1196   Stop();
   1197 }
   1198 
   1199 TEST_F(PipelineIntegrationTest, EncryptedPlayback_ClearStart_WebM) {
   1200   MockMediaSource source("bear-320x240-av_enc-av_clear-1s.webm", kWebM,
   1201                          kAppendWholeFile);
   1202   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
   1203   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
   1204 
   1205   source.EndOfStream();
   1206   ASSERT_EQ(PIPELINE_OK, pipeline_status_);
   1207 
   1208   Play();
   1209 
   1210   ASSERT_TRUE(WaitUntilOnEnded());
   1211   source.Abort();
   1212   Stop();
   1213 }
   1214 
   1215 TEST_F(PipelineIntegrationTest, EncryptedPlayback_NoEncryptedFrames_WebM) {
   1216   MockMediaSource source("bear-320x240-av_enc-av_clear-all.webm", kWebM,
   1217                          kAppendWholeFile);
   1218   FakeEncryptedMedia encrypted_media(new NoResponseApp());
   1219   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
   1220 
   1221   source.EndOfStream();
   1222   ASSERT_EQ(PIPELINE_OK, pipeline_status_);
   1223 
   1224   Play();
   1225 
   1226   ASSERT_TRUE(WaitUntilOnEnded());
   1227   source.Abort();
   1228   Stop();
   1229 }
   1230 
   1231 #if defined(USE_PROPRIETARY_CODECS)
   1232 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_VideoOnly) {
   1233   MockMediaSource source("bear-1280x720-v_frag-cenc.mp4", kMP4Video,
   1234                          kAppendWholeFile);
   1235   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
   1236   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
   1237 
   1238   source.EndOfStream();
   1239   ASSERT_EQ(PIPELINE_OK, pipeline_status_);
   1240 
   1241   Play();
   1242 
   1243   ASSERT_TRUE(WaitUntilOnEnded());
   1244   source.Abort();
   1245   Stop();
   1246 }
   1247 
   1248 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_AudioOnly) {
   1249   MockMediaSource source("bear-1280x720-a_frag-cenc.mp4", kMP4Audio,
   1250                          kAppendWholeFile);
   1251   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
   1252   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
   1253 
   1254   source.EndOfStream();
   1255   ASSERT_EQ(PIPELINE_OK, pipeline_status_);
   1256 
   1257   Play();
   1258 
   1259   ASSERT_TRUE(WaitUntilOnEnded());
   1260   source.Abort();
   1261   Stop();
   1262 }
   1263 
   1264 TEST_F(PipelineIntegrationTest,
   1265        EncryptedPlayback_NoEncryptedFrames_MP4_CENC_VideoOnly) {
   1266   MockMediaSource source("bear-1280x720-v_frag-cenc_clear-all.mp4", kMP4Video,
   1267                          kAppendWholeFile);
   1268   FakeEncryptedMedia encrypted_media(new NoResponseApp());
   1269   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
   1270 
   1271   source.EndOfStream();
   1272   ASSERT_EQ(PIPELINE_OK, pipeline_status_);
   1273 
   1274   Play();
   1275 
   1276   ASSERT_TRUE(WaitUntilOnEnded());
   1277   source.Abort();
   1278   Stop();
   1279 }
   1280 
   1281 TEST_F(PipelineIntegrationTest,
   1282        EncryptedPlayback_NoEncryptedFrames_MP4_CENC_AudioOnly) {
   1283   MockMediaSource source("bear-1280x720-a_frag-cenc_clear-all.mp4", kMP4Audio,
   1284                          kAppendWholeFile);
   1285   FakeEncryptedMedia encrypted_media(new NoResponseApp());
   1286   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
   1287 
   1288   source.EndOfStream();
   1289   ASSERT_EQ(PIPELINE_OK, pipeline_status_);
   1290 
   1291   Play();
   1292 
   1293   ASSERT_TRUE(WaitUntilOnEnded());
   1294   source.Abort();
   1295   Stop();
   1296 }
   1297 
   1298 TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_VideoOnly_MP4_AVC3) {
   1299   MockMediaSource source("bear-1280x720-v_frag-avc3.mp4", kMP4VideoAVC3,
   1300                          kAppendWholeFile);
   1301   StartPipelineWithMediaSource(&source);
   1302   source.EndOfStream();
   1303 
   1304   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
   1305   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
   1306   EXPECT_EQ(k1280IsoAVC3FileDurationMs,
   1307             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
   1308 
   1309   Play();
   1310 
   1311   ASSERT_TRUE(WaitUntilOnEnded());
   1312   source.Abort();
   1313   Stop();
   1314 }
   1315 
   1316 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_KeyRotation_Video) {
   1317   MockMediaSource source("bear-1280x720-v_frag-cenc-key_rotation.mp4",
   1318                          kMP4Video, kAppendWholeFile);
   1319   FakeEncryptedMedia encrypted_media(new RotatingKeyProvidingApp());
   1320   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
   1321 
   1322   source.EndOfStream();
   1323   ASSERT_EQ(PIPELINE_OK, pipeline_status_);
   1324 
   1325   Play();
   1326 
   1327   ASSERT_TRUE(WaitUntilOnEnded());
   1328   source.Abort();
   1329   Stop();
   1330 }
   1331 
   1332 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_KeyRotation_Audio) {
   1333   MockMediaSource source("bear-1280x720-a_frag-cenc-key_rotation.mp4",
   1334                          kMP4Audio, kAppendWholeFile);
   1335   FakeEncryptedMedia encrypted_media(new RotatingKeyProvidingApp());
   1336   StartPipelineWithEncryptedMedia(&source, &encrypted_media);
   1337 
   1338   source.EndOfStream();
   1339   ASSERT_EQ(PIPELINE_OK, pipeline_status_);
   1340 
   1341   Play();
   1342 
   1343   ASSERT_TRUE(WaitUntilOnEnded());
   1344   source.Abort();
   1345   Stop();
   1346 }
   1347 #endif
   1348 
   1349 // TODO(acolwell): Fix flakiness http://crbug.com/117921
   1350 TEST_F(PipelineIntegrationTest, DISABLED_SeekWhilePaused) {
   1351   ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240.webm"), PIPELINE_OK));
   1352 
   1353   base::TimeDelta duration(pipeline_->GetMediaDuration());
   1354   base::TimeDelta start_seek_time(duration / 4);
   1355   base::TimeDelta seek_time(duration * 3 / 4);
   1356 
   1357   Play();
   1358   ASSERT_TRUE(WaitUntilCurrentTimeIsAfter(start_seek_time));
   1359   Pause();
   1360   ASSERT_TRUE(Seek(seek_time));
   1361   EXPECT_EQ(pipeline_->GetMediaTime(), seek_time);
   1362   Play();
   1363   ASSERT_TRUE(WaitUntilOnEnded());
   1364 
   1365   // Make sure seeking after reaching the end works as expected.
   1366   Pause();
   1367   ASSERT_TRUE(Seek(seek_time));
   1368   EXPECT_EQ(pipeline_->GetMediaTime(), seek_time);
   1369   Play();
   1370   ASSERT_TRUE(WaitUntilOnEnded());
   1371 }
   1372 
   1373 // TODO(acolwell): Fix flakiness http://crbug.com/117921
   1374 TEST_F(PipelineIntegrationTest, DISABLED_SeekWhilePlaying) {
   1375   ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240.webm"), PIPELINE_OK));
   1376 
   1377   base::TimeDelta duration(pipeline_->GetMediaDuration());
   1378   base::TimeDelta start_seek_time(duration / 4);
   1379   base::TimeDelta seek_time(duration * 3 / 4);
   1380 
   1381   Play();
   1382   ASSERT_TRUE(WaitUntilCurrentTimeIsAfter(start_seek_time));
   1383   ASSERT_TRUE(Seek(seek_time));
   1384   EXPECT_GE(pipeline_->GetMediaTime(), seek_time);
   1385   ASSERT_TRUE(WaitUntilOnEnded());
   1386 
   1387   // Make sure seeking after reaching the end works as expected.
   1388   ASSERT_TRUE(Seek(seek_time));
   1389   EXPECT_GE(pipeline_->GetMediaTime(), seek_time);
   1390   ASSERT_TRUE(WaitUntilOnEnded());
   1391 }
   1392 
   1393 // Verify audio decoder & renderer can handle aborted demuxer reads.
   1394 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_AudioOnly) {
   1395   ASSERT_TRUE(TestSeekDuringRead("bear-320x240-audio-only.webm", kAudioOnlyWebM,
   1396                                  8192,
   1397                                  base::TimeDelta::FromMilliseconds(464),
   1398                                  base::TimeDelta::FromMilliseconds(617),
   1399                                  0x10CA, 19730));
   1400 }
   1401 
   1402 // Verify video decoder & renderer can handle aborted demuxer reads.
   1403 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_VideoOnly) {
   1404   ASSERT_TRUE(TestSeekDuringRead("bear-320x240-video-only.webm", kVideoOnlyWebM,
   1405                                  32768,
   1406                                  base::TimeDelta::FromMilliseconds(167),
   1407                                  base::TimeDelta::FromMilliseconds(1668),
   1408                                  0x1C896, 65536));
   1409 }
   1410 
   1411 // Verify that Opus audio in WebM containers can be played back.
   1412 TEST_F(PipelineIntegrationTest, BasicPlayback_AudioOnly_Opus_WebM) {
   1413   ASSERT_TRUE(Start(GetTestDataFilePath("bear-opus-end-trimming.webm"),
   1414                     PIPELINE_OK));
   1415   Play();
   1416   ASSERT_TRUE(WaitUntilOnEnded());
   1417 }
   1418 
   1419 // Verify that VP9 video in WebM containers can be played back.
   1420 TEST_F(PipelineIntegrationTest, BasicPlayback_VideoOnly_VP9_WebM) {
   1421   ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp9.webm"),
   1422                     PIPELINE_OK));
   1423   Play();
   1424   ASSERT_TRUE(WaitUntilOnEnded());
   1425 }
   1426 
   1427 // Verify that VP9 video and Opus audio in the same WebM container can be played
   1428 // back.
   1429 TEST_F(PipelineIntegrationTest, BasicPlayback_VP9_Opus_WebM) {
   1430   ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp9-opus.webm"),
   1431                     PIPELINE_OK));
   1432   Play();
   1433   ASSERT_TRUE(WaitUntilOnEnded());
   1434 }
   1435 
   1436 // Verify that VP8 video with alpha channel can be played back.
   1437 TEST_F(PipelineIntegrationTest, BasicPlayback_VP8A_WebM) {
   1438   ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp8a.webm"),
   1439                     PIPELINE_OK));
   1440   Play();
   1441   ASSERT_TRUE(WaitUntilOnEnded());
   1442   EXPECT_EQ(last_video_frame_format_, VideoFrame::YV12A);
   1443 }
   1444 
   1445 // Verify that VP8A video with odd width/height can be played back.
   1446 TEST_F(PipelineIntegrationTest, BasicPlayback_VP8A_Odd_WebM) {
   1447   ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp8a-odd-dimensions.webm"),
   1448                     PIPELINE_OK));
   1449   Play();
   1450   ASSERT_TRUE(WaitUntilOnEnded());
   1451   EXPECT_EQ(last_video_frame_format_, VideoFrame::YV12A);
   1452 }
   1453 
   1454 // Verify that VP8 video with inband text track can be played back.
   1455 TEST_F(PipelineIntegrationTest,
   1456        BasicPlayback_VP8_WebVTT_WebM) {
   1457   ASSERT_TRUE(Start(GetTestDataFilePath("bear-vp8-webvtt.webm"),
   1458                     PIPELINE_OK));
   1459   Play();
   1460   ASSERT_TRUE(WaitUntilOnEnded());
   1461 }
   1462 
   1463 // Verify that VP9 video with 4:4:4 subsampling can be played back.
   1464 TEST_F(PipelineIntegrationTest, P444_VP9_WebM) {
   1465   ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240-P444.webm"),
   1466                     PIPELINE_OK));
   1467   Play();
   1468   ASSERT_TRUE(WaitUntilOnEnded());
   1469   EXPECT_EQ(last_video_frame_format_, VideoFrame::YV24);
   1470 }
   1471 
   1472 // Verify that videos with an odd frame size playback successfully.
   1473 TEST_F(PipelineIntegrationTest, BasicPlayback_OddVideoSize) {
   1474   ASSERT_TRUE(Start(GetTestDataFilePath("butterfly-853x480.webm"),
   1475                     PIPELINE_OK));
   1476   Play();
   1477   ASSERT_TRUE(WaitUntilOnEnded());
   1478 }
   1479 
   1480 }  // namespace media
   1481