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
24using ::testing::AnyNumber;
25using ::testing::Exactly;
26using ::testing::InSequence;
27using ::testing::NotNull;
28using ::testing::Return;
29using ::testing::SaveArg;
30using ::testing::SetArgumentPointee;
31using ::testing::_;
32
33namespace media {
34
35const 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.
41const 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.
46const uint8 kVP8Interframe[] = { 0x11, 0x00, 0x00 };
47
48static const uint8 kCuesHeader[] = {
49  0x1C, 0x53, 0xBB, 0x6B,  // Cues ID
50  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // cues(size = 0)
51};
52
53const int kTracksHeaderSize = sizeof(kTracksHeader);
54const 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.
58const int kAudioTrackSizeOffset = 1;
59const int kAudioTrackSizeWidth = 8;
60const 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.
65const int kVideoTrackSizeOffset = 1;
66const int kVideoTrackSizeWidth = 8;
67const int kVideoTrackEntryHeaderSize =
68    kVideoTrackSizeOffset + kVideoTrackSizeWidth;
69
70const int kVideoTrackNum = 1;
71const int kAudioTrackNum = 2;
72const int kTextTrackNum = 3;
73const int kAlternateTextTrackNum = 4;
74
75const int kAudioBlockDuration = 23;
76const int kVideoBlockDuration = 33;
77const int kTextBlockDuration = 100;
78const int kBlockSize = 10;
79
80const char kSourceId[] = "SourceId";
81const char kDefaultFirstClusterRange[] = "{ [0,46) }";
82const int kDefaultFirstClusterEndTimestamp = 66;
83const int kDefaultSecondClusterEndTimestamp = 132;
84
85base::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.
92static 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
102MATCHER_P(HasTimestamp, timestamp_in_ms, "") {
103  return arg.get() && !arg->end_of_stream() &&
104         arg->timestamp().InMilliseconds() == timestamp_in_ms;
105}
106
107MATCHER(IsEndOfStream, "") { return arg.get() && arg->end_of_stream(); }
108
109static 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
118static 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
126static 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
134static void OnSeekDone_OKExpected(bool* called, PipelineStatus status) {
135  EXPECT_EQ(status, PIPELINE_OK);
136  *called = true;
137}
138
139static void LogFunc(const std::string& str) { DVLOG(1) << str; }
140
141class 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
1042TEST_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.
1115TEST_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
1183TEST_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
1228TEST_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.
1265TEST_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
1279TEST_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.
1298TEST_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.
1328TEST_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.
1350TEST_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.
1361TEST_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().
1391TEST_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.
1403TEST_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
1421TEST_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
1438TEST_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
1463TEST_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
1489TEST_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.
1509TEST_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.
1520TEST_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
1527TEST_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
1542TEST_F(ChunkDemuxerTest, EndOfStreamWithNoMediaAppend) {
1543  ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1544
1545  CheckExpectedRanges("{ }");
1546  MarkEndOfStream(PIPELINE_OK);
1547  CheckExpectedRanges("{ }");
1548}
1549
1550TEST_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
1561TEST_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.
1573class 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.
1621TEST_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.
1656TEST_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
1695TEST_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.
1726TEST_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.
1765TEST_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
1797TEST_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
1816TEST_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
1830TEST_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
1850TEST_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
1870TEST_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.
1885TEST_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
1938TEST_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
1953TEST_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
1967TEST_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
1981TEST_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
1994TEST_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
2008TEST_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
2028TEST_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.
2048TEST_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.
2077TEST_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
2086TEST_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
2116TEST_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.
2145TEST_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).
2202TEST_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.
2231TEST_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.
2267TEST_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.
2289TEST_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
2310TEST_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
2367TEST_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.
2394TEST_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
2452TEST_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
2470TEST_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
2488TEST_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
2509TEST_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
2521TEST_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.
2536TEST_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
2563TEST_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
2600TEST_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.
2612TEST_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
2637TEST_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
2684TEST_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
2728TEST_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
2775TEST_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
2786TEST_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
2795TEST_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
2825TEST_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)
2847TEST_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
2892TEST_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
2930TEST_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
2965TEST_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
2974TEST_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
2985TEST_F(ChunkDemuxerTest, ZeroLengthAppend) {
2986  ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2987  AppendData(NULL, 0);
2988}
2989
2990TEST_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.
3008TEST_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.
3017TEST_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
3080TEST_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
3094TEST_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
3137TEST_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
3165TEST_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
3200TEST_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
3215TEST_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
3238TEST_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
3278TEST_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
3317TEST_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
3325TEST_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
3365TEST_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.
3395TEST_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
3450TEST_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
3461TEST_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
3475TEST_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