OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/bind.h" | 5 #include "base/bind.h" |
6 #include "media/base/audio_decoder_config.h" | 6 #include "media/base/audio_decoder_config.h" |
7 #include "media/base/decoder_buffer.h" | 7 #include "media/base/decoder_buffer.h" |
8 #include "media/base/mock_callback.h" | 8 #include "media/base/mock_callback.h" |
9 #include "media/base/mock_demuxer_host.h" | 9 #include "media/base/mock_demuxer_host.h" |
10 #include "media/base/test_data_util.h" | 10 #include "media/base/test_data_util.h" |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
69 arg->GetTimestamp().InMilliseconds() == timestamp_in_ms; | 69 arg->GetTimestamp().InMilliseconds() == timestamp_in_ms; |
70 } | 70 } |
71 | 71 |
72 static void OnReadDone(const base::TimeDelta& expected_time, | 72 static void OnReadDone(const base::TimeDelta& expected_time, |
73 bool* called, | 73 bool* called, |
74 const scoped_refptr<DecoderBuffer>& buffer) { | 74 const scoped_refptr<DecoderBuffer>& buffer) { |
75 EXPECT_EQ(expected_time, buffer->GetTimestamp()); | 75 EXPECT_EQ(expected_time, buffer->GetTimestamp()); |
76 *called = true; | 76 *called = true; |
77 } | 77 } |
78 | 78 |
79 static void OnReadDone_EOSExpected(bool* called, | |
80 const scoped_refptr<DecoderBuffer>& buffer) { | |
81 EXPECT_TRUE(buffer->IsEndOfStream()); | |
annacc
2012/06/07 22:42:07
I thought about modifying EndOfStreamHelper to che
| |
82 *called = true; | |
83 } | |
84 | |
79 class MockChunkDemuxerClient : public ChunkDemuxerClient { | 85 class MockChunkDemuxerClient : public ChunkDemuxerClient { |
80 public: | 86 public: |
81 MockChunkDemuxerClient() {} | 87 MockChunkDemuxerClient() {} |
82 virtual ~MockChunkDemuxerClient() {} | 88 virtual ~MockChunkDemuxerClient() {} |
83 | 89 |
84 MOCK_METHOD1(DemuxerOpened, void(ChunkDemuxer* demuxer)); | 90 MOCK_METHOD1(DemuxerOpened, void(ChunkDemuxer* demuxer)); |
85 MOCK_METHOD0(DemuxerClosed, void()); | 91 MOCK_METHOD0(DemuxerClosed, void()); |
86 // TODO(xhwang): This is a workaround of the issue that move-only parameters | 92 // TODO(xhwang): This is a workaround of the issue that move-only parameters |
87 // are not supported in mocked methods. Remove this when the issue is fixed. | 93 // are not supported in mocked methods. Remove this when the issue is fixed. |
88 // See http://code.google.com/p/googletest/issues/detail?id=395 | 94 // See http://code.google.com/p/googletest/issues/detail?id=395 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
168 video_track_entry->GetDataSize() + | 174 video_track_entry->GetDataSize() + |
169 video_content_encodings->GetDataSize() - | 175 video_content_encodings->GetDataSize() - |
170 kVideoTrackEntryHeaderSize); | 176 kVideoTrackEntryHeaderSize); |
171 buf += video_content_encodings->GetDataSize(); | 177 buf += video_content_encodings->GetDataSize(); |
172 } | 178 } |
173 buf += video_track_entry->GetDataSize(); | 179 buf += video_track_entry->GetDataSize(); |
174 } | 180 } |
175 } | 181 } |
176 | 182 |
177 ChunkDemuxer::Status AddId() { | 183 ChunkDemuxer::Status AddId() { |
178 std::vector<std::string> codecs(2); | 184 return AddId(kSourceId, true, true); |
179 codecs[0] = "vp8"; | 185 } |
180 codecs[1] = "vorbis"; | 186 |
181 return demuxer_->AddId(kSourceId, "video/webm", codecs); | 187 ChunkDemuxer::Status AddId(const std::string& source_id, |
188 bool has_audio, bool has_video) { | |
189 std::vector<std::string> codecs; | |
190 std::string type; | |
191 | |
192 if (has_audio) { | |
193 codecs.push_back("vorbis"); | |
194 type = "audio/webm"; | |
195 } | |
196 | |
197 if (has_video) { | |
198 codecs.push_back("vp8"); | |
199 type = "video/webm"; | |
200 } | |
201 | |
202 if (!has_audio && !has_video) { | |
203 return AddId(kSourceId, true, true); | |
204 } | |
annacc
2012/06/07 22:42:07
This is required because TestInit appends info tra
acolwell GONE FROM CHROMIUM
2012/06/08 00:29:07
This looks right to me.
| |
205 | |
206 return demuxer_->AddId(source_id, type, codecs); | |
182 } | 207 } |
183 | 208 |
184 bool AppendData(const uint8* data, size_t length) { | 209 bool AppendData(const uint8* data, size_t length) { |
210 return AppendData(kSourceId, data, length); | |
211 } | |
212 | |
213 bool AppendData(const std::string& source_id, | |
214 const uint8* data, size_t length) { | |
185 CHECK(length); | 215 CHECK(length); |
186 EXPECT_CALL(host_, AddBufferedByteRange(_, _)).Times(AnyNumber()) | 216 EXPECT_CALL(host_, AddBufferedByteRange(_, _)).Times(AnyNumber()) |
187 .WillRepeatedly(SaveArg<1>(&buffered_bytes_)); | 217 .WillRepeatedly(SaveArg<1>(&buffered_bytes_)); |
188 EXPECT_CALL(host_, SetNetworkActivity(true)) | 218 EXPECT_CALL(host_, SetNetworkActivity(true)) |
189 .Times(AnyNumber()); | 219 .Times(AnyNumber()); |
190 return demuxer_->AppendData(kSourceId, data, length); | 220 return demuxer_->AppendData(source_id, data, length); |
191 } | 221 } |
192 | 222 |
193 bool AppendDataInPieces(const uint8* data, size_t length) { | 223 bool AppendDataInPieces(const uint8* data, size_t length) { |
194 return AppendDataInPieces(data, length, 7); | 224 return AppendDataInPieces(data, length, 7); |
195 } | 225 } |
196 | 226 |
197 bool AppendDataInPieces(const uint8* data, size_t length, size_t piece_size) { | 227 bool AppendDataInPieces(const uint8* data, size_t length, size_t piece_size) { |
198 const uint8* start = data; | 228 const uint8* start = data; |
199 const uint8* end = data + length; | 229 const uint8* end = data + length; |
200 while (start < end) { | 230 while (start < end) { |
201 int64 old_buffered_bytes = buffered_bytes_; | 231 int64 old_buffered_bytes = buffered_bytes_; |
202 size_t append_size = std::min(piece_size, | 232 size_t append_size = std::min(piece_size, |
203 static_cast<size_t>(end - start)); | 233 static_cast<size_t>(end - start)); |
204 if (!AppendData(start, append_size)) | 234 if (!AppendData(start, append_size)) |
205 return false; | 235 return false; |
206 start += append_size; | 236 start += append_size; |
207 | 237 |
208 EXPECT_GT(buffered_bytes_, old_buffered_bytes); | 238 EXPECT_GT(buffered_bytes_, old_buffered_bytes); |
209 } | 239 } |
210 return true; | 240 return true; |
211 } | 241 } |
212 | 242 |
213 bool AppendInfoTracks(bool has_audio, bool has_video, | 243 bool AppendInfoTracks(bool has_audio, bool has_video, |
214 bool video_content_encoded) { | 244 bool video_content_encoded) { |
245 return AppendInfoTracks(kSourceId, has_audio, has_video, | |
246 video_content_encoded); | |
247 } | |
248 | |
249 bool AppendInfoTracks(const std::string& source_id, | |
250 bool has_audio, bool has_video, | |
251 bool video_content_encoded) { | |
215 scoped_array<uint8> info_tracks; | 252 scoped_array<uint8> info_tracks; |
216 int info_tracks_size = 0; | 253 int info_tracks_size = 0; |
217 CreateInfoTracks(has_audio, has_video, video_content_encoded, | 254 CreateInfoTracks(has_audio, has_video, video_content_encoded, |
218 &info_tracks, &info_tracks_size); | 255 &info_tracks, &info_tracks_size); |
219 return AppendData(info_tracks.get(), info_tracks_size); | 256 return AppendData(source_id, info_tracks.get(), info_tracks_size); |
220 } | 257 } |
221 | 258 |
222 void InitDoneCalled(PipelineStatus expected_status, | 259 void InitDoneCalled(PipelineStatus expected_status, |
223 PipelineStatus status) { | 260 PipelineStatus status) { |
224 EXPECT_EQ(status, expected_status); | 261 EXPECT_EQ(status, expected_status); |
225 } | 262 } |
226 | 263 |
227 PipelineStatusCB CreateInitDoneCB(const base::TimeDelta& expected_duration, | 264 PipelineStatusCB CreateInitDoneCB(const base::TimeDelta& expected_duration, |
228 PipelineStatus expected_status) { | 265 PipelineStatus expected_status) { |
229 if (expected_status == PIPELINE_OK) | 266 if (expected_status == PIPELINE_OK) |
230 EXPECT_CALL(host_, SetDuration(expected_duration)); | 267 EXPECT_CALL(host_, SetDuration(expected_duration)); |
231 | 268 |
232 return base::Bind(&ChunkDemuxerTest::InitDoneCalled, | 269 return base::Bind(&ChunkDemuxerTest::InitDoneCalled, |
233 base::Unretained(this), | 270 base::Unretained(this), |
234 expected_status); | 271 expected_status); |
235 } | 272 } |
236 | 273 |
237 bool InitDemuxer(bool has_audio, bool has_video, | 274 bool InitDemuxer(bool has_audio, bool has_video, |
238 bool video_content_encoded) { | 275 bool video_content_encoded) { |
239 PipelineStatus expected_status = | 276 PipelineStatus expected_status = |
240 (has_audio || has_video) ? PIPELINE_OK : DEMUXER_ERROR_COULD_NOT_OPEN; | 277 (has_audio || has_video) ? PIPELINE_OK : DEMUXER_ERROR_COULD_NOT_OPEN; |
241 | 278 |
242 EXPECT_CALL(*client_, DemuxerOpened(_)); | 279 EXPECT_CALL(*client_, DemuxerOpened(_)); |
243 demuxer_->Initialize( | 280 demuxer_->Initialize( |
244 &host_, CreateInitDoneCB(kDefaultDuration(), expected_status)); | 281 &host_, CreateInitDoneCB(kDefaultDuration(), expected_status)); |
245 | 282 |
246 if (AddId() != ChunkDemuxer::kOk) | 283 if (AddId(kSourceId, has_audio, has_video) != ChunkDemuxer::kOk) |
247 return false; | 284 return false; |
248 | 285 |
249 return AppendInfoTracks(has_audio, has_video, video_content_encoded); | 286 return AppendInfoTracks(has_audio, has_video, video_content_encoded); |
250 } | 287 } |
251 | 288 |
289 bool InitDemuxerAudioAndVideoSources(const std::string& audio_id, | |
290 const std::string& video_id) { | |
291 EXPECT_CALL(*client_, DemuxerOpened(_)); | |
292 demuxer_->Initialize( | |
293 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK)); | |
294 | |
295 if (AddId(audio_id, true, false) != ChunkDemuxer::kOk) | |
296 return false; | |
297 if (AddId(video_id, false, true) != ChunkDemuxer::kOk) | |
298 return false; | |
299 | |
300 bool success; | |
301 success = AppendInfoTracks(audio_id, true, false, false); | |
acolwell GONE FROM CHROMIUM
2012/06/08 00:29:07
Move this assignement to the line above.
annacc
2012/06/08 22:12:23
Done.
| |
302 success = success && AppendInfoTracks(video_id, false, true, false); | |
acolwell GONE FROM CHROMIUM
2012/06/08 00:29:07
You could use &= here
annacc
2012/06/08 22:12:23
Done.
| |
303 return success; | |
304 } | |
305 | |
252 void ShutdownDemuxer() { | 306 void ShutdownDemuxer() { |
253 if (demuxer_) { | 307 if (demuxer_) { |
254 EXPECT_CALL(*client_, DemuxerClosed()); | 308 EXPECT_CALL(*client_, DemuxerClosed()); |
255 demuxer_->Shutdown(); | 309 demuxer_->Shutdown(); |
256 } | 310 } |
257 } | 311 } |
258 | 312 |
259 void AddSimpleBlock(ClusterBuilder* cb, int track_num, int64 timecode) { | 313 void AddSimpleBlock(ClusterBuilder* cb, int track_num, int64 timecode) { |
260 uint8 data[] = { 0x00 }; | 314 uint8 data[] = { 0x00 }; |
261 cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data)); | 315 cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data)); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
308 } else { | 362 } else { |
309 cb.AddBlockGroup(kVideoTrackNum, video_timecode, kVideoBlockDuration, | 363 cb.AddBlockGroup(kVideoTrackNum, video_timecode, kVideoBlockDuration, |
310 video_flag, data.get(), size); | 364 video_flag, data.get(), size); |
311 cb.AddBlockGroup(kAudioTrackNum, audio_timecode, kAudioBlockDuration, | 365 cb.AddBlockGroup(kAudioTrackNum, audio_timecode, kAudioBlockDuration, |
312 kWebMFlagKeyframe, data.get(), size); | 366 kWebMFlagKeyframe, data.get(), size); |
313 } | 367 } |
314 | 368 |
315 return cb.Finish(); | 369 return cb.Finish(); |
316 } | 370 } |
317 | 371 |
372 scoped_ptr<Cluster> GenerateSingleStreamCluster(int audio_timecode, | |
acolwell GONE FROM CHROMIUM
2012/06/08 00:29:07
how about just timecode since I don't see anything
annacc
2012/06/08 22:12:23
Whoops, leftover from a previous idea. Done.
| |
373 int block_count, | |
374 int track_number, | |
375 int block_duration) { | |
376 CHECK_GT(block_count, 0); | |
377 | |
378 int size = 10; | |
379 scoped_array<uint8> data(new uint8[size]); | |
380 | |
381 ClusterBuilder cb; | |
382 cb.SetClusterTimecode(audio_timecode); | |
383 | |
384 // Create simple blocks for everything except the last block. | |
385 for (int i = 0; i < block_count - 1; i++) { | |
386 cb.AddSimpleBlock(track_number, audio_timecode, kWebMFlagKeyframe, | |
387 data.get(), size); | |
388 audio_timecode += block_duration; | |
389 } | |
390 | |
391 // Make the last block a BlockGroups so that it doesn't get delayed by the | |
acolwell GONE FROM CHROMIUM
2012/06/08 00:29:07
s/BlockGroups/BlockGroup
annacc
2012/06/08 22:12:23
Done.
| |
392 // block duration calculation logic. | |
393 cb.AddBlockGroup(track_number, audio_timecode, block_duration, | |
394 kWebMFlagKeyframe, data.get(), size); | |
395 return cb.Finish(); | |
396 } | |
397 | |
318 void GenerateExpectedReads(int timecode, int block_count, | 398 void GenerateExpectedReads(int timecode, int block_count, |
319 DemuxerStream* audio, | 399 DemuxerStream* audio, |
320 DemuxerStream* video) { | 400 DemuxerStream* video) { |
321 CHECK_GT(block_count, 0); | 401 CHECK_GT(block_count, 0); |
322 int audio_timecode = timecode; | 402 int audio_timecode = timecode; |
323 int video_timecode = timecode; | 403 int video_timecode = timecode; |
324 | 404 |
325 if (block_count == 1) { | 405 if (block_count == 1) { |
326 ExpectRead(audio, audio_timecode); | 406 ExpectRead(audio, audio_timecode); |
327 return; | 407 return; |
(...skipping 29 matching lines...) Expand all Loading... | |
357 | 437 |
358 // Test parsing a WebM file. | 438 // Test parsing a WebM file. |
359 // |filename| - The name of the file in media/test/data to parse. | 439 // |filename| - The name of the file in media/test/data to parse. |
360 // |timestamps| - The expected timestamps on the parsed buffers. | 440 // |timestamps| - The expected timestamps on the parsed buffers. |
361 // a timestamp of kSkip indicates that a Read() call for that stream | 441 // a timestamp of kSkip indicates that a Read() call for that stream |
362 // shouldn't be made on that iteration of the loop. If both streams have | 442 // shouldn't be made on that iteration of the loop. If both streams have |
363 // a kSkip then the loop will terminate. | 443 // a kSkip then the loop will terminate. |
364 bool ParseWebMFile(const std::string& filename, | 444 bool ParseWebMFile(const std::string& filename, |
365 const BufferTimestamps* timestamps, | 445 const BufferTimestamps* timestamps, |
366 const base::TimeDelta& duration) { | 446 const base::TimeDelta& duration) { |
447 return ParseWebMFile(filename, timestamps, duration, true, true); | |
448 } | |
449 | |
450 bool ParseWebMFile(const std::string& filename, | |
451 const BufferTimestamps* timestamps, | |
452 const base::TimeDelta& duration, | |
453 bool has_audio, bool has_video) { | |
367 EXPECT_CALL(*client_, DemuxerOpened(_)); | 454 EXPECT_CALL(*client_, DemuxerOpened(_)); |
368 demuxer_->Initialize( | 455 demuxer_->Initialize( |
369 &host_, CreateInitDoneCB(duration, PIPELINE_OK)); | 456 &host_, CreateInitDoneCB(duration, PIPELINE_OK)); |
370 | 457 |
371 if (AddId() != ChunkDemuxer::kOk) | 458 if (AddId(kSourceId, has_audio, has_video) != ChunkDemuxer::kOk) |
372 return false; | 459 return false; |
373 | 460 |
374 // Read a WebM file into memory and send the data to the demuxer. | 461 // Read a WebM file into memory and send the data to the demuxer. |
375 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename); | 462 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename); |
376 if (!AppendDataInPieces(buffer->GetData(), buffer->GetDataSize(), 512)) | 463 if (!AppendDataInPieces(buffer->GetData(), buffer->GetDataSize(), 512)) |
377 return false; | 464 return false; |
378 | 465 |
379 scoped_refptr<DemuxerStream> audio = | 466 scoped_refptr<DemuxerStream> audio = |
380 demuxer_->GetStream(DemuxerStream::AUDIO); | 467 demuxer_->GetStream(DemuxerStream::AUDIO); |
381 scoped_refptr<DemuxerStream> video = | 468 scoped_refptr<DemuxerStream> video = |
(...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
949 struct BufferTimestamps buffer_timestamps[] = { | 1036 struct BufferTimestamps buffer_timestamps[] = { |
950 {kSkip, 0}, | 1037 {kSkip, 0}, |
951 {kSkip, 3}, | 1038 {kSkip, 3}, |
952 {kSkip, 6}, | 1039 {kSkip, 6}, |
953 {kSkip, 9}, | 1040 {kSkip, 9}, |
954 {kSkip, 12}, | 1041 {kSkip, 12}, |
955 {kSkip, kSkip}, | 1042 {kSkip, kSkip}, |
956 }; | 1043 }; |
957 | 1044 |
958 ASSERT_TRUE(ParseWebMFile("bear-320x240-audio-only.webm", buffer_timestamps, | 1045 ASSERT_TRUE(ParseWebMFile("bear-320x240-audio-only.webm", buffer_timestamps, |
959 base::TimeDelta::FromMilliseconds(2744))); | 1046 base::TimeDelta::FromMilliseconds(2744), |
1047 true, false)); | |
960 } | 1048 } |
961 | 1049 |
962 TEST_F(ChunkDemuxerTest, TestWebMFile_VideoOnly) { | 1050 TEST_F(ChunkDemuxerTest, TestWebMFile_VideoOnly) { |
963 struct BufferTimestamps buffer_timestamps[] = { | 1051 struct BufferTimestamps buffer_timestamps[] = { |
964 {0, kSkip}, | 1052 {0, kSkip}, |
965 {33, kSkip}, | 1053 {33, kSkip}, |
966 {67, kSkip}, | 1054 {67, kSkip}, |
967 {100, kSkip}, | 1055 {100, kSkip}, |
968 {133, kSkip}, | 1056 {133, kSkip}, |
969 {kSkip, kSkip}, | 1057 {kSkip, kSkip}, |
970 }; | 1058 }; |
971 | 1059 |
972 ASSERT_TRUE(ParseWebMFile("bear-320x240-video-only.webm", buffer_timestamps, | 1060 ASSERT_TRUE(ParseWebMFile("bear-320x240-video-only.webm", buffer_timestamps, |
973 base::TimeDelta::FromMilliseconds(2703))); | 1061 base::TimeDelta::FromMilliseconds(2703), |
1062 false, true)); | |
974 } | 1063 } |
975 | 1064 |
976 TEST_F(ChunkDemuxerTest, TestWebMFile_AltRefFrames) { | 1065 TEST_F(ChunkDemuxerTest, TestWebMFile_AltRefFrames) { |
977 struct BufferTimestamps buffer_timestamps[] = { | 1066 struct BufferTimestamps buffer_timestamps[] = { |
978 {0, 0}, | 1067 {0, 0}, |
979 {33, 3}, | 1068 {33, 3}, |
980 {33, 6}, | 1069 {33, 6}, |
981 {67, 9}, | 1070 {67, 9}, |
982 {100, 12}, | 1071 {100, 12}, |
983 {kSkip, kSkip}, | 1072 {kSkip, kSkip}, |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1089 DEMUXER_ERROR_COULD_NOT_OPEN)); | 1178 DEMUXER_ERROR_COULD_NOT_OPEN)); |
1090 | 1179 |
1091 std::vector<std::string> codecs(1); | 1180 std::vector<std::string> codecs(1); |
1092 codecs[0] = "vp8"; | 1181 codecs[0] = "vp8"; |
1093 ASSERT_EQ(demuxer_->AddId(kSourceId, "video/webm", codecs), | 1182 ASSERT_EQ(demuxer_->AddId(kSourceId, "video/webm", codecs), |
1094 ChunkDemuxer::kOk); | 1183 ChunkDemuxer::kOk); |
1095 | 1184 |
1096 ASSERT_TRUE(AppendInfoTracks(true, true, false)); | 1185 ASSERT_TRUE(AppendInfoTracks(true, true, false)); |
1097 } | 1186 } |
1098 | 1187 |
1188 TEST_F(ChunkDemuxerTest, TestAddSeparateSourcesForAudioAndVideo) { | |
1189 std::string audio_id = "audio1"; | |
1190 std::string video_id = "video1"; | |
1191 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id)); | |
1192 | |
1193 scoped_refptr<DemuxerStream> audio = | |
1194 demuxer_->GetStream(DemuxerStream::AUDIO); | |
1195 scoped_refptr<DemuxerStream> video = | |
1196 demuxer_->GetStream(DemuxerStream::VIDEO); | |
1197 | |
1198 bool audio_read_done = false; | |
1199 bool video_read_done = false; | |
1200 audio->Read(base::Bind(&OnReadDone, | |
1201 base::TimeDelta::FromMilliseconds(0), | |
1202 &audio_read_done)); | |
1203 | |
1204 video->Read(base::Bind(&OnReadDone, | |
1205 base::TimeDelta::FromMilliseconds(0), | |
1206 &video_read_done)); | |
1207 | |
1208 scoped_ptr<Cluster> cluster_a( | |
1209 GenerateSingleStreamCluster(0, 4, kAudioTrackNum, kAudioBlockDuration)); | |
1210 | |
1211 scoped_ptr<Cluster> cluster_v( | |
1212 GenerateSingleStreamCluster(0, 4, kVideoTrackNum, kVideoBlockDuration)); | |
1213 | |
1214 // Append audio and video data into separate source ids. | |
1215 ASSERT_TRUE(AppendData(audio_id, cluster_a->data(), cluster_a->size())); | |
1216 ASSERT_TRUE(AppendData(video_id, cluster_v->data(), cluster_v->size())); | |
1217 | |
1218 EXPECT_TRUE(audio_read_done); | |
1219 EXPECT_TRUE(video_read_done); | |
acolwell GONE FROM CHROMIUM
2012/06/08 00:29:07
Consider creating the single stream equivalent of
annacc
2012/06/08 22:12:23
Done.
| |
1220 } | |
1221 | |
1222 TEST_F(ChunkDemuxerTest, TestAddIdFailures) { | |
1223 EXPECT_CALL(*client_, DemuxerOpened(_)); | |
1224 demuxer_->Initialize( | |
1225 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK)); | |
1226 | |
1227 std::string audio_id = "audio1"; | |
1228 std::string video_id = "video1"; | |
1229 | |
1230 ASSERT_EQ(AddId(audio_id, true, false), ChunkDemuxer::kOk); | |
1231 | |
1232 // Adding an id with audio/video should fail because we already added audio. | |
1233 ASSERT_EQ(AddId(), ChunkDemuxer::kReachedIdLimit); | |
1234 | |
1235 ASSERT_TRUE(AppendInfoTracks(audio_id, true, false, false)); | |
1236 | |
1237 // Adding an id after append should fail. | |
1238 ASSERT_EQ(AddId(video_id, false, true), ChunkDemuxer::kReachedIdLimit); | |
1239 } | |
1240 | |
1241 // Test that Read() calls after a RemoveId() return "end of stream" buffers. | |
1242 TEST_F(ChunkDemuxerTest, TestRemoveId) { | |
1243 std::string audio_id = "audio1"; | |
1244 std::string video_id = "video1"; | |
1245 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id)); | |
1246 | |
1247 scoped_ptr<Cluster> cluster_a( | |
1248 GenerateSingleStreamCluster(0, 4, kAudioTrackNum, kAudioBlockDuration)); | |
1249 | |
1250 scoped_ptr<Cluster> cluster_v( | |
1251 GenerateSingleStreamCluster(0, 4, kVideoTrackNum, kVideoBlockDuration)); | |
1252 | |
1253 // Append audio and video data into separate source ids. | |
1254 ASSERT_TRUE(AppendData(audio_id, cluster_a->data(), cluster_a->size())); | |
1255 ASSERT_TRUE(AppendData(video_id, cluster_v->data(), cluster_v->size())); | |
1256 | |
1257 // Read() from audio should return normal buffers. | |
1258 bool audio_read_done = false; | |
1259 scoped_refptr<DemuxerStream> audio = | |
1260 demuxer_->GetStream(DemuxerStream::AUDIO); | |
1261 audio->Read(base::Bind(&OnReadDone, | |
1262 base::TimeDelta::FromMilliseconds(0), | |
1263 &audio_read_done)); | |
1264 EXPECT_TRUE(audio_read_done); | |
1265 | |
1266 // Remove the audio id. | |
1267 demuxer_->RemoveId(audio_id); | |
1268 | |
1269 // Read() from audio should return "end of stream" buffers. | |
1270 audio_read_done = false; | |
1271 audio->Read(base::Bind(&OnReadDone_EOSExpected, | |
1272 &audio_read_done)); | |
1273 EXPECT_TRUE(audio_read_done); | |
1274 | |
1275 // Read() from video should still return normal buffers. | |
1276 bool video_read_done = false; | |
1277 scoped_refptr<DemuxerStream> video = | |
1278 demuxer_->GetStream(DemuxerStream::VIDEO); | |
1279 video->Read(base::Bind(&OnReadDone, | |
1280 base::TimeDelta::FromMilliseconds(0), | |
1281 &video_read_done)); | |
1282 EXPECT_TRUE(video_read_done); | |
1283 } | |
1284 | |
1285 // Test that Seek() successfully seeks to all source IDs. | |
1286 TEST_F(ChunkDemuxerTest, TestSeekAudioAndVideoSources) { | |
1287 std::string audio_id = "audio1"; | |
1288 std::string video_id = "video1"; | |
1289 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id)); | |
1290 | |
1291 scoped_ptr<Cluster> cluster_a1( | |
1292 GenerateSingleStreamCluster(0, 4, kAudioTrackNum, kAudioBlockDuration)); | |
1293 | |
1294 scoped_ptr<Cluster> cluster_v1( | |
1295 GenerateSingleStreamCluster(0, 4, kVideoTrackNum, kVideoBlockDuration)); | |
1296 | |
1297 ASSERT_TRUE(AppendData(audio_id, cluster_a1->data(), cluster_a1->size())); | |
1298 ASSERT_TRUE(AppendData(video_id, cluster_v1->data(), cluster_v1->size())); | |
1299 | |
1300 // Read() should return buffers at 0. | |
1301 bool audio_read_done = false; | |
1302 bool video_read_done = false; | |
1303 scoped_refptr<DemuxerStream> audio = | |
1304 demuxer_->GetStream(DemuxerStream::AUDIO); | |
1305 scoped_refptr<DemuxerStream> video = | |
1306 demuxer_->GetStream(DemuxerStream::VIDEO); | |
1307 | |
1308 audio->Read(base::Bind(&OnReadDone, | |
1309 base::TimeDelta::FromMilliseconds(0), | |
1310 &audio_read_done)); | |
1311 video->Read(base::Bind(&OnReadDone, | |
1312 base::TimeDelta::FromMilliseconds(0), | |
1313 &video_read_done)); | |
1314 EXPECT_TRUE(audio_read_done); | |
1315 EXPECT_TRUE(video_read_done); | |
1316 | |
1317 // Seek to 3. | |
acolwell GONE FROM CHROMIUM
2012/06/08 00:29:07
Might want to also indicate that 3 is used because
annacc
2012/06/08 22:12:23
Done.
| |
1318 demuxer_->StartWaitingForSeek(); | |
1319 demuxer_->Seek(base::TimeDelta::FromSeconds(3), | |
1320 NewExpectedStatusCB(PIPELINE_OK)); | |
1321 | |
1322 scoped_ptr<Cluster> cluster_a2( | |
1323 GenerateSingleStreamCluster(3000, 4, kAudioTrackNum, | |
1324 kAudioBlockDuration)); | |
1325 | |
1326 scoped_ptr<Cluster> cluster_v2( | |
1327 GenerateSingleStreamCluster(3000, 4, kVideoTrackNum, | |
1328 kVideoBlockDuration)); | |
1329 | |
1330 ASSERT_TRUE(AppendData(audio_id, cluster_a2->data(), cluster_a2->size())); | |
1331 ASSERT_TRUE(AppendData(video_id, cluster_v2->data(), cluster_v2->size())); | |
1332 | |
1333 // Read() should return buffers at 3 after the seek. | |
1334 audio_read_done = false; | |
1335 video_read_done = false; | |
1336 audio->Read(base::Bind(&OnReadDone, | |
acolwell GONE FROM CHROMIUM
2012/06/08 00:29:07
WDYT about putting these reads right above the clu
| |
1337 base::TimeDelta::FromSeconds(3), | |
1338 &audio_read_done)); | |
1339 video->Read(base::Bind(&OnReadDone, | |
1340 base::TimeDelta::FromSeconds(3), | |
1341 &video_read_done)); | |
1342 EXPECT_TRUE(audio_read_done); | |
1343 EXPECT_TRUE(video_read_done); | |
1344 } | |
1345 | |
1099 } // namespace media | 1346 } // namespace media |
OLD | NEW |