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 <algorithm>
      6 
      7 #include "base/bind.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "base/strings/string_number_conversions.h"
     10 #include "base/strings/string_split.h"
     11 #include "base/strings/string_util.h"
     12 #include "media/base/audio_decoder_config.h"
     13 #include "media/base/decoder_buffer.h"
     14 #include "media/base/decrypt_config.h"
     15 #include "media/base/mock_demuxer_host.h"
     16 #include "media/base/test_data_util.h"
     17 #include "media/base/test_helpers.h"
     18 #include "media/filters/chunk_demuxer.h"
     19 #include "media/formats/webm/cluster_builder.h"
     20 #include "media/formats/webm/webm_constants.h"
     21 #include "media/formats/webm/webm_crypto_helpers.h"
     22 #include "testing/gtest/include/gtest/gtest.h"
     23 
     24 using ::testing::AnyNumber;
     25 using ::testing::Exactly;
     26 using ::testing::InSequence;
     27 using ::testing::NotNull;
     28 using ::testing::Return;
     29 using ::testing::SaveArg;
     30 using ::testing::SetArgumentPointee;
     31 using ::testing::_;
     32 
     33 namespace media {
     34 
     35 const uint8 kTracksHeader[] = {
     36   0x16, 0x54, 0xAE, 0x6B,  // Tracks ID
     37   0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // tracks(size = 0)
     38 };
     39 
     40 // WebM Block bytes that represent a VP8 keyframe.
     41 const uint8 kVP8Keyframe[] = {
     42   0x010, 0x00, 0x00, 0x9d, 0x01, 0x2a, 0x00, 0x10, 0x00, 0x10, 0x00
     43 };
     44 
     45 // WebM Block bytes that represent a VP8 interframe.
     46 const uint8 kVP8Interframe[] = { 0x11, 0x00, 0x00 };
     47 
     48 static const uint8 kCuesHeader[] = {
     49   0x1C, 0x53, 0xBB, 0x6B,  // Cues ID
     50   0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // cues(size = 0)
     51 };
     52 
     53 const int kTracksHeaderSize = sizeof(kTracksHeader);
     54 const int kTracksSizeOffset = 4;
     55 
     56 // The size of TrackEntry element in test file "webm_vorbis_track_entry" starts
     57 // at index 1 and spans 8 bytes.
     58 const int kAudioTrackSizeOffset = 1;
     59 const int kAudioTrackSizeWidth = 8;
     60 const int kAudioTrackEntryHeaderSize =
     61     kAudioTrackSizeOffset + kAudioTrackSizeWidth;
     62 
     63 // The size of TrackEntry element in test file "webm_vp8_track_entry" starts at
     64 // index 1 and spans 8 bytes.
     65 const int kVideoTrackSizeOffset = 1;
     66 const int kVideoTrackSizeWidth = 8;
     67 const int kVideoTrackEntryHeaderSize =
     68     kVideoTrackSizeOffset + kVideoTrackSizeWidth;
     69 
     70 const int kVideoTrackNum = 1;
     71 const int kAudioTrackNum = 2;
     72 const int kTextTrackNum = 3;
     73 const int kAlternateTextTrackNum = 4;
     74 
     75 const int kAudioBlockDuration = 23;
     76 const int kVideoBlockDuration = 33;
     77 const int kTextBlockDuration = 100;
     78 const int kBlockSize = 10;
     79 
     80 const char kSourceId[] = "SourceId";
     81 const char kDefaultFirstClusterRange[] = "{ [0,46) }";
     82 const int kDefaultFirstClusterEndTimestamp = 66;
     83 const int kDefaultSecondClusterEndTimestamp = 132;
     84 
     85 base::TimeDelta kDefaultDuration() {
     86   return base::TimeDelta::FromMilliseconds(201224);
     87 }
     88 
     89 // Write an integer into buffer in the form of vint that spans 8 bytes.
     90 // The data pointed by |buffer| should be at least 8 bytes long.
     91 // |number| should be in the range 0 <= number < 0x00FFFFFFFFFFFFFF.
     92 static void WriteInt64(uint8* buffer, int64 number) {
     93   DCHECK(number >= 0 && number < 0x00FFFFFFFFFFFFFFLL);
     94   buffer[0] = 0x01;
     95   int64 tmp = number;
     96   for (int i = 7; i > 0; i--) {
     97     buffer[i] = tmp & 0xff;
     98     tmp >>= 8;
     99   }
    100 }
    101 
    102 MATCHER_P(HasTimestamp, timestamp_in_ms, "") {
    103   return arg.get() && !arg->end_of_stream() &&
    104          arg->timestamp().InMilliseconds() == timestamp_in_ms;
    105 }
    106 
    107 MATCHER(IsEndOfStream, "") { return arg.get() && arg->end_of_stream(); }
    108 
    109 static void OnReadDone(const base::TimeDelta& expected_time,
    110                        bool* called,
    111                        DemuxerStream::Status status,
    112                        const scoped_refptr<DecoderBuffer>& buffer) {
    113   EXPECT_EQ(status, DemuxerStream::kOk);
    114   EXPECT_EQ(expected_time, buffer->timestamp());
    115   *called = true;
    116 }
    117 
    118 static void OnReadDone_AbortExpected(
    119     bool* called, DemuxerStream::Status status,
    120     const scoped_refptr<DecoderBuffer>& buffer) {
    121   EXPECT_EQ(status, DemuxerStream::kAborted);
    122   EXPECT_EQ(NULL, buffer.get());
    123   *called = true;
    124 }
    125 
    126 static void OnReadDone_EOSExpected(bool* called,
    127                                    DemuxerStream::Status status,
    128                                    const scoped_refptr<DecoderBuffer>& buffer) {
    129   EXPECT_EQ(status, DemuxerStream::kOk);
    130   EXPECT_TRUE(buffer->end_of_stream());
    131   *called = true;
    132 }
    133 
    134 static void OnSeekDone_OKExpected(bool* called, PipelineStatus status) {
    135   EXPECT_EQ(status, PIPELINE_OK);
    136   *called = true;
    137 }
    138 
    139 static void LogFunc(const std::string& str) { DVLOG(1) << str; }
    140 
    141 class ChunkDemuxerTest : public ::testing::Test {
    142  protected:
    143   enum CodecsIndex {
    144     AUDIO,
    145     VIDEO,
    146     MAX_CODECS_INDEX
    147   };
    148 
    149   // Default cluster to append first for simple tests.
    150   scoped_ptr<Cluster> kDefaultFirstCluster() {
    151     return GenerateCluster(0, 4);
    152   }
    153 
    154   // Default cluster to append after kDefaultFirstCluster()
    155   // has been appended. This cluster starts with blocks that
    156   // have timestamps consistent with the end times of the blocks
    157   // in kDefaultFirstCluster() so that these two clusters represent
    158   // a continuous region.
    159   scoped_ptr<Cluster> kDefaultSecondCluster() {
    160     return GenerateCluster(46, 66, 5);
    161   }
    162 
    163   ChunkDemuxerTest()
    164       : append_window_end_for_next_append_(kInfiniteDuration()) {
    165     CreateNewDemuxer();
    166   }
    167 
    168   void CreateNewDemuxer() {
    169     base::Closure open_cb =
    170         base::Bind(&ChunkDemuxerTest::DemuxerOpened, base::Unretained(this));
    171     Demuxer::NeedKeyCB need_key_cb =
    172         base::Bind(&ChunkDemuxerTest::DemuxerNeedKey, base::Unretained(this));
    173     demuxer_.reset(
    174         new ChunkDemuxer(open_cb, need_key_cb, base::Bind(&LogFunc), true));
    175   }
    176 
    177   virtual ~ChunkDemuxerTest() {
    178     ShutdownDemuxer();
    179   }
    180 
    181   void CreateInitSegment(int stream_flags,
    182                          bool is_audio_encrypted,
    183                          bool is_video_encrypted,
    184                          scoped_ptr<uint8[]>* buffer,
    185                          int* size) {
    186     CreateInitSegmentInternal(
    187         stream_flags, is_audio_encrypted, is_video_encrypted, buffer, false,
    188         size);
    189   }
    190 
    191   void CreateInitSegmentWithAlternateTextTrackNum(int stream_flags,
    192                                                   bool is_audio_encrypted,
    193                                                   bool is_video_encrypted,
    194                                                   scoped_ptr<uint8[]>* buffer,
    195                                                   int* size) {
    196     DCHECK(stream_flags & HAS_TEXT);
    197     CreateInitSegmentInternal(
    198         stream_flags, is_audio_encrypted, is_video_encrypted, buffer, true,
    199         size);
    200   }
    201 
    202   void CreateInitSegmentInternal(int stream_flags,
    203                                  bool is_audio_encrypted,
    204                                  bool is_video_encrypted,
    205                                  scoped_ptr<uint8[]>* buffer,
    206                                  bool use_alternate_text_track_id,
    207                                  int* size) {
    208     bool has_audio = (stream_flags & HAS_AUDIO) != 0;
    209     bool has_video = (stream_flags & HAS_VIDEO) != 0;
    210     bool has_text = (stream_flags & HAS_TEXT) != 0;
    211     scoped_refptr<DecoderBuffer> ebml_header;
    212     scoped_refptr<DecoderBuffer> info;
    213     scoped_refptr<DecoderBuffer> audio_track_entry;
    214     scoped_refptr<DecoderBuffer> video_track_entry;
    215     scoped_refptr<DecoderBuffer> audio_content_encodings;
    216     scoped_refptr<DecoderBuffer> video_content_encodings;
    217     scoped_refptr<DecoderBuffer> text_track_entry;
    218 
    219     ebml_header = ReadTestDataFile("webm_ebml_element");
    220 
    221     info = ReadTestDataFile("webm_info_element");
    222 
    223     int tracks_element_size = 0;
    224 
    225     if (has_audio) {
    226       audio_track_entry = ReadTestDataFile("webm_vorbis_track_entry");
    227       tracks_element_size += audio_track_entry->data_size();
    228       if (is_audio_encrypted) {
    229         audio_content_encodings = ReadTestDataFile("webm_content_encodings");
    230         tracks_element_size += audio_content_encodings->data_size();
    231       }
    232     }
    233 
    234     if (has_video) {
    235       video_track_entry = ReadTestDataFile("webm_vp8_track_entry");
    236       tracks_element_size += video_track_entry->data_size();
    237       if (is_video_encrypted) {
    238         video_content_encodings = ReadTestDataFile("webm_content_encodings");
    239         tracks_element_size += video_content_encodings->data_size();
    240       }
    241     }
    242 
    243     if (has_text) {
    244       // TODO(matthewjheaney): create an abstraction to do
    245       // this (http://crbug/321454).
    246       // We need it to also handle the creation of multiple text tracks.
    247       //
    248       // This is the track entry for a text track,
    249       // TrackEntry [AE], size=30
    250       //   TrackNum [D7], size=1, val=3 (or 4 if use_alternate_text_track_id)
    251       //   TrackUID [73] [C5], size=1, value=3 (must remain constant for same
    252       //     track, even if TrackNum changes)
    253       //   TrackType [83], size=1, val=0x11
    254       //   CodecId [86], size=18, val="D_WEBVTT/SUBTITLES"
    255       char str[] = "\xAE\x9E\xD7\x81\x03\x73\xC5\x81\x03"
    256                    "\x83\x81\x11\x86\x92"
    257                    "D_WEBVTT/SUBTITLES";
    258       DCHECK_EQ(str[4], kTextTrackNum);
    259       if (use_alternate_text_track_id)
    260         str[4] = kAlternateTextTrackNum;
    261 
    262       const int len = strlen(str);
    263       DCHECK_EQ(len, 32);
    264       const uint8* const buf = reinterpret_cast<const uint8*>(str);
    265       text_track_entry = DecoderBuffer::CopyFrom(buf, len);
    266       tracks_element_size += text_track_entry->data_size();
    267     }
    268 
    269     *size = ebml_header->data_size() + info->data_size() +
    270         kTracksHeaderSize + tracks_element_size;
    271 
    272     buffer->reset(new uint8[*size]);
    273 
    274     uint8* buf = buffer->get();
    275     memcpy(buf, ebml_header->data(), ebml_header->data_size());
    276     buf += ebml_header->data_size();
    277 
    278     memcpy(buf, info->data(), info->data_size());
    279     buf += info->data_size();
    280 
    281     memcpy(buf, kTracksHeader, kTracksHeaderSize);
    282     WriteInt64(buf + kTracksSizeOffset, tracks_element_size);
    283     buf += kTracksHeaderSize;
    284 
    285     // TODO(xhwang): Simplify this! Probably have test data files that contain
    286     // ContentEncodings directly instead of trying to create one at run-time.
    287     if (has_audio) {
    288       memcpy(buf, audio_track_entry->data(),
    289              audio_track_entry->data_size());
    290       if (is_audio_encrypted) {
    291         memcpy(buf + audio_track_entry->data_size(),
    292                audio_content_encodings->data(),
    293                audio_content_encodings->data_size());
    294         WriteInt64(buf + kAudioTrackSizeOffset,
    295                    audio_track_entry->data_size() +
    296                    audio_content_encodings->data_size() -
    297                    kAudioTrackEntryHeaderSize);
    298         buf += audio_content_encodings->data_size();
    299       }
    300       buf += audio_track_entry->data_size();
    301     }
    302 
    303     if (has_video) {
    304       memcpy(buf, video_track_entry->data(),
    305              video_track_entry->data_size());
    306       if (is_video_encrypted) {
    307         memcpy(buf + video_track_entry->data_size(),
    308                video_content_encodings->data(),
    309                video_content_encodings->data_size());
    310         WriteInt64(buf + kVideoTrackSizeOffset,
    311                    video_track_entry->data_size() +
    312                    video_content_encodings->data_size() -
    313                    kVideoTrackEntryHeaderSize);
    314         buf += video_content_encodings->data_size();
    315       }
    316       buf += video_track_entry->data_size();
    317     }
    318 
    319     if (has_text) {
    320       memcpy(buf, text_track_entry->data(),
    321              text_track_entry->data_size());
    322       buf += text_track_entry->data_size();
    323     }
    324   }
    325 
    326   ChunkDemuxer::Status AddId() {
    327     return AddId(kSourceId, HAS_AUDIO | HAS_VIDEO);
    328   }
    329 
    330   ChunkDemuxer::Status AddId(const std::string& source_id, int stream_flags) {
    331     bool has_audio = (stream_flags & HAS_AUDIO) != 0;
    332     bool has_video = (stream_flags & HAS_VIDEO) != 0;
    333     std::vector<std::string> codecs;
    334     std::string type;
    335 
    336     if (has_audio) {
    337       codecs.push_back("vorbis");
    338       type = "audio/webm";
    339     }
    340 
    341     if (has_video) {
    342       codecs.push_back("vp8");
    343       type = "video/webm";
    344     }
    345 
    346     if (!has_audio && !has_video) {
    347       return AddId(kSourceId, HAS_AUDIO | HAS_VIDEO);
    348     }
    349 
    350     return demuxer_->AddId(source_id, type, codecs);
    351   }
    352 
    353   ChunkDemuxer::Status AddIdForMp2tSource(const std::string& source_id) {
    354     std::vector<std::string> codecs;
    355     std::string type = "video/mp2t";
    356     codecs.push_back("mp4a.40.2");
    357     codecs.push_back("avc1.640028");
    358     return demuxer_->AddId(source_id, type, codecs);
    359   }
    360 
    361   void AppendData(const uint8* data, size_t length) {
    362     AppendData(kSourceId, data, length);
    363   }
    364 
    365   void AppendCluster(const std::string& source_id,
    366                      scoped_ptr<Cluster> cluster) {
    367     AppendData(source_id, cluster->data(), cluster->size());
    368   }
    369 
    370   void AppendCluster(scoped_ptr<Cluster> cluster) {
    371     AppendCluster(kSourceId, cluster.Pass());
    372   }
    373 
    374   void AppendCluster(int timecode, int block_count) {
    375     AppendCluster(GenerateCluster(timecode, block_count));
    376   }
    377 
    378   void AppendSingleStreamCluster(const std::string& source_id, int track_number,
    379                                  int timecode, int block_count) {
    380     int block_duration = 0;
    381     switch (track_number) {
    382       case kVideoTrackNum:
    383         block_duration = kVideoBlockDuration;
    384         break;
    385       case kAudioTrackNum:
    386         block_duration = kAudioBlockDuration;
    387         break;
    388       case kTextTrackNum:  // Fall-through.
    389       case kAlternateTextTrackNum:
    390         block_duration = kTextBlockDuration;
    391         break;
    392     }
    393     ASSERT_NE(block_duration, 0);
    394     int end_timecode = timecode + block_count * block_duration;
    395     AppendCluster(source_id,
    396                   GenerateSingleStreamCluster(
    397                       timecode, end_timecode, track_number, block_duration));
    398   }
    399 
    400   // |cluster_description| - A space delimited string of buffer info that
    401   //  is used to construct a cluster. Each buffer info is a timestamp in
    402   //  milliseconds and optionally followed by a 'K' to indicate that a buffer
    403   //  should be marked as a keyframe. For example "0K 30 60" should constuct
    404   //  a cluster with 3 blocks: a keyframe with timestamp 0 and 2 non-keyframes
    405   //  at 30ms and 60ms.
    406   void AppendSingleStreamCluster(const std::string& source_id, int track_number,
    407                                  const std::string& cluster_description) {
    408     std::vector<std::string> timestamps;
    409     base::SplitString(cluster_description, ' ', &timestamps);
    410 
    411     ClusterBuilder cb;
    412     std::vector<uint8> data(10);
    413     for (size_t i = 0; i < timestamps.size(); ++i) {
    414       std::string timestamp_str = timestamps[i];
    415       int block_flags = 0;
    416       if (EndsWith(timestamp_str, "K", true)) {
    417         block_flags = kWebMFlagKeyframe;
    418         // Remove the "K" off of the token.
    419         timestamp_str = timestamp_str.substr(0, timestamps[i].length() - 1);
    420       }
    421       int timestamp_in_ms;
    422       CHECK(base::StringToInt(timestamp_str, &timestamp_in_ms));
    423 
    424       if (i == 0)
    425         cb.SetClusterTimecode(timestamp_in_ms);
    426 
    427       if (track_number == kTextTrackNum ||
    428           track_number == kAlternateTextTrackNum) {
    429         cb.AddBlockGroup(track_number, timestamp_in_ms, kTextBlockDuration,
    430                          block_flags, &data[0], data.size());
    431       } else {
    432         cb.AddSimpleBlock(track_number, timestamp_in_ms, block_flags,
    433                           &data[0], data.size());
    434       }
    435     }
    436     AppendCluster(source_id, cb.Finish());
    437   }
    438 
    439   void AppendData(const std::string& source_id,
    440                   const uint8* data, size_t length) {
    441     EXPECT_CALL(host_, AddBufferedTimeRange(_, _)).Times(AnyNumber());
    442 
    443     demuxer_->AppendData(source_id, data, length,
    444                          append_window_start_for_next_append_,
    445                          append_window_end_for_next_append_,
    446                          &timestamp_offset_map_[source_id]);
    447   }
    448 
    449   void AppendDataInPieces(const uint8* data, size_t length) {
    450     AppendDataInPieces(data, length, 7);
    451   }
    452 
    453   void AppendDataInPieces(const uint8* data, size_t length, size_t piece_size) {
    454     const uint8* start = data;
    455     const uint8* end = data + length;
    456     while (start < end) {
    457       size_t append_size = std::min(piece_size,
    458                                     static_cast<size_t>(end - start));
    459       AppendData(start, append_size);
    460       start += append_size;
    461     }
    462   }
    463 
    464   void AppendInitSegment(int stream_flags) {
    465     AppendInitSegmentWithSourceId(kSourceId, stream_flags);
    466   }
    467 
    468   void AppendInitSegmentWithSourceId(const std::string& source_id,
    469                                      int stream_flags) {
    470     AppendInitSegmentWithEncryptedInfo(source_id, stream_flags, false, false);
    471   }
    472 
    473   void AppendInitSegmentWithEncryptedInfo(const std::string& source_id,
    474                                           int stream_flags,
    475                                           bool is_audio_encrypted,
    476                                           bool is_video_encrypted) {
    477     scoped_ptr<uint8[]> info_tracks;
    478     int info_tracks_size = 0;
    479     CreateInitSegment(stream_flags,
    480                       is_audio_encrypted, is_video_encrypted,
    481                       &info_tracks, &info_tracks_size);
    482     AppendData(source_id, info_tracks.get(), info_tracks_size);
    483   }
    484 
    485   void AppendGarbage() {
    486     // Fill up an array with gibberish.
    487     int garbage_cluster_size = 10;
    488     scoped_ptr<uint8[]> garbage_cluster(new uint8[garbage_cluster_size]);
    489     for (int i = 0; i < garbage_cluster_size; ++i)
    490       garbage_cluster[i] = i;
    491     AppendData(garbage_cluster.get(), garbage_cluster_size);
    492   }
    493 
    494   void InitDoneCalled(PipelineStatus expected_status,
    495                       PipelineStatus status) {
    496     EXPECT_EQ(status, expected_status);
    497   }
    498 
    499   void AppendEmptyCluster(int timecode) {
    500     AppendCluster(GenerateEmptyCluster(timecode));
    501   }
    502 
    503   PipelineStatusCB CreateInitDoneCB(const base::TimeDelta& expected_duration,
    504                                     PipelineStatus expected_status) {
    505     if (expected_duration != kNoTimestamp())
    506       EXPECT_CALL(host_, SetDuration(expected_duration));
    507     return CreateInitDoneCB(expected_status);
    508   }
    509 
    510   PipelineStatusCB CreateInitDoneCB(PipelineStatus expected_status) {
    511     return base::Bind(&ChunkDemuxerTest::InitDoneCalled,
    512                       base::Unretained(this),
    513                       expected_status);
    514   }
    515 
    516   enum StreamFlags {
    517     HAS_AUDIO = 1 << 0,
    518     HAS_VIDEO = 1 << 1,
    519     HAS_TEXT = 1 << 2
    520   };
    521 
    522   bool InitDemuxer(int stream_flags) {
    523     return InitDemuxerWithEncryptionInfo(stream_flags, false, false);
    524   }
    525 
    526   bool InitDemuxerWithEncryptionInfo(
    527       int stream_flags, bool is_audio_encrypted, bool is_video_encrypted) {
    528 
    529     PipelineStatus expected_status =
    530         (stream_flags != 0) ? PIPELINE_OK : DEMUXER_ERROR_COULD_NOT_OPEN;
    531 
    532     base::TimeDelta expected_duration = kNoTimestamp();
    533     if (expected_status == PIPELINE_OK)
    534       expected_duration = kDefaultDuration();
    535 
    536     EXPECT_CALL(*this, DemuxerOpened());
    537     demuxer_->Initialize(
    538         &host_, CreateInitDoneCB(expected_duration, expected_status), true);
    539 
    540     if (AddId(kSourceId, stream_flags) != ChunkDemuxer::kOk)
    541       return false;
    542 
    543     AppendInitSegmentWithEncryptedInfo(
    544         kSourceId, stream_flags,
    545         is_audio_encrypted, is_video_encrypted);
    546     return true;
    547   }
    548 
    549   bool InitDemuxerAudioAndVideoSourcesText(const std::string& audio_id,
    550                                            const std::string& video_id,
    551                                            bool has_text) {
    552     EXPECT_CALL(*this, DemuxerOpened());
    553     demuxer_->Initialize(
    554         &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
    555 
    556     if (AddId(audio_id, HAS_AUDIO) != ChunkDemuxer::kOk)
    557       return false;
    558     if (AddId(video_id, HAS_VIDEO) != ChunkDemuxer::kOk)
    559       return false;
    560 
    561     int audio_flags = HAS_AUDIO;
    562     int video_flags = HAS_VIDEO;
    563 
    564     if (has_text) {
    565       audio_flags |= HAS_TEXT;
    566       video_flags |= HAS_TEXT;
    567     }
    568 
    569     AppendInitSegmentWithSourceId(audio_id, audio_flags);
    570     AppendInitSegmentWithSourceId(video_id, video_flags);
    571     return true;
    572   }
    573 
    574   bool InitDemuxerAudioAndVideoSources(const std::string& audio_id,
    575                                        const std::string& video_id) {
    576     return InitDemuxerAudioAndVideoSourcesText(audio_id, video_id, false);
    577   }
    578 
    579   // Initializes the demuxer with data from 2 files with different
    580   // decoder configurations. This is used to test the decoder config change
    581   // logic.
    582   //
    583   // bear-320x240.webm VideoDecoderConfig returns 320x240 for its natural_size()
    584   // bear-640x360.webm VideoDecoderConfig returns 640x360 for its natural_size()
    585   // The resulting video stream returns data from each file for the following
    586   // time ranges.
    587   // bear-320x240.webm : [0-501)       [801-2736)
    588   // bear-640x360.webm :       [527-793)
    589   //
    590   // bear-320x240.webm AudioDecoderConfig returns 3863 for its extra_data_size()
    591   // bear-640x360.webm AudioDecoderConfig returns 3935 for its extra_data_size()
    592   // The resulting audio stream returns data from each file for the following
    593   // time ranges.
    594   // bear-320x240.webm : [0-524)       [779-2736)
    595   // bear-640x360.webm :       [527-759)
    596   bool InitDemuxerWithConfigChangeData() {
    597     scoped_refptr<DecoderBuffer> bear1 = ReadTestDataFile("bear-320x240.webm");
    598     scoped_refptr<DecoderBuffer> bear2 = ReadTestDataFile("bear-640x360.webm");
    599 
    600     EXPECT_CALL(*this, DemuxerOpened());
    601 
    602     demuxer_->Initialize(
    603         &host_, CreateInitDoneCB(base::TimeDelta::FromMilliseconds(2744),
    604                                  PIPELINE_OK), true);
    605 
    606     if (AddId(kSourceId, HAS_AUDIO | HAS_VIDEO) != ChunkDemuxer::kOk)
    607       return false;
    608 
    609     // Append the whole bear1 file.
    610     // TODO(wolenetz/acolwell): Remove this extra SetDuration expectation once
    611     // the files are fixed to have the correct duration in their init segments,
    612     // and the CreateInitDoneCB() call, above, is fixed to used that duration.
    613     // See http://crbug.com/354284.
    614     EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2746)));
    615     AppendData(bear1->data(), bear1->data_size());
    616     // Last audio frame has timestamp 2721 and duration 24 (estimated from max
    617     // seen so far for audio track).
    618     // Last video frame has timestamp 2703 and duration 33 (from TrackEntry
    619     // DefaultDuration for video track).
    620     CheckExpectedRanges(kSourceId, "{ [0,2736) }");
    621 
    622     // Append initialization segment for bear2.
    623     // Note: Offsets here and below are derived from
    624     // media/test/data/bear-640x360-manifest.js and
    625     // media/test/data/bear-320x240-manifest.js which were
    626     // generated from media/test/data/bear-640x360.webm and
    627     // media/test/data/bear-320x240.webm respectively.
    628     AppendData(bear2->data(), 4340);
    629 
    630     // Append a media segment that goes from [0.527000, 1.014000).
    631     AppendData(bear2->data() + 55290, 18785);
    632     CheckExpectedRanges(kSourceId, "{ [0,1027) [1201,2736) }");
    633 
    634     // Append initialization segment for bear1 & fill gap with [779-1197)
    635     // segment.
    636     AppendData(bear1->data(), 4370);
    637     AppendData(bear1->data() + 72737, 28183);
    638     CheckExpectedRanges(kSourceId, "{ [0,2736) }");
    639 
    640     MarkEndOfStream(PIPELINE_OK);
    641     return true;
    642   }
    643 
    644   void ShutdownDemuxer() {
    645     if (demuxer_) {
    646       demuxer_->Shutdown();
    647       message_loop_.RunUntilIdle();
    648     }
    649   }
    650 
    651   void AddSimpleBlock(ClusterBuilder* cb, int track_num, int64 timecode) {
    652     uint8 data[] = { 0x00 };
    653     cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data));
    654   }
    655 
    656   scoped_ptr<Cluster> GenerateCluster(int timecode, int block_count) {
    657     return GenerateCluster(timecode, timecode, block_count);
    658   }
    659 
    660   void AddVideoBlockGroup(ClusterBuilder* cb, int track_num, int64 timecode,
    661                           int duration, int flags) {
    662     const uint8* data =
    663         (flags & kWebMFlagKeyframe) != 0 ? kVP8Keyframe : kVP8Interframe;
    664     int size = (flags & kWebMFlagKeyframe) != 0 ? sizeof(kVP8Keyframe) :
    665         sizeof(kVP8Interframe);
    666     cb->AddBlockGroup(track_num, timecode, duration, flags, data, size);
    667   }
    668 
    669   scoped_ptr<Cluster> GenerateCluster(int first_audio_timecode,
    670                                       int first_video_timecode,
    671                                       int block_count) {
    672     return GenerateCluster(first_audio_timecode, first_video_timecode,
    673                            block_count, false);
    674   }
    675   scoped_ptr<Cluster> GenerateCluster(int first_audio_timecode,
    676                                       int first_video_timecode,
    677                                       int block_count,
    678                                       bool unknown_size) {
    679     CHECK_GT(block_count, 0);
    680 
    681     int size = 10;
    682     scoped_ptr<uint8[]> data(new uint8[size]);
    683 
    684     ClusterBuilder cb;
    685     cb.SetClusterTimecode(std::min(first_audio_timecode, first_video_timecode));
    686 
    687     if (block_count == 1) {
    688       cb.AddBlockGroup(kAudioTrackNum, first_audio_timecode,
    689                        kAudioBlockDuration, kWebMFlagKeyframe,
    690                        data.get(), size);
    691       return cb.Finish();
    692     }
    693 
    694     int audio_timecode = first_audio_timecode;
    695     int video_timecode = first_video_timecode;
    696 
    697     // Create simple blocks for everything except the last 2 blocks.
    698     // The first video frame must be a keyframe.
    699     uint8 video_flag = kWebMFlagKeyframe;
    700     for (int i = 0; i < block_count - 2; i++) {
    701       if (audio_timecode <= video_timecode) {
    702         cb.AddSimpleBlock(kAudioTrackNum, audio_timecode, kWebMFlagKeyframe,
    703                           data.get(), size);
    704         audio_timecode += kAudioBlockDuration;
    705         continue;
    706       }
    707 
    708       cb.AddSimpleBlock(kVideoTrackNum, video_timecode, video_flag, data.get(),
    709                         size);
    710       video_timecode += kVideoBlockDuration;
    711       video_flag = 0;
    712     }
    713 
    714     // Make the last 2 blocks BlockGroups so that they don't get delayed by the
    715     // block duration calculation logic.
    716     if (audio_timecode <= video_timecode) {
    717       cb.AddBlockGroup(kAudioTrackNum, audio_timecode, kAudioBlockDuration,
    718                        kWebMFlagKeyframe, data.get(), size);
    719       AddVideoBlockGroup(&cb, kVideoTrackNum, video_timecode,
    720                          kVideoBlockDuration, video_flag);
    721     } else {
    722       AddVideoBlockGroup(&cb, kVideoTrackNum, video_timecode,
    723                          kVideoBlockDuration, video_flag);
    724       cb.AddBlockGroup(kAudioTrackNum, audio_timecode, kAudioBlockDuration,
    725                        kWebMFlagKeyframe, data.get(), size);
    726     }
    727 
    728     return unknown_size ? cb.FinishWithUnknownSize() : cb.Finish();
    729   }
    730 
    731   scoped_ptr<Cluster> GenerateSingleStreamCluster(int timecode,
    732                                                   int end_timecode,
    733                                                   int track_number,
    734                                                   int block_duration) {
    735     CHECK_GT(end_timecode, timecode);
    736 
    737     std::vector<uint8> data(kBlockSize);
    738 
    739     ClusterBuilder cb;
    740     cb.SetClusterTimecode(timecode);
    741 
    742     // Create simple blocks for everything except the last block.
    743     while (timecode < (end_timecode - block_duration)) {
    744       cb.AddSimpleBlock(track_number, timecode, kWebMFlagKeyframe,
    745                         &data[0], data.size());
    746       timecode += block_duration;
    747     }
    748 
    749     if (track_number == kVideoTrackNum) {
    750       AddVideoBlockGroup(&cb, track_number, timecode, block_duration,
    751                          kWebMFlagKeyframe);
    752     } else {
    753       cb.AddBlockGroup(track_number, timecode, block_duration,
    754                        kWebMFlagKeyframe, &data[0], data.size());
    755     }
    756 
    757     return cb.Finish();
    758   }
    759 
    760   void Read(DemuxerStream::Type type, const DemuxerStream::ReadCB& read_cb) {
    761     demuxer_->GetStream(type)->Read(read_cb);
    762     message_loop_.RunUntilIdle();
    763   }
    764 
    765   void ReadAudio(const DemuxerStream::ReadCB& read_cb) {
    766     Read(DemuxerStream::AUDIO, read_cb);
    767   }
    768 
    769   void ReadVideo(const DemuxerStream::ReadCB& read_cb) {
    770     Read(DemuxerStream::VIDEO, read_cb);
    771   }
    772 
    773   void GenerateExpectedReads(int timecode, int block_count) {
    774     GenerateExpectedReads(timecode, timecode, block_count);
    775   }
    776 
    777   void GenerateExpectedReads(int start_audio_timecode,
    778                              int start_video_timecode,
    779                              int block_count) {
    780     CHECK_GT(block_count, 0);
    781 
    782     if (block_count == 1) {
    783       ExpectRead(DemuxerStream::AUDIO, start_audio_timecode);
    784       return;
    785     }
    786 
    787     int audio_timecode = start_audio_timecode;
    788     int video_timecode = start_video_timecode;
    789 
    790     for (int i = 0; i < block_count; i++) {
    791       if (audio_timecode <= video_timecode) {
    792         ExpectRead(DemuxerStream::AUDIO, audio_timecode);
    793         audio_timecode += kAudioBlockDuration;
    794         continue;
    795       }
    796 
    797       ExpectRead(DemuxerStream::VIDEO, video_timecode);
    798       video_timecode += kVideoBlockDuration;
    799     }
    800   }
    801 
    802   void GenerateSingleStreamExpectedReads(int timecode,
    803                                          int block_count,
    804                                          DemuxerStream::Type type,
    805                                          int block_duration) {
    806     CHECK_GT(block_count, 0);
    807     int stream_timecode = timecode;
    808 
    809     for (int i = 0; i < block_count; i++) {
    810       ExpectRead(type, stream_timecode);
    811       stream_timecode += block_duration;
    812     }
    813   }
    814 
    815   void GenerateAudioStreamExpectedReads(int timecode, int block_count) {
    816     GenerateSingleStreamExpectedReads(
    817         timecode, block_count, DemuxerStream::AUDIO, kAudioBlockDuration);
    818   }
    819 
    820   void GenerateVideoStreamExpectedReads(int timecode, int block_count) {
    821     GenerateSingleStreamExpectedReads(
    822         timecode, block_count, DemuxerStream::VIDEO, kVideoBlockDuration);
    823   }
    824 
    825   scoped_ptr<Cluster> GenerateEmptyCluster(int timecode) {
    826     ClusterBuilder cb;
    827     cb.SetClusterTimecode(timecode);
    828     return cb.Finish();
    829   }
    830 
    831   void CheckExpectedRanges(const std::string& expected) {
    832     CheckExpectedRanges(kSourceId, expected);
    833   }
    834 
    835   void CheckExpectedRanges(const std::string&  id,
    836                            const std::string& expected) {
    837     Ranges<base::TimeDelta> r = demuxer_->GetBufferedRanges(id);
    838 
    839     std::stringstream ss;
    840     ss << "{ ";
    841     for (size_t i = 0; i < r.size(); ++i) {
    842       ss << "[" << r.start(i).InMilliseconds() << ","
    843          << r.end(i).InMilliseconds() << ") ";
    844     }
    845     ss << "}";
    846     EXPECT_EQ(expected, ss.str());
    847   }
    848 
    849   MOCK_METHOD2(ReadDone, void(DemuxerStream::Status status,
    850                               const scoped_refptr<DecoderBuffer>&));
    851 
    852   void StoreStatusAndBuffer(DemuxerStream::Status* status_out,
    853                             scoped_refptr<DecoderBuffer>* buffer_out,
    854                             DemuxerStream::Status status,
    855                             const scoped_refptr<DecoderBuffer>& buffer) {
    856     *status_out = status;
    857     *buffer_out = buffer;
    858   }
    859 
    860   void ReadUntilNotOkOrEndOfStream(DemuxerStream::Type type,
    861                                    DemuxerStream::Status* status,
    862                                    base::TimeDelta* last_timestamp) {
    863     DemuxerStream* stream = demuxer_->GetStream(type);
    864     scoped_refptr<DecoderBuffer> buffer;
    865 
    866     *last_timestamp = kNoTimestamp();
    867     do {
    868       stream->Read(base::Bind(&ChunkDemuxerTest::StoreStatusAndBuffer,
    869                               base::Unretained(this), status, &buffer));
    870       base::MessageLoop::current()->RunUntilIdle();
    871       if (*status == DemuxerStream::kOk && !buffer->end_of_stream())
    872         *last_timestamp = buffer->timestamp();
    873     } while (*status == DemuxerStream::kOk && !buffer->end_of_stream());
    874   }
    875 
    876   void ExpectEndOfStream(DemuxerStream::Type type) {
    877     EXPECT_CALL(*this, ReadDone(DemuxerStream::kOk, IsEndOfStream()));
    878     demuxer_->GetStream(type)->Read(base::Bind(
    879         &ChunkDemuxerTest::ReadDone, base::Unretained(this)));
    880     message_loop_.RunUntilIdle();
    881   }
    882 
    883   void ExpectRead(DemuxerStream::Type type, int64 timestamp_in_ms) {
    884     EXPECT_CALL(*this, ReadDone(DemuxerStream::kOk,
    885                                 HasTimestamp(timestamp_in_ms)));
    886     demuxer_->GetStream(type)->Read(base::Bind(
    887         &ChunkDemuxerTest::ReadDone, base::Unretained(this)));
    888     message_loop_.RunUntilIdle();
    889   }
    890 
    891   void ExpectConfigChanged(DemuxerStream::Type type) {
    892     EXPECT_CALL(*this, ReadDone(DemuxerStream::kConfigChanged, _));
    893     demuxer_->GetStream(type)->Read(base::Bind(
    894         &ChunkDemuxerTest::ReadDone, base::Unretained(this)));
    895     message_loop_.RunUntilIdle();
    896   }
    897 
    898   void CheckExpectedBuffers(DemuxerStream* stream,
    899                             const std::string& expected) {
    900     std::vector<std::string> timestamps;
    901     base::SplitString(expected, ' ', &timestamps);
    902     std::stringstream ss;
    903     for (size_t i = 0; i < timestamps.size(); ++i) {
    904       // Initialize status to kAborted since it's possible for Read() to return
    905       // without calling StoreStatusAndBuffer() if it doesn't have any buffers
    906       // left to return.
    907       DemuxerStream::Status status = DemuxerStream::kAborted;
    908       scoped_refptr<DecoderBuffer> buffer;
    909       stream->Read(base::Bind(&ChunkDemuxerTest::StoreStatusAndBuffer,
    910                               base::Unretained(this), &status, &buffer));
    911       base::MessageLoop::current()->RunUntilIdle();
    912       if (status != DemuxerStream::kOk || buffer->end_of_stream())
    913         break;
    914 
    915       if (i > 0)
    916         ss << " ";
    917       ss << buffer->timestamp().InMilliseconds();
    918 
    919       // Handle preroll buffers.
    920       if (EndsWith(timestamps[i], "P", true)) {
    921         ASSERT_EQ(kInfiniteDuration(), buffer->discard_padding().first);
    922         ASSERT_EQ(base::TimeDelta(), buffer->discard_padding().second);
    923         ss << "P";
    924       }
    925     }
    926     EXPECT_EQ(expected, ss.str());
    927   }
    928 
    929   MOCK_METHOD1(Checkpoint, void(int id));
    930 
    931   struct BufferTimestamps {
    932     int video_time_ms;
    933     int audio_time_ms;
    934   };
    935   static const int kSkip = -1;
    936 
    937   // Test parsing a WebM file.
    938   // |filename| - The name of the file in media/test/data to parse.
    939   // |timestamps| - The expected timestamps on the parsed buffers.
    940   //    a timestamp of kSkip indicates that a Read() call for that stream
    941   //    shouldn't be made on that iteration of the loop. If both streams have
    942   //    a kSkip then the loop will terminate.
    943   bool ParseWebMFile(const std::string& filename,
    944                      const BufferTimestamps* timestamps,
    945                      const base::TimeDelta& duration) {
    946     return ParseWebMFile(filename, timestamps, duration, HAS_AUDIO | HAS_VIDEO);
    947   }
    948 
    949   bool ParseWebMFile(const std::string& filename,
    950                      const BufferTimestamps* timestamps,
    951                      const base::TimeDelta& duration,
    952                      int stream_flags) {
    953     EXPECT_CALL(*this, DemuxerOpened());
    954     demuxer_->Initialize(
    955         &host_, CreateInitDoneCB(duration, PIPELINE_OK), true);
    956 
    957     if (AddId(kSourceId, stream_flags) != ChunkDemuxer::kOk)
    958       return false;
    959 
    960     // Read a WebM file into memory and send the data to the demuxer.
    961     scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename);
    962     AppendDataInPieces(buffer->data(), buffer->data_size(), 512);
    963 
    964     // Verify that the timestamps on the first few packets match what we
    965     // expect.
    966     for (size_t i = 0;
    967          (timestamps[i].audio_time_ms != kSkip ||
    968           timestamps[i].video_time_ms != kSkip);
    969          i++) {
    970       bool audio_read_done = false;
    971       bool video_read_done = false;
    972 
    973       if (timestamps[i].audio_time_ms != kSkip) {
    974         ReadAudio(base::Bind(&OnReadDone,
    975                              base::TimeDelta::FromMilliseconds(
    976                                  timestamps[i].audio_time_ms),
    977                              &audio_read_done));
    978         EXPECT_TRUE(audio_read_done);
    979       }
    980 
    981       if (timestamps[i].video_time_ms != kSkip) {
    982         ReadVideo(base::Bind(&OnReadDone,
    983                              base::TimeDelta::FromMilliseconds(
    984                                  timestamps[i].video_time_ms),
    985                              &video_read_done));
    986         EXPECT_TRUE(video_read_done);
    987       }
    988     }
    989 
    990     return true;
    991   }
    992 
    993   MOCK_METHOD0(DemuxerOpened, void());
    994   // TODO(xhwang): This is a workaround of the issue that move-only parameters
    995   // are not supported in mocked methods. Remove this when the issue is fixed
    996   // (http://code.google.com/p/googletest/issues/detail?id=395) or when we use
    997   // std::string instead of scoped_ptr<uint8[]> (http://crbug.com/130689).
    998   MOCK_METHOD3(NeedKeyMock, void(const std::string& type,
    999                                  const uint8* init_data, int init_data_size));
   1000   void DemuxerNeedKey(const std::string& type,
   1001                       const std::vector<uint8>& init_data) {
   1002     const uint8* init_data_ptr = init_data.empty() ? NULL : &init_data[0];
   1003     NeedKeyMock(type, init_data_ptr, init_data.size());
   1004   }
   1005 
   1006   void Seek(base::TimeDelta seek_time) {
   1007     demuxer_->StartWaitingForSeek(seek_time);
   1008     demuxer_->Seek(seek_time, NewExpectedStatusCB(PIPELINE_OK));
   1009     message_loop_.RunUntilIdle();
   1010   }
   1011 
   1012   void MarkEndOfStream(PipelineStatus status) {
   1013     demuxer_->MarkEndOfStream(status);
   1014     message_loop_.RunUntilIdle();
   1015   }
   1016 
   1017   bool SetTimestampOffset(const std::string& id,
   1018                           base::TimeDelta timestamp_offset) {
   1019     if (demuxer_->IsParsingMediaSegment(id))
   1020       return false;
   1021 
   1022     timestamp_offset_map_[id] = timestamp_offset;
   1023     return true;
   1024   }
   1025 
   1026   base::MessageLoop message_loop_;
   1027   MockDemuxerHost host_;
   1028 
   1029   scoped_ptr<ChunkDemuxer> demuxer_;
   1030 
   1031   base::TimeDelta append_window_start_for_next_append_;
   1032   base::TimeDelta append_window_end_for_next_append_;
   1033 
   1034   // Map of source id to timestamp offset to use for the next AppendData()
   1035   // operation for that source id.
   1036   std::map<std::string, base::TimeDelta> timestamp_offset_map_;
   1037 
   1038  private:
   1039   DISALLOW_COPY_AND_ASSIGN(ChunkDemuxerTest);
   1040 };
   1041 
   1042 TEST_F(ChunkDemuxerTest, Init) {
   1043   // Test no streams, audio-only, video-only, and audio & video scenarios.
   1044   // Audio and video streams can be encrypted or not encrypted.
   1045   for (int i = 0; i < 16; i++) {
   1046     bool has_audio = (i & 0x1) != 0;
   1047     bool has_video = (i & 0x2) != 0;
   1048     bool is_audio_encrypted = (i & 0x4) != 0;
   1049     bool is_video_encrypted = (i & 0x8) != 0;
   1050 
   1051     // No test on invalid combination.
   1052     if ((!has_audio && is_audio_encrypted) ||
   1053         (!has_video && is_video_encrypted)) {
   1054       continue;
   1055     }
   1056 
   1057     CreateNewDemuxer();
   1058 
   1059     if (is_audio_encrypted || is_video_encrypted) {
   1060       int need_key_count = (is_audio_encrypted ? 1 : 0) +
   1061                            (is_video_encrypted ? 1 : 0);
   1062       EXPECT_CALL(*this, NeedKeyMock(kWebMEncryptInitDataType, NotNull(),
   1063                                      DecryptConfig::kDecryptionKeySize))
   1064           .Times(Exactly(need_key_count));
   1065     }
   1066 
   1067     int stream_flags = 0;
   1068     if (has_audio)
   1069       stream_flags |= HAS_AUDIO;
   1070 
   1071     if (has_video)
   1072       stream_flags |= HAS_VIDEO;
   1073 
   1074     ASSERT_TRUE(InitDemuxerWithEncryptionInfo(
   1075         stream_flags, is_audio_encrypted, is_video_encrypted));
   1076 
   1077     DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO);
   1078     if (has_audio) {
   1079       ASSERT_TRUE(audio_stream);
   1080 
   1081       const AudioDecoderConfig& config = audio_stream->audio_decoder_config();
   1082       EXPECT_EQ(kCodecVorbis, config.codec());
   1083       EXPECT_EQ(32, config.bits_per_channel());
   1084       EXPECT_EQ(CHANNEL_LAYOUT_STEREO, config.channel_layout());
   1085       EXPECT_EQ(44100, config.samples_per_second());
   1086       EXPECT_TRUE(config.extra_data());
   1087       EXPECT_GT(config.extra_data_size(), 0u);
   1088       EXPECT_EQ(kSampleFormatPlanarF32, config.sample_format());
   1089       EXPECT_EQ(is_audio_encrypted,
   1090                 audio_stream->audio_decoder_config().is_encrypted());
   1091       EXPECT_TRUE(static_cast<ChunkDemuxerStream*>(audio_stream)
   1092                       ->supports_partial_append_window_trimming());
   1093     } else {
   1094       EXPECT_FALSE(audio_stream);
   1095     }
   1096 
   1097     DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
   1098     if (has_video) {
   1099       EXPECT_TRUE(video_stream);
   1100       EXPECT_EQ(is_video_encrypted,
   1101                 video_stream->video_decoder_config().is_encrypted());
   1102       EXPECT_FALSE(static_cast<ChunkDemuxerStream*>(video_stream)
   1103                        ->supports_partial_append_window_trimming());
   1104     } else {
   1105       EXPECT_FALSE(video_stream);
   1106     }
   1107 
   1108     ShutdownDemuxer();
   1109     demuxer_.reset();
   1110   }
   1111 }
   1112 
   1113 // TODO(acolwell): Fold this test into Init tests since the tests are
   1114 // almost identical.
   1115 TEST_F(ChunkDemuxerTest, InitText) {
   1116   // Test with 1 video stream and 1 text streams, and 0 or 1 audio streams.
   1117   // No encryption cases handled here.
   1118   bool has_video = true;
   1119   bool is_audio_encrypted = false;
   1120   bool is_video_encrypted = false;
   1121   for (int i = 0; i < 2; i++) {
   1122     bool has_audio = (i & 0x1) != 0;
   1123 
   1124     CreateNewDemuxer();
   1125 
   1126     DemuxerStream* text_stream = NULL;
   1127     TextTrackConfig text_config;
   1128     EXPECT_CALL(host_, AddTextStream(_, _))
   1129         .WillOnce(DoAll(SaveArg<0>(&text_stream),
   1130                         SaveArg<1>(&text_config)));
   1131 
   1132     int stream_flags = HAS_TEXT;
   1133     if (has_audio)
   1134       stream_flags |= HAS_AUDIO;
   1135 
   1136     if (has_video)
   1137       stream_flags |= HAS_VIDEO;
   1138 
   1139     ASSERT_TRUE(InitDemuxerWithEncryptionInfo(
   1140         stream_flags, is_audio_encrypted, is_video_encrypted));
   1141     ASSERT_TRUE(text_stream);
   1142     EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
   1143     EXPECT_EQ(kTextSubtitles, text_config.kind());
   1144     EXPECT_FALSE(static_cast<ChunkDemuxerStream*>(text_stream)
   1145                      ->supports_partial_append_window_trimming());
   1146 
   1147     DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO);
   1148     if (has_audio) {
   1149       ASSERT_TRUE(audio_stream);
   1150 
   1151       const AudioDecoderConfig& config = audio_stream->audio_decoder_config();
   1152       EXPECT_EQ(kCodecVorbis, config.codec());
   1153       EXPECT_EQ(32, config.bits_per_channel());
   1154       EXPECT_EQ(CHANNEL_LAYOUT_STEREO, config.channel_layout());
   1155       EXPECT_EQ(44100, config.samples_per_second());
   1156       EXPECT_TRUE(config.extra_data());
   1157       EXPECT_GT(config.extra_data_size(), 0u);
   1158       EXPECT_EQ(kSampleFormatPlanarF32, config.sample_format());
   1159       EXPECT_EQ(is_audio_encrypted,
   1160                 audio_stream->audio_decoder_config().is_encrypted());
   1161       EXPECT_TRUE(static_cast<ChunkDemuxerStream*>(audio_stream)
   1162                       ->supports_partial_append_window_trimming());
   1163     } else {
   1164       EXPECT_FALSE(audio_stream);
   1165     }
   1166 
   1167     DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
   1168     if (has_video) {
   1169       EXPECT_TRUE(video_stream);
   1170       EXPECT_EQ(is_video_encrypted,
   1171                 video_stream->video_decoder_config().is_encrypted());
   1172       EXPECT_FALSE(static_cast<ChunkDemuxerStream*>(video_stream)
   1173                        ->supports_partial_append_window_trimming());
   1174     } else {
   1175       EXPECT_FALSE(video_stream);
   1176     }
   1177 
   1178     ShutdownDemuxer();
   1179     demuxer_.reset();
   1180   }
   1181 }
   1182 
   1183 TEST_F(ChunkDemuxerTest, SingleTextTrackIdChange) {
   1184   // Test with 1 video stream, 1 audio, and 1 text stream. Send a second init
   1185   // segment in which the text track ID changes. Verify appended buffers before
   1186   // and after the second init segment map to the same underlying track buffers.
   1187   CreateNewDemuxer();
   1188   DemuxerStream* text_stream = NULL;
   1189   TextTrackConfig text_config;
   1190   EXPECT_CALL(host_, AddTextStream(_, _))
   1191       .WillOnce(DoAll(SaveArg<0>(&text_stream),
   1192                       SaveArg<1>(&text_config)));
   1193   ASSERT_TRUE(InitDemuxerWithEncryptionInfo(
   1194       HAS_TEXT | HAS_AUDIO | HAS_VIDEO, false, false));
   1195   DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO);
   1196   DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
   1197   ASSERT_TRUE(audio_stream);
   1198   ASSERT_TRUE(video_stream);
   1199   ASSERT_TRUE(text_stream);
   1200 
   1201   AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "0K 23K");
   1202   AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "0K 30");
   1203   AppendSingleStreamCluster(kSourceId, kTextTrackNum, "10K");
   1204   CheckExpectedRanges(kSourceId, "{ [0,46) }");
   1205 
   1206   scoped_ptr<uint8[]> info_tracks;
   1207   int info_tracks_size = 0;
   1208   CreateInitSegmentWithAlternateTextTrackNum(HAS_TEXT | HAS_AUDIO | HAS_VIDEO,
   1209                                              false, false,
   1210                                              &info_tracks, &info_tracks_size);
   1211   demuxer_->AppendData(kSourceId, info_tracks.get(), info_tracks_size,
   1212                        append_window_start_for_next_append_,
   1213                        append_window_end_for_next_append_,
   1214                        &timestamp_offset_map_[kSourceId]);
   1215 
   1216   AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "46K 69K");
   1217   AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "60K");
   1218   AppendSingleStreamCluster(kSourceId, kAlternateTextTrackNum, "45K");
   1219 
   1220   CheckExpectedRanges(kSourceId, "{ [0,92) }");
   1221   CheckExpectedBuffers(audio_stream, "0 23 46 69");
   1222   CheckExpectedBuffers(video_stream, "0 30 60");
   1223   CheckExpectedBuffers(text_stream, "10 45");
   1224 
   1225   ShutdownDemuxer();
   1226 }
   1227 
   1228 TEST_F(ChunkDemuxerTest, InitSegmentSetsNeedRandomAccessPointFlag) {
   1229   // Tests that non-keyframes following an init segment are allowed
   1230   // and dropped, as expected if the initialization segment received
   1231   // algorithm correctly sets the needs random access point flag to true for all
   1232   // track buffers. Note that the first initialization segment is insufficient
   1233   // to fully test this since needs random access point flag initializes to
   1234   // true.
   1235   CreateNewDemuxer();
   1236   DemuxerStream* text_stream = NULL;
   1237   EXPECT_CALL(host_, AddTextStream(_, _))
   1238       .WillOnce(SaveArg<0>(&text_stream));
   1239   ASSERT_TRUE(InitDemuxerWithEncryptionInfo(
   1240       HAS_TEXT | HAS_AUDIO | HAS_VIDEO, false, false));
   1241   DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO);
   1242   DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
   1243   ASSERT_TRUE(audio_stream && video_stream && text_stream);
   1244 
   1245   AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "0 23K");
   1246   AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "0 30K");
   1247   AppendSingleStreamCluster(kSourceId, kTextTrackNum, "0 40K");
   1248   CheckExpectedRanges(kSourceId, "{ [30,46) }");
   1249 
   1250   AppendInitSegment(HAS_TEXT | HAS_AUDIO | HAS_VIDEO);
   1251   AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "46 69K");
   1252   AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "60 90K");
   1253   AppendSingleStreamCluster(kSourceId, kTextTrackNum, "80 90K");
   1254   CheckExpectedRanges(kSourceId, "{ [30,92) }");
   1255 
   1256   CheckExpectedBuffers(audio_stream, "23 69");
   1257   CheckExpectedBuffers(video_stream, "30 90");
   1258 
   1259   // WebM parser marks all text buffers as keyframes.
   1260   CheckExpectedBuffers(text_stream, "0 40 80 90");
   1261 }
   1262 
   1263 // Make sure that the demuxer reports an error if Shutdown()
   1264 // is called before all the initialization segments are appended.
   1265 TEST_F(ChunkDemuxerTest, Shutdown_BeforeAllInitSegmentsAppended) {
   1266   EXPECT_CALL(*this, DemuxerOpened());
   1267   demuxer_->Initialize(
   1268       &host_, CreateInitDoneCB(
   1269           kDefaultDuration(), DEMUXER_ERROR_COULD_NOT_OPEN), true);
   1270 
   1271   EXPECT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk);
   1272   EXPECT_EQ(AddId("video", HAS_VIDEO), ChunkDemuxer::kOk);
   1273 
   1274   AppendInitSegmentWithSourceId("audio", HAS_AUDIO);
   1275 
   1276   ShutdownDemuxer();
   1277 }
   1278 
   1279 TEST_F(ChunkDemuxerTest, Shutdown_BeforeAllInitSegmentsAppendedText) {
   1280   EXPECT_CALL(*this, DemuxerOpened());
   1281   demuxer_->Initialize(
   1282       &host_, CreateInitDoneCB(
   1283           kDefaultDuration(), DEMUXER_ERROR_COULD_NOT_OPEN), true);
   1284 
   1285   EXPECT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk);
   1286   EXPECT_EQ(AddId("video_and_text", HAS_VIDEO), ChunkDemuxer::kOk);
   1287 
   1288   EXPECT_CALL(host_, AddTextStream(_, _))
   1289       .Times(Exactly(1));
   1290 
   1291   AppendInitSegmentWithSourceId("video_and_text", HAS_VIDEO | HAS_TEXT);
   1292 
   1293   ShutdownDemuxer();
   1294 }
   1295 
   1296 // Verifies that all streams waiting for data receive an end of stream
   1297 // buffer when Shutdown() is called.
   1298 TEST_F(ChunkDemuxerTest, Shutdown_EndOfStreamWhileWaitingForData) {
   1299   DemuxerStream* text_stream = NULL;
   1300   EXPECT_CALL(host_, AddTextStream(_, _))
   1301       .WillOnce(SaveArg<0>(&text_stream));
   1302   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT));
   1303 
   1304   DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO);
   1305   DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
   1306 
   1307   bool audio_read_done = false;
   1308   bool video_read_done = false;
   1309   bool text_read_done = false;
   1310   audio_stream->Read(base::Bind(&OnReadDone_EOSExpected, &audio_read_done));
   1311   video_stream->Read(base::Bind(&OnReadDone_EOSExpected, &video_read_done));
   1312   text_stream->Read(base::Bind(&OnReadDone_EOSExpected, &text_read_done));
   1313   message_loop_.RunUntilIdle();
   1314 
   1315   EXPECT_FALSE(audio_read_done);
   1316   EXPECT_FALSE(video_read_done);
   1317   EXPECT_FALSE(text_read_done);
   1318 
   1319   ShutdownDemuxer();
   1320 
   1321   EXPECT_TRUE(audio_read_done);
   1322   EXPECT_TRUE(video_read_done);
   1323   EXPECT_TRUE(text_read_done);
   1324 }
   1325 
   1326 // Test that Seek() completes successfully when the first cluster
   1327 // arrives.
   1328 TEST_F(ChunkDemuxerTest, AppendDataAfterSeek) {
   1329   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   1330   AppendCluster(kDefaultFirstCluster());
   1331 
   1332   InSequence s;
   1333 
   1334   EXPECT_CALL(*this, Checkpoint(1));
   1335 
   1336   Seek(base::TimeDelta::FromMilliseconds(46));
   1337 
   1338   EXPECT_CALL(*this, Checkpoint(2));
   1339 
   1340   Checkpoint(1);
   1341 
   1342   AppendCluster(kDefaultSecondCluster());
   1343 
   1344   message_loop_.RunUntilIdle();
   1345 
   1346   Checkpoint(2);
   1347 }
   1348 
   1349 // Test that parsing errors are handled for clusters appended after init.
   1350 TEST_F(ChunkDemuxerTest, ErrorWhileParsingClusterAfterInit) {
   1351   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   1352   AppendCluster(kDefaultFirstCluster());
   1353 
   1354   EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
   1355   AppendGarbage();
   1356 }
   1357 
   1358 // Test the case where a Seek() is requested while the parser
   1359 // is in the middle of cluster. This is to verify that the parser
   1360 // does not reset itself on a seek.
   1361 TEST_F(ChunkDemuxerTest, SeekWhileParsingCluster) {
   1362   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   1363 
   1364   InSequence s;
   1365 
   1366   scoped_ptr<Cluster> cluster_a(GenerateCluster(0, 6));
   1367 
   1368   // Split the cluster into two appends at an arbitrary point near the end.
   1369   int first_append_size = cluster_a->size() - 11;
   1370   int second_append_size = cluster_a->size() - first_append_size;
   1371 
   1372   // Append the first part of the cluster.
   1373   AppendData(cluster_a->data(), first_append_size);
   1374 
   1375   ExpectRead(DemuxerStream::AUDIO, 0);
   1376   ExpectRead(DemuxerStream::VIDEO, 0);
   1377   ExpectRead(DemuxerStream::AUDIO, kAudioBlockDuration);
   1378 
   1379   Seek(base::TimeDelta::FromSeconds(5));
   1380 
   1381   // Append the rest of the cluster.
   1382   AppendData(cluster_a->data() + first_append_size, second_append_size);
   1383 
   1384   // Append the new cluster and verify that only the blocks
   1385   // in the new cluster are returned.
   1386   AppendCluster(GenerateCluster(5000, 6));
   1387   GenerateExpectedReads(5000, 6);
   1388 }
   1389 
   1390 // Test the case where AppendData() is called before Init().
   1391 TEST_F(ChunkDemuxerTest, AppendDataBeforeInit) {
   1392   scoped_ptr<uint8[]> info_tracks;
   1393   int info_tracks_size = 0;
   1394   CreateInitSegment(HAS_AUDIO | HAS_VIDEO,
   1395                     false, false, &info_tracks, &info_tracks_size);
   1396   demuxer_->AppendData(kSourceId, info_tracks.get(), info_tracks_size,
   1397                        append_window_start_for_next_append_,
   1398                        append_window_end_for_next_append_,
   1399                        &timestamp_offset_map_[kSourceId]);
   1400 }
   1401 
   1402 // Make sure Read() callbacks are dispatched with the proper data.
   1403 TEST_F(ChunkDemuxerTest, Read) {
   1404   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   1405 
   1406   AppendCluster(kDefaultFirstCluster());
   1407 
   1408   bool audio_read_done = false;
   1409   bool video_read_done = false;
   1410   ReadAudio(base::Bind(&OnReadDone,
   1411                        base::TimeDelta::FromMilliseconds(0),
   1412                        &audio_read_done));
   1413   ReadVideo(base::Bind(&OnReadDone,
   1414                        base::TimeDelta::FromMilliseconds(0),
   1415                        &video_read_done));
   1416 
   1417   EXPECT_TRUE(audio_read_done);
   1418   EXPECT_TRUE(video_read_done);
   1419 }
   1420 
   1421 TEST_F(ChunkDemuxerTest, OutOfOrderClusters) {
   1422   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   1423   AppendCluster(kDefaultFirstCluster());
   1424   AppendCluster(GenerateCluster(10, 4));
   1425 
   1426   // Make sure that AppendCluster() does not fail with a cluster that has
   1427   // overlaps with the previously appended cluster.
   1428   AppendCluster(GenerateCluster(5, 4));
   1429 
   1430   // Verify that AppendData() can still accept more data.
   1431   scoped_ptr<Cluster> cluster_c(GenerateCluster(45, 2));
   1432   demuxer_->AppendData(kSourceId, cluster_c->data(), cluster_c->size(),
   1433                        append_window_start_for_next_append_,
   1434                        append_window_end_for_next_append_,
   1435                        &timestamp_offset_map_[kSourceId]);
   1436 }
   1437 
   1438 TEST_F(ChunkDemuxerTest, NonMonotonicButAboveClusterTimecode) {
   1439   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   1440   AppendCluster(kDefaultFirstCluster());
   1441 
   1442   ClusterBuilder cb;
   1443 
   1444   // Test the case where block timecodes are not monotonically
   1445   // increasing but stay above the cluster timecode.
   1446   cb.SetClusterTimecode(5);
   1447   AddSimpleBlock(&cb, kAudioTrackNum, 5);
   1448   AddSimpleBlock(&cb, kVideoTrackNum, 10);
   1449   AddSimpleBlock(&cb, kAudioTrackNum, 7);
   1450   AddSimpleBlock(&cb, kVideoTrackNum, 15);
   1451 
   1452   EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
   1453   AppendCluster(cb.Finish());
   1454 
   1455   // Verify that AppendData() ignores data after the error.
   1456   scoped_ptr<Cluster> cluster_b(GenerateCluster(20, 2));
   1457   demuxer_->AppendData(kSourceId, cluster_b->data(), cluster_b->size(),
   1458                        append_window_start_for_next_append_,
   1459                        append_window_end_for_next_append_,
   1460                        &timestamp_offset_map_[kSourceId]);
   1461 }
   1462 
   1463 TEST_F(ChunkDemuxerTest, BackwardsAndBeforeClusterTimecode) {
   1464   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   1465   AppendCluster(kDefaultFirstCluster());
   1466 
   1467   ClusterBuilder cb;
   1468 
   1469   // Test timecodes going backwards and including values less than the cluster
   1470   // timecode.
   1471   cb.SetClusterTimecode(5);
   1472   AddSimpleBlock(&cb, kAudioTrackNum, 5);
   1473   AddSimpleBlock(&cb, kVideoTrackNum, 5);
   1474   AddSimpleBlock(&cb, kAudioTrackNum, 3);
   1475   AddSimpleBlock(&cb, kVideoTrackNum, 3);
   1476 
   1477   EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
   1478   AppendCluster(cb.Finish());
   1479 
   1480   // Verify that AppendData() ignores data after the error.
   1481   scoped_ptr<Cluster> cluster_b(GenerateCluster(6, 2));
   1482   demuxer_->AppendData(kSourceId, cluster_b->data(), cluster_b->size(),
   1483                        append_window_start_for_next_append_,
   1484                        append_window_end_for_next_append_,
   1485                        &timestamp_offset_map_[kSourceId]);
   1486 }
   1487 
   1488 
   1489 TEST_F(ChunkDemuxerTest, PerStreamMonotonicallyIncreasingTimestamps) {
   1490   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   1491   AppendCluster(kDefaultFirstCluster());
   1492 
   1493   ClusterBuilder cb;
   1494 
   1495   // Test monotonic increasing timestamps on a per stream
   1496   // basis.
   1497   cb.SetClusterTimecode(5);
   1498   AddSimpleBlock(&cb, kAudioTrackNum, 5);
   1499   AddSimpleBlock(&cb, kVideoTrackNum, 5);
   1500   AddSimpleBlock(&cb, kAudioTrackNum, 4);
   1501   AddSimpleBlock(&cb, kVideoTrackNum, 7);
   1502 
   1503   EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
   1504   AppendCluster(cb.Finish());
   1505 }
   1506 
   1507 // Test the case where a cluster is passed to AppendCluster() before
   1508 // INFO & TRACKS data.
   1509 TEST_F(ChunkDemuxerTest, ClusterBeforeInitSegment) {
   1510   EXPECT_CALL(*this, DemuxerOpened());
   1511   demuxer_->Initialize(
   1512       &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN), true);
   1513 
   1514   ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
   1515 
   1516   AppendCluster(GenerateCluster(0, 1));
   1517 }
   1518 
   1519 // Test cases where we get an MarkEndOfStream() call during initialization.
   1520 TEST_F(ChunkDemuxerTest, EOSDuringInit) {
   1521   EXPECT_CALL(*this, DemuxerOpened());
   1522   demuxer_->Initialize(
   1523       &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN), true);
   1524   MarkEndOfStream(PIPELINE_OK);
   1525 }
   1526 
   1527 TEST_F(ChunkDemuxerTest, EndOfStreamWithNoAppend) {
   1528   EXPECT_CALL(*this, DemuxerOpened());
   1529   demuxer_->Initialize(
   1530       &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN), true);
   1531 
   1532   ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
   1533 
   1534   CheckExpectedRanges("{ }");
   1535   MarkEndOfStream(PIPELINE_OK);
   1536   ShutdownDemuxer();
   1537   CheckExpectedRanges("{ }");
   1538   demuxer_->RemoveId(kSourceId);
   1539   demuxer_.reset();
   1540 }
   1541 
   1542 TEST_F(ChunkDemuxerTest, EndOfStreamWithNoMediaAppend) {
   1543   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   1544 
   1545   CheckExpectedRanges("{ }");
   1546   MarkEndOfStream(PIPELINE_OK);
   1547   CheckExpectedRanges("{ }");
   1548 }
   1549 
   1550 TEST_F(ChunkDemuxerTest, DecodeErrorEndOfStream) {
   1551   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   1552 
   1553   AppendCluster(kDefaultFirstCluster());
   1554   CheckExpectedRanges(kDefaultFirstClusterRange);
   1555 
   1556   EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
   1557   MarkEndOfStream(PIPELINE_ERROR_DECODE);
   1558   CheckExpectedRanges(kDefaultFirstClusterRange);
   1559 }
   1560 
   1561 TEST_F(ChunkDemuxerTest, NetworkErrorEndOfStream) {
   1562   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   1563 
   1564   AppendCluster(kDefaultFirstCluster());
   1565   CheckExpectedRanges(kDefaultFirstClusterRange);
   1566 
   1567   EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_NETWORK));
   1568   MarkEndOfStream(PIPELINE_ERROR_NETWORK);
   1569 }
   1570 
   1571 // Helper class to reduce duplicate code when testing end of stream
   1572 // Read() behavior.
   1573 class EndOfStreamHelper {
   1574  public:
   1575   explicit EndOfStreamHelper(Demuxer* demuxer)
   1576       : demuxer_(demuxer),
   1577         audio_read_done_(false),
   1578         video_read_done_(false) {
   1579   }
   1580 
   1581   // Request a read on the audio and video streams.
   1582   void RequestReads() {
   1583     EXPECT_FALSE(audio_read_done_);
   1584     EXPECT_FALSE(video_read_done_);
   1585 
   1586     DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
   1587     DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
   1588 
   1589     audio->Read(base::Bind(&OnEndOfStreamReadDone, &audio_read_done_));
   1590     video->Read(base::Bind(&OnEndOfStreamReadDone, &video_read_done_));
   1591     base::MessageLoop::current()->RunUntilIdle();
   1592   }
   1593 
   1594   // Check to see if |audio_read_done_| and |video_read_done_| variables
   1595   // match |expected|.
   1596   void CheckIfReadDonesWereCalled(bool expected) {
   1597     base::MessageLoop::current()->RunUntilIdle();
   1598     EXPECT_EQ(expected, audio_read_done_);
   1599     EXPECT_EQ(expected, video_read_done_);
   1600   }
   1601 
   1602  private:
   1603   static void OnEndOfStreamReadDone(
   1604       bool* called,
   1605       DemuxerStream::Status status,
   1606       const scoped_refptr<DecoderBuffer>& buffer) {
   1607     EXPECT_EQ(status, DemuxerStream::kOk);
   1608     EXPECT_TRUE(buffer->end_of_stream());
   1609     *called = true;
   1610   }
   1611 
   1612   Demuxer* demuxer_;
   1613   bool audio_read_done_;
   1614   bool video_read_done_;
   1615 
   1616   DISALLOW_COPY_AND_ASSIGN(EndOfStreamHelper);
   1617 };
   1618 
   1619 // Make sure that all pending reads that we don't have media data for get an
   1620 // "end of stream" buffer when MarkEndOfStream() is called.
   1621 TEST_F(ChunkDemuxerTest, EndOfStreamWithPendingReads) {
   1622   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   1623 
   1624   AppendCluster(GenerateCluster(0, 2));
   1625 
   1626   bool audio_read_done_1 = false;
   1627   bool video_read_done_1 = false;
   1628   EndOfStreamHelper end_of_stream_helper_1(demuxer_.get());
   1629   EndOfStreamHelper end_of_stream_helper_2(demuxer_.get());
   1630 
   1631   ReadAudio(base::Bind(&OnReadDone,
   1632                        base::TimeDelta::FromMilliseconds(0),
   1633                        &audio_read_done_1));
   1634   ReadVideo(base::Bind(&OnReadDone,
   1635                        base::TimeDelta::FromMilliseconds(0),
   1636                        &video_read_done_1));
   1637   message_loop_.RunUntilIdle();
   1638 
   1639   EXPECT_TRUE(audio_read_done_1);
   1640   EXPECT_TRUE(video_read_done_1);
   1641 
   1642   end_of_stream_helper_1.RequestReads();
   1643 
   1644   EXPECT_CALL(host_, SetDuration(
   1645       base::TimeDelta::FromMilliseconds(kVideoBlockDuration)));
   1646   MarkEndOfStream(PIPELINE_OK);
   1647 
   1648   end_of_stream_helper_1.CheckIfReadDonesWereCalled(true);
   1649 
   1650   end_of_stream_helper_2.RequestReads();
   1651   end_of_stream_helper_2.CheckIfReadDonesWereCalled(true);
   1652 }
   1653 
   1654 // Make sure that all Read() calls after we get an MarkEndOfStream()
   1655 // call return an "end of stream" buffer.
   1656 TEST_F(ChunkDemuxerTest, ReadsAfterEndOfStream) {
   1657   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   1658 
   1659   AppendCluster(GenerateCluster(0, 2));
   1660 
   1661   bool audio_read_done_1 = false;
   1662   bool video_read_done_1 = false;
   1663   EndOfStreamHelper end_of_stream_helper_1(demuxer_.get());
   1664   EndOfStreamHelper end_of_stream_helper_2(demuxer_.get());
   1665   EndOfStreamHelper end_of_stream_helper_3(demuxer_.get());
   1666 
   1667   ReadAudio(base::Bind(&OnReadDone,
   1668                        base::TimeDelta::FromMilliseconds(0),
   1669                        &audio_read_done_1));
   1670   ReadVideo(base::Bind(&OnReadDone,
   1671                        base::TimeDelta::FromMilliseconds(0),
   1672                        &video_read_done_1));
   1673 
   1674   end_of_stream_helper_1.RequestReads();
   1675 
   1676   EXPECT_TRUE(audio_read_done_1);
   1677   EXPECT_TRUE(video_read_done_1);
   1678   end_of_stream_helper_1.CheckIfReadDonesWereCalled(false);
   1679 
   1680   EXPECT_CALL(host_, SetDuration(
   1681       base::TimeDelta::FromMilliseconds(kVideoBlockDuration)));
   1682   MarkEndOfStream(PIPELINE_OK);
   1683 
   1684   end_of_stream_helper_1.CheckIfReadDonesWereCalled(true);
   1685 
   1686   // Request a few more reads and make sure we immediately get
   1687   // end of stream buffers.
   1688   end_of_stream_helper_2.RequestReads();
   1689   end_of_stream_helper_2.CheckIfReadDonesWereCalled(true);
   1690 
   1691   end_of_stream_helper_3.RequestReads();
   1692   end_of_stream_helper_3.CheckIfReadDonesWereCalled(true);
   1693 }
   1694 
   1695 TEST_F(ChunkDemuxerTest, EndOfStreamDuringCanceledSeek) {
   1696   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   1697 
   1698   AppendCluster(0, 10);
   1699   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(138)));
   1700   MarkEndOfStream(PIPELINE_OK);
   1701 
   1702   // Start the first seek.
   1703   Seek(base::TimeDelta::FromMilliseconds(20));
   1704 
   1705   // Simulate another seek being requested before the first
   1706   // seek has finished prerolling.
   1707   base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(30);
   1708   demuxer_->CancelPendingSeek(seek_time2);
   1709 
   1710   // Finish second seek.
   1711   Seek(seek_time2);
   1712 
   1713   DemuxerStream::Status status;
   1714   base::TimeDelta last_timestamp;
   1715 
   1716   // Make sure audio can reach end of stream.
   1717   ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
   1718   ASSERT_EQ(status, DemuxerStream::kOk);
   1719 
   1720   // Make sure video can reach end of stream.
   1721   ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
   1722   ASSERT_EQ(status, DemuxerStream::kOk);
   1723 }
   1724 
   1725 // Verify buffered range change behavior for audio/video/text tracks.
   1726 TEST_F(ChunkDemuxerTest, EndOfStreamRangeChanges) {
   1727   DemuxerStream* text_stream = NULL;
   1728 
   1729   EXPECT_CALL(host_, AddTextStream(_, _))
   1730       .WillOnce(SaveArg<0>(&text_stream));
   1731   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT));
   1732 
   1733   AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "0K 33");
   1734   AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "0K 23K");
   1735 
   1736   // Check expected ranges and verify that an empty text track does not
   1737   // affect the expected ranges.
   1738   CheckExpectedRanges(kSourceId, "{ [0,46) }");
   1739 
   1740   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(66)));
   1741   MarkEndOfStream(PIPELINE_OK);
   1742 
   1743   // Check expected ranges and verify that an empty text track does not
   1744   // affect the expected ranges.
   1745   CheckExpectedRanges(kSourceId, "{ [0,66) }");
   1746 
   1747   // Unmark end of stream state and verify that the ranges return to
   1748   // their pre-"end of stream" values.
   1749   demuxer_->UnmarkEndOfStream();
   1750   CheckExpectedRanges(kSourceId, "{ [0,46) }");
   1751 
   1752   // Add text track data and verify that the buffered ranges don't change
   1753   // since the intersection of all the tracks doesn't change.
   1754   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(200)));
   1755   AppendSingleStreamCluster(kSourceId, kTextTrackNum, "0K 100K");
   1756   CheckExpectedRanges(kSourceId, "{ [0,46) }");
   1757 
   1758   // Mark end of stream and verify that text track data is reflected in
   1759   // the new range.
   1760   MarkEndOfStream(PIPELINE_OK);
   1761   CheckExpectedRanges(kSourceId, "{ [0,200) }");
   1762 }
   1763 
   1764 // Make sure AppendData() will accept elements that span multiple calls.
   1765 TEST_F(ChunkDemuxerTest, AppendingInPieces) {
   1766   EXPECT_CALL(*this, DemuxerOpened());
   1767   demuxer_->Initialize(
   1768       &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
   1769 
   1770   ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
   1771 
   1772   scoped_ptr<uint8[]> info_tracks;
   1773   int info_tracks_size = 0;
   1774   CreateInitSegment(HAS_AUDIO | HAS_VIDEO,
   1775                     false, false, &info_tracks, &info_tracks_size);
   1776 
   1777   scoped_ptr<Cluster> cluster_a(kDefaultFirstCluster());
   1778   scoped_ptr<Cluster> cluster_b(kDefaultSecondCluster());
   1779 
   1780   size_t buffer_size = info_tracks_size + cluster_a->size() + cluster_b->size();
   1781   scoped_ptr<uint8[]> buffer(new uint8[buffer_size]);
   1782   uint8* dst = buffer.get();
   1783   memcpy(dst, info_tracks.get(), info_tracks_size);
   1784   dst += info_tracks_size;
   1785 
   1786   memcpy(dst, cluster_a->data(), cluster_a->size());
   1787   dst += cluster_a->size();
   1788 
   1789   memcpy(dst, cluster_b->data(), cluster_b->size());
   1790   dst += cluster_b->size();
   1791 
   1792   AppendDataInPieces(buffer.get(), buffer_size);
   1793 
   1794   GenerateExpectedReads(0, 9);
   1795 }
   1796 
   1797 TEST_F(ChunkDemuxerTest, WebMFile_AudioAndVideo) {
   1798   struct BufferTimestamps buffer_timestamps[] = {
   1799     {0, 0},
   1800     {33, 3},
   1801     {67, 6},
   1802     {100, 9},
   1803     {133, 12},
   1804     {kSkip, kSkip},
   1805   };
   1806 
   1807   // TODO(wolenetz/acolwell): Remove this SetDuration expectation and update the
   1808   // ParseWebMFile() call's expected duration, below, once the file is fixed to
   1809   // have the correct duration in the init segment. See http://crbug.com/354284.
   1810   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2746)));
   1811 
   1812   ASSERT_TRUE(ParseWebMFile("bear-320x240.webm", buffer_timestamps,
   1813                             base::TimeDelta::FromMilliseconds(2744)));
   1814 }
   1815 
   1816 TEST_F(ChunkDemuxerTest, WebMFile_LiveAudioAndVideo) {
   1817   struct BufferTimestamps buffer_timestamps[] = {
   1818     {0, 0},
   1819     {33, 3},
   1820     {67, 6},
   1821     {100, 9},
   1822     {133, 12},
   1823     {kSkip, kSkip},
   1824   };
   1825 
   1826   ASSERT_TRUE(ParseWebMFile("bear-320x240-live.webm", buffer_timestamps,
   1827                             kInfiniteDuration()));
   1828 }
   1829 
   1830 TEST_F(ChunkDemuxerTest, WebMFile_AudioOnly) {
   1831   struct BufferTimestamps buffer_timestamps[] = {
   1832     {kSkip, 0},
   1833     {kSkip, 3},
   1834     {kSkip, 6},
   1835     {kSkip, 9},
   1836     {kSkip, 12},
   1837     {kSkip, kSkip},
   1838   };
   1839 
   1840   // TODO(wolenetz/acolwell): Remove this SetDuration expectation and update the
   1841   // ParseWebMFile() call's expected duration, below, once the file is fixed to
   1842   // have the correct duration in the init segment. See http://crbug.com/354284.
   1843   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2746)));
   1844 
   1845   ASSERT_TRUE(ParseWebMFile("bear-320x240-audio-only.webm", buffer_timestamps,
   1846                             base::TimeDelta::FromMilliseconds(2744),
   1847                             HAS_AUDIO));
   1848 }
   1849 
   1850 TEST_F(ChunkDemuxerTest, WebMFile_VideoOnly) {
   1851   struct BufferTimestamps buffer_timestamps[] = {
   1852     {0, kSkip},
   1853     {33, kSkip},
   1854     {67, kSkip},
   1855     {100, kSkip},
   1856     {133, kSkip},
   1857     {kSkip, kSkip},
   1858   };
   1859 
   1860   // TODO(wolenetz/acolwell): Remove this SetDuration expectation and update the
   1861   // ParseWebMFile() call's expected duration, below, once the file is fixed to
   1862   // have the correct duration in the init segment. See http://crbug.com/354284.
   1863   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2736)));
   1864 
   1865   ASSERT_TRUE(ParseWebMFile("bear-320x240-video-only.webm", buffer_timestamps,
   1866                             base::TimeDelta::FromMilliseconds(2703),
   1867                             HAS_VIDEO));
   1868 }
   1869 
   1870 TEST_F(ChunkDemuxerTest, WebMFile_AltRefFrames) {
   1871   struct BufferTimestamps buffer_timestamps[] = {
   1872     {0, 0},
   1873     {33, 3},
   1874     {33, 6},
   1875     {67, 9},
   1876     {100, 12},
   1877     {kSkip, kSkip},
   1878   };
   1879 
   1880   ASSERT_TRUE(ParseWebMFile("bear-320x240-altref.webm", buffer_timestamps,
   1881                             base::TimeDelta::FromMilliseconds(2767)));
   1882 }
   1883 
   1884 // Verify that we output buffers before the entire cluster has been parsed.
   1885 TEST_F(ChunkDemuxerTest, IncrementalClusterParsing) {
   1886   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   1887   AppendEmptyCluster(0);
   1888 
   1889   scoped_ptr<Cluster> cluster(GenerateCluster(0, 6));
   1890 
   1891   bool audio_read_done = false;
   1892   bool video_read_done = false;
   1893   ReadAudio(base::Bind(&OnReadDone,
   1894                        base::TimeDelta::FromMilliseconds(0),
   1895                        &audio_read_done));
   1896   ReadVideo(base::Bind(&OnReadDone,
   1897                        base::TimeDelta::FromMilliseconds(0),
   1898                        &video_read_done));
   1899 
   1900   // Make sure the reads haven't completed yet.
   1901   EXPECT_FALSE(audio_read_done);
   1902   EXPECT_FALSE(video_read_done);
   1903 
   1904   // Append data one byte at a time until one or both reads complete.
   1905   int i = 0;
   1906   for (; i < cluster->size() && !(audio_read_done || video_read_done); ++i) {
   1907     AppendData(cluster->data() + i, 1);
   1908     message_loop_.RunUntilIdle();
   1909   }
   1910 
   1911   EXPECT_TRUE(audio_read_done || video_read_done);
   1912   EXPECT_GT(i, 0);
   1913   EXPECT_LT(i, cluster->size());
   1914 
   1915   audio_read_done = false;
   1916   video_read_done = false;
   1917   ReadAudio(base::Bind(&OnReadDone,
   1918                        base::TimeDelta::FromMilliseconds(23),
   1919                        &audio_read_done));
   1920   ReadVideo(base::Bind(&OnReadDone,
   1921                        base::TimeDelta::FromMilliseconds(33),
   1922                        &video_read_done));
   1923 
   1924   // Make sure the reads haven't completed yet.
   1925   EXPECT_FALSE(audio_read_done);
   1926   EXPECT_FALSE(video_read_done);
   1927 
   1928   // Append the remaining data.
   1929   ASSERT_LT(i, cluster->size());
   1930   AppendData(cluster->data() + i, cluster->size() - i);
   1931 
   1932   message_loop_.RunUntilIdle();
   1933 
   1934   EXPECT_TRUE(audio_read_done);
   1935   EXPECT_TRUE(video_read_done);
   1936 }
   1937 
   1938 TEST_F(ChunkDemuxerTest, ParseErrorDuringInit) {
   1939   EXPECT_CALL(*this, DemuxerOpened());
   1940   demuxer_->Initialize(
   1941       &host_, CreateInitDoneCB(
   1942           kNoTimestamp(), DEMUXER_ERROR_COULD_NOT_OPEN), true);
   1943 
   1944   ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
   1945 
   1946   uint8 tmp = 0;
   1947   demuxer_->AppendData(kSourceId, &tmp, 1,
   1948                        append_window_start_for_next_append_,
   1949                        append_window_end_for_next_append_,
   1950                        &timestamp_offset_map_[kSourceId]);
   1951 }
   1952 
   1953 TEST_F(ChunkDemuxerTest, AVHeadersWithAudioOnlyType) {
   1954   EXPECT_CALL(*this, DemuxerOpened());
   1955   demuxer_->Initialize(
   1956       &host_, CreateInitDoneCB(kNoTimestamp(),
   1957                                DEMUXER_ERROR_COULD_NOT_OPEN), true);
   1958 
   1959   std::vector<std::string> codecs(1);
   1960   codecs[0] = "vorbis";
   1961   ASSERT_EQ(demuxer_->AddId(kSourceId, "audio/webm", codecs),
   1962             ChunkDemuxer::kOk);
   1963 
   1964   AppendInitSegment(HAS_AUDIO | HAS_VIDEO);
   1965 }
   1966 
   1967 TEST_F(ChunkDemuxerTest, AVHeadersWithVideoOnlyType) {
   1968   EXPECT_CALL(*this, DemuxerOpened());
   1969   demuxer_->Initialize(
   1970       &host_, CreateInitDoneCB(kNoTimestamp(),
   1971                                DEMUXER_ERROR_COULD_NOT_OPEN), true);
   1972 
   1973   std::vector<std::string> codecs(1);
   1974   codecs[0] = "vp8";
   1975   ASSERT_EQ(demuxer_->AddId(kSourceId, "video/webm", codecs),
   1976             ChunkDemuxer::kOk);
   1977 
   1978   AppendInitSegment(HAS_AUDIO | HAS_VIDEO);
   1979 }
   1980 
   1981 TEST_F(ChunkDemuxerTest, MultipleHeaders) {
   1982   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   1983 
   1984   AppendCluster(kDefaultFirstCluster());
   1985 
   1986   // Append another identical initialization segment.
   1987   AppendInitSegment(HAS_AUDIO | HAS_VIDEO);
   1988 
   1989   AppendCluster(kDefaultSecondCluster());
   1990 
   1991   GenerateExpectedReads(0, 9);
   1992 }
   1993 
   1994 TEST_F(ChunkDemuxerTest, AddSeparateSourcesForAudioAndVideo) {
   1995   std::string audio_id = "audio1";
   1996   std::string video_id = "video1";
   1997   ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
   1998 
   1999   // Append audio and video data into separate source ids.
   2000   AppendCluster(audio_id,
   2001       GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
   2002   GenerateAudioStreamExpectedReads(0, 4);
   2003   AppendCluster(video_id,
   2004       GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
   2005   GenerateVideoStreamExpectedReads(0, 4);
   2006 }
   2007 
   2008 TEST_F(ChunkDemuxerTest, AddSeparateSourcesForAudioAndVideoText) {
   2009   // TODO(matthewjheaney): Here and elsewhere, we need more tests
   2010   // for inband text tracks (http://crbug/321455).
   2011 
   2012   std::string audio_id = "audio1";
   2013   std::string video_id = "video1";
   2014 
   2015   EXPECT_CALL(host_, AddTextStream(_, _))
   2016     .Times(Exactly(2));
   2017   ASSERT_TRUE(InitDemuxerAudioAndVideoSourcesText(audio_id, video_id, true));
   2018 
   2019   // Append audio and video data into separate source ids.
   2020   AppendCluster(audio_id,
   2021       GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
   2022   GenerateAudioStreamExpectedReads(0, 4);
   2023   AppendCluster(video_id,
   2024       GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
   2025   GenerateVideoStreamExpectedReads(0, 4);
   2026 }
   2027 
   2028 TEST_F(ChunkDemuxerTest, AddIdFailures) {
   2029   EXPECT_CALL(*this, DemuxerOpened());
   2030   demuxer_->Initialize(
   2031       &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
   2032 
   2033   std::string audio_id = "audio1";
   2034   std::string video_id = "video1";
   2035 
   2036   ASSERT_EQ(AddId(audio_id, HAS_AUDIO), ChunkDemuxer::kOk);
   2037 
   2038   // Adding an id with audio/video should fail because we already added audio.
   2039   ASSERT_EQ(AddId(), ChunkDemuxer::kReachedIdLimit);
   2040 
   2041   AppendInitSegmentWithSourceId(audio_id, HAS_AUDIO);
   2042 
   2043   // Adding an id after append should fail.
   2044   ASSERT_EQ(AddId(video_id, HAS_VIDEO), ChunkDemuxer::kReachedIdLimit);
   2045 }
   2046 
   2047 // Test that Read() calls after a RemoveId() return "end of stream" buffers.
   2048 TEST_F(ChunkDemuxerTest, RemoveId) {
   2049   std::string audio_id = "audio1";
   2050   std::string video_id = "video1";
   2051   ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
   2052 
   2053   // Append audio and video data into separate source ids.
   2054   AppendCluster(audio_id,
   2055       GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
   2056   AppendCluster(video_id,
   2057       GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
   2058 
   2059   // Read() from audio should return normal buffers.
   2060   GenerateAudioStreamExpectedReads(0, 4);
   2061 
   2062   // Remove the audio id.
   2063   demuxer_->RemoveId(audio_id);
   2064 
   2065   // Read() from audio should return "end of stream" buffers.
   2066   bool audio_read_done = false;
   2067   ReadAudio(base::Bind(&OnReadDone_EOSExpected, &audio_read_done));
   2068   message_loop_.RunUntilIdle();
   2069   EXPECT_TRUE(audio_read_done);
   2070 
   2071   // Read() from video should still return normal buffers.
   2072   GenerateVideoStreamExpectedReads(0, 4);
   2073 }
   2074 
   2075 // Test that removing an ID immediately after adding it does not interfere with
   2076 // quota for new IDs in the future.
   2077 TEST_F(ChunkDemuxerTest, RemoveAndAddId) {
   2078   std::string audio_id_1 = "audio1";
   2079   ASSERT_TRUE(AddId(audio_id_1, HAS_AUDIO) == ChunkDemuxer::kOk);
   2080   demuxer_->RemoveId(audio_id_1);
   2081 
   2082   std::string audio_id_2 = "audio2";
   2083   ASSERT_TRUE(AddId(audio_id_2, HAS_AUDIO) == ChunkDemuxer::kOk);
   2084 }
   2085 
   2086 TEST_F(ChunkDemuxerTest, SeekCanceled) {
   2087   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   2088 
   2089   // Append cluster at the beginning of the stream.
   2090   AppendCluster(GenerateCluster(0, 4));
   2091 
   2092   // Seek to an unbuffered region.
   2093   Seek(base::TimeDelta::FromSeconds(50));
   2094 
   2095   // Attempt to read in unbuffered area; should not fulfill the read.
   2096   bool audio_read_done = false;
   2097   bool video_read_done = false;
   2098   ReadAudio(base::Bind(&OnReadDone_AbortExpected, &audio_read_done));
   2099   ReadVideo(base::Bind(&OnReadDone_AbortExpected, &video_read_done));
   2100   EXPECT_FALSE(audio_read_done);
   2101   EXPECT_FALSE(video_read_done);
   2102 
   2103   // Now cancel the pending seek, which should flush the reads with empty
   2104   // buffers.
   2105   base::TimeDelta seek_time = base::TimeDelta::FromSeconds(0);
   2106   demuxer_->CancelPendingSeek(seek_time);
   2107   message_loop_.RunUntilIdle();
   2108   EXPECT_TRUE(audio_read_done);
   2109   EXPECT_TRUE(video_read_done);
   2110 
   2111   // A seek back to the buffered region should succeed.
   2112   Seek(seek_time);
   2113   GenerateExpectedReads(0, 4);
   2114 }
   2115 
   2116 TEST_F(ChunkDemuxerTest, SeekCanceledWhileWaitingForSeek) {
   2117   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   2118 
   2119   // Append cluster at the beginning of the stream.
   2120   AppendCluster(GenerateCluster(0, 4));
   2121 
   2122   // Start waiting for a seek.
   2123   base::TimeDelta seek_time1 = base::TimeDelta::FromSeconds(50);
   2124   base::TimeDelta seek_time2 = base::TimeDelta::FromSeconds(0);
   2125   demuxer_->StartWaitingForSeek(seek_time1);
   2126 
   2127   // Now cancel the upcoming seek to an unbuffered region.
   2128   demuxer_->CancelPendingSeek(seek_time2);
   2129   demuxer_->Seek(seek_time1, NewExpectedStatusCB(PIPELINE_OK));
   2130 
   2131   // Read requests should be fulfilled with empty buffers.
   2132   bool audio_read_done = false;
   2133   bool video_read_done = false;
   2134   ReadAudio(base::Bind(&OnReadDone_AbortExpected, &audio_read_done));
   2135   ReadVideo(base::Bind(&OnReadDone_AbortExpected, &video_read_done));
   2136   EXPECT_TRUE(audio_read_done);
   2137   EXPECT_TRUE(video_read_done);
   2138 
   2139   // A seek back to the buffered region should succeed.
   2140   Seek(seek_time2);
   2141   GenerateExpectedReads(0, 4);
   2142 }
   2143 
   2144 // Test that Seek() successfully seeks to all source IDs.
   2145 TEST_F(ChunkDemuxerTest, SeekAudioAndVideoSources) {
   2146   std::string audio_id = "audio1";
   2147   std::string video_id = "video1";
   2148   ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
   2149 
   2150   AppendCluster(
   2151       audio_id,
   2152       GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
   2153   AppendCluster(
   2154       video_id,
   2155       GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
   2156 
   2157   // Read() should return buffers at 0.
   2158   bool audio_read_done = false;
   2159   bool video_read_done = false;
   2160   ReadAudio(base::Bind(&OnReadDone,
   2161                        base::TimeDelta::FromMilliseconds(0),
   2162                        &audio_read_done));
   2163   ReadVideo(base::Bind(&OnReadDone,
   2164                        base::TimeDelta::FromMilliseconds(0),
   2165                        &video_read_done));
   2166   EXPECT_TRUE(audio_read_done);
   2167   EXPECT_TRUE(video_read_done);
   2168 
   2169   // Seek to 3 (an unbuffered region).
   2170   Seek(base::TimeDelta::FromSeconds(3));
   2171 
   2172   audio_read_done = false;
   2173   video_read_done = false;
   2174   ReadAudio(base::Bind(&OnReadDone,
   2175                        base::TimeDelta::FromSeconds(3),
   2176                        &audio_read_done));
   2177   ReadVideo(base::Bind(&OnReadDone,
   2178                        base::TimeDelta::FromSeconds(3),
   2179                        &video_read_done));
   2180   // Read()s should not return until after data is appended at the Seek point.
   2181   EXPECT_FALSE(audio_read_done);
   2182   EXPECT_FALSE(video_read_done);
   2183 
   2184   AppendCluster(audio_id,
   2185                 GenerateSingleStreamCluster(
   2186                     3000, 3092, kAudioTrackNum, kAudioBlockDuration));
   2187   AppendCluster(video_id,
   2188                 GenerateSingleStreamCluster(
   2189                     3000, 3132, kVideoTrackNum, kVideoBlockDuration));
   2190 
   2191   message_loop_.RunUntilIdle();
   2192 
   2193   // Read() should return buffers at 3.
   2194   EXPECT_TRUE(audio_read_done);
   2195   EXPECT_TRUE(video_read_done);
   2196 }
   2197 
   2198 // Test that Seek() completes successfully when EndOfStream
   2199 // is called before data is available for that seek point.
   2200 // This scenario might be useful if seeking past the end of stream
   2201 // of either audio or video (or both).
   2202 TEST_F(ChunkDemuxerTest, EndOfStreamAfterPastEosSeek) {
   2203   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   2204 
   2205   AppendCluster(GenerateSingleStreamCluster(0, 120, kAudioTrackNum, 10));
   2206   AppendCluster(GenerateSingleStreamCluster(0, 100, kVideoTrackNum, 5));
   2207 
   2208   // Seeking past the end of video.
   2209   // Note: audio data is available for that seek point.
   2210   bool seek_cb_was_called = false;
   2211   base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(110);
   2212   demuxer_->StartWaitingForSeek(seek_time);
   2213   demuxer_->Seek(seek_time,
   2214                  base::Bind(OnSeekDone_OKExpected, &seek_cb_was_called));
   2215   message_loop_.RunUntilIdle();
   2216 
   2217   EXPECT_FALSE(seek_cb_was_called);
   2218 
   2219   EXPECT_CALL(host_, SetDuration(
   2220       base::TimeDelta::FromMilliseconds(120)));
   2221   MarkEndOfStream(PIPELINE_OK);
   2222   message_loop_.RunUntilIdle();
   2223 
   2224   EXPECT_TRUE(seek_cb_was_called);
   2225 
   2226   ShutdownDemuxer();
   2227 }
   2228 
   2229 // Test that EndOfStream is ignored if coming during a pending seek
   2230 // whose seek time is before some existing ranges.
   2231 TEST_F(ChunkDemuxerTest, EndOfStreamDuringPendingSeek) {
   2232   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   2233 
   2234   AppendCluster(GenerateSingleStreamCluster(0, 120, kAudioTrackNum, 10));
   2235   AppendCluster(GenerateSingleStreamCluster(0, 100, kVideoTrackNum, 5));
   2236   AppendCluster(GenerateSingleStreamCluster(200, 300, kAudioTrackNum, 10));
   2237   AppendCluster(GenerateSingleStreamCluster(200, 300, kVideoTrackNum, 5));
   2238 
   2239   bool seek_cb_was_called = false;
   2240   base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(160);
   2241   demuxer_->StartWaitingForSeek(seek_time);
   2242   demuxer_->Seek(seek_time,
   2243                  base::Bind(OnSeekDone_OKExpected, &seek_cb_was_called));
   2244   message_loop_.RunUntilIdle();
   2245 
   2246   EXPECT_FALSE(seek_cb_was_called);
   2247 
   2248   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(300)));
   2249   MarkEndOfStream(PIPELINE_OK);
   2250   message_loop_.RunUntilIdle();
   2251 
   2252   EXPECT_FALSE(seek_cb_was_called);
   2253 
   2254   demuxer_->UnmarkEndOfStream();
   2255 
   2256   AppendCluster(GenerateSingleStreamCluster(140, 180, kAudioTrackNum, 10));
   2257   AppendCluster(GenerateSingleStreamCluster(140, 180, kVideoTrackNum, 5));
   2258 
   2259   message_loop_.RunUntilIdle();
   2260 
   2261   EXPECT_TRUE(seek_cb_was_called);
   2262 
   2263   ShutdownDemuxer();
   2264 }
   2265 
   2266 // Test ranges in an audio-only stream.
   2267 TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioIdOnly) {
   2268   EXPECT_CALL(*this, DemuxerOpened());
   2269   demuxer_->Initialize(
   2270       &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
   2271 
   2272   ASSERT_EQ(AddId(kSourceId, HAS_AUDIO), ChunkDemuxer::kOk);
   2273   AppendInitSegment(HAS_AUDIO);
   2274 
   2275   // Test a simple cluster.
   2276   AppendCluster(
   2277       GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
   2278 
   2279   CheckExpectedRanges("{ [0,92) }");
   2280 
   2281   // Append a disjoint cluster to check for two separate ranges.
   2282   AppendCluster(GenerateSingleStreamCluster(
   2283       150, 219, kAudioTrackNum, kAudioBlockDuration));
   2284 
   2285   CheckExpectedRanges("{ [0,92) [150,219) }");
   2286 }
   2287 
   2288 // Test ranges in a video-only stream.
   2289 TEST_F(ChunkDemuxerTest, GetBufferedRanges_VideoIdOnly) {
   2290   EXPECT_CALL(*this, DemuxerOpened());
   2291   demuxer_->Initialize(
   2292       &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
   2293 
   2294   ASSERT_EQ(AddId(kSourceId, HAS_VIDEO), ChunkDemuxer::kOk);
   2295   AppendInitSegment(HAS_VIDEO);
   2296 
   2297   // Test a simple cluster.
   2298   AppendCluster(
   2299       GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
   2300 
   2301   CheckExpectedRanges("{ [0,132) }");
   2302 
   2303   // Append a disjoint cluster to check for two separate ranges.
   2304   AppendCluster(GenerateSingleStreamCluster(
   2305       200, 299, kVideoTrackNum, kVideoBlockDuration));
   2306 
   2307   CheckExpectedRanges("{ [0,132) [200,299) }");
   2308 }
   2309 
   2310 TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioVideo) {
   2311   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   2312 
   2313   // Audio: 0 -> 23
   2314   // Video: 0 -> 33
   2315   // Buffered Range: 0 -> 23
   2316   // Audio block duration is smaller than video block duration,
   2317   // so the buffered ranges should correspond to the audio blocks.
   2318   AppendCluster(GenerateSingleStreamCluster(
   2319       0, kAudioBlockDuration, kAudioTrackNum, kAudioBlockDuration));
   2320   AppendCluster(GenerateSingleStreamCluster(
   2321       0, kVideoBlockDuration, kVideoTrackNum, kVideoBlockDuration));
   2322 
   2323   CheckExpectedRanges("{ [0,23) }");
   2324 
   2325   // Audio: 300 -> 400
   2326   // Video: 320 -> 420
   2327   // Buffered Range: 320 -> 400  (end overlap)
   2328   AppendCluster(GenerateSingleStreamCluster(300, 400, kAudioTrackNum, 50));
   2329   AppendCluster(GenerateSingleStreamCluster(320, 420, kVideoTrackNum, 50));
   2330 
   2331   CheckExpectedRanges("{ [0,23) [320,400) }");
   2332 
   2333   // Audio: 520 -> 590
   2334   // Video: 500 -> 570
   2335   // Buffered Range: 520 -> 570  (front overlap)
   2336   AppendCluster(GenerateSingleStreamCluster(520, 590, kAudioTrackNum, 70));
   2337   AppendCluster(GenerateSingleStreamCluster(500, 570, kVideoTrackNum, 70));
   2338 
   2339   CheckExpectedRanges("{ [0,23) [320,400) [520,570) }");
   2340 
   2341   // Audio: 720 -> 750
   2342   // Video: 700 -> 770
   2343   // Buffered Range: 720 -> 750  (complete overlap, audio)
   2344   AppendCluster(GenerateSingleStreamCluster(720, 750, kAudioTrackNum, 30));
   2345   AppendCluster(GenerateSingleStreamCluster(700, 770, kVideoTrackNum, 70));
   2346 
   2347   CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) }");
   2348 
   2349   // Audio: 900 -> 970
   2350   // Video: 920 -> 950
   2351   // Buffered Range: 920 -> 950  (complete overlap, video)
   2352   AppendCluster(GenerateSingleStreamCluster(900, 970, kAudioTrackNum, 70));
   2353   AppendCluster(GenerateSingleStreamCluster(920, 950, kVideoTrackNum, 30));
   2354 
   2355   CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) [920,950) }");
   2356 
   2357   // Appending within buffered range should not affect buffered ranges.
   2358   AppendCluster(GenerateSingleStreamCluster(930, 950, kAudioTrackNum, 20));
   2359   CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) [920,950) }");
   2360 
   2361   // Appending to single stream outside buffered ranges should not affect
   2362   // buffered ranges.
   2363   AppendCluster(GenerateSingleStreamCluster(1230, 1240, kVideoTrackNum, 10));
   2364   CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) [920,950) }");
   2365 }
   2366 
   2367 TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioVideoText) {
   2368   EXPECT_CALL(host_, AddTextStream(_, _));
   2369   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT));
   2370 
   2371   // Append audio & video data
   2372   AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "0K 23");
   2373   AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "0K 33");
   2374 
   2375   // Verify that a text track with no cues does not result in an empty buffered
   2376   // range.
   2377   CheckExpectedRanges("{ [0,46) }");
   2378 
   2379   // Add some text cues.
   2380   AppendSingleStreamCluster(kSourceId, kTextTrackNum, "0K 100K");
   2381 
   2382   // Verify that the new cues did not affect the buffered ranges.
   2383   CheckExpectedRanges("{ [0,46) }");
   2384 
   2385   // Remove the buffered range.
   2386   demuxer_->Remove(kSourceId, base::TimeDelta(),
   2387                    base::TimeDelta::FromMilliseconds(46));
   2388   CheckExpectedRanges("{ }");
   2389 }
   2390 
   2391 // Once MarkEndOfStream() is called, GetBufferedRanges should not cut off any
   2392 // over-hanging tails at the end of the ranges as this is likely due to block
   2393 // duration differences.
   2394 TEST_F(ChunkDemuxerTest, GetBufferedRanges_EndOfStream) {
   2395   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   2396 
   2397   AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "0K 23K");
   2398   AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "0K 33");
   2399 
   2400   CheckExpectedRanges("{ [0,46) }");
   2401 
   2402   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(66)));
   2403   MarkEndOfStream(PIPELINE_OK);
   2404 
   2405   // Verify that the range extends to the end of the video data.
   2406   CheckExpectedRanges("{ [0,66) }");
   2407 
   2408   // Verify that the range reverts to the intersection when end of stream
   2409   // has been cancelled.
   2410   demuxer_->UnmarkEndOfStream();
   2411   CheckExpectedRanges("{ [0,46) }");
   2412 
   2413   // Append and remove data so that the 2 streams' end ranges do not overlap.
   2414 
   2415   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(246)));
   2416   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(398)));
   2417   AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "200K 223K");
   2418   AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
   2419                             "200K 233 266 299 332K 365");
   2420 
   2421   // At this point, the per-stream ranges are as follows:
   2422   // Audio: [0,46) [200,246)
   2423   // Video: [0,66) [200,398)
   2424   CheckExpectedRanges("{ [0,46) [200,246) }");
   2425 
   2426   demuxer_->Remove(kSourceId, base::TimeDelta::FromMilliseconds(200),
   2427                    base::TimeDelta::FromMilliseconds(300));
   2428 
   2429   // At this point, the per-stream ranges are as follows:
   2430   // Audio: [0,46)
   2431   // Video: [0,66) [332,398)
   2432   CheckExpectedRanges("{ [0,46) }");
   2433 
   2434   AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "200K 223K");
   2435   AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "200K 233");
   2436 
   2437   // At this point, the per-stream ranges are as follows:
   2438   // Audio: [0,46) [200,246)
   2439   // Video: [0,66) [200,266) [332,398)
   2440   // NOTE: The last range on each stream do not overlap in time.
   2441   CheckExpectedRanges("{ [0,46) [200,246) }");
   2442 
   2443   MarkEndOfStream(PIPELINE_OK);
   2444 
   2445   // NOTE: The last range on each stream gets extended to the highest
   2446   // end timestamp according to the spec. The last audio range gets extended
   2447   // from [200,246) to [200,398) which is why the intersection results in the
   2448   // middle range getting larger AND the new range appearing.
   2449   CheckExpectedRanges("{ [0,46) [200,266) [332,398) }");
   2450 }
   2451 
   2452 TEST_F(ChunkDemuxerTest, DifferentStreamTimecodes) {
   2453   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   2454 
   2455   // Create a cluster where the video timecode begins 25ms after the audio.
   2456   AppendCluster(GenerateCluster(0, 25, 8));
   2457 
   2458   Seek(base::TimeDelta::FromSeconds(0));
   2459   GenerateExpectedReads(0, 25, 8);
   2460 
   2461   // Seek to 5 seconds.
   2462   Seek(base::TimeDelta::FromSeconds(5));
   2463 
   2464   // Generate a cluster to fulfill this seek, where audio timecode begins 25ms
   2465   // after the video.
   2466   AppendCluster(GenerateCluster(5025, 5000, 8));
   2467   GenerateExpectedReads(5025, 5000, 8);
   2468 }
   2469 
   2470 TEST_F(ChunkDemuxerTest, DifferentStreamTimecodesSeparateSources) {
   2471   std::string audio_id = "audio1";
   2472   std::string video_id = "video1";
   2473   ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
   2474 
   2475   // Generate two streams where the video stream starts 5ms after the audio
   2476   // stream and append them.
   2477   AppendCluster(audio_id, GenerateSingleStreamCluster(
   2478       25, 4 * kAudioBlockDuration + 25, kAudioTrackNum, kAudioBlockDuration));
   2479   AppendCluster(video_id, GenerateSingleStreamCluster(
   2480       30, 4 * kVideoBlockDuration + 30, kVideoTrackNum, kVideoBlockDuration));
   2481 
   2482   // Both streams should be able to fulfill a seek to 25.
   2483   Seek(base::TimeDelta::FromMilliseconds(25));
   2484   GenerateAudioStreamExpectedReads(25, 4);
   2485   GenerateVideoStreamExpectedReads(30, 4);
   2486 }
   2487 
   2488 TEST_F(ChunkDemuxerTest, DifferentStreamTimecodesOutOfRange) {
   2489   std::string audio_id = "audio1";
   2490   std::string video_id = "video1";
   2491   ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
   2492 
   2493   // Generate two streams where the video stream starts 10s after the audio
   2494   // stream and append them.
   2495   AppendCluster(audio_id, GenerateSingleStreamCluster(0,
   2496       4 * kAudioBlockDuration + 0, kAudioTrackNum, kAudioBlockDuration));
   2497   AppendCluster(video_id, GenerateSingleStreamCluster(10000,
   2498       4 * kVideoBlockDuration + 10000, kVideoTrackNum, kVideoBlockDuration));
   2499 
   2500   // Should not be able to fulfill a seek to 0.
   2501   base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(0);
   2502   demuxer_->StartWaitingForSeek(seek_time);
   2503   demuxer_->Seek(seek_time,
   2504                  NewExpectedStatusCB(PIPELINE_ERROR_ABORT));
   2505   ExpectRead(DemuxerStream::AUDIO, 0);
   2506   ExpectEndOfStream(DemuxerStream::VIDEO);
   2507 }
   2508 
   2509 TEST_F(ChunkDemuxerTest, ClusterWithNoBuffers) {
   2510   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   2511 
   2512   // Generate and append an empty cluster beginning at 0.
   2513   AppendEmptyCluster(0);
   2514 
   2515   // Sanity check that data can be appended after this cluster correctly.
   2516   AppendCluster(GenerateCluster(0, 2));
   2517   ExpectRead(DemuxerStream::AUDIO, 0);
   2518   ExpectRead(DemuxerStream::VIDEO, 0);
   2519 }
   2520 
   2521 TEST_F(ChunkDemuxerTest, CodecPrefixMatching) {
   2522   ChunkDemuxer::Status expected = ChunkDemuxer::kNotSupported;
   2523 
   2524 #if defined(USE_PROPRIETARY_CODECS)
   2525   expected = ChunkDemuxer::kOk;
   2526 #endif
   2527 
   2528   std::vector<std::string> codecs;
   2529   codecs.push_back("avc1.4D4041");
   2530 
   2531   EXPECT_EQ(demuxer_->AddId("source_id", "video/mp4", codecs), expected);
   2532 }
   2533 
   2534 // Test codec ID's that are not compliant with RFC6381, but have been
   2535 // seen in the wild.
   2536 TEST_F(ChunkDemuxerTest, CodecIDsThatAreNotRFC6381Compliant) {
   2537   ChunkDemuxer::Status expected = ChunkDemuxer::kNotSupported;
   2538 
   2539 #if defined(USE_PROPRIETARY_CODECS)
   2540   expected = ChunkDemuxer::kOk;
   2541 #endif
   2542   const char* codec_ids[] = {
   2543     // GPAC places leading zeros on the audio object type.
   2544     "mp4a.40.02",
   2545     "mp4a.40.05"
   2546   };
   2547 
   2548   for (size_t i = 0; i < arraysize(codec_ids); ++i) {
   2549     std::vector<std::string> codecs;
   2550     codecs.push_back(codec_ids[i]);
   2551 
   2552     ChunkDemuxer::Status result =
   2553         demuxer_->AddId("source_id", "audio/mp4", codecs);
   2554 
   2555     EXPECT_EQ(result, expected)
   2556         << "Fail to add codec_id '" << codec_ids[i] << "'";
   2557 
   2558     if (result == ChunkDemuxer::kOk)
   2559       demuxer_->RemoveId("source_id");
   2560   }
   2561 }
   2562 
   2563 TEST_F(ChunkDemuxerTest, EndOfStreamStillSetAfterSeek) {
   2564   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   2565 
   2566   EXPECT_CALL(host_, SetDuration(_))
   2567       .Times(AnyNumber());
   2568 
   2569   base::TimeDelta kLastAudioTimestamp = base::TimeDelta::FromMilliseconds(92);
   2570   base::TimeDelta kLastVideoTimestamp = base::TimeDelta::FromMilliseconds(99);
   2571 
   2572   AppendCluster(kDefaultFirstCluster());
   2573   AppendCluster(kDefaultSecondCluster());
   2574   MarkEndOfStream(PIPELINE_OK);
   2575 
   2576   DemuxerStream::Status status;
   2577   base::TimeDelta last_timestamp;
   2578 
   2579   // Verify that we can read audio & video to the end w/o problems.
   2580   ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
   2581   EXPECT_EQ(DemuxerStream::kOk, status);
   2582   EXPECT_EQ(kLastAudioTimestamp, last_timestamp);
   2583 
   2584   ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
   2585   EXPECT_EQ(DemuxerStream::kOk, status);
   2586   EXPECT_EQ(kLastVideoTimestamp, last_timestamp);
   2587 
   2588   // Seek back to 0 and verify that we can read to the end again..
   2589   Seek(base::TimeDelta::FromMilliseconds(0));
   2590 
   2591   ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
   2592   EXPECT_EQ(DemuxerStream::kOk, status);
   2593   EXPECT_EQ(kLastAudioTimestamp, last_timestamp);
   2594 
   2595   ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
   2596   EXPECT_EQ(DemuxerStream::kOk, status);
   2597   EXPECT_EQ(kLastVideoTimestamp, last_timestamp);
   2598 }
   2599 
   2600 TEST_F(ChunkDemuxerTest, GetBufferedRangesBeforeInitSegment) {
   2601   EXPECT_CALL(*this, DemuxerOpened());
   2602   demuxer_->Initialize(&host_, CreateInitDoneCB(PIPELINE_OK), true);
   2603   ASSERT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk);
   2604   ASSERT_EQ(AddId("video", HAS_VIDEO), ChunkDemuxer::kOk);
   2605 
   2606   CheckExpectedRanges("audio", "{ }");
   2607   CheckExpectedRanges("video", "{ }");
   2608 }
   2609 
   2610 // Test that Seek() completes successfully when the first cluster
   2611 // arrives.
   2612 TEST_F(ChunkDemuxerTest, EndOfStreamDuringSeek) {
   2613   InSequence s;
   2614 
   2615   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   2616 
   2617   AppendCluster(kDefaultFirstCluster());
   2618 
   2619   base::TimeDelta seek_time = base::TimeDelta::FromSeconds(0);
   2620   demuxer_->StartWaitingForSeek(seek_time);
   2621 
   2622   AppendCluster(kDefaultSecondCluster());
   2623   EXPECT_CALL(host_, SetDuration(
   2624       base::TimeDelta::FromMilliseconds(kDefaultSecondClusterEndTimestamp)));
   2625   MarkEndOfStream(PIPELINE_OK);
   2626 
   2627   demuxer_->Seek(seek_time, NewExpectedStatusCB(PIPELINE_OK));
   2628 
   2629   GenerateExpectedReads(0, 4);
   2630   GenerateExpectedReads(46, 66, 5);
   2631 
   2632   EndOfStreamHelper end_of_stream_helper(demuxer_.get());
   2633   end_of_stream_helper.RequestReads();
   2634   end_of_stream_helper.CheckIfReadDonesWereCalled(true);
   2635 }
   2636 
   2637 TEST_F(ChunkDemuxerTest, ConfigChange_Video) {
   2638   InSequence s;
   2639 
   2640   ASSERT_TRUE(InitDemuxerWithConfigChangeData());
   2641 
   2642   DemuxerStream::Status status;
   2643   base::TimeDelta last_timestamp;
   2644 
   2645   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
   2646 
   2647   // Fetch initial video config and verify it matches what we expect.
   2648   const VideoDecoderConfig& video_config_1 = video->video_decoder_config();
   2649   ASSERT_TRUE(video_config_1.IsValidConfig());
   2650   EXPECT_EQ(video_config_1.natural_size().width(), 320);
   2651   EXPECT_EQ(video_config_1.natural_size().height(), 240);
   2652 
   2653   ExpectRead(DemuxerStream::VIDEO, 0);
   2654 
   2655   ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
   2656 
   2657   ASSERT_EQ(status, DemuxerStream::kConfigChanged);
   2658   EXPECT_EQ(last_timestamp.InMilliseconds(), 501);
   2659 
   2660   // Fetch the new decoder config.
   2661   const VideoDecoderConfig& video_config_2 = video->video_decoder_config();
   2662   ASSERT_TRUE(video_config_2.IsValidConfig());
   2663   EXPECT_EQ(video_config_2.natural_size().width(), 640);
   2664   EXPECT_EQ(video_config_2.natural_size().height(), 360);
   2665 
   2666   ExpectRead(DemuxerStream::VIDEO, 527);
   2667 
   2668   // Read until the next config change.
   2669   ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
   2670   ASSERT_EQ(status, DemuxerStream::kConfigChanged);
   2671   EXPECT_EQ(last_timestamp.InMilliseconds(), 793);
   2672 
   2673   // Get the new config and verify that it matches the first one.
   2674   ASSERT_TRUE(video_config_1.Matches(video->video_decoder_config()));
   2675 
   2676   ExpectRead(DemuxerStream::VIDEO, 801);
   2677 
   2678   // Read until the end of the stream just to make sure there aren't any other
   2679   // config changes.
   2680   ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
   2681   ASSERT_EQ(status, DemuxerStream::kOk);
   2682 }
   2683 
   2684 TEST_F(ChunkDemuxerTest, ConfigChange_Audio) {
   2685   InSequence s;
   2686 
   2687   ASSERT_TRUE(InitDemuxerWithConfigChangeData());
   2688 
   2689   DemuxerStream::Status status;
   2690   base::TimeDelta last_timestamp;
   2691 
   2692   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
   2693 
   2694   // Fetch initial audio config and verify it matches what we expect.
   2695   const AudioDecoderConfig& audio_config_1 = audio->audio_decoder_config();
   2696   ASSERT_TRUE(audio_config_1.IsValidConfig());
   2697   EXPECT_EQ(audio_config_1.samples_per_second(), 44100);
   2698   EXPECT_EQ(audio_config_1.extra_data_size(), 3863u);
   2699 
   2700   ExpectRead(DemuxerStream::AUDIO, 0);
   2701 
   2702   // The first config change seen is from a splice frame representing an overlap
   2703   // of buffer from config 1 by buffers from config 2.
   2704   ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
   2705   ASSERT_EQ(status, DemuxerStream::kConfigChanged);
   2706   EXPECT_EQ(last_timestamp.InMilliseconds(), 524);
   2707 
   2708   // Fetch the new decoder config.
   2709   const AudioDecoderConfig& audio_config_2 = audio->audio_decoder_config();
   2710   ASSERT_TRUE(audio_config_2.IsValidConfig());
   2711   EXPECT_EQ(audio_config_2.samples_per_second(), 44100);
   2712   EXPECT_EQ(audio_config_2.extra_data_size(), 3935u);
   2713 
   2714   // The next config change is from a splice frame representing an overlap of
   2715   // buffers from config 2 by buffers from config 1.
   2716   ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
   2717   ASSERT_EQ(status, DemuxerStream::kConfigChanged);
   2718   EXPECT_EQ(last_timestamp.InMilliseconds(), 782);
   2719   ASSERT_TRUE(audio_config_1.Matches(audio->audio_decoder_config()));
   2720 
   2721   // Read until the end of the stream just to make sure there aren't any other
   2722   // config changes.
   2723   ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
   2724   ASSERT_EQ(status, DemuxerStream::kOk);
   2725   EXPECT_EQ(last_timestamp.InMilliseconds(), 2744);
   2726 }
   2727 
   2728 TEST_F(ChunkDemuxerTest, ConfigChange_Seek) {
   2729   InSequence s;
   2730 
   2731   ASSERT_TRUE(InitDemuxerWithConfigChangeData());
   2732 
   2733   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
   2734 
   2735   // Fetch initial video config and verify it matches what we expect.
   2736   const VideoDecoderConfig& video_config_1 = video->video_decoder_config();
   2737   ASSERT_TRUE(video_config_1.IsValidConfig());
   2738   EXPECT_EQ(video_config_1.natural_size().width(), 320);
   2739   EXPECT_EQ(video_config_1.natural_size().height(), 240);
   2740 
   2741   ExpectRead(DemuxerStream::VIDEO, 0);
   2742 
   2743   // Seek to a location with a different config.
   2744   Seek(base::TimeDelta::FromMilliseconds(527));
   2745 
   2746   // Verify that the config change is signalled.
   2747   ExpectConfigChanged(DemuxerStream::VIDEO);
   2748 
   2749   // Fetch the new decoder config and verify it is what we expect.
   2750   const VideoDecoderConfig& video_config_2 = video->video_decoder_config();
   2751   ASSERT_TRUE(video_config_2.IsValidConfig());
   2752   EXPECT_EQ(video_config_2.natural_size().width(), 640);
   2753   EXPECT_EQ(video_config_2.natural_size().height(), 360);
   2754 
   2755   // Verify that Read() will return a buffer now.
   2756   ExpectRead(DemuxerStream::VIDEO, 527);
   2757 
   2758   // Seek back to the beginning and verify we get another config change.
   2759   Seek(base::TimeDelta::FromMilliseconds(0));
   2760   ExpectConfigChanged(DemuxerStream::VIDEO);
   2761   ASSERT_TRUE(video_config_1.Matches(video->video_decoder_config()));
   2762   ExpectRead(DemuxerStream::VIDEO, 0);
   2763 
   2764   // Seek to a location that requires a config change and then
   2765   // seek to a new location that has the same configuration as
   2766   // the start of the file without a Read() in the middle.
   2767   Seek(base::TimeDelta::FromMilliseconds(527));
   2768   Seek(base::TimeDelta::FromMilliseconds(801));
   2769 
   2770   // Verify that no config change is signalled.
   2771   ExpectRead(DemuxerStream::VIDEO, 801);
   2772   ASSERT_TRUE(video_config_1.Matches(video->video_decoder_config()));
   2773 }
   2774 
   2775 TEST_F(ChunkDemuxerTest, TimestampPositiveOffset) {
   2776   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   2777 
   2778   ASSERT_TRUE(SetTimestampOffset(kSourceId, base::TimeDelta::FromSeconds(30)));
   2779   AppendCluster(GenerateCluster(0, 2));
   2780 
   2781   Seek(base::TimeDelta::FromMilliseconds(30000));
   2782 
   2783   GenerateExpectedReads(30000, 2);
   2784 }
   2785 
   2786 TEST_F(ChunkDemuxerTest, TimestampNegativeOffset) {
   2787   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   2788 
   2789   ASSERT_TRUE(SetTimestampOffset(kSourceId, base::TimeDelta::FromSeconds(-1)));
   2790   AppendCluster(GenerateCluster(1000, 2));
   2791 
   2792   GenerateExpectedReads(0, 2);
   2793 }
   2794 
   2795 TEST_F(ChunkDemuxerTest, TimestampOffsetSeparateStreams) {
   2796   std::string audio_id = "audio1";
   2797   std::string video_id = "video1";
   2798   ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
   2799 
   2800   ASSERT_TRUE(SetTimestampOffset(
   2801       audio_id, base::TimeDelta::FromMilliseconds(-2500)));
   2802   ASSERT_TRUE(SetTimestampOffset(
   2803       video_id, base::TimeDelta::FromMilliseconds(-2500)));
   2804   AppendCluster(audio_id, GenerateSingleStreamCluster(2500,
   2805       2500 + kAudioBlockDuration * 4, kAudioTrackNum, kAudioBlockDuration));
   2806   AppendCluster(video_id, GenerateSingleStreamCluster(2500,
   2807       2500 + kVideoBlockDuration * 4, kVideoTrackNum, kVideoBlockDuration));
   2808   GenerateAudioStreamExpectedReads(0, 4);
   2809   GenerateVideoStreamExpectedReads(0, 4);
   2810 
   2811   Seek(base::TimeDelta::FromMilliseconds(27300));
   2812 
   2813   ASSERT_TRUE(SetTimestampOffset(
   2814       audio_id, base::TimeDelta::FromMilliseconds(27300)));
   2815   ASSERT_TRUE(SetTimestampOffset(
   2816       video_id, base::TimeDelta::FromMilliseconds(27300)));
   2817   AppendCluster(audio_id, GenerateSingleStreamCluster(
   2818       0, kAudioBlockDuration * 4, kAudioTrackNum, kAudioBlockDuration));
   2819   AppendCluster(video_id, GenerateSingleStreamCluster(
   2820       0, kVideoBlockDuration * 4, kVideoTrackNum, kVideoBlockDuration));
   2821   GenerateVideoStreamExpectedReads(27300, 4);
   2822   GenerateAudioStreamExpectedReads(27300, 4);
   2823 }
   2824 
   2825 TEST_F(ChunkDemuxerTest, IsParsingMediaSegmentMidMediaSegment) {
   2826   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   2827 
   2828   scoped_ptr<Cluster> cluster = GenerateCluster(0, 2);
   2829   // Append only part of the cluster data.
   2830   AppendData(cluster->data(), cluster->size() - 13);
   2831 
   2832   // Confirm we're in the middle of parsing a media segment.
   2833   ASSERT_TRUE(demuxer_->IsParsingMediaSegment(kSourceId));
   2834 
   2835   demuxer_->Abort(kSourceId,
   2836                   append_window_start_for_next_append_,
   2837                   append_window_end_for_next_append_,
   2838                   &timestamp_offset_map_[kSourceId]);
   2839 
   2840   // After Abort(), parsing should no longer be in the middle of a media
   2841   // segment.
   2842   ASSERT_FALSE(demuxer_->IsParsingMediaSegment(kSourceId));
   2843 }
   2844 
   2845 #if defined(USE_PROPRIETARY_CODECS)
   2846 #if defined(ENABLE_MPEG2TS_STREAM_PARSER)
   2847 TEST_F(ChunkDemuxerTest, EmitBuffersDuringAbort) {
   2848   EXPECT_CALL(*this, DemuxerOpened());
   2849   demuxer_->Initialize(
   2850       &host_, CreateInitDoneCB(kInfiniteDuration(), PIPELINE_OK), true);
   2851   EXPECT_EQ(ChunkDemuxer::kOk, AddIdForMp2tSource(kSourceId));
   2852 
   2853   // For info:
   2854   // DTS/PTS derived using dvbsnoop -s ts -if bear-1280x720.ts -tssubdecode
   2855   // Video: first PES:
   2856   //        PTS: 126912 (0x0001efc0)  [= 90 kHz-Timestamp: 0:00:01.4101]
   2857   //        DTS: 123909 (0x0001e405)  [= 90 kHz-Timestamp: 0:00:01.3767]
   2858   // Audio: first PES:
   2859   //        PTS: 126000 (0x0001ec30)  [= 90 kHz-Timestamp: 0:00:01.4000]
   2860   //        DTS: 123910 (0x0001e406)  [= 90 kHz-Timestamp: 0:00:01.3767]
   2861   // Video: last PES:
   2862   //        PTS: 370155 (0x0005a5eb)  [= 90 kHz-Timestamp: 0:00:04.1128]
   2863   //        DTS: 367152 (0x00059a30)  [= 90 kHz-Timestamp: 0:00:04.0794]
   2864   // Audio: last PES:
   2865   //        PTS: 353788 (0x000565fc)  [= 90 kHz-Timestamp: 0:00:03.9309]
   2866 
   2867   scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile("bear-1280x720.ts");
   2868   AppendData(kSourceId, buffer->data(), buffer->data_size());
   2869 
   2870   // Confirm we're in the middle of parsing a media segment.
   2871   ASSERT_TRUE(demuxer_->IsParsingMediaSegment(kSourceId));
   2872 
   2873   // Abort on the Mpeg2 TS parser triggers the emission of the last video
   2874   // buffer which is pending in the stream parser.
   2875   Ranges<base::TimeDelta> range_before_abort =
   2876       demuxer_->GetBufferedRanges(kSourceId);
   2877   demuxer_->Abort(kSourceId,
   2878                   append_window_start_for_next_append_,
   2879                   append_window_end_for_next_append_,
   2880                   &timestamp_offset_map_[kSourceId]);
   2881   Ranges<base::TimeDelta> range_after_abort =
   2882       demuxer_->GetBufferedRanges(kSourceId);
   2883 
   2884   ASSERT_EQ(range_before_abort.size(), 1u);
   2885   ASSERT_EQ(range_after_abort.size(), 1u);
   2886   EXPECT_EQ(range_after_abort.start(0), range_before_abort.start(0));
   2887   EXPECT_GT(range_after_abort.end(0), range_before_abort.end(0));
   2888 }
   2889 #endif
   2890 #endif
   2891 
   2892 TEST_F(ChunkDemuxerTest, WebMIsParsingMediaSegmentDetection) {
   2893   const uint8 kBuffer[] = {
   2894     0x1F, 0x43, 0xB6, 0x75, 0x83,  // CLUSTER (size = 3)
   2895     0xE7, 0x81, 0x01,                // Cluster TIMECODE (value = 1)
   2896 
   2897     0x1F, 0x43, 0xB6, 0x75, 0xFF,  // CLUSTER (size = unknown; really 3 due to:)
   2898     0xE7, 0x81, 0x02,                // Cluster TIMECODE (value = 2)
   2899     /* e.g. put some blocks here... */
   2900     0x1A, 0x45, 0xDF, 0xA3, 0x8A,  // EBMLHEADER (size = 10, not fully appended)
   2901   };
   2902 
   2903   // This array indicates expected return value of IsParsingMediaSegment()
   2904   // following each incrementally appended byte in |kBuffer|.
   2905   const bool kExpectedReturnValues[] = {
   2906     false, false, false, false, true,
   2907     true, true, false,
   2908 
   2909     false, false, false, false, true,
   2910     true, true, true,
   2911 
   2912     true, true, true, true, false,
   2913   };
   2914 
   2915   COMPILE_ASSERT(arraysize(kBuffer) == arraysize(kExpectedReturnValues),
   2916       test_arrays_out_of_sync);
   2917   COMPILE_ASSERT(arraysize(kBuffer) == sizeof(kBuffer), not_one_byte_per_index);
   2918 
   2919   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   2920 
   2921   for (size_t i = 0; i < sizeof(kBuffer); i++) {
   2922     DVLOG(3) << "Appending and testing index " << i;
   2923     AppendData(kBuffer + i, 1);
   2924     bool expected_return_value = kExpectedReturnValues[i];
   2925     EXPECT_EQ(expected_return_value,
   2926               demuxer_->IsParsingMediaSegment(kSourceId));
   2927   }
   2928 }
   2929 
   2930 TEST_F(ChunkDemuxerTest, DurationChange) {
   2931   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   2932   const int kStreamDuration = kDefaultDuration().InMilliseconds();
   2933 
   2934   // Add data leading up to the currently set duration.
   2935   AppendCluster(GenerateCluster(kStreamDuration - kAudioBlockDuration,
   2936                                 kStreamDuration - kVideoBlockDuration,
   2937                                 2));
   2938 
   2939   CheckExpectedRanges(kSourceId, "{ [201191,201224) }");
   2940 
   2941   // Add data beginning at the currently set duration and expect a new duration
   2942   // to be signaled. Note that the last video block will have a higher end
   2943   // timestamp than the last audio block.
   2944   const int kNewStreamDurationVideo = kStreamDuration + kVideoBlockDuration;
   2945   EXPECT_CALL(host_, SetDuration(
   2946       base::TimeDelta::FromMilliseconds(kNewStreamDurationVideo)));
   2947   AppendCluster(GenerateCluster(kDefaultDuration().InMilliseconds(), 2));
   2948 
   2949   CheckExpectedRanges(kSourceId, "{ [201191,201247) }");
   2950 
   2951   // Add more data to the end of each media type. Note that the last audio block
   2952   // will have a higher end timestamp than the last video block.
   2953   const int kFinalStreamDuration = kStreamDuration + kAudioBlockDuration * 3;
   2954   EXPECT_CALL(host_, SetDuration(
   2955       base::TimeDelta::FromMilliseconds(kFinalStreamDuration)));
   2956   AppendCluster(GenerateCluster(kStreamDuration + kAudioBlockDuration,
   2957                                 kStreamDuration + kVideoBlockDuration,
   2958                                 3));
   2959 
   2960   // See that the range has increased appropriately (but not to the full
   2961   // duration of 201293, since there is not enough video appended for that).
   2962   CheckExpectedRanges(kSourceId, "{ [201191,201290) }");
   2963 }
   2964 
   2965 TEST_F(ChunkDemuxerTest, DurationChangeTimestampOffset) {
   2966   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   2967   ASSERT_TRUE(SetTimestampOffset(kSourceId, kDefaultDuration()));
   2968   EXPECT_CALL(host_, SetDuration(
   2969       kDefaultDuration() + base::TimeDelta::FromMilliseconds(
   2970           kVideoBlockDuration * 2)));
   2971   AppendCluster(GenerateCluster(0, 4));
   2972 }
   2973 
   2974 TEST_F(ChunkDemuxerTest, EndOfStreamTruncateDuration) {
   2975   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   2976 
   2977   AppendCluster(kDefaultFirstCluster());
   2978 
   2979   EXPECT_CALL(host_, SetDuration(
   2980       base::TimeDelta::FromMilliseconds(kDefaultFirstClusterEndTimestamp)));
   2981   MarkEndOfStream(PIPELINE_OK);
   2982 }
   2983 
   2984 
   2985 TEST_F(ChunkDemuxerTest, ZeroLengthAppend) {
   2986   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   2987   AppendData(NULL, 0);
   2988 }
   2989 
   2990 TEST_F(ChunkDemuxerTest, AppendAfterEndOfStream) {
   2991   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   2992 
   2993   EXPECT_CALL(host_, SetDuration(_))
   2994       .Times(AnyNumber());
   2995 
   2996   AppendCluster(kDefaultFirstCluster());
   2997   MarkEndOfStream(PIPELINE_OK);
   2998 
   2999   demuxer_->UnmarkEndOfStream();
   3000 
   3001   AppendCluster(kDefaultSecondCluster());
   3002   MarkEndOfStream(PIPELINE_OK);
   3003 }
   3004 
   3005 // Test receiving a Shutdown() call before we get an Initialize()
   3006 // call. This can happen if video element gets destroyed before
   3007 // the pipeline has a chance to initialize the demuxer.
   3008 TEST_F(ChunkDemuxerTest, Shutdown_BeforeInitialize) {
   3009   demuxer_->Shutdown();
   3010   demuxer_->Initialize(
   3011       &host_, CreateInitDoneCB(DEMUXER_ERROR_COULD_NOT_OPEN), true);
   3012   message_loop_.RunUntilIdle();
   3013 }
   3014 
   3015 // Verifies that signaling end of stream while stalled at a gap
   3016 // boundary does not trigger end of stream buffers to be returned.
   3017 TEST_F(ChunkDemuxerTest, EndOfStreamWhileWaitingForGapToBeFilled) {
   3018   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   3019 
   3020   AppendCluster(0, 10);
   3021   AppendCluster(300, 10);
   3022   CheckExpectedRanges(kSourceId, "{ [0,132) [300,432) }");
   3023 
   3024   GenerateExpectedReads(0, 10);
   3025 
   3026   bool audio_read_done = false;
   3027   bool video_read_done = false;
   3028   ReadAudio(base::Bind(&OnReadDone,
   3029                        base::TimeDelta::FromMilliseconds(138),
   3030                        &audio_read_done));
   3031   ReadVideo(base::Bind(&OnReadDone,
   3032                        base::TimeDelta::FromMilliseconds(138),
   3033                        &video_read_done));
   3034 
   3035   // Verify that the reads didn't complete
   3036   EXPECT_FALSE(audio_read_done);
   3037   EXPECT_FALSE(video_read_done);
   3038 
   3039   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(438)));
   3040   MarkEndOfStream(PIPELINE_OK);
   3041 
   3042   // Verify that the reads still haven't completed.
   3043   EXPECT_FALSE(audio_read_done);
   3044   EXPECT_FALSE(video_read_done);
   3045 
   3046   demuxer_->UnmarkEndOfStream();
   3047 
   3048   AppendCluster(138, 22);
   3049 
   3050   message_loop_.RunUntilIdle();
   3051 
   3052   CheckExpectedRanges(kSourceId, "{ [0,435) }");
   3053 
   3054   // Verify that the reads have completed.
   3055   EXPECT_TRUE(audio_read_done);
   3056   EXPECT_TRUE(video_read_done);
   3057 
   3058   // Read the rest of the buffers.
   3059   GenerateExpectedReads(161, 171, 20);
   3060 
   3061   // Verify that reads block because the append cleared the end of stream state.
   3062   audio_read_done = false;
   3063   video_read_done = false;
   3064   ReadAudio(base::Bind(&OnReadDone_EOSExpected,
   3065                        &audio_read_done));
   3066   ReadVideo(base::Bind(&OnReadDone_EOSExpected,
   3067                        &video_read_done));
   3068 
   3069   // Verify that the reads don't complete.
   3070   EXPECT_FALSE(audio_read_done);
   3071   EXPECT_FALSE(video_read_done);
   3072 
   3073   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(437)));
   3074   MarkEndOfStream(PIPELINE_OK);
   3075 
   3076   EXPECT_TRUE(audio_read_done);
   3077   EXPECT_TRUE(video_read_done);
   3078 }
   3079 
   3080 TEST_F(ChunkDemuxerTest, CanceledSeekDuringInitialPreroll) {
   3081   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   3082 
   3083   // Cancel preroll.
   3084   base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(200);
   3085   demuxer_->CancelPendingSeek(seek_time);
   3086 
   3087   // Initiate the seek to the new location.
   3088   Seek(seek_time);
   3089 
   3090   // Append data to satisfy the seek.
   3091   AppendCluster(seek_time.InMilliseconds(), 10);
   3092 }
   3093 
   3094 TEST_F(ChunkDemuxerTest, GCDuringSeek) {
   3095   ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
   3096 
   3097   demuxer_->SetMemoryLimitsForTesting(5 * kBlockSize);
   3098 
   3099   base::TimeDelta seek_time1 = base::TimeDelta::FromMilliseconds(1000);
   3100   base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(500);
   3101 
   3102   // Initiate a seek to |seek_time1|.
   3103   Seek(seek_time1);
   3104 
   3105   // Append data to satisfy the first seek request.
   3106   AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
   3107                             seek_time1.InMilliseconds(), 5);
   3108   CheckExpectedRanges(kSourceId, "{ [1000,1115) }");
   3109 
   3110   // Signal that the second seek is starting.
   3111   demuxer_->StartWaitingForSeek(seek_time2);
   3112 
   3113   // Append data to satisfy the second seek. This append triggers
   3114   // the garbage collection logic since we set the memory limit to
   3115   // 5 blocks.
   3116   AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
   3117                             seek_time2.InMilliseconds(), 5);
   3118 
   3119   // Verify that the buffers that cover |seek_time2| do not get
   3120   // garbage collected.
   3121   CheckExpectedRanges(kSourceId, "{ [500,615) }");
   3122 
   3123   // Complete the seek.
   3124   demuxer_->Seek(seek_time2, NewExpectedStatusCB(PIPELINE_OK));
   3125 
   3126 
   3127   // Append more data and make sure that the blocks for |seek_time2|
   3128   // don't get removed.
   3129   //
   3130   // NOTE: The current GC algorithm tries to preserve the GOP at the
   3131   //  current position as well as the last appended GOP. This is
   3132   //  why there are 2 ranges in the expectations.
   3133   AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 700, 5);
   3134   CheckExpectedRanges(kSourceId, "{ [500,592) [792,815) }");
   3135 }
   3136 
   3137 TEST_F(ChunkDemuxerTest, AppendWindow_Video) {
   3138   ASSERT_TRUE(InitDemuxer(HAS_VIDEO));
   3139   DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
   3140 
   3141   // Set the append window to [50,280).
   3142   append_window_start_for_next_append_ = base::TimeDelta::FromMilliseconds(50);
   3143   append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(280);
   3144 
   3145   // Append a cluster that starts before and ends after the append window.
   3146   AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
   3147                             "0K 30 60 90 120K 150 180 210 240K 270 300 330K");
   3148 
   3149   // Verify that GOPs that start outside the window are not included
   3150   // in the buffer. Also verify that buffers that start inside the
   3151   // window and extend beyond the end of the window are not included.
   3152   CheckExpectedRanges(kSourceId, "{ [120,270) }");
   3153   CheckExpectedBuffers(stream, "120 150 180 210 240");
   3154 
   3155   // Extend the append window to [50,650).
   3156   append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(650);
   3157 
   3158   // Append more data and verify that adding buffers start at the next
   3159   // keyframe.
   3160   AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
   3161                             "360 390 420K 450 480 510 540K 570 600 630K");
   3162   CheckExpectedRanges(kSourceId, "{ [120,270) [420,630) }");
   3163 }
   3164 
   3165 TEST_F(ChunkDemuxerTest, AppendWindow_Audio) {
   3166   ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
   3167   DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::AUDIO);
   3168 
   3169   // Set the append window to [50,280).
   3170   append_window_start_for_next_append_ = base::TimeDelta::FromMilliseconds(50);
   3171   append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(280);
   3172 
   3173   // Append a cluster that starts before and ends after the append window.
   3174   AppendSingleStreamCluster(
   3175       kSourceId, kAudioTrackNum,
   3176       "0K 30K 60K 90K 120K 150K 180K 210K 240K 270K 300K 330K");
   3177 
   3178   // Verify that frames that end outside the window are not included
   3179   // in the buffer. Also verify that buffers that start inside the
   3180   // window and extend beyond the end of the window are not included.
   3181   //
   3182   // The first 50ms of the range should be truncated since it overlaps
   3183   // the start of the append window.
   3184   CheckExpectedRanges(kSourceId, "{ [50,270) }");
   3185 
   3186   // The "50P" buffer is the "0" buffer marked for complete discard.  The next
   3187   // "50" buffer is the "30" buffer marked with 20ms of start discard.
   3188   CheckExpectedBuffers(stream, "50P 50 60 90 120 150 180 210 240");
   3189 
   3190   // Extend the append window to [50,650).
   3191   append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(650);
   3192 
   3193   // Append more data and verify that a new range is created.
   3194   AppendSingleStreamCluster(
   3195       kSourceId, kAudioTrackNum,
   3196       "360K 390K 420K 450K 480K 510K 540K 570K 600K 630K");
   3197   CheckExpectedRanges(kSourceId, "{ [50,270) [360,630) }");
   3198 }
   3199 
   3200 TEST_F(ChunkDemuxerTest, AppendWindow_AudioOverlapStartAndEnd) {
   3201   ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
   3202 
   3203   // Set the append window to [10,20).
   3204   append_window_start_for_next_append_ = base::TimeDelta::FromMilliseconds(10);
   3205   append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(20);
   3206 
   3207   // Append a cluster that starts before and ends after the append window.
   3208   AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "0K");
   3209 
   3210   // Verify that everything is dropped in this case.  No partial append should
   3211   // be generated.
   3212   CheckExpectedRanges(kSourceId, "{ }");
   3213 }
   3214 
   3215 TEST_F(ChunkDemuxerTest, AppendWindow_WebMFile_AudioOnly) {
   3216   EXPECT_CALL(*this, DemuxerOpened());
   3217   demuxer_->Initialize(
   3218       &host_,
   3219       CreateInitDoneCB(base::TimeDelta::FromMilliseconds(2744), PIPELINE_OK),
   3220       true);
   3221   ASSERT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, HAS_AUDIO));
   3222 
   3223   // Set the append window to [50,150).
   3224   append_window_start_for_next_append_ = base::TimeDelta::FromMilliseconds(50);
   3225   append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(150);
   3226 
   3227   // Read a WebM file into memory and send the data to the demuxer.  The chunk
   3228   // size has been chosen carefully to ensure the preroll buffer used by the
   3229   // partial append window trim must come from a previous Append() call.
   3230   scoped_refptr<DecoderBuffer> buffer =
   3231       ReadTestDataFile("bear-320x240-audio-only.webm");
   3232   AppendDataInPieces(buffer->data(), buffer->data_size(), 128);
   3233 
   3234   DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::AUDIO);
   3235   CheckExpectedBuffers(stream, "50P 50 62 86 109 122 125 128");
   3236 }
   3237 
   3238 TEST_F(ChunkDemuxerTest, AppendWindow_AudioConfigUpdateRemovesPreroll) {
   3239   EXPECT_CALL(*this, DemuxerOpened());
   3240   demuxer_->Initialize(
   3241       &host_,
   3242       CreateInitDoneCB(base::TimeDelta::FromMilliseconds(2744), PIPELINE_OK),
   3243       true);
   3244   ASSERT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, HAS_AUDIO));
   3245 
   3246   // Set the append window such that the first file is completely before the
   3247   // append window.
   3248   // TODO(wolenetz/acolwell): Update this duration once the files are fixed to
   3249   // have the correct duration in their init segments, and the
   3250   // CreateInitDoneCB() call, above, is fixed to used that duration. See
   3251   // http://crbug.com/354284.
   3252   const base::TimeDelta duration_1 = base::TimeDelta::FromMilliseconds(2746);
   3253   append_window_start_for_next_append_ = duration_1;
   3254 
   3255   // Read a WebM file into memory and append the data.
   3256   scoped_refptr<DecoderBuffer> buffer =
   3257       ReadTestDataFile("bear-320x240-audio-only.webm");
   3258   AppendDataInPieces(buffer->data(), buffer->data_size(), 512);
   3259   CheckExpectedRanges(kSourceId, "{ }");
   3260 
   3261   DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::AUDIO);
   3262   AudioDecoderConfig config_1 = stream->audio_decoder_config();
   3263 
   3264   // Read a second WebM with a different config in and append the data.
   3265   scoped_refptr<DecoderBuffer> buffer2 =
   3266       ReadTestDataFile("bear-320x240-audio-only-48khz.webm");
   3267   EXPECT_CALL(host_, SetDuration(_)).Times(AnyNumber());
   3268   ASSERT_TRUE(SetTimestampOffset(kSourceId, duration_1));
   3269   AppendDataInPieces(buffer2->data(), buffer2->data_size(), 512);
   3270   CheckExpectedRanges(kSourceId, "{ [2746,5519) }");
   3271 
   3272   Seek(duration_1);
   3273   ExpectConfigChanged(DemuxerStream::AUDIO);
   3274   ASSERT_FALSE(config_1.Matches(stream->audio_decoder_config()));
   3275   CheckExpectedBuffers(stream, "2746 2767 2789 2810");
   3276 }
   3277 
   3278 TEST_F(ChunkDemuxerTest, AppendWindow_Text) {
   3279   DemuxerStream* text_stream = NULL;
   3280   EXPECT_CALL(host_, AddTextStream(_, _))
   3281       .WillOnce(SaveArg<0>(&text_stream));
   3282   ASSERT_TRUE(InitDemuxer(HAS_VIDEO | HAS_TEXT));
   3283   DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
   3284 
   3285   // Set the append window to [20,280).
   3286   append_window_start_for_next_append_ = base::TimeDelta::FromMilliseconds(20);
   3287   append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(280);
   3288 
   3289   // Append a cluster that starts before and ends after the append
   3290   // window.
   3291   AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
   3292                             "0K 30 60 90 120K 150 180 210 240K 270 300 330K");
   3293   AppendSingleStreamCluster(kSourceId, kTextTrackNum, "0K 100K 200K 300K");
   3294 
   3295   // Verify that text cues that start outside the window are not included
   3296   // in the buffer. Also verify that cues that extend beyond the
   3297   // window are not included.
   3298   CheckExpectedRanges(kSourceId, "{ [120,270) }");
   3299   CheckExpectedBuffers(video_stream, "120 150 180 210 240");
   3300   CheckExpectedBuffers(text_stream, "100");
   3301 
   3302   // Extend the append window to [20,650).
   3303   append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(650);
   3304 
   3305   // Append more data and verify that a new range is created.
   3306   AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
   3307                             "360 390 420K 450 480 510 540K 570 600 630K");
   3308   AppendSingleStreamCluster(kSourceId, kTextTrackNum, "400K 500K 600K 700K");
   3309   CheckExpectedRanges(kSourceId, "{ [120,270) [420,630) }");
   3310 
   3311   // Seek to the new range and verify that the expected buffers are returned.
   3312   Seek(base::TimeDelta::FromMilliseconds(420));
   3313   CheckExpectedBuffers(video_stream, "420 450 480 510 540 570 600");
   3314   CheckExpectedBuffers(text_stream, "400 500");
   3315 }
   3316 
   3317 TEST_F(ChunkDemuxerTest, StartWaitingForSeekAfterParseError) {
   3318   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   3319   EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
   3320   AppendGarbage();
   3321   base::TimeDelta seek_time = base::TimeDelta::FromSeconds(50);
   3322   demuxer_->StartWaitingForSeek(seek_time);
   3323 }
   3324 
   3325 TEST_F(ChunkDemuxerTest, Remove_AudioVideoText) {
   3326   DemuxerStream* text_stream = NULL;
   3327   EXPECT_CALL(host_, AddTextStream(_, _))
   3328       .WillOnce(SaveArg<0>(&text_stream));
   3329   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT));
   3330 
   3331   DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO);
   3332   DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
   3333 
   3334   AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
   3335                             "0K 20K 40K 60K 80K 100K 120K 140K");
   3336   AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
   3337                             "0K 30 60 90 120K 150 180");
   3338   AppendSingleStreamCluster(kSourceId, kTextTrackNum, "0K 100K 200K");
   3339 
   3340   CheckExpectedBuffers(audio_stream, "0 20 40 60 80 100 120 140");
   3341   CheckExpectedBuffers(video_stream, "0 30 60 90 120 150 180");
   3342   CheckExpectedBuffers(text_stream, "0 100 200");
   3343 
   3344   // Remove the buffers that were added.
   3345   demuxer_->Remove(kSourceId, base::TimeDelta(),
   3346                    base::TimeDelta::FromMilliseconds(300));
   3347 
   3348   // Verify that all the appended data has been removed.
   3349   CheckExpectedRanges(kSourceId, "{ }");
   3350 
   3351   // Append new buffers that are clearly different than the original
   3352   // ones and verify that only the new buffers are returned.
   3353   AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
   3354                             "1K 21K 41K 61K 81K 101K 121K 141K");
   3355   AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
   3356                             "1K 31 61 91 121K 151 181");
   3357   AppendSingleStreamCluster(kSourceId, kTextTrackNum, "1K 101K 201K");
   3358 
   3359   Seek(base::TimeDelta());
   3360   CheckExpectedBuffers(audio_stream, "1 21 41 61 81 101 121 141");
   3361   CheckExpectedBuffers(video_stream, "1 31 61 91 121 151 181");
   3362   CheckExpectedBuffers(text_stream, "1 101 201");
   3363 }
   3364 
   3365 TEST_F(ChunkDemuxerTest, Remove_StartAtDuration) {
   3366   ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
   3367   DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO);
   3368 
   3369   // Set the duration to something small so that the append that
   3370   // follows updates the duration to reflect the end of the appended data.
   3371   EXPECT_CALL(host_, SetDuration(
   3372       base::TimeDelta::FromMilliseconds(1)));
   3373   demuxer_->SetDuration(0.001);
   3374 
   3375   EXPECT_CALL(host_, SetDuration(
   3376       base::TimeDelta::FromMilliseconds(160)));
   3377   AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
   3378                             "0K 20K 40K 60K 80K 100K 120K 140K");
   3379 
   3380   CheckExpectedRanges(kSourceId, "{ [0,160) }");
   3381   CheckExpectedBuffers(audio_stream, "0 20 40 60 80 100 120 140");
   3382 
   3383   demuxer_->Remove(kSourceId,
   3384                    base::TimeDelta::FromSecondsD(demuxer_->GetDuration()),
   3385                    kInfiniteDuration());
   3386 
   3387   Seek(base::TimeDelta());
   3388   CheckExpectedRanges(kSourceId, "{ [0,160) }");
   3389   CheckExpectedBuffers(audio_stream, "0 20 40 60 80 100 120 140");
   3390 }
   3391 
   3392 // Verifies that a Seek() will complete without text cues for
   3393 // the seek point and will return cues after the seek position
   3394 // when they are eventually appended.
   3395 TEST_F(ChunkDemuxerTest, SeekCompletesWithoutTextCues) {
   3396   DemuxerStream* text_stream = NULL;
   3397   EXPECT_CALL(host_, AddTextStream(_, _))
   3398       .WillOnce(SaveArg<0>(&text_stream));
   3399   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT));
   3400 
   3401   DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO);
   3402   DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
   3403 
   3404   base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(120);
   3405   bool seek_cb_was_called = false;
   3406   demuxer_->StartWaitingForSeek(seek_time);
   3407   demuxer_->Seek(seek_time,
   3408                  base::Bind(OnSeekDone_OKExpected, &seek_cb_was_called));
   3409   message_loop_.RunUntilIdle();
   3410 
   3411   EXPECT_FALSE(seek_cb_was_called);
   3412 
   3413   bool text_read_done = false;
   3414   text_stream->Read(base::Bind(&OnReadDone,
   3415                                base::TimeDelta::FromMilliseconds(125),
   3416                                &text_read_done));
   3417 
   3418   // Append audio & video data so the seek completes.
   3419   AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
   3420                             "0K 20K 40K 60K 80K 100K 120K 140K 160K 180K");
   3421   AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
   3422                             "0K 30 60 90 120K 150 180 210");
   3423 
   3424   message_loop_.RunUntilIdle();
   3425   EXPECT_TRUE(seek_cb_was_called);
   3426   EXPECT_FALSE(text_read_done);
   3427 
   3428   // Read some audio & video buffers to further verify seek completion.
   3429   CheckExpectedBuffers(audio_stream, "120 140");
   3430   CheckExpectedBuffers(video_stream, "120 150");
   3431 
   3432   EXPECT_FALSE(text_read_done);
   3433 
   3434   // Append text cues that start after the seek point and verify that
   3435   // they are returned by Read() calls.
   3436   AppendSingleStreamCluster(kSourceId, kTextTrackNum, "125K 175K 225K");
   3437 
   3438   message_loop_.RunUntilIdle();
   3439   EXPECT_TRUE(text_read_done);
   3440 
   3441   // NOTE: we start at 175 here because the buffer at 125 was returned
   3442   // to the pending read initiated above.
   3443   CheckExpectedBuffers(text_stream, "175 225");
   3444 
   3445   // Verify that audio & video streams continue to return expected values.
   3446   CheckExpectedBuffers(audio_stream, "160 180");
   3447   CheckExpectedBuffers(video_stream, "180 210");
   3448 }
   3449 
   3450 TEST_F(ChunkDemuxerTest, ClusterWithUnknownSize) {
   3451   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   3452 
   3453   AppendCluster(GenerateCluster(0, 0, 4, true));
   3454   CheckExpectedRanges(kSourceId, "{ [0,46) }");
   3455 
   3456   // A new cluster indicates end of the previous cluster with unknown size.
   3457   AppendCluster(GenerateCluster(46, 66, 5, true));
   3458   CheckExpectedRanges(kSourceId, "{ [0,115) }");
   3459 }
   3460 
   3461 TEST_F(ChunkDemuxerTest, CuesBetweenClustersWithUnknownSize) {
   3462   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   3463 
   3464   // Add two clusters separated by Cues in a single Append() call.
   3465   scoped_ptr<Cluster> cluster = GenerateCluster(0, 0, 4, true);
   3466   std::vector<uint8> data(cluster->data(), cluster->data() + cluster->size());
   3467   data.insert(data.end(), kCuesHeader, kCuesHeader + sizeof(kCuesHeader));
   3468   cluster = GenerateCluster(46, 66, 5, true);
   3469   data.insert(data.end(), cluster->data(), cluster->data() + cluster->size());
   3470   AppendData(&*data.begin(), data.size());
   3471 
   3472   CheckExpectedRanges(kSourceId, "{ [0,115) }");
   3473 }
   3474 
   3475 TEST_F(ChunkDemuxerTest, CuesBetweenClusters) {
   3476   ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
   3477 
   3478   AppendCluster(GenerateCluster(0, 0, 4));
   3479   AppendData(kCuesHeader, sizeof(kCuesHeader));
   3480   AppendCluster(GenerateCluster(46, 66, 5));
   3481   CheckExpectedRanges(kSourceId, "{ [0,115) }");
   3482 }
   3483 
   3484 }  // namespace media
   3485