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