ChunkDemuxerTest()
: append_window_end_for_next_append_(kInfiniteDuration()) {
+ init_segment_received_cb_ =
+ base::Bind(&ChunkDemuxerTest::InitSegmentReceived,
+ base::Unretained(this));
CreateNewDemuxer();
}
demuxer_->AppendData(source_id, data, length,
append_window_start_for_next_append_,
append_window_end_for_next_append_,
- ×tamp_offset_map_[source_id]);
+ ×tamp_offset_map_[source_id],
+ init_segment_received_cb_);
}
void AppendDataInPieces(const uint8* data, size_t length) {
expected_duration = kDefaultDuration();
EXPECT_CALL(*this, DemuxerOpened());
+
+ // Adding expectation prior to CreateInitDoneCB() here because InSequence
+ // tests require init segment received before duration set. Also, only
+ // expect an init segment received callback if there is actually a track in
+ // it.
+ if (stream_flags != 0)
+ EXPECT_CALL(*this, InitSegmentReceived());
+
demuxer_->Initialize(
&host_, CreateInitDoneCB(expected_duration, expected_status), true);
video_flags |= HAS_TEXT;
}
+ EXPECT_CALL(*this, InitSegmentReceived());
AppendInitSegmentWithSourceId(audio_id, audio_flags);
+ EXPECT_CALL(*this, InitSegmentReceived());
AppendInitSegmentWithSourceId(video_id, video_flags);
return true;
}
EXPECT_CALL(*this, DemuxerOpened());
+ // Adding expectation prior to CreateInitDoneCB() here because InSequence
+ // tests require init segment received before duration set.
+ EXPECT_CALL(*this, InitSegmentReceived());
demuxer_->Initialize(
&host_, CreateInitDoneCB(base::TimeDelta::FromMilliseconds(2744),
PIPELINE_OK), true);
// media/test/data/bear-320x240-manifest.js which were
// generated from media/test/data/bear-640x360.webm and
// media/test/data/bear-320x240.webm respectively.
+ EXPECT_CALL(*this, InitSegmentReceived());
AppendData(bear2->data(), 4340);
// Append a media segment that goes from [0.527000, 1.014000).
// Append initialization segment for bear1 & fill gap with [779-1197)
// segment.
+ EXPECT_CALL(*this, InitSegmentReceived());
AppendData(bear1->data(), 4370);
AppendData(bear1->data() + 72737, 28183);
CheckExpectedRanges(kSourceId, "{ [0,2736) }");
void CheckExpectedRanges(const std::string& id,
const std::string& expected) {
- Ranges<base::TimeDelta> r = demuxer_->GetBufferedRanges(id);
+ CheckExpectedRanges(demuxer_->GetBufferedRanges(id), expected);
+ }
+
+ void CheckExpectedRanges(DemuxerStream::Type type,
+ const std::string& expected) {
+ ChunkDemuxerStream* stream =
+ static_cast<ChunkDemuxerStream*>(demuxer_->GetStream(type));
+ CheckExpectedRanges(stream->GetBufferedRanges(kDefaultDuration()),
+ expected);
+ }
+ void CheckExpectedRanges(const Ranges<base::TimeDelta>& r,
+ const std::string& expected) {
std::stringstream ss;
ss << "{ ";
for (size_t i = 0; i < r.size(); ++i) {
// Read a WebM file into memory and send the data to the demuxer.
scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename);
+ EXPECT_CALL(*this, InitSegmentReceived());
AppendDataInPieces(buffer->data(), buffer->data_size(), 512);
// Verify that the timestamps on the first few packets match what we
NeedKeyMock(type, init_data_ptr, init_data.size());
}
+ MOCK_METHOD0(InitSegmentReceived, void(void));
+
void Seek(base::TimeDelta seek_time) {
demuxer_->StartWaitingForSeek(seek_time);
demuxer_->Seek(seek_time, NewExpectedStatusCB(PIPELINE_OK));
MockDemuxerHost host_;
scoped_ptr<ChunkDemuxer> demuxer_;
+ ChunkDemuxer::InitSegmentReceivedCB init_segment_received_cb_;
base::TimeDelta append_window_start_for_next_append_;
base::TimeDelta append_window_end_for_next_append_;
CreateInitSegmentWithAlternateTextTrackNum(HAS_TEXT | HAS_AUDIO | HAS_VIDEO,
false, false,
&info_tracks, &info_tracks_size);
+ EXPECT_CALL(*this, InitSegmentReceived());
demuxer_->AppendData(kSourceId, info_tracks.get(), info_tracks_size,
append_window_start_for_next_append_,
append_window_end_for_next_append_,
- ×tamp_offset_map_[kSourceId]);
+ ×tamp_offset_map_[kSourceId],
+ init_segment_received_cb_);
AppendMuxedCluster(
MuxedStreamInfo(kAudioTrackNum, "46K 69K"),
MuxedStreamInfo(kTextTrackNum, "25K 40K"));
CheckExpectedRanges(kSourceId, "{ [23,46) }");
+ EXPECT_CALL(*this, InitSegmentReceived());
AppendInitSegment(HAS_TEXT | HAS_AUDIO | HAS_VIDEO);
AppendMuxedCluster(
MuxedStreamInfo(kAudioTrackNum, "46K 69K"),
EXPECT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk);
EXPECT_EQ(AddId("video", HAS_VIDEO), ChunkDemuxer::kOk);
+ EXPECT_CALL(*this, InitSegmentReceived());
AppendInitSegmentWithSourceId("audio", HAS_AUDIO);
ShutdownDemuxer();
EXPECT_CALL(host_, AddTextStream(_, _))
.Times(Exactly(1));
+ EXPECT_CALL(*this, InitSegmentReceived());
AppendInitSegmentWithSourceId("video_and_text", HAS_VIDEO | HAS_TEXT);
ShutdownDemuxer();
demuxer_->AppendData(kSourceId, info_tracks.get(), info_tracks_size,
append_window_start_for_next_append_,
append_window_end_for_next_append_,
- ×tamp_offset_map_[kSourceId]);
+ ×tamp_offset_map_[kSourceId],
+ init_segment_received_cb_);
}
// Make sure Read() callbacks are dispatched with the proper data.
demuxer_->AppendData(kSourceId, cluster_c->data(), cluster_c->size(),
append_window_start_for_next_append_,
append_window_end_for_next_append_,
- ×tamp_offset_map_[kSourceId]);
+ ×tamp_offset_map_[kSourceId],
+ init_segment_received_cb_);
}
TEST_F(ChunkDemuxerTest, NonMonotonicButAboveClusterTimecode) {
demuxer_->AppendData(kSourceId, cluster_b->data(), cluster_b->size(),
append_window_start_for_next_append_,
append_window_end_for_next_append_,
- ×tamp_offset_map_[kSourceId]);
+ ×tamp_offset_map_[kSourceId],
+ init_segment_received_cb_);
}
TEST_F(ChunkDemuxerTest, BackwardsAndBeforeClusterTimecode) {
demuxer_->AppendData(kSourceId, cluster_b->data(), cluster_b->size(),
append_window_start_for_next_append_,
append_window_end_for_next_append_,
- ×tamp_offset_map_[kSourceId]);
+ ×tamp_offset_map_[kSourceId],
+ init_segment_received_cb_);
}
memcpy(dst, cluster_b->data(), cluster_b->size());
dst += cluster_b->size();
+ EXPECT_CALL(*this, InitSegmentReceived());
AppendDataInPieces(buffer.get(), buffer_size);
GenerateExpectedReads(0, 9);
demuxer_->AppendData(kSourceId, &tmp, 1,
append_window_start_for_next_append_,
append_window_end_for_next_append_,
- ×tamp_offset_map_[kSourceId]);
+ ×tamp_offset_map_[kSourceId],
+ init_segment_received_cb_);
}
TEST_F(ChunkDemuxerTest, AVHeadersWithAudioOnlyType) {
AppendCluster(kDefaultFirstCluster());
// Append another identical initialization segment.
+ EXPECT_CALL(*this, InitSegmentReceived());
AppendInitSegment(HAS_AUDIO | HAS_VIDEO);
AppendCluster(kDefaultSecondCluster());
// Adding an id with audio/video should fail because we already added audio.
ASSERT_EQ(AddId(), ChunkDemuxer::kReachedIdLimit);
+ EXPECT_CALL(*this, InitSegmentReceived());
AppendInitSegmentWithSourceId(audio_id, HAS_AUDIO);
// Adding an id after append should fail.
&host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
ASSERT_EQ(AddId(kSourceId, HAS_AUDIO), ChunkDemuxer::kOk);
+ EXPECT_CALL(*this, InitSegmentReceived());
AppendInitSegment(HAS_AUDIO);
// Test a simple cluster.
&host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
ASSERT_EQ(AddId(kSourceId, HAS_VIDEO), ChunkDemuxer::kOk);
+ EXPECT_CALL(*this, InitSegmentReceived());
AppendInitSegment(HAS_VIDEO);
// Test a simple cluster.
// PTS: 353788 (0x000565fc) [= 90 kHz-Timestamp: 0:00:03.9309]
scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile("bear-1280x720.ts");
+ EXPECT_CALL(*this, InitSegmentReceived());
AppendData(kSourceId, buffer->data(), buffer->data_size());
// Confirm we're in the middle of parsing a media segment.
// PTS: 353788 (0x000565fc) [= 90 kHz-Timestamp: 0:00:03.9309]
scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile("bear-1280x720.ts");
+ EXPECT_CALL(*this, InitSegmentReceived());
AppendData(kSourceId, buffer->data(), buffer->data_size());
// Confirm we're in the middle of parsing a media segment.
AppendCluster(seek_time.InMilliseconds(), 10);
}
+TEST_F(ChunkDemuxerTest, SetMemoryLimitType) {
+ ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
+
+ // Set different memory limits for audio and video.
+ demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 10 * kBlockSize);
+ demuxer_->SetMemoryLimits(DemuxerStream::VIDEO, 5 * kBlockSize);
+
+ base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(1000);
+
+ // Append data at the start that can be garbage collected:
+ AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 10);
+ AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 0, 5);
+
+ CheckExpectedRanges(DemuxerStream::AUDIO, "{ [0,230) }");
+ CheckExpectedRanges(DemuxerStream::VIDEO, "{ [0,165) }");
+
+ // Seek so we can garbage collect the data appended above.
+ Seek(seek_time);
+
+ // Append data at seek_time.
+ AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
+ seek_time.InMilliseconds(), 10);
+ AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
+ seek_time.InMilliseconds(), 5);
+
+ // Verify that the old data, and nothing more, has been garbage collected.
+ CheckExpectedRanges(DemuxerStream::AUDIO, "{ [1000,1230) }");
+ CheckExpectedRanges(DemuxerStream::VIDEO, "{ [1000,1165) }");
+}
+
TEST_F(ChunkDemuxerTest, GCDuringSeek) {
ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
- demuxer_->SetMemoryLimitsForTesting(5 * kBlockSize);
+ demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 5 * kBlockSize);
base::TimeDelta seek_time1 = base::TimeDelta::FromMilliseconds(1000);
base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(500);
// partial append window trim must come from a previous Append() call.
scoped_refptr<DecoderBuffer> buffer =
ReadTestDataFile("bear-320x240-audio-only.webm");
+ EXPECT_CALL(*this, InitSegmentReceived());
AppendDataInPieces(buffer->data(), buffer->data_size(), 128);
DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::AUDIO);
// Read a WebM file into memory and append the data.
scoped_refptr<DecoderBuffer> buffer =
ReadTestDataFile("bear-320x240-audio-only.webm");
+ EXPECT_CALL(*this, InitSegmentReceived());
AppendDataInPieces(buffer->data(), buffer->data_size(), 512);
CheckExpectedRanges(kSourceId, "{ }");
// Read a second WebM with a different config in and append the data.
scoped_refptr<DecoderBuffer> buffer2 =
ReadTestDataFile("bear-320x240-audio-only-48khz.webm");
+ EXPECT_CALL(*this, InitSegmentReceived());
EXPECT_CALL(host_, SetDuration(_)).Times(AnyNumber());
ASSERT_TRUE(SetTimestampOffset(kSourceId, duration_1));
AppendDataInPieces(buffer2->data(), buffer2->data_size(), 512);