Index: media/filters/chunk_demuxer_unittest.cc |
diff --git a/media/filters/chunk_demuxer_unittest.cc b/media/filters/chunk_demuxer_unittest.cc |
index be8a2a225129dd10a1665280dd11e2755763699b..2a88a3e5b6a43245a134c44d594b6267eb1ffc73 100644 |
--- a/media/filters/chunk_demuxer_unittest.cc |
+++ b/media/filters/chunk_demuxer_unittest.cc |
@@ -171,10 +171,13 @@ class ChunkDemuxerTest : public testing::Test { |
ShutdownDemuxer(); |
} |
- void CreateInitSegment(bool has_audio, bool has_video, bool has_text, |
+ void CreateInitSegment(int stream_flags, |
bool is_audio_encrypted, bool is_video_encrypted, |
scoped_ptr<uint8[]>* buffer, |
int* size) { |
+ bool has_audio = (stream_flags & HAS_AUDIO) != 0; |
+ bool has_video = (stream_flags & HAS_VIDEO) != 0; |
+ bool has_text = (stream_flags & HAS_TEXT) != 0; |
scoped_refptr<DecoderBuffer> ebml_header; |
scoped_refptr<DecoderBuffer> info; |
scoped_refptr<DecoderBuffer> audio_track_entry; |
@@ -286,11 +289,12 @@ class ChunkDemuxerTest : public testing::Test { |
} |
ChunkDemuxer::Status AddId() { |
- return AddId(kSourceId, true, true); |
+ return AddId(kSourceId, HAS_AUDIO | HAS_VIDEO); |
} |
- ChunkDemuxer::Status AddId(const std::string& source_id, |
- bool has_audio, bool has_video) { |
+ ChunkDemuxer::Status AddId(const std::string& source_id, int stream_flags) { |
+ bool has_audio = (stream_flags & HAS_AUDIO) != 0; |
+ bool has_video = (stream_flags & HAS_VIDEO) != 0; |
std::vector<std::string> codecs; |
std::string type; |
@@ -305,7 +309,7 @@ class ChunkDemuxerTest : public testing::Test { |
} |
if (!has_audio && !has_video) { |
- return AddId(kSourceId, true, true); |
+ return AddId(kSourceId, HAS_AUDIO | HAS_VIDEO); |
} |
return demuxer_->AddId(source_id, type, codecs); |
@@ -408,25 +412,22 @@ class ChunkDemuxerTest : public testing::Test { |
} |
} |
- void AppendInitSegment(bool has_audio, bool has_video) { |
- AppendInitSegmentWithSourceId(kSourceId, has_audio, has_video, false); |
+ void AppendInitSegment(int stream_flags) { |
+ AppendInitSegmentWithSourceId(kSourceId, stream_flags); |
} |
void AppendInitSegmentWithSourceId(const std::string& source_id, |
- bool has_audio, bool has_video, |
- bool has_text) { |
- AppendInitSegmentWithEncryptedInfo( |
- source_id, has_audio, has_video, has_text, false, false); |
+ int stream_flags) { |
+ AppendInitSegmentWithEncryptedInfo(source_id, stream_flags, false, false); |
} |
void AppendInitSegmentWithEncryptedInfo(const std::string& source_id, |
- bool has_audio, bool has_video, |
- bool has_text, |
+ int stream_flags, |
bool is_audio_encrypted, |
bool is_video_encrypted) { |
scoped_ptr<uint8[]> info_tracks; |
int info_tracks_size = 0; |
- CreateInitSegment(has_audio, has_video, has_text, |
+ CreateInitSegment(stream_flags, |
is_audio_encrypted, is_video_encrypted, |
&info_tracks, &info_tracks_size); |
AppendData(source_id, info_tracks.get(), info_tracks_size); |
@@ -470,18 +471,14 @@ class ChunkDemuxerTest : public testing::Test { |
}; |
bool InitDemuxer(int stream_flags) { |
- return InitDemuxerWithEncryptionInfo( |
- (stream_flags & HAS_AUDIO) != 0, |
- (stream_flags & HAS_VIDEO) != 0, |
- (stream_flags & HAS_TEXT) != 0, |
- false, false); |
+ return InitDemuxerWithEncryptionInfo(stream_flags, false, false); |
} |
bool InitDemuxerWithEncryptionInfo( |
- bool has_audio, bool has_video, bool has_text, |
- bool is_audio_encrypted, bool is_video_encrypted) { |
+ int stream_flags, bool is_audio_encrypted, bool is_video_encrypted) { |
+ |
PipelineStatus expected_status = |
- (has_audio || has_video) ? PIPELINE_OK : DEMUXER_ERROR_COULD_NOT_OPEN; |
+ (stream_flags != 0) ? PIPELINE_OK : DEMUXER_ERROR_COULD_NOT_OPEN; |
base::TimeDelta expected_duration = kNoTimestamp(); |
if (expected_status == PIPELINE_OK) |
@@ -491,11 +488,11 @@ class ChunkDemuxerTest : public testing::Test { |
demuxer_->Initialize( |
&host_, CreateInitDoneCB(expected_duration, expected_status), true); |
- if (AddId(kSourceId, has_audio, has_video) != ChunkDemuxer::kOk) |
+ if (AddId(kSourceId, stream_flags) != ChunkDemuxer::kOk) |
return false; |
AppendInitSegmentWithEncryptedInfo( |
- kSourceId, has_audio, has_video, has_text, |
+ kSourceId, stream_flags, |
is_audio_encrypted, is_video_encrypted); |
return true; |
} |
@@ -507,13 +504,21 @@ class ChunkDemuxerTest : public testing::Test { |
demuxer_->Initialize( |
&host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true); |
- if (AddId(audio_id, true, false) != ChunkDemuxer::kOk) |
+ if (AddId(audio_id, HAS_AUDIO) != ChunkDemuxer::kOk) |
return false; |
- if (AddId(video_id, false, true) != ChunkDemuxer::kOk) |
+ if (AddId(video_id, HAS_VIDEO) != ChunkDemuxer::kOk) |
return false; |
- AppendInitSegmentWithSourceId(audio_id, true, false, has_text); |
- AppendInitSegmentWithSourceId(video_id, false, true, has_text); |
+ int audio_flags = HAS_AUDIO; |
+ int video_flags = HAS_VIDEO; |
+ |
+ if (has_text) { |
+ audio_flags |= HAS_TEXT; |
+ video_flags |= HAS_TEXT; |
+ } |
+ |
+ AppendInitSegmentWithSourceId(audio_id, audio_flags); |
+ AppendInitSegmentWithSourceId(video_id, video_flags); |
return true; |
} |
@@ -548,7 +553,7 @@ class ChunkDemuxerTest : public testing::Test { |
&host_, CreateInitDoneCB(base::TimeDelta::FromMilliseconds(2744), |
PIPELINE_OK), true); |
- if (AddId(kSourceId, true, true) != ChunkDemuxer::kOk) |
+ if (AddId(kSourceId, HAS_AUDIO | HAS_VIDEO) != ChunkDemuxer::kOk) |
return false; |
// Append the whole bear1 file. |
@@ -863,18 +868,18 @@ class ChunkDemuxerTest : public testing::Test { |
bool ParseWebMFile(const std::string& filename, |
const BufferTimestamps* timestamps, |
const base::TimeDelta& duration) { |
- return ParseWebMFile(filename, timestamps, duration, true, true); |
+ return ParseWebMFile(filename, timestamps, duration, HAS_AUDIO | HAS_VIDEO); |
} |
bool ParseWebMFile(const std::string& filename, |
const BufferTimestamps* timestamps, |
const base::TimeDelta& duration, |
- bool has_audio, bool has_video) { |
+ int stream_flags) { |
EXPECT_CALL(*this, DemuxerOpened()); |
demuxer_->Initialize( |
&host_, CreateInitDoneCB(duration, PIPELINE_OK), true); |
- if (AddId(kSourceId, has_audio, has_video) != ChunkDemuxer::kOk) |
+ if (AddId(kSourceId, stream_flags) != ChunkDemuxer::kOk) |
return false; |
// Read a WebM file into memory and send the data to the demuxer. |
@@ -968,8 +973,15 @@ TEST_F(ChunkDemuxerTest, Init) { |
.Times(Exactly(need_key_count)); |
} |
+ int stream_flags = 0; |
+ if (has_audio) |
+ stream_flags |= HAS_AUDIO; |
+ |
+ if (has_video) |
+ stream_flags |= HAS_VIDEO; |
+ |
ASSERT_TRUE(InitDemuxerWithEncryptionInfo( |
- has_audio, has_video, false, is_audio_encrypted, is_video_encrypted)); |
+ stream_flags, is_audio_encrypted, is_video_encrypted)); |
DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); |
if (has_audio) { |
@@ -1003,6 +1015,8 @@ TEST_F(ChunkDemuxerTest, Init) { |
} |
} |
+// TODO(acolwell): Fold this test into Init tests since the tests are |
+// almost identical. |
TEST_F(ChunkDemuxerTest, InitText) { |
// Test with 1 video stream and 1 text streams, and 0 or 1 audio streams. |
// No encryption cases handled here. |
@@ -1020,8 +1034,15 @@ TEST_F(ChunkDemuxerTest, InitText) { |
.WillOnce(DoAll(SaveArg<0>(&text_stream), |
SaveArg<1>(&text_config))); |
+ int stream_flags = HAS_TEXT; |
+ if (has_audio) |
+ stream_flags |= HAS_AUDIO; |
+ |
+ if (has_video) |
+ stream_flags |= HAS_VIDEO; |
+ |
ASSERT_TRUE(InitDemuxerWithEncryptionInfo( |
- has_audio, has_video, true, is_audio_encrypted, is_video_encrypted)); |
+ stream_flags, is_audio_encrypted, is_video_encrypted)); |
ASSERT_TRUE(text_stream); |
EXPECT_EQ(DemuxerStream::TEXT, text_stream->type()); |
EXPECT_EQ(kTextSubtitles, text_config.kind()); |
@@ -1060,31 +1081,65 @@ TEST_F(ChunkDemuxerTest, InitText) { |
// Make sure that the demuxer reports an error if Shutdown() |
// is called before all the initialization segments are appended. |
-TEST_F(ChunkDemuxerTest, ShutdownBeforeAllInitSegmentsAppended) { |
+TEST_F(ChunkDemuxerTest, Shutdown_BeforeAllInitSegmentsAppended) { |
EXPECT_CALL(*this, DemuxerOpened()); |
demuxer_->Initialize( |
&host_, CreateInitDoneCB( |
kDefaultDuration(), DEMUXER_ERROR_COULD_NOT_OPEN), true); |
- EXPECT_EQ(AddId("audio", true, false), ChunkDemuxer::kOk); |
- EXPECT_EQ(AddId("video", false, true), ChunkDemuxer::kOk); |
+ EXPECT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk); |
+ EXPECT_EQ(AddId("video", HAS_VIDEO), ChunkDemuxer::kOk); |
+ |
+ AppendInitSegmentWithSourceId("audio", HAS_AUDIO); |
- AppendInitSegmentWithSourceId("audio", true, false, false); |
+ ShutdownDemuxer(); |
} |
-TEST_F(ChunkDemuxerTest, ShutdownBeforeAllInitSegmentsAppendedText) { |
+TEST_F(ChunkDemuxerTest, Shutdown_BeforeAllInitSegmentsAppendedText) { |
EXPECT_CALL(*this, DemuxerOpened()); |
demuxer_->Initialize( |
&host_, CreateInitDoneCB( |
kDefaultDuration(), DEMUXER_ERROR_COULD_NOT_OPEN), true); |
- EXPECT_EQ(AddId("audio", true, false), ChunkDemuxer::kOk); |
- EXPECT_EQ(AddId("video", false, true), ChunkDemuxer::kOk); |
+ EXPECT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk); |
+ EXPECT_EQ(AddId("video_and_text", HAS_VIDEO), ChunkDemuxer::kOk); |
EXPECT_CALL(host_, AddTextStream(_, _)) |
.Times(Exactly(1)); |
- AppendInitSegmentWithSourceId("video", false, true, true); |
+ AppendInitSegmentWithSourceId("video_and_text", HAS_VIDEO | HAS_TEXT); |
+ |
+ ShutdownDemuxer(); |
+} |
+ |
+// Verifies that all streams waiting for data receive an end of stream |
+// buffer when Shutdown() is called. |
+TEST_F(ChunkDemuxerTest, Shutdown_EndOfStreamWhileWaitingForData) { |
+ DemuxerStream* text_stream = NULL; |
+ EXPECT_CALL(host_, AddTextStream(_, _)) |
+ .WillOnce(SaveArg<0>(&text_stream)); |
+ ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT)); |
+ |
+ DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); |
+ DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); |
+ |
+ bool audio_read_done = false; |
+ bool video_read_done = false; |
+ bool text_read_done = false; |
+ audio_stream->Read(base::Bind(&OnReadDone_EOSExpected, &audio_read_done)); |
+ video_stream->Read(base::Bind(&OnReadDone_EOSExpected, &video_read_done)); |
+ text_stream->Read(base::Bind(&OnReadDone_EOSExpected, &text_read_done)); |
+ message_loop_.RunUntilIdle(); |
+ |
+ EXPECT_FALSE(audio_read_done); |
+ EXPECT_FALSE(video_read_done); |
+ EXPECT_FALSE(text_read_done); |
+ |
+ ShutdownDemuxer(); |
+ |
+ EXPECT_TRUE(audio_read_done); |
+ EXPECT_TRUE(video_read_done); |
+ EXPECT_TRUE(text_read_done); |
} |
// Test that Seek() completes successfully when the first cluster |
@@ -1159,7 +1214,7 @@ TEST_F(ChunkDemuxerTest, SeekWhileParsingCluster) { |
TEST_F(ChunkDemuxerTest, AppendDataBeforeInit) { |
scoped_ptr<uint8[]> info_tracks; |
int info_tracks_size = 0; |
- CreateInitSegment(true, true, false, |
+ CreateInitSegment(HAS_AUDIO | HAS_VIDEO, |
false, false, &info_tracks, &info_tracks_size); |
demuxer_->AppendData(kSourceId, info_tracks.get(), info_tracks_size); |
@@ -1528,7 +1583,7 @@ TEST_F(ChunkDemuxerTest, AppendingInPieces) { |
scoped_ptr<uint8[]> info_tracks; |
int info_tracks_size = 0; |
- CreateInitSegment(true, true, false, |
+ CreateInitSegment(HAS_AUDIO | HAS_VIDEO, |
false, false, &info_tracks, &info_tracks_size); |
scoped_ptr<Cluster> cluster_a(kDefaultFirstCluster()); |
@@ -1591,7 +1646,7 @@ TEST_F(ChunkDemuxerTest, WebMFile_AudioOnly) { |
ASSERT_TRUE(ParseWebMFile("bear-320x240-audio-only.webm", buffer_timestamps, |
base::TimeDelta::FromMilliseconds(2744), |
- true, false)); |
+ HAS_AUDIO)); |
} |
TEST_F(ChunkDemuxerTest, WebMFile_VideoOnly) { |
@@ -1606,7 +1661,7 @@ TEST_F(ChunkDemuxerTest, WebMFile_VideoOnly) { |
ASSERT_TRUE(ParseWebMFile("bear-320x240-video-only.webm", buffer_timestamps, |
base::TimeDelta::FromMilliseconds(2703), |
- false, true)); |
+ HAS_VIDEO)); |
} |
TEST_F(ChunkDemuxerTest, WebMFile_AltRefFrames) { |
@@ -1710,7 +1765,7 @@ TEST_F(ChunkDemuxerTest, AVHeadersWithAudioOnlyType) { |
ASSERT_EQ(demuxer_->AddId(kSourceId, "audio/webm", codecs), |
ChunkDemuxer::kOk); |
- AppendInitSegment(true, true); |
+ AppendInitSegment(HAS_AUDIO | HAS_VIDEO); |
} |
TEST_F(ChunkDemuxerTest, AVHeadersWithVideoOnlyType) { |
@@ -1724,7 +1779,7 @@ TEST_F(ChunkDemuxerTest, AVHeadersWithVideoOnlyType) { |
ASSERT_EQ(demuxer_->AddId(kSourceId, "video/webm", codecs), |
ChunkDemuxer::kOk); |
- AppendInitSegment(true, true); |
+ AppendInitSegment(HAS_AUDIO | HAS_VIDEO); |
} |
TEST_F(ChunkDemuxerTest, MultipleHeaders) { |
@@ -1733,7 +1788,7 @@ TEST_F(ChunkDemuxerTest, MultipleHeaders) { |
AppendCluster(kDefaultFirstCluster()); |
// Append another identical initialization segment. |
- AppendInitSegment(true, true); |
+ AppendInitSegment(HAS_AUDIO | HAS_VIDEO); |
AppendCluster(kDefaultSecondCluster()); |
@@ -1782,15 +1837,15 @@ TEST_F(ChunkDemuxerTest, AddIdFailures) { |
std::string audio_id = "audio1"; |
std::string video_id = "video1"; |
- ASSERT_EQ(AddId(audio_id, true, false), ChunkDemuxer::kOk); |
+ ASSERT_EQ(AddId(audio_id, HAS_AUDIO), ChunkDemuxer::kOk); |
// Adding an id with audio/video should fail because we already added audio. |
ASSERT_EQ(AddId(), ChunkDemuxer::kReachedIdLimit); |
- AppendInitSegmentWithSourceId(audio_id, true, false, false); |
+ AppendInitSegmentWithSourceId(audio_id, HAS_AUDIO); |
// Adding an id after append should fail. |
- ASSERT_EQ(AddId(video_id, false, true), ChunkDemuxer::kReachedIdLimit); |
+ ASSERT_EQ(AddId(video_id, HAS_VIDEO), ChunkDemuxer::kReachedIdLimit); |
} |
// Test that Read() calls after a RemoveId() return "end of stream" buffers. |
@@ -1825,11 +1880,11 @@ TEST_F(ChunkDemuxerTest, RemoveId) { |
// quota for new IDs in the future. |
TEST_F(ChunkDemuxerTest, RemoveAndAddId) { |
std::string audio_id_1 = "audio1"; |
- ASSERT_TRUE(AddId(audio_id_1, true, false) == ChunkDemuxer::kOk); |
+ ASSERT_TRUE(AddId(audio_id_1, HAS_AUDIO) == ChunkDemuxer::kOk); |
demuxer_->RemoveId(audio_id_1); |
std::string audio_id_2 = "audio2"; |
- ASSERT_TRUE(AddId(audio_id_2, true, false) == ChunkDemuxer::kOk); |
+ ASSERT_TRUE(AddId(audio_id_2, HAS_AUDIO) == ChunkDemuxer::kOk); |
} |
TEST_F(ChunkDemuxerTest, SeekCanceled) { |
@@ -2018,8 +2073,8 @@ TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioIdOnly) { |
demuxer_->Initialize( |
&host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true); |
- ASSERT_EQ(AddId(kSourceId, true, false), ChunkDemuxer::kOk); |
- AppendInitSegment(true, false); |
+ ASSERT_EQ(AddId(kSourceId, HAS_AUDIO), ChunkDemuxer::kOk); |
+ AppendInitSegment(HAS_AUDIO); |
// Test a simple cluster. |
AppendCluster( |
@@ -2040,8 +2095,8 @@ TEST_F(ChunkDemuxerTest, GetBufferedRanges_VideoIdOnly) { |
demuxer_->Initialize( |
&host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true); |
- ASSERT_EQ(AddId(kSourceId, false, true), ChunkDemuxer::kOk); |
- AppendInitSegment(false, true); |
+ ASSERT_EQ(AddId(kSourceId, HAS_VIDEO), ChunkDemuxer::kOk); |
+ AppendInitSegment(HAS_VIDEO); |
// Test a simple cluster. |
AppendCluster( |
@@ -2349,8 +2404,8 @@ TEST_F(ChunkDemuxerTest, EndOfStreamStillSetAfterSeek) { |
TEST_F(ChunkDemuxerTest, GetBufferedRangesBeforeInitSegment) { |
EXPECT_CALL(*this, DemuxerOpened()); |
demuxer_->Initialize(&host_, CreateInitDoneCB(PIPELINE_OK), true); |
- ASSERT_EQ(AddId("audio", true, false), ChunkDemuxer::kOk); |
- ASSERT_EQ(AddId("video", false, true), ChunkDemuxer::kOk); |
+ ASSERT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk); |
+ ASSERT_EQ(AddId("video", HAS_VIDEO), ChunkDemuxer::kOk); |
CheckExpectedRanges("audio", "{ }"); |
CheckExpectedRanges("video", "{ }"); |
@@ -2668,7 +2723,7 @@ TEST_F(ChunkDemuxerTest, AppendAfterEndOfStream) { |
// Test receiving a Shutdown() call before we get an Initialize() |
// call. This can happen if video element gets destroyed before |
// the pipeline has a chance to initialize the demuxer. |
-TEST_F(ChunkDemuxerTest, ShutdownBeforeInitialize) { |
+TEST_F(ChunkDemuxerTest, Shutdown_BeforeInitialize) { |
demuxer_->Shutdown(); |
demuxer_->Initialize( |
&host_, CreateInitDoneCB(DEMUXER_ERROR_COULD_NOT_OPEN), true); |
@@ -2822,7 +2877,7 @@ TEST_F(ChunkDemuxerTest, RemoveBeforeInitSegment) { |
demuxer_->Initialize( |
&host_, CreateInitDoneCB(kNoTimestamp(), PIPELINE_OK), true); |
- EXPECT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, true, true)); |
+ EXPECT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, HAS_AUDIO | HAS_VIDEO)); |
demuxer_->Remove(kSourceId, base::TimeDelta::FromMilliseconds(0), |
base::TimeDelta::FromMilliseconds(1)); |
@@ -2941,4 +2996,102 @@ TEST_F(ChunkDemuxerTest, StartWaitingForSeekAfterParseError) { |
demuxer_->StartWaitingForSeek(seek_time); |
} |
+TEST_F(ChunkDemuxerTest, Remove_AudioVideoText) { |
+ DemuxerStream* text_stream = NULL; |
+ EXPECT_CALL(host_, AddTextStream(_, _)) |
+ .WillOnce(SaveArg<0>(&text_stream)); |
+ ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT)); |
+ |
+ DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); |
+ DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); |
+ |
+ AppendSingleStreamCluster(kSourceId, kAudioTrackNum, |
+ "0K 20K 40K 60K 80K 100K 120K 140K"); |
+ AppendSingleStreamCluster(kSourceId, kVideoTrackNum, |
+ "0K 30 60 90 120K 150 180"); |
+ AppendSingleStreamCluster(kSourceId, kTextTrackNum, "0K 100K 200K"); |
+ |
+ CheckExpectedBuffers(audio_stream, "0 20 40 60 80 100 120 140"); |
+ CheckExpectedBuffers(video_stream, "0 30 60 90 120 150 180"); |
+ CheckExpectedBuffers(text_stream, "0 100 200"); |
+ |
+ // Remove the buffers that were added. |
+ demuxer_->Remove(kSourceId, base::TimeDelta(), |
+ base::TimeDelta::FromMilliseconds(300)); |
+ |
+ // Verify that all the appended data has been removed. |
+ CheckExpectedRanges(kSourceId, "{ }"); |
+ |
+ // Append new buffers that are clearly different than the original |
+ // ones and verify that only the new buffers are returned. |
+ AppendSingleStreamCluster(kSourceId, kAudioTrackNum, |
+ "1K 21K 41K 61K 81K 101K 121K 141K"); |
+ AppendSingleStreamCluster(kSourceId, kVideoTrackNum, |
+ "1K 31 61 91 121K 151 181"); |
+ AppendSingleStreamCluster(kSourceId, kTextTrackNum, "1K 101K 201K"); |
+ |
+ Seek(base::TimeDelta()); |
+ CheckExpectedBuffers(audio_stream, "1 21 41 61 81 101 121 141"); |
+ CheckExpectedBuffers(video_stream, "1 31 61 91 121 151 181"); |
+ CheckExpectedBuffers(text_stream, "1 101 201"); |
+} |
+ |
+// Verifies that a Seek() will complete without text cues for |
+// the seek point and will return cues after the seek position |
+// when they are eventually appended. |
+TEST_F(ChunkDemuxerTest, SeekCompletesWithoutTextCues) { |
+ DemuxerStream* text_stream = NULL; |
+ EXPECT_CALL(host_, AddTextStream(_, _)) |
+ .WillOnce(SaveArg<0>(&text_stream)); |
+ ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT)); |
+ |
+ DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); |
+ DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); |
+ |
+ base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(120); |
+ bool seek_cb_was_called = false; |
+ demuxer_->StartWaitingForSeek(seek_time); |
+ demuxer_->Seek(seek_time, |
+ base::Bind(OnSeekDone_OKExpected, &seek_cb_was_called)); |
+ message_loop_.RunUntilIdle(); |
+ |
+ EXPECT_FALSE(seek_cb_was_called); |
+ |
+ bool text_read_done = false; |
+ text_stream->Read(base::Bind(&OnReadDone, |
+ base::TimeDelta::FromMilliseconds(125), |
+ &text_read_done)); |
+ |
+ // Append audio & video data so the seek completes. |
+ AppendSingleStreamCluster(kSourceId, kAudioTrackNum, |
+ "0K 20K 40K 60K 80K 100K 120K 140K 160K 180K"); |
+ AppendSingleStreamCluster(kSourceId, kVideoTrackNum, |
+ "0K 30 60 90 120K 150 180 210"); |
+ |
+ message_loop_.RunUntilIdle(); |
+ EXPECT_TRUE(seek_cb_was_called); |
+ EXPECT_FALSE(text_read_done); |
+ |
+ // Read some audio & video buffers to further verify seek completion. |
+ CheckExpectedBuffers(audio_stream, "120 140"); |
+ CheckExpectedBuffers(video_stream, "120 150"); |
+ |
+ EXPECT_FALSE(text_read_done); |
+ |
+ // Append text cues that start after the seek point and verify that |
+ // they are returned by Read() calls. |
+ AppendSingleStreamCluster(kSourceId, kTextTrackNum, "125K 175K 225K"); |
+ |
+ message_loop_.RunUntilIdle(); |
+ EXPECT_TRUE(text_read_done); |
+ |
+ // NOTE: we start at 175 here because the buffer at 125 was returned |
+ // to the pending read initiated above. |
+ CheckExpectedBuffers(text_stream, "175 225"); |
+ |
+ // Verify that audio & video streams contiue to return expected values. |
+ CheckExpectedBuffers(audio_stream, "160 180"); |
+ CheckExpectedBuffers(video_stream, "180 210"); |
+} |
+ |
} // namespace media |