chunk_demuxer_unittest.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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 "base/bind.h"
6#include "base/message_loop.h"
7#include "media/base/audio_decoder_config.h"
8#include "media/base/decoder_buffer.h"
9#include "media/base/mock_callback.h"
10#include "media/base/mock_demuxer_host.h"
11#include "media/base/test_data_util.h"
12#include "media/filters/chunk_demuxer.h"
13#include "media/webm/cluster_builder.h"
14#include "media/webm/webm_constants.h"
15#include "testing/gtest/include/gtest/gtest.h"
16
17using ::testing::AnyNumber;
18using ::testing::Exactly;
19using ::testing::InSequence;
20using ::testing::NotNull;
21using ::testing::Return;
22using ::testing::SaveArg;
23using ::testing::SetArgumentPointee;
24using ::testing::_;
25
26namespace media {
27
28static const uint8 kTracksHeader[] = {
29  0x16, 0x54, 0xAE, 0x6B,  // Tracks ID
30  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // tracks(size = 0)
31};
32
33static const int kTracksHeaderSize = sizeof(kTracksHeader);
34static const int kTracksSizeOffset = 4;
35
36// The size of TrackEntry element in test file "webm_vorbis_track_entry" starts
37// at index 1 and spans 8 bytes.
38static const int kAudioTrackSizeOffset = 1;
39static const int kAudioTrackSizeWidth = 8;
40static const int kAudioTrackEntryHeaderSize = kAudioTrackSizeOffset +
41                                              kAudioTrackSizeWidth;
42
43// The size of TrackEntry element in test file "webm_vp8_track_entry" starts at
44// index 1 and spans 8 bytes.
45static const int kVideoTrackSizeOffset = 1;
46static const int kVideoTrackSizeWidth = 8;
47static const int kVideoTrackEntryHeaderSize = kVideoTrackSizeOffset +
48                                              kVideoTrackSizeWidth;
49
50static const int kVideoTrackNum = 1;
51static const int kAudioTrackNum = 2;
52
53static const int kAudioBlockDuration = 23;
54static const int kVideoBlockDuration = 33;
55
56static const char* kSourceId = "SourceId";
57static const char* kDefaultFirstClusterRange = "{ [0,46) }";
58static const int kDefaultFirstClusterEndTimestamp = 66;
59static const int kDefaultSecondClusterEndTimestamp = 132;
60
61static const char kWebMInitDataType[] = "video/webm";
62
63base::TimeDelta kDefaultDuration() {
64  return base::TimeDelta::FromMilliseconds(201224);
65}
66
67// Write an integer into buffer in the form of vint that spans 8 bytes.
68// The data pointed by |buffer| should be at least 8 bytes long.
69// |number| should be in the range 0 <= number < 0x00FFFFFFFFFFFFFF.
70static void WriteInt64(uint8* buffer, int64 number) {
71  DCHECK(number >= 0 && number < GG_LONGLONG(0x00FFFFFFFFFFFFFF));
72  buffer[0] = 0x01;
73  int64 tmp = number;
74  for (int i = 7; i > 0; i--) {
75    buffer[i] = tmp & 0xff;
76    tmp >>= 8;
77  }
78}
79
80MATCHER_P(HasTimestamp, timestamp_in_ms, "") {
81  return arg && !arg->IsEndOfStream() &&
82      arg->GetTimestamp().InMilliseconds() == timestamp_in_ms;
83}
84
85MATCHER(IsEndOfStream, "") {
86  return arg && arg->IsEndOfStream();
87}
88
89static void OnReadDone(const base::TimeDelta& expected_time,
90                       bool* called,
91                       DemuxerStream::Status status,
92                       const scoped_refptr<DecoderBuffer>& buffer) {
93  EXPECT_EQ(status, DemuxerStream::kOk);
94  EXPECT_EQ(expected_time, buffer->GetTimestamp());
95  *called = true;
96}
97
98static void OnReadDone_AbortExpected(
99    bool* called, DemuxerStream::Status status,
100    const scoped_refptr<DecoderBuffer>& buffer) {
101  EXPECT_EQ(status, DemuxerStream::kAborted);
102  EXPECT_EQ(NULL, buffer.get());
103  *called = true;
104}
105
106static void OnReadDone_EOSExpected(bool* called,
107                                   DemuxerStream::Status status,
108                                   const scoped_refptr<DecoderBuffer>& buffer) {
109  EXPECT_EQ(status, DemuxerStream::kOk);
110  EXPECT_TRUE(buffer->IsEndOfStream());
111  *called = true;
112}
113
114static void StoreStatusAndBuffer(DemuxerStream::Status* status_out,
115                                 scoped_refptr<DecoderBuffer>* buffer_out,
116                                 DemuxerStream::Status status,
117                                 const scoped_refptr<DecoderBuffer>& buffer) {
118  *status_out = status;
119  *buffer_out = buffer;
120}
121
122static void ReadUntilNotOkOrEndOfStream(
123    const scoped_refptr<DemuxerStream>& stream,
124    DemuxerStream::Status* status,
125    base::TimeDelta* last_timestamp) {
126  scoped_refptr<DecoderBuffer> buffer;
127
128  *last_timestamp = kNoTimestamp();
129  do {
130    stream->Read(base::Bind(&StoreStatusAndBuffer, status, &buffer));
131    if (*status == DemuxerStream::kOk && !buffer->IsEndOfStream())
132      *last_timestamp = buffer->GetTimestamp();
133  } while (*status == DemuxerStream::kOk && !buffer->IsEndOfStream());
134}
135
136class ChunkDemuxerTest : public testing::Test {
137 protected:
138  enum CodecsIndex {
139    AUDIO,
140    VIDEO,
141    MAX_CODECS_INDEX
142  };
143
144  // Default cluster to append first for simple tests.
145  scoped_ptr<Cluster> kDefaultFirstCluster() {
146    return GenerateCluster(0, 4);
147  }
148
149  // Default cluster to append after kDefaultFirstCluster()
150  // has been appended. This cluster starts with blocks that
151  // have timestamps consistent with the end times of the blocks
152  // in kDefaultFirstCluster() so that these two clusters represent
153  // a continuous region.
154  scoped_ptr<Cluster> kDefaultSecondCluster() {
155    return GenerateCluster(46, 66, 5);
156  }
157
158  ChunkDemuxerTest() {
159    CreateNewDemuxer();
160  }
161
162  void CreateNewDemuxer() {
163    base::Closure open_cb =
164        base::Bind(&ChunkDemuxerTest::DemuxerOpened, base::Unretained(this));
165    ChunkDemuxer::NeedKeyCB need_key_cb =
166        base::Bind(&ChunkDemuxerTest::DemuxerNeedKey, base::Unretained(this));
167    demuxer_ = new ChunkDemuxer(open_cb, need_key_cb);
168  }
169
170  virtual ~ChunkDemuxerTest() {
171    ShutdownDemuxer();
172  }
173
174  void CreateInitSegment(bool has_audio, bool has_video,
175                         bool is_audio_encrypted, bool is_video_encrypted,
176                         scoped_array<uint8>* buffer,
177                         int* size) {
178    scoped_refptr<DecoderBuffer> ebml_header;
179    scoped_refptr<DecoderBuffer> info;
180    scoped_refptr<DecoderBuffer> audio_track_entry;
181    scoped_refptr<DecoderBuffer> video_track_entry;
182    scoped_refptr<DecoderBuffer> audio_content_encodings;
183    scoped_refptr<DecoderBuffer> video_content_encodings;
184
185    ebml_header = ReadTestDataFile("webm_ebml_element");
186
187    info = ReadTestDataFile("webm_info_element");
188
189    int tracks_element_size = 0;
190
191    if (has_audio) {
192      audio_track_entry = ReadTestDataFile("webm_vorbis_track_entry");
193      tracks_element_size += audio_track_entry->GetDataSize();
194      if (is_audio_encrypted) {
195        audio_content_encodings = ReadTestDataFile("webm_content_encodings");
196        tracks_element_size += audio_content_encodings->GetDataSize();
197      }
198    }
199
200    if (has_video) {
201      video_track_entry = ReadTestDataFile("webm_vp8_track_entry");
202      tracks_element_size += video_track_entry->GetDataSize();
203      if (is_video_encrypted) {
204        video_content_encodings = ReadTestDataFile("webm_content_encodings");
205        tracks_element_size += video_content_encodings->GetDataSize();
206      }
207    }
208
209    *size = ebml_header->GetDataSize() + info->GetDataSize() +
210        kTracksHeaderSize + tracks_element_size;
211
212    buffer->reset(new uint8[*size]);
213
214    uint8* buf = buffer->get();
215    memcpy(buf, ebml_header->GetData(), ebml_header->GetDataSize());
216    buf += ebml_header->GetDataSize();
217
218    memcpy(buf, info->GetData(), info->GetDataSize());
219    buf += info->GetDataSize();
220
221    memcpy(buf, kTracksHeader, kTracksHeaderSize);
222    WriteInt64(buf + kTracksSizeOffset, tracks_element_size);
223    buf += kTracksHeaderSize;
224
225    // TODO(xhwang): Simplify this! Probably have test data files that contain
226    // ContentEncodings directly instead of trying to create one at run-time.
227    if (has_audio) {
228      memcpy(buf, audio_track_entry->GetData(),
229             audio_track_entry->GetDataSize());
230      if (is_audio_encrypted) {
231        memcpy(buf + audio_track_entry->GetDataSize(),
232               audio_content_encodings->GetData(),
233               audio_content_encodings->GetDataSize());
234        WriteInt64(buf + kAudioTrackSizeOffset,
235                   audio_track_entry->GetDataSize() +
236                   audio_content_encodings->GetDataSize() -
237                   kAudioTrackEntryHeaderSize);
238        buf += audio_content_encodings->GetDataSize();
239      }
240      buf += audio_track_entry->GetDataSize();
241    }
242
243    if (has_video) {
244      memcpy(buf, video_track_entry->GetData(),
245             video_track_entry->GetDataSize());
246      if (is_video_encrypted) {
247        memcpy(buf + video_track_entry->GetDataSize(),
248               video_content_encodings->GetData(),
249               video_content_encodings->GetDataSize());
250        WriteInt64(buf + kVideoTrackSizeOffset,
251                   video_track_entry->GetDataSize() +
252                   video_content_encodings->GetDataSize() -
253                   kVideoTrackEntryHeaderSize);
254        buf += video_content_encodings->GetDataSize();
255      }
256      buf += video_track_entry->GetDataSize();
257    }
258  }
259
260  ChunkDemuxer::Status AddId() {
261    return AddId(kSourceId, true, true);
262  }
263
264  ChunkDemuxer::Status AddId(const std::string& source_id,
265                             bool has_audio, bool has_video) {
266    std::vector<std::string> codecs;
267    std::string type;
268
269    if (has_audio) {
270      codecs.push_back("vorbis");
271      type = "audio/webm";
272    }
273
274    if (has_video) {
275      codecs.push_back("vp8");
276      type = "video/webm";
277    }
278
279    if (!has_audio && !has_video) {
280      return AddId(kSourceId, true, true);
281    }
282
283    return demuxer_->AddId(source_id, type, codecs);
284  }
285
286  bool AppendData(const uint8* data, size_t length) {
287    return AppendData(kSourceId, data, length);
288  }
289
290  bool AppendCluster(int timecode, int block_count) {
291    scoped_ptr<Cluster> cluster(GenerateCluster(timecode, block_count));
292    return AppendData(kSourceId, cluster->data(), cluster->size());
293  }
294
295  bool AppendData(const std::string& source_id,
296                  const uint8* data, size_t length) {
297    CHECK(length);
298    EXPECT_CALL(host_, AddBufferedTimeRange(_, _)).Times(AnyNumber());
299    return demuxer_->AppendData(source_id, data, length);
300  }
301
302  bool AppendDataInPieces(const uint8* data, size_t length) {
303    return AppendDataInPieces(data, length, 7);
304  }
305
306  bool AppendDataInPieces(const uint8* data, size_t length, size_t piece_size) {
307    const uint8* start = data;
308    const uint8* end = data + length;
309    while (start < end) {
310      size_t append_size = std::min(piece_size,
311                                    static_cast<size_t>(end - start));
312      if (!AppendData(start, append_size))
313        return false;
314      start += append_size;
315    }
316    return true;
317  }
318
319  bool AppendInitSegment(bool has_audio, bool has_video) {
320    return AppendInitSegmentWithSourceId(kSourceId, has_audio, has_video);
321  }
322
323  bool AppendInitSegmentWithSourceId(const std::string& source_id,
324                                     bool has_audio, bool has_video) {
325    return AppendInitSegmentWithEncryptedInfo(
326        source_id, has_audio, has_video, false, false);
327  }
328
329  bool AppendInitSegmentWithEncryptedInfo(const std::string& source_id,
330                                          bool has_audio, bool has_video,
331                                          bool is_audio_encrypted,
332                                          bool is_video_encrypted) {
333    scoped_array<uint8> info_tracks;
334    int info_tracks_size = 0;
335    CreateInitSegment(has_audio, has_video,
336                      is_audio_encrypted, is_video_encrypted,
337                      &info_tracks, &info_tracks_size);
338    return AppendData(source_id, info_tracks.get(), info_tracks_size);
339  }
340
341  bool AppendGarbage() {
342    // Fill up an array with gibberish.
343    int garbage_cluster_size = 10;
344    scoped_array<uint8> garbage_cluster(new uint8[garbage_cluster_size]);
345    for (int i = 0; i < garbage_cluster_size; ++i)
346      garbage_cluster[i] = i;
347    return AppendData(garbage_cluster.get(), garbage_cluster_size);
348  }
349
350  void InitDoneCalled(PipelineStatus expected_status,
351                      PipelineStatus status) {
352    EXPECT_EQ(status, expected_status);
353  }
354
355  bool AppendEmptyCluster(int timecode) {
356    scoped_ptr<Cluster> empty_cluster = GenerateEmptyCluster(timecode);
357    return AppendData(empty_cluster->data(), empty_cluster->size());
358  }
359
360  PipelineStatusCB CreateInitDoneCB(const base::TimeDelta& expected_duration,
361                                    PipelineStatus expected_status) {
362    if (expected_duration != kNoTimestamp())
363      EXPECT_CALL(host_, SetDuration(expected_duration));
364    return CreateInitDoneCB(expected_status);
365  }
366
367  PipelineStatusCB CreateInitDoneCB(PipelineStatus expected_status) {
368    return base::Bind(&ChunkDemuxerTest::InitDoneCalled,
369                      base::Unretained(this),
370                      expected_status);
371  }
372
373  bool InitDemuxer(bool has_audio, bool has_video) {
374    return InitDemuxerWithEncryptionInfo(has_audio, has_video, false, false);
375  }
376
377  bool InitDemuxerWithEncryptionInfo(
378      bool has_audio, bool has_video,
379      bool is_audio_encrypted, bool is_video_encrypted) {
380    PipelineStatus expected_status =
381        (has_audio || has_video) ? PIPELINE_OK : DEMUXER_ERROR_COULD_NOT_OPEN;
382
383    base::TimeDelta expected_duration = kNoTimestamp();
384    if (expected_status == PIPELINE_OK)
385      expected_duration = kDefaultDuration();
386
387    EXPECT_CALL(*this, DemuxerOpened());
388    demuxer_->Initialize(
389        &host_, CreateInitDoneCB(expected_duration, expected_status));
390
391    if (AddId(kSourceId, has_audio, has_video) != ChunkDemuxer::kOk)
392      return false;
393
394    return AppendInitSegmentWithEncryptedInfo(
395        kSourceId, has_audio, has_video,
396        is_audio_encrypted, is_video_encrypted);
397  }
398
399  bool InitDemuxerAudioAndVideoSources(const std::string& audio_id,
400                                       const std::string& video_id) {
401    EXPECT_CALL(*this, DemuxerOpened());
402    demuxer_->Initialize(
403        &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK));
404
405    if (AddId(audio_id, true, false) != ChunkDemuxer::kOk)
406      return false;
407    if (AddId(video_id, false, true) != ChunkDemuxer::kOk)
408      return false;
409
410    bool success = AppendInitSegmentWithSourceId(audio_id, true, false);
411    success &= AppendInitSegmentWithSourceId(video_id, false, true);
412    return success;
413  }
414
415  // Initializes the demuxer with data from 2 files with different
416  // decoder configurations. This is used to test the decoder config change
417  // logic.
418  //
419  // bear-320x240.webm VideoDecoderConfig returns 320x240 for its natural_size()
420  // bear-640x360.webm VideoDecoderConfig returns 640x360 for its natural_size()
421  // The resulting video stream returns data from each file for the following
422  // time ranges.
423  // bear-320x240.webm : [0-501)       [801-2737)
424  // bear-640x360.webm :       [527-793)
425  //
426  // bear-320x240.webm AudioDecoderConfig returns 3863 for its extra_data_size()
427  // bear-640x360.webm AudioDecoderConfig returns 3935 for its extra_data_size()
428  // The resulting audio stream returns data from each file for the following
429  // time ranges.
430  // bear-320x240.webm : [0-524)       [779-2737)
431  // bear-640x360.webm :       [527-759)
432  bool InitDemuxerWithConfigChangeData() {
433    scoped_refptr<DecoderBuffer> bear1 = ReadTestDataFile("bear-320x240.webm");
434    scoped_refptr<DecoderBuffer> bear2 = ReadTestDataFile("bear-640x360.webm");
435
436    EXPECT_CALL(*this, DemuxerOpened());
437    demuxer_->Initialize(
438        &host_, CreateInitDoneCB(base::TimeDelta::FromMilliseconds(2744),
439                                 PIPELINE_OK));
440
441    if (AddId(kSourceId, true, true) != ChunkDemuxer::kOk)
442      return false;
443
444    // Append the whole bear1 file.
445    if (!AppendData(bear1->GetData(), bear1->GetDataSize()))
446      return false;
447    CheckExpectedRanges(kSourceId, "{ [0,2737) }");
448
449    // Append initialization segment for bear2.
450    // Note: Offsets here and below are derived from
451    // media/test/data/bear-640x360-manifest.js and
452    // media/test/data/bear-320x240-manifest.js which were
453    // generated from media/test/data/bear-640x360.webm and
454    // media/test/data/bear-320x240.webm respectively.
455    if (!AppendData(bear2->GetData(), 4340))
456      return false;
457
458    // Append a media segment that goes from [0.527000, 1.014000).
459    if (!AppendData(bear2->GetData() + 55290, 18785))
460      return false;
461    CheckExpectedRanges(kSourceId, "{ [0,1028) [1201,2737) }");
462
463    // Append initialization segment for bear1 & fill gap with [779-1197)
464    // segment.
465    if (!AppendData(bear1->GetData(), 4370) ||
466        !AppendData(bear1->GetData() + 72737, 28183)) {
467      return false;
468    }
469    CheckExpectedRanges(kSourceId, "{ [0,2737) }");
470
471    return demuxer_->EndOfStream(PIPELINE_OK);
472  }
473
474  void ShutdownDemuxer() {
475    if (demuxer_)
476      demuxer_->Shutdown();
477  }
478
479  void AddSimpleBlock(ClusterBuilder* cb, int track_num, int64 timecode) {
480    uint8 data[] = { 0x00 };
481    cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data));
482  }
483
484  scoped_ptr<Cluster> GenerateCluster(int timecode, int block_count) {
485    return GenerateCluster(timecode, timecode, block_count);
486  }
487
488  scoped_ptr<Cluster> GenerateCluster(int first_audio_timecode,
489                                      int first_video_timecode,
490                                      int block_count) {
491    CHECK_GT(block_count, 0);
492
493    int size = 10;
494    scoped_array<uint8> data(new uint8[size]);
495
496    ClusterBuilder cb;
497    cb.SetClusterTimecode(std::min(first_audio_timecode, first_video_timecode));
498
499    if (block_count == 1) {
500      cb.AddBlockGroup(kAudioTrackNum, first_audio_timecode,
501                       kAudioBlockDuration, kWebMFlagKeyframe,
502                       data.get(), size);
503      return cb.Finish();
504    }
505
506    int audio_timecode = first_audio_timecode;
507    int video_timecode = first_video_timecode;
508
509    // Create simple blocks for everything except the last 2 blocks.
510    // The first video frame must be a keyframe.
511    uint8 video_flag = kWebMFlagKeyframe;
512    for (int i = 0; i < block_count - 2; i++) {
513      if (audio_timecode <= video_timecode) {
514        cb.AddSimpleBlock(kAudioTrackNum, audio_timecode, kWebMFlagKeyframe,
515                          data.get(), size);
516        audio_timecode += kAudioBlockDuration;
517        continue;
518      }
519
520      cb.AddSimpleBlock(kVideoTrackNum, video_timecode, video_flag, data.get(),
521                        size);
522      video_timecode += kVideoBlockDuration;
523      video_flag = 0;
524    }
525
526    // Make the last 2 blocks BlockGroups so that they don't get delayed by the
527    // block duration calculation logic.
528    if (audio_timecode <= video_timecode) {
529      cb.AddBlockGroup(kAudioTrackNum, audio_timecode, kAudioBlockDuration,
530                       kWebMFlagKeyframe, data.get(), size);
531      cb.AddBlockGroup(kVideoTrackNum, video_timecode, kVideoBlockDuration,
532                       video_flag, data.get(), size);
533    } else {
534      cb.AddBlockGroup(kVideoTrackNum, video_timecode, kVideoBlockDuration,
535                       video_flag, data.get(), size);
536      cb.AddBlockGroup(kAudioTrackNum, audio_timecode, kAudioBlockDuration,
537                       kWebMFlagKeyframe, data.get(), size);
538    }
539
540    return cb.Finish();
541  }
542
543  scoped_ptr<Cluster> GenerateSingleStreamCluster(int timecode,
544                                                  int end_timecode,
545                                                  int track_number,
546                                                  int block_duration) {
547    CHECK_GT(end_timecode, timecode);
548
549    int size = 10;
550    scoped_array<uint8> data(new uint8[size]);
551
552    ClusterBuilder cb;
553    cb.SetClusterTimecode(timecode);
554
555    // Create simple blocks for everything except the last block.
556    for (int i = 0; timecode < (end_timecode - block_duration); i++) {
557      cb.AddSimpleBlock(track_number, timecode, kWebMFlagKeyframe,
558                        data.get(), size);
559      timecode += block_duration;
560    }
561
562    // Make the last block a BlockGroup so that it doesn't get delayed by the
563    // block duration calculation logic.
564    cb.AddBlockGroup(track_number, timecode, block_duration,
565                      kWebMFlagKeyframe, data.get(), size);
566    return cb.Finish();
567  }
568
569  void GenerateExpectedReads(int timecode, int block_count,
570                             DemuxerStream* audio,
571                             DemuxerStream* video) {
572    GenerateExpectedReads(timecode, timecode, block_count, audio, video);
573  }
574
575  void GenerateExpectedReads(int start_audio_timecode,
576                             int start_video_timecode,
577                             int block_count, DemuxerStream* audio,
578                             DemuxerStream* video) {
579    CHECK_GT(block_count, 0);
580
581    if (block_count == 1) {
582      ExpectRead(audio, start_audio_timecode);
583      return;
584    }
585
586    int audio_timecode = start_audio_timecode;
587    int video_timecode = start_video_timecode;
588
589    for (int i = 0; i < block_count; i++) {
590      if (audio_timecode <= video_timecode) {
591        ExpectRead(audio, audio_timecode);
592        audio_timecode += kAudioBlockDuration;
593        continue;
594      }
595
596      ExpectRead(video, video_timecode);
597      video_timecode += kVideoBlockDuration;
598    }
599  }
600
601  void GenerateSingleStreamExpectedReads(
602      int timecode, int block_count, DemuxerStream* stream,
603      int block_duration) {
604    CHECK_GT(block_count, 0);
605    int stream_timecode = timecode;
606
607    for (int i = 0; i < block_count; i++) {
608      ExpectRead(stream, stream_timecode);
609      stream_timecode += block_duration;
610    }
611  }
612
613  scoped_ptr<Cluster> GenerateEmptyCluster(int timecode) {
614    ClusterBuilder cb;
615    cb.SetClusterTimecode(timecode);
616    return cb.Finish();
617  }
618
619  void CheckExpectedRanges(const std::string& expected) {
620    CheckExpectedRanges(kSourceId, expected);
621  }
622
623  void CheckExpectedRanges(const std::string&  id,
624                           const std::string& expected) {
625    Ranges<base::TimeDelta> r = demuxer_->GetBufferedRanges(id);
626
627    std::stringstream ss;
628    ss << "{ ";
629    for (size_t i = 0; i < r.size(); ++i) {
630      ss << "[" << r.start(i).InMilliseconds() << ","
631         << r.end(i).InMilliseconds() << ") ";
632    }
633    ss << "}";
634    EXPECT_EQ(ss.str(), expected);
635  }
636
637  MOCK_METHOD2(ReadDone, void(DemuxerStream::Status status,
638                              const scoped_refptr<DecoderBuffer>&));
639
640  void ExpectEndOfStream(DemuxerStream* stream) {
641    EXPECT_CALL(*this, ReadDone(DemuxerStream::kOk, IsEndOfStream()));
642    stream->Read(base::Bind(&ChunkDemuxerTest::ReadDone,
643                            base::Unretained(this)));
644  }
645
646  void ExpectRead(DemuxerStream* stream, int64 timestamp_in_ms) {
647    EXPECT_CALL(*this, ReadDone(DemuxerStream::kOk,
648                                HasTimestamp(timestamp_in_ms)));
649    stream->Read(base::Bind(&ChunkDemuxerTest::ReadDone,
650                            base::Unretained(this)));
651  }
652
653  void ExpectConfigChanged(DemuxerStream* stream) {
654    EXPECT_CALL(*this, ReadDone(DemuxerStream::kConfigChanged, _));
655    stream->Read(base::Bind(&ChunkDemuxerTest::ReadDone,
656                            base::Unretained(this)));
657  }
658
659  MOCK_METHOD1(Checkpoint, void(int id));
660
661  struct BufferTimestamps {
662    int video_time_ms;
663    int audio_time_ms;
664  };
665  static const int kSkip = -1;
666
667  // Test parsing a WebM file.
668  // |filename| - The name of the file in media/test/data to parse.
669  // |timestamps| - The expected timestamps on the parsed buffers.
670  //    a timestamp of kSkip indicates that a Read() call for that stream
671  //    shouldn't be made on that iteration of the loop. If both streams have
672  //    a kSkip then the loop will terminate.
673  bool ParseWebMFile(const std::string& filename,
674                     const BufferTimestamps* timestamps,
675                     const base::TimeDelta& duration) {
676    return ParseWebMFile(filename, timestamps, duration, true, true);
677  }
678
679  bool ParseWebMFile(const std::string& filename,
680                     const BufferTimestamps* timestamps,
681                     const base::TimeDelta& duration,
682                     bool has_audio, bool has_video) {
683    EXPECT_CALL(*this, DemuxerOpened());
684    demuxer_->Initialize(
685        &host_, CreateInitDoneCB(duration, PIPELINE_OK));
686
687    if (AddId(kSourceId, has_audio, has_video) != ChunkDemuxer::kOk)
688      return false;
689
690    // Read a WebM file into memory and send the data to the demuxer.
691    scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename);
692    if (!AppendDataInPieces(buffer->GetData(), buffer->GetDataSize(), 512))
693      return false;
694
695    scoped_refptr<DemuxerStream> audio =
696        demuxer_->GetStream(DemuxerStream::AUDIO);
697    scoped_refptr<DemuxerStream> video =
698        demuxer_->GetStream(DemuxerStream::VIDEO);
699
700    // Verify that the timestamps on the first few packets match what we
701    // expect.
702    for (size_t i = 0;
703         (timestamps[i].audio_time_ms != kSkip ||
704          timestamps[i].video_time_ms != kSkip);
705         i++) {
706      bool audio_read_done = false;
707      bool video_read_done = false;
708
709      if (timestamps[i].audio_time_ms != kSkip) {
710        DCHECK(audio);
711        audio->Read(base::Bind(&OnReadDone,
712                               base::TimeDelta::FromMilliseconds(
713                                   timestamps[i].audio_time_ms),
714                               &audio_read_done));
715        EXPECT_TRUE(audio_read_done);
716      }
717
718      if (timestamps[i].video_time_ms != kSkip) {
719        DCHECK(video);
720        video->Read(base::Bind(&OnReadDone,
721                               base::TimeDelta::FromMilliseconds(
722                                   timestamps[i].video_time_ms),
723                               &video_read_done));
724
725        EXPECT_TRUE(video_read_done);
726      }
727    }
728
729    return true;
730  }
731
732  MOCK_METHOD0(DemuxerOpened, void());
733  // TODO(xhwang): This is a workaround of the issue that move-only parameters
734  // are not supported in mocked methods. Remove this when the issue is fixed
735  // (http://code.google.com/p/googletest/issues/detail?id=395) or when we use
736  // std::string instead of scoped_array<uint8> (http://crbug.com/130689).
737  MOCK_METHOD3(NeedKeyMock, void(const std::string& type,
738                                 const uint8* init_data, int init_data_size));
739  void DemuxerNeedKey(const std::string& type,
740                      scoped_array<uint8> init_data, int init_data_size) {
741    NeedKeyMock(type, init_data.get(), init_data_size);
742  }
743
744  MessageLoop message_loop_;
745  MockDemuxerHost host_;
746
747  scoped_refptr<ChunkDemuxer> demuxer_;
748
749 private:
750  DISALLOW_COPY_AND_ASSIGN(ChunkDemuxerTest);
751};
752
753TEST_F(ChunkDemuxerTest, TestInit) {
754  // Test no streams, audio-only, video-only, and audio & video scenarios.
755  // Audio and video streams can be encrypted or not encrypted.
756  for (int i = 0; i < 16; i++) {
757    bool has_audio = (i & 0x1) != 0;
758    bool has_video = (i & 0x2) != 0;
759    bool is_audio_encrypted = (i & 0x4) != 0;
760    bool is_video_encrypted = (i & 0x8) != 0;
761
762    // No test on invalid combination.
763    if ((!has_audio && is_audio_encrypted) ||
764        (!has_video && is_video_encrypted)) {
765      continue;
766    }
767
768    CreateNewDemuxer();
769
770    if (is_audio_encrypted || is_video_encrypted) {
771      int need_key_count = (is_audio_encrypted ? 1 : 0) +
772                           (is_video_encrypted ? 1 : 0);
773      EXPECT_CALL(*this, NeedKeyMock(kWebMInitDataType, NotNull(), 16))
774          .Times(Exactly(need_key_count));
775    }
776
777    ASSERT_TRUE(InitDemuxerWithEncryptionInfo(
778        has_audio, has_video, is_audio_encrypted, is_video_encrypted));
779
780    scoped_refptr<DemuxerStream> audio_stream =
781        demuxer_->GetStream(DemuxerStream::AUDIO);
782    if (has_audio) {
783      ASSERT_TRUE(audio_stream);
784
785      const AudioDecoderConfig& config = audio_stream->audio_decoder_config();
786      EXPECT_EQ(kCodecVorbis, config.codec());
787      EXPECT_EQ(16, config.bits_per_channel());
788      EXPECT_EQ(CHANNEL_LAYOUT_STEREO, config.channel_layout());
789      EXPECT_EQ(44100, config.samples_per_second());
790      EXPECT_TRUE(config.extra_data());
791      EXPECT_GT(config.extra_data_size(), 0u);
792      EXPECT_EQ(is_audio_encrypted,
793                audio_stream->audio_decoder_config().is_encrypted());
794    } else {
795      EXPECT_FALSE(audio_stream);
796    }
797
798    scoped_refptr<DemuxerStream> video_stream =
799        demuxer_->GetStream(DemuxerStream::VIDEO);
800    if (has_video) {
801      EXPECT_TRUE(video_stream);
802      EXPECT_EQ(is_video_encrypted,
803                video_stream->video_decoder_config().is_encrypted());
804    } else {
805      EXPECT_FALSE(video_stream);
806    }
807
808    ShutdownDemuxer();
809    demuxer_ = NULL;
810  }
811}
812
813// Make sure that the demuxer reports an error if Shutdown()
814// is called before all the initialization segments are appended.
815TEST_F(ChunkDemuxerTest, TestShutdownBeforeAllInitSegmentsAppended) {
816  EXPECT_CALL(*this, DemuxerOpened());
817  demuxer_->Initialize(
818      &host_, CreateInitDoneCB(
819          kDefaultDuration(), DEMUXER_ERROR_COULD_NOT_OPEN));
820
821  EXPECT_EQ(AddId("audio", true, false), ChunkDemuxer::kOk);
822  EXPECT_EQ(AddId("video", false, true), ChunkDemuxer::kOk);
823
824  EXPECT_TRUE(AppendInitSegmentWithSourceId("audio", true, false));
825}
826
827// Test that Seek() completes successfully when the first cluster
828// arrives.
829TEST_F(ChunkDemuxerTest, TestAppendDataAfterSeek) {
830  ASSERT_TRUE(InitDemuxer(true, true));
831  scoped_ptr<Cluster> first_cluster(kDefaultFirstCluster());
832  ASSERT_TRUE(AppendData(first_cluster->data(), first_cluster->size()));
833
834  InSequence s;
835
836  EXPECT_CALL(*this, Checkpoint(1));
837
838  demuxer_->Seek(base::TimeDelta::FromMilliseconds(46),
839                 NewExpectedStatusCB(PIPELINE_OK));
840
841  EXPECT_CALL(*this, Checkpoint(2));
842
843  scoped_ptr<Cluster> cluster(kDefaultSecondCluster());
844
845  Checkpoint(1);
846
847  ASSERT_TRUE(AppendData(cluster->data(), cluster->size()));
848
849  Checkpoint(2);
850}
851
852// Test that parsing errors are handled for clusters appended after init.
853TEST_F(ChunkDemuxerTest, TestErrorWhileParsingClusterAfterInit) {
854  ASSERT_TRUE(InitDemuxer(true, true));
855  scoped_ptr<Cluster> first_cluster(kDefaultFirstCluster());
856  ASSERT_TRUE(AppendData(first_cluster->data(), first_cluster->size()));
857
858  EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
859  ASSERT_TRUE(AppendGarbage());
860}
861
862// Test the case where a Seek() is requested while the parser
863// is in the middle of cluster. This is to verify that the parser
864// does not reset itself on a seek.
865TEST_F(ChunkDemuxerTest, TestSeekWhileParsingCluster) {
866  ASSERT_TRUE(InitDemuxer(true, true));
867
868  scoped_refptr<DemuxerStream> audio =
869      demuxer_->GetStream(DemuxerStream::AUDIO);
870  scoped_refptr<DemuxerStream> video =
871      demuxer_->GetStream(DemuxerStream::VIDEO);
872
873  InSequence s;
874
875  scoped_ptr<Cluster> cluster_a(GenerateCluster(0, 6));
876
877  // Split the cluster into two appends at an arbitrary point near the end.
878  int first_append_size = cluster_a->size() - 11;
879  int second_append_size = cluster_a->size() - first_append_size;
880
881  // Append the first part of the cluster.
882  ASSERT_TRUE(AppendData(cluster_a->data(), first_append_size));
883
884  ExpectRead(audio, 0);
885  ExpectRead(video, 0);
886  ExpectRead(audio, kAudioBlockDuration);
887  // Note: We skip trying to read a video buffer here because computing
888  // the duration for this block relies on successfully parsing the last block
889  // in the cluster the cluster.
890  ExpectRead(audio, 2 * kAudioBlockDuration);
891
892  demuxer_->StartWaitingForSeek();
893  demuxer_->Seek(base::TimeDelta::FromSeconds(5),
894                 NewExpectedStatusCB(PIPELINE_OK));
895
896  // Append the rest of the cluster.
897  ASSERT_TRUE(AppendData(cluster_a->data() + first_append_size,
898                         second_append_size));
899
900  // Append the new cluster and verify that only the blocks
901  // in the new cluster are returned.
902  scoped_ptr<Cluster> cluster_b(GenerateCluster(5000, 6));
903  ASSERT_TRUE(AppendData(cluster_b->data(), cluster_b->size()));
904  GenerateExpectedReads(5000, 6, audio, video);
905}
906
907// Test the case where AppendData() is called before Init().
908TEST_F(ChunkDemuxerTest, TestAppendDataBeforeInit) {
909  scoped_array<uint8> info_tracks;
910  int info_tracks_size = 0;
911  CreateInitSegment(true, true, false, false, &info_tracks, &info_tracks_size);
912
913  EXPECT_FALSE(demuxer_->AppendData(kSourceId, info_tracks.get(),
914                                    info_tracks_size));
915}
916
917// Make sure Read() callbacks are dispatched with the proper data.
918TEST_F(ChunkDemuxerTest, TestRead) {
919  ASSERT_TRUE(InitDemuxer(true, true));
920
921  scoped_ptr<Cluster> cluster(kDefaultFirstCluster());
922  ASSERT_TRUE(AppendData(cluster->data(), cluster->size()));
923
924  scoped_refptr<DemuxerStream> audio =
925      demuxer_->GetStream(DemuxerStream::AUDIO);
926  scoped_refptr<DemuxerStream> video =
927      demuxer_->GetStream(DemuxerStream::VIDEO);
928
929  bool audio_read_done = false;
930  bool video_read_done = false;
931  audio->Read(base::Bind(&OnReadDone,
932                         base::TimeDelta::FromMilliseconds(0),
933                         &audio_read_done));
934  video->Read(base::Bind(&OnReadDone,
935                         base::TimeDelta::FromMilliseconds(0),
936                         &video_read_done));
937
938  EXPECT_TRUE(audio_read_done);
939  EXPECT_TRUE(video_read_done);
940}
941
942TEST_F(ChunkDemuxerTest, TestOutOfOrderClusters) {
943  ASSERT_TRUE(InitDemuxer(true, true));
944  scoped_ptr<Cluster> cluster(kDefaultFirstCluster());
945  ASSERT_TRUE(AppendData(cluster->data(), cluster->size()));
946
947  scoped_ptr<Cluster> cluster_a(GenerateCluster(10, 4));
948  ASSERT_TRUE(AppendData(cluster_a->data(), cluster_a->size()));
949
950  // Cluster B starts before cluster_a and has data
951  // that overlaps.
952  scoped_ptr<Cluster> cluster_b(GenerateCluster(5, 4));
953
954  // Make sure that AppendData() does not fail.
955  ASSERT_TRUE(AppendData(cluster_b->data(), cluster_b->size()));
956
957  // Verify that AppendData() can still accept more data.
958  scoped_ptr<Cluster> cluster_c(GenerateCluster(45, 2));
959  ASSERT_TRUE(demuxer_->AppendData(kSourceId, cluster_c->data(),
960                                   cluster_c->size()));
961}
962
963TEST_F(ChunkDemuxerTest, TestNonMonotonicButAboveClusterTimecode) {
964  ASSERT_TRUE(InitDemuxer(true, true));
965  scoped_ptr<Cluster> first_cluster(kDefaultFirstCluster());
966  ASSERT_TRUE(AppendData(first_cluster->data(), first_cluster->size()));
967
968  ClusterBuilder cb;
969
970  // Test the case where block timecodes are not monotonically
971  // increasing but stay above the cluster timecode.
972  cb.SetClusterTimecode(5);
973  AddSimpleBlock(&cb, kAudioTrackNum, 5);
974  AddSimpleBlock(&cb, kVideoTrackNum, 10);
975  AddSimpleBlock(&cb, kAudioTrackNum, 7);
976  AddSimpleBlock(&cb, kVideoTrackNum, 15);
977  scoped_ptr<Cluster> cluster_a(cb.Finish());
978
979  EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
980  ASSERT_TRUE(AppendData(cluster_a->data(), cluster_a->size()));
981
982  // Verify that AppendData() doesn't accept more data now.
983  scoped_ptr<Cluster> cluster_b(GenerateCluster(20, 2));
984  EXPECT_FALSE(demuxer_->AppendData(kSourceId, cluster_b->data(),
985                                    cluster_b->size()));
986}
987
988TEST_F(ChunkDemuxerTest, TestBackwardsAndBeforeClusterTimecode) {
989  ASSERT_TRUE(InitDemuxer(true, true));
990  scoped_ptr<Cluster> first_cluster(kDefaultFirstCluster());
991  ASSERT_TRUE(AppendData(first_cluster->data(), first_cluster->size()));
992
993  ClusterBuilder cb;
994
995  // Test timecodes going backwards and including values less than the cluster
996  // timecode.
997  cb.SetClusterTimecode(5);
998  AddSimpleBlock(&cb, kAudioTrackNum, 5);
999  AddSimpleBlock(&cb, kVideoTrackNum, 5);
1000  AddSimpleBlock(&cb, kAudioTrackNum, 3);
1001  AddSimpleBlock(&cb, kVideoTrackNum, 3);
1002  scoped_ptr<Cluster> cluster_a(cb.Finish());
1003
1004  EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
1005  ASSERT_TRUE(AppendData(cluster_a->data(), cluster_a->size()));
1006
1007  // Verify that AppendData() doesn't accept more data now.
1008  scoped_ptr<Cluster> cluster_b(GenerateCluster(6, 2));
1009  EXPECT_FALSE(demuxer_->AppendData(kSourceId, cluster_b->data(),
1010                                    cluster_b->size()));
1011}
1012
1013
1014TEST_F(ChunkDemuxerTest, TestPerStreamMonotonicallyIncreasingTimestamps) {
1015  ASSERT_TRUE(InitDemuxer(true, true));
1016  scoped_ptr<Cluster> first_cluster(kDefaultFirstCluster());
1017  ASSERT_TRUE(AppendData(first_cluster->data(), first_cluster->size()));
1018
1019  ClusterBuilder cb;
1020
1021  // Test monotonic increasing timestamps on a per stream
1022  // basis.
1023  cb.SetClusterTimecode(5);
1024  AddSimpleBlock(&cb, kAudioTrackNum, 5);
1025  AddSimpleBlock(&cb, kVideoTrackNum, 5);
1026  AddSimpleBlock(&cb, kAudioTrackNum, 4);
1027  AddSimpleBlock(&cb, kVideoTrackNum, 7);
1028  scoped_ptr<Cluster> cluster(cb.Finish());
1029
1030  EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
1031  ASSERT_TRUE(AppendData(cluster->data(), cluster->size()));
1032}
1033
1034// Test the case where a cluster is passed to AppendData() before
1035// INFO & TRACKS data.
1036TEST_F(ChunkDemuxerTest, TestClusterBeforeInitSegment) {
1037  EXPECT_CALL(*this, DemuxerOpened());
1038  demuxer_->Initialize(
1039      &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN));
1040
1041  ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
1042
1043  scoped_ptr<Cluster> cluster(GenerateCluster(0, 1));
1044
1045  ASSERT_TRUE(AppendData(cluster->data(), cluster->size()));
1046}
1047
1048// Test cases where we get an EndOfStream() call during initialization.
1049TEST_F(ChunkDemuxerTest, TestEOSDuringInit) {
1050  EXPECT_CALL(*this, DemuxerOpened());
1051  demuxer_->Initialize(
1052      &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN));
1053  demuxer_->EndOfStream(PIPELINE_OK);
1054}
1055
1056TEST_F(ChunkDemuxerTest, TestEndOfStreamWithNoAppend) {
1057  EXPECT_CALL(*this, DemuxerOpened());
1058  demuxer_->Initialize(
1059      &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN));
1060
1061  ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
1062
1063  CheckExpectedRanges("{ }");
1064  demuxer_->EndOfStream(PIPELINE_OK);
1065  ShutdownDemuxer();
1066  CheckExpectedRanges("{ }");
1067  demuxer_->RemoveId(kSourceId);
1068  demuxer_ = NULL;
1069}
1070
1071TEST_F(ChunkDemuxerTest, TestEndOfStreamWithNoMediaAppend) {
1072  ASSERT_TRUE(InitDemuxer(true, true));
1073
1074  CheckExpectedRanges("{ }");
1075  demuxer_->EndOfStream(PIPELINE_OK);
1076  CheckExpectedRanges("{ }");
1077}
1078
1079TEST_F(ChunkDemuxerTest, TestDecodeErrorEndOfStream) {
1080  ASSERT_TRUE(InitDemuxer(true, true));
1081
1082  scoped_ptr<Cluster> cluster(kDefaultFirstCluster());
1083  ASSERT_TRUE(AppendData(cluster->data(), cluster->size()));
1084  CheckExpectedRanges(kDefaultFirstClusterRange);
1085
1086  EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
1087  demuxer_->EndOfStream(PIPELINE_ERROR_DECODE);
1088  CheckExpectedRanges(kDefaultFirstClusterRange);
1089}
1090
1091TEST_F(ChunkDemuxerTest, TestNetworkErrorEndOfStream) {
1092  ASSERT_TRUE(InitDemuxer(true, true));
1093
1094  scoped_ptr<Cluster> cluster(kDefaultFirstCluster());
1095  ASSERT_TRUE(AppendData(cluster->data(), cluster->size()));
1096  CheckExpectedRanges(kDefaultFirstClusterRange);
1097
1098  EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_NETWORK));
1099  demuxer_->EndOfStream(PIPELINE_ERROR_NETWORK);
1100}
1101
1102// Helper class to reduce duplicate code when testing end of stream
1103// Read() behavior.
1104class EndOfStreamHelper {
1105 public:
1106  explicit EndOfStreamHelper(const scoped_refptr<Demuxer> demuxer)
1107      : demuxer_(demuxer),
1108        audio_read_done_(false),
1109        video_read_done_(false) {
1110  }
1111
1112  // Request a read on the audio and video streams.
1113  void RequestReads() {
1114    EXPECT_FALSE(audio_read_done_);
1115    EXPECT_FALSE(video_read_done_);
1116
1117    scoped_refptr<DemuxerStream> audio =
1118        demuxer_->GetStream(DemuxerStream::AUDIO);
1119    scoped_refptr<DemuxerStream> video =
1120        demuxer_->GetStream(DemuxerStream::VIDEO);
1121
1122    audio->Read(base::Bind(&OnEndOfStreamReadDone,
1123                           &audio_read_done_));
1124
1125    video->Read(base::Bind(&OnEndOfStreamReadDone,
1126                           &video_read_done_));
1127  }
1128
1129  // Check to see if |audio_read_done_| and |video_read_done_| variables
1130  // match |expected|.
1131  void CheckIfReadDonesWereCalled(bool expected) {
1132    EXPECT_EQ(expected, audio_read_done_);
1133    EXPECT_EQ(expected, video_read_done_);
1134  }
1135
1136 private:
1137  static void OnEndOfStreamReadDone(
1138      bool* called,
1139      DemuxerStream::Status status,
1140      const scoped_refptr<DecoderBuffer>& buffer) {
1141    EXPECT_EQ(status, DemuxerStream::kOk);
1142    EXPECT_TRUE(buffer->IsEndOfStream());
1143    *called = true;
1144  }
1145
1146  scoped_refptr<Demuxer> demuxer_;
1147  bool audio_read_done_;
1148  bool video_read_done_;
1149
1150  DISALLOW_COPY_AND_ASSIGN(EndOfStreamHelper);
1151};
1152
1153// Make sure that all pending reads that we don't have media data for get an
1154// "end of stream" buffer when EndOfStream() is called.
1155TEST_F(ChunkDemuxerTest, TestEndOfStreamWithPendingReads) {
1156  ASSERT_TRUE(InitDemuxer(true, true));
1157
1158  scoped_ptr<Cluster> cluster(GenerateCluster(0, 2));
1159  ASSERT_TRUE(AppendData(cluster->data(), cluster->size()));
1160
1161  scoped_refptr<DemuxerStream> audio =
1162      demuxer_->GetStream(DemuxerStream::AUDIO);
1163  scoped_refptr<DemuxerStream> video =
1164      demuxer_->GetStream(DemuxerStream::VIDEO);
1165
1166  bool audio_read_done_1 = false;
1167  bool video_read_done_1 = false;
1168  EndOfStreamHelper end_of_stream_helper_1(demuxer_);
1169  EndOfStreamHelper end_of_stream_helper_2(demuxer_);
1170
1171  audio->Read(base::Bind(&OnReadDone,
1172                         base::TimeDelta::FromMilliseconds(0),
1173                         &audio_read_done_1));
1174
1175  video->Read(base::Bind(&OnReadDone,
1176                         base::TimeDelta::FromMilliseconds(0),
1177                         &video_read_done_1));
1178
1179  end_of_stream_helper_1.RequestReads();
1180  end_of_stream_helper_2.RequestReads();
1181
1182  EXPECT_TRUE(audio_read_done_1);
1183  EXPECT_TRUE(video_read_done_1);
1184  end_of_stream_helper_1.CheckIfReadDonesWereCalled(false);
1185  end_of_stream_helper_2.CheckIfReadDonesWereCalled(false);
1186
1187  EXPECT_CALL(host_, SetDuration(
1188      base::TimeDelta::FromMilliseconds(kVideoBlockDuration)));
1189  demuxer_->EndOfStream(PIPELINE_OK);
1190
1191  end_of_stream_helper_1.CheckIfReadDonesWereCalled(true);
1192  end_of_stream_helper_2.CheckIfReadDonesWereCalled(true);
1193}
1194
1195// Make sure that all Read() calls after we get an EndOfStream()
1196// call return an "end of stream" buffer.
1197TEST_F(ChunkDemuxerTest, TestReadsAfterEndOfStream) {
1198  ASSERT_TRUE(InitDemuxer(true, true));
1199
1200  scoped_ptr<Cluster> cluster(GenerateCluster(0, 2));
1201  ASSERT_TRUE(AppendData(cluster->data(), cluster->size()));
1202
1203  scoped_refptr<DemuxerStream> audio =
1204      demuxer_->GetStream(DemuxerStream::AUDIO);
1205  scoped_refptr<DemuxerStream> video =
1206      demuxer_->GetStream(DemuxerStream::VIDEO);
1207
1208  bool audio_read_done_1 = false;
1209  bool video_read_done_1 = false;
1210  EndOfStreamHelper end_of_stream_helper_1(demuxer_);
1211  EndOfStreamHelper end_of_stream_helper_2(demuxer_);
1212  EndOfStreamHelper end_of_stream_helper_3(demuxer_);
1213
1214  audio->Read(base::Bind(&OnReadDone,
1215                         base::TimeDelta::FromMilliseconds(0),
1216                         &audio_read_done_1));
1217
1218  video->Read(base::Bind(&OnReadDone,
1219                         base::TimeDelta::FromMilliseconds(0),
1220                         &video_read_done_1));
1221
1222  end_of_stream_helper_1.RequestReads();
1223
1224  EXPECT_TRUE(audio_read_done_1);
1225  EXPECT_TRUE(video_read_done_1);
1226  end_of_stream_helper_1.CheckIfReadDonesWereCalled(false);
1227
1228  EXPECT_CALL(host_, SetDuration(
1229      base::TimeDelta::FromMilliseconds(kVideoBlockDuration)));
1230  EXPECT_TRUE(demuxer_->EndOfStream(PIPELINE_OK));
1231
1232  end_of_stream_helper_1.CheckIfReadDonesWereCalled(true);
1233
1234  // Request a few more reads and make sure we immediately get
1235  // end of stream buffers.
1236  end_of_stream_helper_2.RequestReads();
1237  end_of_stream_helper_2.CheckIfReadDonesWereCalled(true);
1238
1239  end_of_stream_helper_3.RequestReads();
1240  end_of_stream_helper_3.CheckIfReadDonesWereCalled(true);
1241}
1242
1243TEST_F(ChunkDemuxerTest, TestEndOfStreamDuringCanceledSeek) {
1244  ASSERT_TRUE(InitDemuxer(true, true));
1245  scoped_refptr<DemuxerStream> audio =
1246      demuxer_->GetStream(DemuxerStream::AUDIO);
1247  scoped_refptr<DemuxerStream> video =
1248      demuxer_->GetStream(DemuxerStream::VIDEO);
1249
1250  ASSERT_TRUE(AppendCluster(0, 10));
1251  EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(138)));
1252  EXPECT_TRUE(demuxer_->EndOfStream(PIPELINE_OK));
1253
1254  // Start the first seek.
1255  demuxer_->StartWaitingForSeek();
1256
1257  // Call EndOfStream() before the demuxer is notified of the desired
1258  // seek point. This simulates end of stream being called before the
1259  // pipeline gets a chance to call Seek().
1260  EXPECT_TRUE(demuxer_->EndOfStream(PIPELINE_OK));
1261
1262  // Simulate the pipeline finally calling Seek().
1263  demuxer_->Seek(base::TimeDelta::FromMilliseconds(20),
1264                 NewExpectedStatusCB(PIPELINE_OK));
1265
1266  // Simulate another seek being requested before the first
1267  // seek has finished prerolling.
1268  demuxer_->CancelPendingSeek();
1269
1270  // Call EndOfStream() again since the second seek should clear the
1271  // previous end of stream state.
1272  EXPECT_TRUE(demuxer_->EndOfStream(PIPELINE_OK));
1273
1274  // Finish second seek.
1275  demuxer_->StartWaitingForSeek();
1276  demuxer_->Seek(base::TimeDelta::FromMilliseconds(30),
1277                 NewExpectedStatusCB(PIPELINE_OK));
1278
1279  DemuxerStream::Status status;
1280  base::TimeDelta last_timestamp;
1281
1282  // Make sure audio can reach end of stream.
1283  ReadUntilNotOkOrEndOfStream(audio, &status, &last_timestamp);
1284  ASSERT_EQ(status, DemuxerStream::kOk);
1285
1286  // Make sure video can reach end of stream.
1287  ReadUntilNotOkOrEndOfStream(video, &status, &last_timestamp);
1288  ASSERT_EQ(status, DemuxerStream::kOk);
1289}
1290
1291// Make sure AppendData() will accept elements that span multiple calls.
1292TEST_F(ChunkDemuxerTest, TestAppendingInPieces) {
1293  EXPECT_CALL(*this, DemuxerOpened());
1294  demuxer_->Initialize(
1295      &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK));
1296
1297  ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
1298
1299  scoped_array<uint8> info_tracks;
1300  int info_tracks_size = 0;
1301  CreateInitSegment(true, true, false, false, &info_tracks, &info_tracks_size);
1302
1303  scoped_ptr<Cluster> cluster_a(kDefaultFirstCluster());
1304  scoped_ptr<Cluster> cluster_b(kDefaultSecondCluster());
1305
1306  size_t buffer_size = info_tracks_size + cluster_a->size() + cluster_b->size();
1307  scoped_array<uint8> buffer(new uint8[buffer_size]);
1308  uint8* dst = buffer.get();
1309  memcpy(dst, info_tracks.get(), info_tracks_size);
1310  dst += info_tracks_size;
1311
1312  memcpy(dst, cluster_a->data(), cluster_a->size());
1313  dst += cluster_a->size();
1314
1315  memcpy(dst, cluster_b->data(), cluster_b->size());
1316  dst += cluster_b->size();
1317
1318  ASSERT_TRUE(AppendDataInPieces(buffer.get(), buffer_size));
1319
1320  scoped_refptr<DemuxerStream> audio =
1321      demuxer_->GetStream(DemuxerStream::AUDIO);
1322  scoped_refptr<DemuxerStream> video =
1323      demuxer_->GetStream(DemuxerStream::VIDEO);
1324
1325  ASSERT_TRUE(audio);
1326  ASSERT_TRUE(video);
1327
1328  GenerateExpectedReads(0, 9, audio, video);
1329}
1330
1331TEST_F(ChunkDemuxerTest, TestWebMFile_AudioAndVideo) {
1332  struct BufferTimestamps buffer_timestamps[] = {
1333    {0, 0},
1334    {33, 3},
1335    {67, 6},
1336    {100, 9},
1337    {133, 12},
1338    {kSkip, kSkip},
1339  };
1340
1341  ASSERT_TRUE(ParseWebMFile("bear-320x240.webm", buffer_timestamps,
1342                            base::TimeDelta::FromMilliseconds(2744)));
1343}
1344
1345TEST_F(ChunkDemuxerTest, TestWebMFile_LiveAudioAndVideo) {
1346  struct BufferTimestamps buffer_timestamps[] = {
1347    {0, 0},
1348    {33, 3},
1349    {67, 6},
1350    {100, 9},
1351    {133, 12},
1352    {kSkip, kSkip},
1353  };
1354
1355  ASSERT_TRUE(ParseWebMFile("bear-320x240-live.webm", buffer_timestamps,
1356                            kInfiniteDuration()));
1357}
1358
1359TEST_F(ChunkDemuxerTest, TestWebMFile_AudioOnly) {
1360  struct BufferTimestamps buffer_timestamps[] = {
1361    {kSkip, 0},
1362    {kSkip, 3},
1363    {kSkip, 6},
1364    {kSkip, 9},
1365    {kSkip, 12},
1366    {kSkip, kSkip},
1367  };
1368
1369  ASSERT_TRUE(ParseWebMFile("bear-320x240-audio-only.webm", buffer_timestamps,
1370                            base::TimeDelta::FromMilliseconds(2744),
1371                            true, false));
1372}
1373
1374TEST_F(ChunkDemuxerTest, TestWebMFile_VideoOnly) {
1375  struct BufferTimestamps buffer_timestamps[] = {
1376    {0, kSkip},
1377    {33, kSkip},
1378    {67, kSkip},
1379    {100, kSkip},
1380    {133, kSkip},
1381    {kSkip, kSkip},
1382  };
1383
1384  ASSERT_TRUE(ParseWebMFile("bear-320x240-video-only.webm", buffer_timestamps,
1385                            base::TimeDelta::FromMilliseconds(2703),
1386                            false, true));
1387}
1388
1389TEST_F(ChunkDemuxerTest, TestWebMFile_AltRefFrames) {
1390  struct BufferTimestamps buffer_timestamps[] = {
1391    {0, 0},
1392    {33, 3},
1393    {33, 6},
1394    {67, 9},
1395    {100, 12},
1396    {kSkip, kSkip},
1397  };
1398
1399  ASSERT_TRUE(ParseWebMFile("bear-320x240-altref.webm", buffer_timestamps,
1400                            base::TimeDelta::FromMilliseconds(2767)));
1401}
1402
1403// Verify that we output buffers before the entire cluster has been parsed.
1404TEST_F(ChunkDemuxerTest, TestIncrementalClusterParsing) {
1405  ASSERT_TRUE(InitDemuxer(true, true));
1406  ASSERT_TRUE(AppendEmptyCluster(0));
1407
1408  scoped_ptr<Cluster> cluster(GenerateCluster(0, 6));
1409  scoped_refptr<DemuxerStream> audio =
1410      demuxer_->GetStream(DemuxerStream::AUDIO);
1411  scoped_refptr<DemuxerStream> video =
1412      demuxer_->GetStream(DemuxerStream::VIDEO);
1413
1414  bool audio_read_done = false;
1415  bool video_read_done = false;
1416  audio->Read(base::Bind(&OnReadDone,
1417                         base::TimeDelta::FromMilliseconds(0),
1418                         &audio_read_done));
1419
1420  video->Read(base::Bind(&OnReadDone,
1421                         base::TimeDelta::FromMilliseconds(0),
1422                         &video_read_done));
1423
1424  // Make sure the reads haven't completed yet.
1425  EXPECT_FALSE(audio_read_done);
1426  EXPECT_FALSE(video_read_done);
1427
1428  // Append data one byte at a time until the audio read completes.
1429  int i = 0;
1430  for (; i < cluster->size() && !audio_read_done; ++i) {
1431    ASSERT_TRUE(AppendData(cluster->data() + i, 1));
1432  }
1433
1434  EXPECT_TRUE(audio_read_done);
1435  EXPECT_FALSE(video_read_done);
1436  EXPECT_GT(i, 0);
1437  EXPECT_LT(i, cluster->size());
1438
1439  // Append data one byte at a time until the video read completes.
1440  for (; i < cluster->size() && !video_read_done; ++i) {
1441    ASSERT_TRUE(AppendData(cluster->data() + i, 1));
1442  }
1443
1444  EXPECT_TRUE(video_read_done);
1445  EXPECT_LT(i, cluster->size());
1446
1447  audio_read_done = false;
1448  video_read_done = false;
1449  audio->Read(base::Bind(&OnReadDone,
1450                         base::TimeDelta::FromMilliseconds(23),
1451                         &audio_read_done));
1452
1453  video->Read(base::Bind(&OnReadDone,
1454                         base::TimeDelta::FromMilliseconds(33),
1455                         &video_read_done));
1456
1457  // Make sure the reads haven't completed yet.
1458  EXPECT_FALSE(audio_read_done);
1459  EXPECT_FALSE(video_read_done);
1460
1461  // Append the remaining data.
1462  ASSERT_LT(i, cluster->size());
1463  ASSERT_TRUE(AppendData(cluster->data() + i, cluster->size() - i));
1464
1465  EXPECT_TRUE(audio_read_done);
1466  EXPECT_TRUE(video_read_done);
1467}
1468
1469TEST_F(ChunkDemuxerTest, TestParseErrorDuringInit) {
1470  EXPECT_CALL(*this, DemuxerOpened());
1471  demuxer_->Initialize(
1472      &host_, CreateInitDoneCB(
1473          kNoTimestamp(), DEMUXER_ERROR_COULD_NOT_OPEN));
1474
1475  ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
1476
1477  uint8 tmp = 0;
1478  ASSERT_TRUE(demuxer_->AppendData(kSourceId, &tmp, 1));
1479}
1480
1481TEST_F(ChunkDemuxerTest, TestAVHeadersWithAudioOnlyType) {
1482  EXPECT_CALL(*this, DemuxerOpened());
1483  demuxer_->Initialize(
1484      &host_, CreateInitDoneCB(kNoTimestamp(),
1485                               DEMUXER_ERROR_COULD_NOT_OPEN));
1486
1487  std::vector<std::string> codecs(1);
1488  codecs[0] = "vorbis";
1489  ASSERT_EQ(demuxer_->AddId(kSourceId, "audio/webm", codecs),
1490            ChunkDemuxer::kOk);
1491
1492  ASSERT_TRUE(AppendInitSegment(true, true));
1493}
1494
1495TEST_F(ChunkDemuxerTest, TestAVHeadersWithVideoOnlyType) {
1496  EXPECT_CALL(*this, DemuxerOpened());
1497  demuxer_->Initialize(
1498      &host_, CreateInitDoneCB(kNoTimestamp(),
1499                               DEMUXER_ERROR_COULD_NOT_OPEN));
1500
1501  std::vector<std::string> codecs(1);
1502  codecs[0] = "vp8";
1503  ASSERT_EQ(demuxer_->AddId(kSourceId, "video/webm", codecs),
1504            ChunkDemuxer::kOk);
1505
1506  ASSERT_TRUE(AppendInitSegment(true, true));
1507}
1508
1509TEST_F(ChunkDemuxerTest, TestMultipleHeaders) {
1510  ASSERT_TRUE(InitDemuxer(true, true));
1511
1512  scoped_refptr<DemuxerStream> audio =
1513      demuxer_->GetStream(DemuxerStream::AUDIO);
1514  scoped_refptr<DemuxerStream> video =
1515      demuxer_->GetStream(DemuxerStream::VIDEO);
1516
1517  scoped_ptr<Cluster> cluster_a(kDefaultFirstCluster());
1518  ASSERT_TRUE(AppendData(cluster_a->data(), cluster_a->size()));
1519
1520  // Append another identical initialization segment.
1521  ASSERT_TRUE(AppendInitSegment(true, true));
1522
1523  scoped_ptr<Cluster> cluster_b(kDefaultSecondCluster());
1524  ASSERT_TRUE(AppendData(cluster_b->data(), cluster_b->size()));
1525
1526  GenerateExpectedReads(0, 9, audio, video);
1527}
1528
1529TEST_F(ChunkDemuxerTest, TestAddSeparateSourcesForAudioAndVideo) {
1530  std::string audio_id = "audio1";
1531  std::string video_id = "video1";
1532  ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1533
1534  scoped_refptr<DemuxerStream> audio =
1535      demuxer_->GetStream(DemuxerStream::AUDIO);
1536  scoped_refptr<DemuxerStream> video =
1537      demuxer_->GetStream(DemuxerStream::VIDEO);
1538
1539  scoped_ptr<Cluster> cluster_a(
1540      GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
1541
1542  scoped_ptr<Cluster> cluster_v(
1543      GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
1544
1545  // Append audio and video data into separate source ids.
1546  ASSERT_TRUE(AppendData(audio_id, cluster_a->data(), cluster_a->size()));
1547  GenerateSingleStreamExpectedReads(0, 4, audio, kAudioBlockDuration);
1548  ASSERT_TRUE(AppendData(video_id, cluster_v->data(), cluster_v->size()));
1549  GenerateSingleStreamExpectedReads(0, 4, video, kVideoBlockDuration);
1550}
1551
1552TEST_F(ChunkDemuxerTest, TestAddIdFailures) {
1553  EXPECT_CALL(*this, DemuxerOpened());
1554  demuxer_->Initialize(
1555      &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK));
1556
1557  std::string audio_id = "audio1";
1558  std::string video_id = "video1";
1559
1560  ASSERT_EQ(AddId(audio_id, true, false), ChunkDemuxer::kOk);
1561
1562  // Adding an id with audio/video should fail because we already added audio.
1563  ASSERT_EQ(AddId(), ChunkDemuxer::kReachedIdLimit);
1564
1565  ASSERT_TRUE(AppendInitSegmentWithSourceId(audio_id, true, false));
1566
1567  // Adding an id after append should fail.
1568  ASSERT_EQ(AddId(video_id, false, true), ChunkDemuxer::kReachedIdLimit);
1569}
1570
1571// Test that Read() calls after a RemoveId() return "end of stream" buffers.
1572TEST_F(ChunkDemuxerTest, TestRemoveId) {
1573  std::string audio_id = "audio1";
1574  std::string video_id = "video1";
1575  ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1576
1577  scoped_ptr<Cluster> cluster_a(
1578      GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
1579
1580  scoped_ptr<Cluster> cluster_v(
1581      GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
1582
1583  // Append audio and video data into separate source ids.
1584  ASSERT_TRUE(AppendData(audio_id, cluster_a->data(), cluster_a->size()));
1585  ASSERT_TRUE(AppendData(video_id, cluster_v->data(), cluster_v->size()));
1586
1587  // Read() from audio should return normal buffers.
1588  scoped_refptr<DemuxerStream> audio =
1589      demuxer_->GetStream(DemuxerStream::AUDIO);
1590  GenerateSingleStreamExpectedReads(0, 4, audio, kAudioBlockDuration);
1591
1592  // Remove the audio id.
1593  demuxer_->RemoveId(audio_id);
1594
1595  // Read() from audio should return "end of stream" buffers.
1596  bool audio_read_done = false;
1597  audio->Read(base::Bind(&OnReadDone_EOSExpected,
1598                         &audio_read_done));
1599  EXPECT_TRUE(audio_read_done);
1600
1601  // Read() from video should still return normal buffers.
1602  scoped_refptr<DemuxerStream> video =
1603      demuxer_->GetStream(DemuxerStream::VIDEO);
1604  GenerateSingleStreamExpectedReads(0, 4, video, kVideoBlockDuration);
1605}
1606
1607// Test that removing an ID immediately after adding it does not interfere with
1608// quota for new IDs in the future.
1609TEST_F(ChunkDemuxerTest, TestRemoveAndAddId) {
1610  std::string audio_id_1 = "audio1";
1611  ASSERT_TRUE(AddId(audio_id_1, true, false) == ChunkDemuxer::kOk);
1612  demuxer_->RemoveId(audio_id_1);
1613
1614  std::string audio_id_2 = "audio2";
1615  ASSERT_TRUE(AddId(audio_id_2, true, false) == ChunkDemuxer::kOk);
1616}
1617
1618TEST_F(ChunkDemuxerTest, TestSeekCanceled) {
1619  ASSERT_TRUE(InitDemuxer(true, true));
1620
1621  scoped_refptr<DemuxerStream> audio =
1622      demuxer_->GetStream(DemuxerStream::AUDIO);
1623  scoped_refptr<DemuxerStream> video =
1624      demuxer_->GetStream(DemuxerStream::VIDEO);
1625
1626  // Append cluster at the beginning of the stream.
1627  scoped_ptr<Cluster> start_cluster(GenerateCluster(0, 4));
1628  ASSERT_TRUE(AppendData(start_cluster->data(), start_cluster->size()));
1629
1630  // Seek to an unbuffered region.
1631  demuxer_->StartWaitingForSeek();
1632  demuxer_->Seek(base::TimeDelta::FromSeconds(50),
1633                 NewExpectedStatusCB(PIPELINE_OK));
1634
1635  // Attempt to read in unbuffered area; should not fulfill the read.
1636  bool audio_read_done = false;
1637  bool video_read_done = false;
1638  audio->Read(base::Bind(&OnReadDone_AbortExpected, &audio_read_done));
1639  video->Read(base::Bind(&OnReadDone_AbortExpected, &video_read_done));
1640  EXPECT_FALSE(audio_read_done);
1641  EXPECT_FALSE(video_read_done);
1642
1643  // Now cancel the pending seek, which should flush the reads with empty
1644  // buffers.
1645  demuxer_->CancelPendingSeek();
1646  EXPECT_TRUE(audio_read_done);
1647  EXPECT_TRUE(video_read_done);
1648
1649  // A seek back to the buffered region should succeed.
1650  demuxer_->StartWaitingForSeek();
1651  demuxer_->Seek(base::TimeDelta::FromSeconds(0),
1652                 NewExpectedStatusCB(PIPELINE_OK));
1653  GenerateExpectedReads(0, 4, audio, video);
1654}
1655
1656TEST_F(ChunkDemuxerTest, TestSeekCanceledWhileWaitingForSeek) {
1657  ASSERT_TRUE(InitDemuxer(true, true));
1658
1659  scoped_refptr<DemuxerStream> audio =
1660      demuxer_->GetStream(DemuxerStream::AUDIO);
1661  scoped_refptr<DemuxerStream> video =
1662      demuxer_->GetStream(DemuxerStream::VIDEO);
1663
1664  // Append cluster at the beginning of the stream.
1665  scoped_ptr<Cluster> start_cluster(GenerateCluster(0, 4));
1666  ASSERT_TRUE(AppendData(start_cluster->data(), start_cluster->size()));
1667
1668  // Start waiting for a seek.
1669  demuxer_->StartWaitingForSeek();
1670
1671  // Now cancel the upcoming seek to an unbuffered region.
1672  demuxer_->CancelPendingSeek();
1673  demuxer_->Seek(base::TimeDelta::FromSeconds(50),
1674                 NewExpectedStatusCB(PIPELINE_OK));
1675
1676  // Read requests should be fulfilled with empty buffers.
1677  bool audio_read_done = false;
1678  bool video_read_done = false;
1679  audio->Read(base::Bind(&OnReadDone_AbortExpected, &audio_read_done));
1680  video->Read(base::Bind(&OnReadDone_AbortExpected, &video_read_done));
1681  EXPECT_TRUE(audio_read_done);
1682  EXPECT_TRUE(video_read_done);
1683
1684  // A seek back to the buffered region should succeed.
1685  demuxer_->StartWaitingForSeek();
1686  demuxer_->Seek(base::TimeDelta::FromSeconds(0),
1687                 NewExpectedStatusCB(PIPELINE_OK));
1688  GenerateExpectedReads(0, 4, audio, video);
1689}
1690
1691// Test that Seek() successfully seeks to all source IDs.
1692TEST_F(ChunkDemuxerTest, TestSeekAudioAndVideoSources) {
1693  std::string audio_id = "audio1";
1694  std::string video_id = "video1";
1695  ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1696
1697  scoped_ptr<Cluster> cluster_a1(
1698      GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
1699
1700  scoped_ptr<Cluster> cluster_v1(
1701      GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
1702
1703  ASSERT_TRUE(AppendData(audio_id, cluster_a1->data(), cluster_a1->size()));
1704  ASSERT_TRUE(AppendData(video_id, cluster_v1->data(), cluster_v1->size()));
1705
1706  // Read() should return buffers at 0.
1707  bool audio_read_done = false;
1708  bool video_read_done = false;
1709  scoped_refptr<DemuxerStream> audio =
1710      demuxer_->GetStream(DemuxerStream::AUDIO);
1711  scoped_refptr<DemuxerStream> video =
1712      demuxer_->GetStream(DemuxerStream::VIDEO);
1713
1714  audio->Read(base::Bind(&OnReadDone,
1715                         base::TimeDelta::FromMilliseconds(0),
1716                         &audio_read_done));
1717  video->Read(base::Bind(&OnReadDone,
1718                         base::TimeDelta::FromMilliseconds(0),
1719                         &video_read_done));
1720  EXPECT_TRUE(audio_read_done);
1721  EXPECT_TRUE(video_read_done);
1722
1723  // Seek to 3 (an unbuffered region).
1724  demuxer_->StartWaitingForSeek();
1725  demuxer_->Seek(base::TimeDelta::FromSeconds(3),
1726                 NewExpectedStatusCB(PIPELINE_OK));
1727
1728  audio_read_done = false;
1729  video_read_done = false;
1730  audio->Read(base::Bind(&OnReadDone,
1731                         base::TimeDelta::FromSeconds(3),
1732                         &audio_read_done));
1733  video->Read(base::Bind(&OnReadDone,
1734                         base::TimeDelta::FromSeconds(3),
1735                         &video_read_done));
1736
1737  // Read()s should not return until after data is appended at the Seek point.
1738  EXPECT_FALSE(audio_read_done);
1739  EXPECT_FALSE(video_read_done);
1740
1741  scoped_ptr<Cluster> cluster_a2(
1742      GenerateSingleStreamCluster(3000, 3092, kAudioTrackNum,
1743                                  kAudioBlockDuration));
1744
1745  scoped_ptr<Cluster> cluster_v2(
1746      GenerateSingleStreamCluster(3000, 3132, kVideoTrackNum,
1747                                  kVideoBlockDuration));
1748
1749  ASSERT_TRUE(AppendData(audio_id, cluster_a2->data(), cluster_a2->size()));
1750  ASSERT_TRUE(AppendData(video_id, cluster_v2->data(), cluster_v2->size()));
1751
1752  // Read() should return buffers at 3.
1753  EXPECT_TRUE(audio_read_done);
1754  EXPECT_TRUE(video_read_done);
1755}
1756
1757// Test ranges in an audio-only stream.
1758TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioIdOnly) {
1759  EXPECT_CALL(*this, DemuxerOpened());
1760  demuxer_->Initialize(
1761      &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK));
1762
1763  ASSERT_EQ(AddId(kSourceId, true, false), ChunkDemuxer::kOk);
1764  ASSERT_TRUE(AppendInitSegment(true, false));
1765
1766  // Test a simple cluster.
1767  scoped_ptr<Cluster> cluster_1(GenerateSingleStreamCluster(0, 92,
1768                                kAudioTrackNum, kAudioBlockDuration));
1769  ASSERT_TRUE(AppendData(cluster_1->data(), cluster_1->size()));
1770
1771  CheckExpectedRanges("{ [0,92) }");
1772
1773  // Append a disjoint cluster to check for two separate ranges.
1774  scoped_ptr<Cluster> cluster_2(GenerateSingleStreamCluster(150, 219,
1775                                kAudioTrackNum, kAudioBlockDuration));
1776
1777  ASSERT_TRUE(AppendData(cluster_2->data(), cluster_2->size()));
1778
1779  CheckExpectedRanges("{ [0,92) [150,219) }");
1780}
1781
1782// Test ranges in a video-only stream.
1783TEST_F(ChunkDemuxerTest, GetBufferedRanges_VideoIdOnly) {
1784  EXPECT_CALL(*this, DemuxerOpened());
1785  demuxer_->Initialize(
1786      &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK));
1787
1788  ASSERT_EQ(AddId(kSourceId, false, true), ChunkDemuxer::kOk);
1789  ASSERT_TRUE(AppendInitSegment(false, true));
1790
1791  // Test a simple cluster.
1792  scoped_ptr<Cluster> cluster_1(GenerateSingleStreamCluster(0, 132,
1793                                kVideoTrackNum, kVideoBlockDuration));
1794
1795  ASSERT_TRUE(AppendData(cluster_1->data(), cluster_1->size()));
1796
1797  CheckExpectedRanges("{ [0,132) }");
1798
1799  // Append a disjoint cluster to check for two separate ranges.
1800  scoped_ptr<Cluster> cluster_2(GenerateSingleStreamCluster(200, 299,
1801                                kVideoTrackNum, kVideoBlockDuration));
1802
1803  ASSERT_TRUE(AppendData(cluster_2->data(), cluster_2->size()));
1804
1805  CheckExpectedRanges("{ [0,132) [200,299) }");
1806}
1807
1808TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioVideo) {
1809  ASSERT_TRUE(InitDemuxer(true, true));
1810
1811  // Audio: 0 -> 23
1812  // Video: 0 -> 33
1813  // Buffered Range: 0 -> 23
1814  // Audio block duration is smaller than video block duration,
1815  // so the buffered ranges should correspond to the audio blocks.
1816  scoped_ptr<Cluster> cluster_a0(
1817      GenerateSingleStreamCluster(0, kAudioBlockDuration, kAudioTrackNum,
1818                                  kAudioBlockDuration));
1819
1820  scoped_ptr<Cluster> cluster_v0(
1821      GenerateSingleStreamCluster(0, kVideoBlockDuration, kVideoTrackNum,
1822                                  kVideoBlockDuration));
1823
1824  ASSERT_TRUE(AppendData(cluster_a0->data(), cluster_a0->size()));
1825  ASSERT_TRUE(AppendData(cluster_v0->data(), cluster_v0->size()));
1826
1827  CheckExpectedRanges("{ [0,23) }");
1828
1829  // Audio: 300 -> 400
1830  // Video: 320 -> 420
1831  // Buffered Range: 320 -> 400  (end overlap)
1832  scoped_ptr<Cluster> cluster_a1(
1833      GenerateSingleStreamCluster(300, 400, kAudioTrackNum, 50));
1834
1835  scoped_ptr<Cluster> cluster_v1(
1836      GenerateSingleStreamCluster(320, 420, kVideoTrackNum, 50));
1837
1838  ASSERT_TRUE(AppendData(cluster_a1->data(), cluster_a1->size()));
1839  ASSERT_TRUE(AppendData(cluster_v1->data(), cluster_v1->size()));
1840
1841  CheckExpectedRanges("{ [0,23) [320,400) }");
1842
1843  // Audio: 520 -> 590
1844  // Video: 500 -> 570
1845  // Buffered Range: 520 -> 570  (front overlap)
1846  scoped_ptr<Cluster> cluster_a2(
1847      GenerateSingleStreamCluster(520, 590, kAudioTrackNum, 70));
1848
1849  scoped_ptr<Cluster> cluster_v2(
1850      GenerateSingleStreamCluster(500, 570, kVideoTrackNum, 70));
1851
1852  ASSERT_TRUE(AppendData(cluster_a2->data(), cluster_a2->size()));
1853  ASSERT_TRUE(AppendData(cluster_v2->data(), cluster_v2->size()));
1854
1855  CheckExpectedRanges("{ [0,23) [320,400) [520,570) }");
1856
1857  // Audio: 720 -> 750
1858  // Video: 700 -> 770
1859  // Buffered Range: 720 -> 750  (complete overlap, audio)
1860  scoped_ptr<Cluster> cluster_a3(
1861      GenerateSingleStreamCluster(720, 750, kAudioTrackNum, 30));
1862
1863  scoped_ptr<Cluster> cluster_v3(
1864      GenerateSingleStreamCluster(700, 770, kVideoTrackNum, 70));
1865
1866  ASSERT_TRUE(AppendData(cluster_a3->data(), cluster_a3->size()));
1867  ASSERT_TRUE(AppendData(cluster_v3->data(), cluster_v3->size()));
1868
1869  CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) }");
1870
1871  // Audio: 900 -> 970
1872  // Video: 920 -> 950
1873  // Buffered Range: 920 -> 950  (complete overlap, video)
1874  scoped_ptr<Cluster> cluster_a4(
1875      GenerateSingleStreamCluster(900, 970, kAudioTrackNum, 70));
1876
1877  scoped_ptr<Cluster> cluster_v4(
1878      GenerateSingleStreamCluster(920, 950, kVideoTrackNum, 30));
1879
1880  ASSERT_TRUE(AppendData(cluster_a4->data(), cluster_a4->size()));
1881  ASSERT_TRUE(AppendData(cluster_v4->data(), cluster_v4->size()));
1882
1883  CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) [920,950) }");
1884
1885  // Appending within buffered range should not affect buffered ranges.
1886  scoped_ptr<Cluster> cluster_a5(
1887      GenerateSingleStreamCluster(930, 950, kAudioTrackNum, 20));
1888  ASSERT_TRUE(AppendData(cluster_a5->data(), cluster_a5->size()));
1889  CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) [920,950) }");
1890
1891  // Appending to single stream outside buffered ranges should not affect
1892  // buffered ranges.
1893  scoped_ptr<Cluster> cluster_v5(
1894      GenerateSingleStreamCluster(1230, 1240, kVideoTrackNum, 10));
1895  ASSERT_TRUE(AppendData(cluster_v5->data(), cluster_v5->size()));
1896  CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) [920,950) }");
1897}
1898
1899// Once EndOfStream() is called, GetBufferedRanges should not cut off any
1900// over-hanging tails at the end of the ranges as this is likely due to block
1901// duration differences.
1902TEST_F(ChunkDemuxerTest, GetBufferedRanges_EndOfStream) {
1903  ASSERT_TRUE(InitDemuxer(true, true));
1904
1905  scoped_ptr<Cluster> cluster_a(
1906      GenerateSingleStreamCluster(0, 90, kAudioTrackNum, 90));
1907  scoped_ptr<Cluster> cluster_v(
1908      GenerateSingleStreamCluster(0, 100, kVideoTrackNum, 100));
1909
1910  ASSERT_TRUE(AppendData(cluster_a->data(), cluster_a->size()));
1911  ASSERT_TRUE(AppendData(cluster_v->data(), cluster_v->size()));
1912
1913  CheckExpectedRanges("{ [0,90) }");
1914
1915  EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(100)));
1916  demuxer_->EndOfStream(PIPELINE_OK);
1917
1918  CheckExpectedRanges("{ [0,100) }");
1919}
1920
1921TEST_F(ChunkDemuxerTest, TestDifferentStreamTimecodes) {
1922  ASSERT_TRUE(InitDemuxer(true, true));
1923
1924  scoped_refptr<DemuxerStream> audio =
1925      demuxer_->GetStream(DemuxerStream::AUDIO);
1926  scoped_refptr<DemuxerStream> video =
1927      demuxer_->GetStream(DemuxerStream::VIDEO);
1928
1929  // Create a cluster where the video timecode begins 25ms after the audio.
1930  scoped_ptr<Cluster> start_cluster(GenerateCluster(0, 25, 8));
1931  ASSERT_TRUE(AppendData(start_cluster->data(), start_cluster->size()));
1932
1933  demuxer_->Seek(base::TimeDelta::FromSeconds(0),
1934                 NewExpectedStatusCB(PIPELINE_OK));
1935  GenerateExpectedReads(0, 25, 8, audio, video);
1936
1937  // Seek to 5 seconds.
1938  demuxer_->StartWaitingForSeek();
1939  demuxer_->Seek(base::TimeDelta::FromSeconds(5),
1940                 NewExpectedStatusCB(PIPELINE_OK));
1941
1942  // Generate a cluster to fulfill this seek, where audio timecode begins 25ms
1943  // after the video.
1944  scoped_ptr<Cluster> middle_cluster(GenerateCluster(5025, 5000, 8));
1945  ASSERT_TRUE(AppendData(middle_cluster->data(), middle_cluster->size()));
1946  GenerateExpectedReads(5025, 5000, 8, audio, video);
1947}
1948
1949TEST_F(ChunkDemuxerTest, TestDifferentStreamTimecodesSeparateSources) {
1950  std::string audio_id = "audio1";
1951  std::string video_id = "video1";
1952  ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1953
1954  scoped_refptr<DemuxerStream> audio =
1955      demuxer_->GetStream(DemuxerStream::AUDIO);
1956  scoped_refptr<DemuxerStream> video =
1957      demuxer_->GetStream(DemuxerStream::VIDEO);
1958
1959  // Generate two streams where the video stream starts 5ms after the audio
1960  // stream and append them.
1961  scoped_ptr<Cluster> cluster_v(
1962      GenerateSingleStreamCluster(30, 4 * kVideoBlockDuration + 30,
1963                                  kVideoTrackNum, kVideoBlockDuration));
1964  scoped_ptr<Cluster> cluster_a(
1965      GenerateSingleStreamCluster(25, 4 * kAudioBlockDuration + 25,
1966                                  kAudioTrackNum, kAudioBlockDuration));
1967  ASSERT_TRUE(AppendData(audio_id, cluster_a->data(), cluster_a->size()));
1968  ASSERT_TRUE(AppendData(video_id, cluster_v->data(), cluster_v->size()));
1969
1970  // Both streams should be able to fulfill a seek to 25.
1971  demuxer_->Seek(base::TimeDelta::FromMilliseconds(25),
1972                 NewExpectedStatusCB(PIPELINE_OK));
1973  GenerateSingleStreamExpectedReads(25, 4, audio, kAudioBlockDuration);
1974  GenerateSingleStreamExpectedReads(30, 4, video, kVideoBlockDuration);
1975}
1976
1977TEST_F(ChunkDemuxerTest, TestDifferentStreamTimecodesOutOfRange) {
1978  std::string audio_id = "audio1";
1979  std::string video_id = "video1";
1980  ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1981
1982  scoped_refptr<DemuxerStream> audio =
1983      demuxer_->GetStream(DemuxerStream::AUDIO);
1984  scoped_refptr<DemuxerStream> video =
1985      demuxer_->GetStream(DemuxerStream::VIDEO);
1986
1987  // Generate two streams where the video stream starts 10s after the audio
1988  // stream and append them.
1989  scoped_ptr<Cluster> cluster_v(
1990      GenerateSingleStreamCluster(10000, 4 * kVideoBlockDuration + 10000,
1991                                  kVideoTrackNum, kVideoBlockDuration));
1992  scoped_ptr<Cluster> cluster_a(
1993      GenerateSingleStreamCluster(0, 4 * kAudioBlockDuration + 0,
1994                                  kAudioTrackNum, kAudioBlockDuration));
1995  ASSERT_TRUE(AppendData(audio_id, cluster_a->data(), cluster_a->size()));
1996  ASSERT_TRUE(AppendData(video_id, cluster_v->data(), cluster_v->size()));
1997
1998  // Should not be able to fulfill a seek to 0.
1999  demuxer_->Seek(base::TimeDelta::FromMilliseconds(0),
2000                 NewExpectedStatusCB(PIPELINE_ERROR_ABORT));
2001  ExpectRead(audio, 0);
2002  ExpectEndOfStream(video);
2003}
2004
2005TEST_F(ChunkDemuxerTest, TestClusterWithNoBuffers) {
2006  ASSERT_TRUE(InitDemuxer(true, true));
2007
2008  // Generate and append an empty cluster beginning at 0.
2009  ASSERT_TRUE(AppendEmptyCluster(0));
2010
2011  // Sanity check that data can be appended after this cluster correctly.
2012  scoped_ptr<Cluster> media_data(GenerateCluster(0, 2));
2013  ASSERT_TRUE(AppendData(media_data->data(), media_data->size()));
2014  scoped_refptr<DemuxerStream> audio =
2015      demuxer_->GetStream(DemuxerStream::AUDIO);
2016  scoped_refptr<DemuxerStream> video =
2017      demuxer_->GetStream(DemuxerStream::VIDEO);
2018  ExpectRead(audio, 0);
2019  ExpectRead(video, 0);
2020}
2021
2022TEST_F(ChunkDemuxerTest, TestCodecPrefixMatching) {
2023  ChunkDemuxer::Status expected = ChunkDemuxer::kNotSupported;
2024
2025#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
2026  expected = ChunkDemuxer::kOk;
2027#endif
2028
2029  std::vector<std::string> codecs;
2030  codecs.push_back("avc1.4D4041");
2031  codecs.push_back("mp4a.40.2");
2032
2033  EXPECT_EQ(demuxer_->AddId("source_id", "video/mp4", codecs), expected);
2034}
2035
2036TEST_F(ChunkDemuxerTest, TestEndOfStreamFailures) {
2037  std::string audio_id = "audio";
2038  std::string video_id = "video";
2039
2040  ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
2041
2042  scoped_ptr<Cluster> cluster_a1(
2043      GenerateSingleStreamCluster(0, 35, kAudioTrackNum, 35));
2044  scoped_ptr<Cluster> cluster_v1(
2045      GenerateSingleStreamCluster(0, 10, kVideoTrackNum, 5));
2046  scoped_ptr<Cluster> cluster_v2(
2047      GenerateSingleStreamCluster(10, 25, kVideoTrackNum, 5));
2048  scoped_ptr<Cluster> cluster_v3(
2049      GenerateSingleStreamCluster(30, 50, kVideoTrackNum, 10));
2050
2051  ASSERT_TRUE(AppendData(audio_id, cluster_a1->data(), cluster_a1->size()));
2052  ASSERT_TRUE(AppendData(video_id, cluster_v1->data(), cluster_v1->size()));
2053  ASSERT_TRUE(AppendData(video_id, cluster_v3->data(), cluster_v3->size()));
2054
2055  CheckExpectedRanges(audio_id, "{ [0,35) }");
2056  CheckExpectedRanges(video_id, "{ [0,10) [30,50) }");
2057
2058  // Make sure that end of stream fails because there is a gap between
2059  // the current position(0) and the end of the appended data.
2060  EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(50)));
2061  ASSERT_FALSE(demuxer_->EndOfStream(PIPELINE_OK));
2062
2063  // Seek to an time that is inside the last ranges for both streams
2064  // and verify that the EndOfStream() is successful.
2065  demuxer_->StartWaitingForSeek();
2066  demuxer_->Seek(base::TimeDelta::FromMilliseconds(30),
2067                 NewExpectedStatusCB(PIPELINE_OK));
2068
2069  ASSERT_TRUE(demuxer_->EndOfStream(PIPELINE_OK));
2070
2071  // Seek back to 0 and verify that EndOfStream() fails again.
2072  demuxer_->StartWaitingForSeek();
2073  demuxer_->Seek(base::TimeDelta::FromMilliseconds(0),
2074                 NewExpectedStatusCB(PIPELINE_OK));
2075
2076  ASSERT_FALSE(demuxer_->EndOfStream(PIPELINE_OK));
2077
2078  // Append the missing range and verify that EndOfStream() succeeds now.
2079  ASSERT_TRUE(AppendData(video_id, cluster_v2->data(), cluster_v2->size()));
2080
2081  CheckExpectedRanges(audio_id, "{ [0,35) }");
2082  CheckExpectedRanges(video_id, "{ [0,50) }");
2083
2084  ASSERT_TRUE(demuxer_->EndOfStream(PIPELINE_OK));
2085}
2086
2087TEST_F(ChunkDemuxerTest, TestGetBufferedRangesBeforeInitSegment) {
2088  EXPECT_CALL(*this, DemuxerOpened());
2089  demuxer_->Initialize(&host_, CreateInitDoneCB(PIPELINE_OK));
2090  ASSERT_EQ(AddId("audio", true, false), ChunkDemuxer::kOk);
2091  ASSERT_EQ(AddId("video", false, true), ChunkDemuxer::kOk);
2092
2093  CheckExpectedRanges("audio", "{ }");
2094  CheckExpectedRanges("video", "{ }");
2095}
2096
2097// Test that Seek() completes successfully when the first cluster
2098// arrives.
2099TEST_F(ChunkDemuxerTest, TestEndOfStreamDuringSeek) {
2100  InSequence s;
2101
2102  ASSERT_TRUE(InitDemuxer(true, true));
2103
2104  scoped_ptr<Cluster> cluster_a(kDefaultFirstCluster());
2105  scoped_ptr<Cluster> cluster_b(kDefaultSecondCluster());
2106  ASSERT_TRUE(AppendData(cluster_a->data(), cluster_a->size()));
2107
2108  demuxer_->StartWaitingForSeek();
2109
2110  ASSERT_TRUE(AppendData(cluster_b->data(), cluster_b->size()));
2111  EXPECT_CALL(host_, SetDuration(
2112      base::TimeDelta::FromMilliseconds(kDefaultSecondClusterEndTimestamp)));
2113  demuxer_->EndOfStream(PIPELINE_OK);
2114
2115  demuxer_->Seek(base::TimeDelta::FromSeconds(0),
2116                 NewExpectedStatusCB(PIPELINE_OK));
2117
2118  scoped_refptr<DemuxerStream> audio =
2119      demuxer_->GetStream(DemuxerStream::AUDIO);
2120  scoped_refptr<DemuxerStream> video =
2121      demuxer_->GetStream(DemuxerStream::VIDEO);
2122
2123  GenerateExpectedReads(0, 4, audio, video);
2124  GenerateExpectedReads(46, 66, 5, audio, video);
2125
2126  EndOfStreamHelper end_of_stream_helper(demuxer_);
2127  end_of_stream_helper.RequestReads();
2128  end_of_stream_helper.CheckIfReadDonesWereCalled(true);
2129}
2130
2131TEST_F(ChunkDemuxerTest, TestConfigChange_Video) {
2132  InSequence s;
2133
2134  ASSERT_TRUE(InitDemuxerWithConfigChangeData());
2135
2136  scoped_refptr<DemuxerStream> stream =
2137      demuxer_->GetStream(DemuxerStream::VIDEO);
2138  DemuxerStream::Status status;
2139  base::TimeDelta last_timestamp;
2140
2141  // Fetch initial video config and verify it matches what we expect.
2142  const VideoDecoderConfig& video_config_1 = stream->video_decoder_config();
2143  ASSERT_TRUE(video_config_1.IsValidConfig());
2144  EXPECT_EQ(video_config_1.natural_size().width(), 320);
2145  EXPECT_EQ(video_config_1.natural_size().height(), 240);
2146
2147  ExpectRead(stream, 0);
2148
2149  ReadUntilNotOkOrEndOfStream(stream, &status, &last_timestamp);
2150
2151  ASSERT_EQ(status, DemuxerStream::kConfigChanged);
2152  EXPECT_EQ(last_timestamp.InMilliseconds(), 501);
2153
2154  // Fetch the new decoder config.
2155  const VideoDecoderConfig& video_config_2 = stream->video_decoder_config();
2156  ASSERT_TRUE(video_config_2.IsValidConfig());
2157  EXPECT_EQ(video_config_2.natural_size().width(), 640);
2158  EXPECT_EQ(video_config_2.natural_size().height(), 360);
2159
2160  ExpectRead(stream, 527);
2161
2162  // Read until the next config change.
2163  ReadUntilNotOkOrEndOfStream(stream, &status, &last_timestamp);
2164  ASSERT_EQ(status, DemuxerStream::kConfigChanged);
2165  EXPECT_EQ(last_timestamp.InMilliseconds(), 793);
2166
2167  // Get the new config and verify that it matches the first one.
2168  ASSERT_TRUE(video_config_1.Matches(stream->video_decoder_config()));
2169
2170  ExpectRead(stream, 801);
2171
2172  // Read until the end of the stream just to make sure there aren't any other
2173  // config changes.
2174  ReadUntilNotOkOrEndOfStream(stream, &status, &last_timestamp);
2175  ASSERT_EQ(status, DemuxerStream::kOk);
2176}
2177
2178TEST_F(ChunkDemuxerTest, TestConfigChange_Audio) {
2179  InSequence s;
2180
2181  ASSERT_TRUE(InitDemuxerWithConfigChangeData());
2182
2183  scoped_refptr<DemuxerStream> stream =
2184      demuxer_->GetStream(DemuxerStream::AUDIO);
2185  DemuxerStream::Status status;
2186  base::TimeDelta last_timestamp;
2187
2188  // Fetch initial audio config and verify it matches what we expect.
2189  const AudioDecoderConfig& audio_config_1 = stream->audio_decoder_config();
2190  ASSERT_TRUE(audio_config_1.IsValidConfig());
2191  EXPECT_EQ(audio_config_1.samples_per_second(), 44100);
2192  EXPECT_EQ(audio_config_1.extra_data_size(), 3863u);
2193
2194  ExpectRead(stream, 0);
2195
2196  ReadUntilNotOkOrEndOfStream(stream, &status, &last_timestamp);
2197
2198  ASSERT_EQ(status, DemuxerStream::kConfigChanged);
2199  EXPECT_EQ(last_timestamp.InMilliseconds(), 524);
2200
2201  // Fetch the new decoder config.
2202  const AudioDecoderConfig& audio_config_2 = stream->audio_decoder_config();
2203  ASSERT_TRUE(audio_config_2.IsValidConfig());
2204  EXPECT_EQ(audio_config_2.samples_per_second(), 44100);
2205  EXPECT_EQ(audio_config_2.extra_data_size(), 3935u);
2206
2207  ExpectRead(stream, 527);
2208
2209  // Read until the next config change.
2210  ReadUntilNotOkOrEndOfStream(stream, &status, &last_timestamp);
2211  ASSERT_EQ(status, DemuxerStream::kConfigChanged);
2212  EXPECT_EQ(last_timestamp.InMilliseconds(), 759);
2213
2214  // Get the new config and verify that it matches the first one.
2215  ASSERT_TRUE(audio_config_1.Matches(stream->audio_decoder_config()));
2216
2217  ExpectRead(stream, 779);
2218
2219  // Read until the end of the stream just to make sure there aren't any other
2220  // config changes.
2221  ReadUntilNotOkOrEndOfStream(stream, &status, &last_timestamp);
2222  ASSERT_EQ(status, DemuxerStream::kOk);
2223}
2224
2225TEST_F(ChunkDemuxerTest, TestConfigChange_Seek) {
2226  InSequence s;
2227
2228  ASSERT_TRUE(InitDemuxerWithConfigChangeData());
2229
2230  scoped_refptr<DemuxerStream> stream =
2231      demuxer_->GetStream(DemuxerStream::VIDEO);
2232
2233  // Fetch initial video config and verify it matches what we expect.
2234  const VideoDecoderConfig& video_config_1 = stream->video_decoder_config();
2235  ASSERT_TRUE(video_config_1.IsValidConfig());
2236  EXPECT_EQ(video_config_1.natural_size().width(), 320);
2237  EXPECT_EQ(video_config_1.natural_size().height(), 240);
2238
2239  ExpectRead(stream, 0);
2240
2241  // Seek to a location with a different config.
2242  demuxer_->Seek(base::TimeDelta::FromMilliseconds(527),
2243                 NewExpectedStatusCB(PIPELINE_OK));
2244
2245  // Verify that the config change is signalled.
2246  ExpectConfigChanged(stream);
2247
2248  // Fetch the new decoder config and verify it is what we expect.
2249  const VideoDecoderConfig& video_config_2 = stream->video_decoder_config();
2250  ASSERT_TRUE(video_config_2.IsValidConfig());
2251  EXPECT_EQ(video_config_2.natural_size().width(), 640);
2252  EXPECT_EQ(video_config_2.natural_size().height(), 360);
2253
2254  // Verify that Read() will return a buffer now.
2255  ExpectRead(stream, 527);
2256
2257  // Seek back to the beginning and verify we get another config change.
2258  demuxer_->Seek(base::TimeDelta::FromMilliseconds(0),
2259                 NewExpectedStatusCB(PIPELINE_OK));
2260  ExpectConfigChanged(stream);
2261  ASSERT_TRUE(video_config_1.Matches(stream->video_decoder_config()));
2262  ExpectRead(stream, 0);
2263
2264  // Seek to a location that requires a config change and then
2265  // seek to a new location that has the same configuration as
2266  // the start of the file without a Read() in the middle.
2267  demuxer_->Seek(base::TimeDelta::FromMilliseconds(527),
2268                 NewExpectedStatusCB(PIPELINE_OK));
2269  demuxer_->Seek(base::TimeDelta::FromMilliseconds(801),
2270                 NewExpectedStatusCB(PIPELINE_OK));
2271
2272  // Verify that no config change is signalled.
2273  ExpectRead(stream, 801);
2274  ASSERT_TRUE(video_config_1.Matches(stream->video_decoder_config()));
2275}
2276
2277TEST_F(ChunkDemuxerTest, TestTimestampPositiveOffset) {
2278  ASSERT_TRUE(InitDemuxer(true, true));
2279
2280  ASSERT_TRUE(demuxer_->SetTimestampOffset(
2281      kSourceId, base::TimeDelta::FromSeconds(30)));
2282  scoped_ptr<Cluster> cluster(GenerateCluster(0, 2));
2283  ASSERT_TRUE(AppendData(cluster->data(), cluster->size()));
2284
2285  demuxer_->StartWaitingForSeek();
2286  demuxer_->Seek(base::TimeDelta::FromMilliseconds(30000),
2287                 NewExpectedStatusCB(PIPELINE_OK));
2288
2289  scoped_refptr<DemuxerStream> audio =
2290      demuxer_->GetStream(DemuxerStream::AUDIO);
2291  scoped_refptr<DemuxerStream> video =
2292      demuxer_->GetStream(DemuxerStream::VIDEO);
2293  GenerateExpectedReads(30000, 2, audio, video);
2294}
2295
2296TEST_F(ChunkDemuxerTest, TestTimestampNegativeOffset) {
2297  ASSERT_TRUE(InitDemuxer(true, true));
2298
2299  ASSERT_TRUE(demuxer_->SetTimestampOffset(
2300      kSourceId, base::TimeDelta::FromSeconds(-1)));
2301  scoped_ptr<Cluster> cluster = GenerateCluster(1000, 2);
2302  ASSERT_TRUE(AppendData(cluster->data(), cluster->size()));
2303
2304  scoped_refptr<DemuxerStream> audio =
2305      demuxer_->GetStream(DemuxerStream::AUDIO);
2306  scoped_refptr<DemuxerStream> video =
2307      demuxer_->GetStream(DemuxerStream::VIDEO);
2308  GenerateExpectedReads(0, 2, audio, video);
2309}
2310
2311TEST_F(ChunkDemuxerTest, TestTimestampOffsetSeparateStreams) {
2312  std::string audio_id = "audio1";
2313  std::string video_id = "video1";
2314  ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
2315
2316  scoped_refptr<DemuxerStream> audio =
2317      demuxer_->GetStream(DemuxerStream::AUDIO);
2318  scoped_refptr<DemuxerStream> video =
2319      demuxer_->GetStream(DemuxerStream::VIDEO);
2320
2321  scoped_ptr<Cluster> cluster_a1(
2322      GenerateSingleStreamCluster(
2323          2500, 2500 + kAudioBlockDuration * 4, kAudioTrackNum,
2324          kAudioBlockDuration));
2325
2326  scoped_ptr<Cluster> cluster_v1(
2327      GenerateSingleStreamCluster(
2328          2500, 2500 + kVideoBlockDuration * 4, kVideoTrackNum,
2329          kVideoBlockDuration));
2330
2331  scoped_ptr<Cluster> cluster_a2(
2332      GenerateSingleStreamCluster(
2333          0, kAudioBlockDuration * 4, kAudioTrackNum, kAudioBlockDuration));
2334
2335  scoped_ptr<Cluster> cluster_v2(
2336      GenerateSingleStreamCluster(
2337          0, kVideoBlockDuration * 4, kVideoTrackNum, kVideoBlockDuration));
2338
2339  ASSERT_TRUE(demuxer_->SetTimestampOffset(
2340      audio_id, base::TimeDelta::FromMilliseconds(-2500)));
2341  ASSERT_TRUE(demuxer_->SetTimestampOffset(
2342      video_id, base::TimeDelta::FromMilliseconds(-2500)));
2343  ASSERT_TRUE(AppendData(audio_id, cluster_a1->data(), cluster_a1->size()));
2344  ASSERT_TRUE(AppendData(video_id, cluster_v1->data(), cluster_v1->size()));
2345  GenerateSingleStreamExpectedReads(0, 4, audio, kAudioBlockDuration);
2346  GenerateSingleStreamExpectedReads(0, 4, video, kVideoBlockDuration);
2347
2348  demuxer_->StartWaitingForSeek();
2349  demuxer_->Seek(base::TimeDelta::FromMilliseconds(27300),
2350                 NewExpectedStatusCB(PIPELINE_OK));
2351
2352  ASSERT_TRUE(demuxer_->SetTimestampOffset(
2353      audio_id, base::TimeDelta::FromMilliseconds(27300)));
2354  ASSERT_TRUE(demuxer_->SetTimestampOffset(
2355      video_id, base::TimeDelta::FromMilliseconds(27300)));
2356  ASSERT_TRUE(AppendData(audio_id, cluster_a2->data(), cluster_a2->size()));
2357  ASSERT_TRUE(AppendData(video_id, cluster_v2->data(), cluster_v2->size()));
2358  GenerateSingleStreamExpectedReads(27300, 4, video, kVideoBlockDuration);
2359  GenerateSingleStreamExpectedReads(27300, 4, audio, kAudioBlockDuration);
2360}
2361
2362TEST_F(ChunkDemuxerTest, TestTimestampOffsetMidParse) {
2363  ASSERT_TRUE(InitDemuxer(true, true));
2364
2365  scoped_ptr<Cluster> cluster = GenerateCluster(0, 2);
2366  // Append only part of the cluster data.
2367  ASSERT_TRUE(AppendData(cluster->data(), cluster->size() - 13));
2368
2369  // Setting a timestamp should fail because we're in the middle of a cluster.
2370  ASSERT_FALSE(demuxer_->SetTimestampOffset(
2371      kSourceId, base::TimeDelta::FromSeconds(25)));
2372
2373  demuxer_->Abort(kSourceId);
2374  // After Abort(), setting a timestamp should succeed since we're no longer
2375  // in the middle of a cluster
2376  ASSERT_TRUE(demuxer_->SetTimestampOffset(
2377      kSourceId, base::TimeDelta::FromSeconds(25)));
2378}
2379
2380TEST_F(ChunkDemuxerTest, TestDurationChange) {
2381  ASSERT_TRUE(InitDemuxer(true, true));
2382  static const int kStreamDuration = kDefaultDuration().InMilliseconds();
2383
2384  // Add data leading up to the currently set duration.
2385  scoped_ptr<Cluster> first_cluster = GenerateCluster(
2386      kStreamDuration - kAudioBlockDuration,
2387      kStreamDuration - kVideoBlockDuration, 2);
2388  ASSERT_TRUE(AppendData(first_cluster->data(), first_cluster->size()));
2389
2390  CheckExpectedRanges(kSourceId, "{ [201191,201224) }");
2391
2392  // Add data at the currently set duration. The duration should not increase.
2393  scoped_ptr<Cluster> second_cluster = GenerateCluster(
2394      kDefaultDuration().InMilliseconds(), 2);
2395  ASSERT_TRUE(AppendData(second_cluster->data(), second_cluster->size()));
2396
2397  // Range should not be affected.
2398  CheckExpectedRanges(kSourceId, "{ [201191,201224) }");
2399
2400  // Now add data past the duration and expect a new duration to be signalled.
2401  static const int kNewStreamDuration =
2402      kStreamDuration + kAudioBlockDuration * 2;
2403  scoped_ptr<Cluster> third_cluster = GenerateCluster(
2404      kStreamDuration + kAudioBlockDuration,
2405      kStreamDuration + kVideoBlockDuration, 2);
2406  EXPECT_CALL(host_, SetDuration(
2407      base::TimeDelta::FromMilliseconds(kNewStreamDuration)));
2408  ASSERT_TRUE(AppendData(third_cluster->data(), third_cluster->size()));
2409
2410  // See that the range has increased appropriately.
2411  CheckExpectedRanges(kSourceId, "{ [201191,201270) }");
2412}
2413
2414TEST_F(ChunkDemuxerTest, TestDurationChangeTimestampOffset) {
2415  ASSERT_TRUE(InitDemuxer(true, true));
2416
2417  ASSERT_TRUE(demuxer_->SetTimestampOffset(kSourceId, kDefaultDuration()));
2418  scoped_ptr<Cluster> cluster = GenerateCluster(0, 4);
2419
2420  EXPECT_CALL(host_, SetDuration(
2421      kDefaultDuration() + base::TimeDelta::FromMilliseconds(
2422          kAudioBlockDuration * 2)));
2423  ASSERT_TRUE(AppendData(cluster->data(), cluster->size()));
2424}
2425
2426TEST_F(ChunkDemuxerTest, TestEndOfStreamTruncateDuration) {
2427  ASSERT_TRUE(InitDemuxer(true, true));
2428
2429  scoped_ptr<Cluster> cluster_a(kDefaultFirstCluster());
2430  ASSERT_TRUE(AppendData(cluster_a->data(), cluster_a->size()));
2431
2432  EXPECT_CALL(host_, SetDuration(
2433      base::TimeDelta::FromMilliseconds(kDefaultFirstClusterEndTimestamp)));
2434  demuxer_->EndOfStream(PIPELINE_OK);
2435}
2436
2437}  // namespace media
2438