Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(136)

Side by Side Diff: media/filters/chunk_demuxer_unittest.cc

Issue 10545066: Implement support for 2 source ids (1 for audio and 1 for video). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: acolwell's suggestions Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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());
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
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 }
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 = AppendInfoTracks(audio_id, true, false, false);
301 success &= AppendInfoTracks(video_id, false, true, false);
302 return success;
303 }
304
252 void ShutdownDemuxer() { 305 void ShutdownDemuxer() {
253 if (demuxer_) { 306 if (demuxer_) {
254 EXPECT_CALL(*client_, DemuxerClosed()); 307 EXPECT_CALL(*client_, DemuxerClosed());
255 demuxer_->Shutdown(); 308 demuxer_->Shutdown();
256 } 309 }
257 } 310 }
258 311
259 void AddSimpleBlock(ClusterBuilder* cb, int track_num, int64 timecode) { 312 void AddSimpleBlock(ClusterBuilder* cb, int track_num, int64 timecode) {
260 uint8 data[] = { 0x00 }; 313 uint8 data[] = { 0x00 };
261 cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data)); 314 cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data));
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 } else { 361 } else {
309 cb.AddBlockGroup(kVideoTrackNum, video_timecode, kVideoBlockDuration, 362 cb.AddBlockGroup(kVideoTrackNum, video_timecode, kVideoBlockDuration,
310 video_flag, data.get(), size); 363 video_flag, data.get(), size);
311 cb.AddBlockGroup(kAudioTrackNum, audio_timecode, kAudioBlockDuration, 364 cb.AddBlockGroup(kAudioTrackNum, audio_timecode, kAudioBlockDuration,
312 kWebMFlagKeyframe, data.get(), size); 365 kWebMFlagKeyframe, data.get(), size);
313 } 366 }
314 367
315 return cb.Finish(); 368 return cb.Finish();
316 } 369 }
317 370
371 scoped_ptr<Cluster> GenerateSingleStreamCluster(int timecode,
372 int block_count,
373 int track_number,
374 int block_duration) {
375 CHECK_GT(block_count, 0);
376
377 int size = 10;
378 scoped_array<uint8> data(new uint8[size]);
379
380 ClusterBuilder cb;
381 cb.SetClusterTimecode(timecode);
382
383 // Create simple blocks for everything except the last block.
384 for (int i = 0; i < block_count - 1; i++) {
385 cb.AddSimpleBlock(track_number, timecode, kWebMFlagKeyframe,
386 data.get(), size);
387 timecode += block_duration;
388 }
389
390 // Make the last block a BlockGroup so that it doesn't get delayed by the
391 // block duration calculation logic.
392 cb.AddBlockGroup(track_number, timecode, block_duration,
393 kWebMFlagKeyframe, data.get(), size);
394 return cb.Finish();
395 }
396
318 void GenerateExpectedReads(int timecode, int block_count, 397 void GenerateExpectedReads(int timecode, int block_count,
319 DemuxerStream* audio, 398 DemuxerStream* audio,
320 DemuxerStream* video) { 399 DemuxerStream* video) {
321 CHECK_GT(block_count, 0); 400 CHECK_GT(block_count, 0);
322 int audio_timecode = timecode; 401 int audio_timecode = timecode;
323 int video_timecode = timecode; 402 int video_timecode = timecode;
324 403
325 if (block_count == 1) { 404 if (block_count == 1) {
326 ExpectRead(audio, audio_timecode); 405 ExpectRead(audio, audio_timecode);
327 return; 406 return;
328 } 407 }
329 408
330 for (int i = 0; i < block_count; i++) { 409 for (int i = 0; i < block_count; i++) {
331 if (audio_timecode <= video_timecode) { 410 if (audio_timecode <= video_timecode) {
332 ExpectRead(audio, audio_timecode); 411 ExpectRead(audio, audio_timecode);
333 audio_timecode += kAudioBlockDuration; 412 audio_timecode += kAudioBlockDuration;
334 continue; 413 continue;
335 } 414 }
336 415
337 ExpectRead(video, video_timecode); 416 ExpectRead(video, video_timecode);
338 video_timecode += kVideoBlockDuration; 417 video_timecode += kVideoBlockDuration;
339 } 418 }
340 } 419 }
341 420
421 void GenerateExpectedReads(int timecode, int block_count,
422 DemuxerStream* stream, int block_duration) {
423 CHECK_GT(block_count, 0);
424 int stream_timecode = timecode;
425
426 for (int i = 0; i < block_count; i++) {
427 ExpectRead(stream, stream_timecode);
428 stream_timecode += block_duration;
429 }
430 }
431
342 MOCK_METHOD1(ReadDone, void(const scoped_refptr<DecoderBuffer>&)); 432 MOCK_METHOD1(ReadDone, void(const scoped_refptr<DecoderBuffer>&));
343 433
344 void ExpectRead(DemuxerStream* stream, int64 timestamp_in_ms) { 434 void ExpectRead(DemuxerStream* stream, int64 timestamp_in_ms) {
345 EXPECT_CALL(*this, ReadDone(HasTimestamp(timestamp_in_ms))); 435 EXPECT_CALL(*this, ReadDone(HasTimestamp(timestamp_in_ms)));
346 stream->Read(base::Bind(&ChunkDemuxerTest::ReadDone, 436 stream->Read(base::Bind(&ChunkDemuxerTest::ReadDone,
347 base::Unretained(this))); 437 base::Unretained(this)));
348 } 438 }
349 439
350 MOCK_METHOD1(Checkpoint, void(int id)); 440 MOCK_METHOD1(Checkpoint, void(int id));
351 441
352 struct BufferTimestamps { 442 struct BufferTimestamps {
353 int video_time_ms; 443 int video_time_ms;
354 int audio_time_ms; 444 int audio_time_ms;
355 }; 445 };
356 static const int kSkip = -1; 446 static const int kSkip = -1;
357 447
358 // Test parsing a WebM file. 448 // Test parsing a WebM file.
359 // |filename| - The name of the file in media/test/data to parse. 449 // |filename| - The name of the file in media/test/data to parse.
360 // |timestamps| - The expected timestamps on the parsed buffers. 450 // |timestamps| - The expected timestamps on the parsed buffers.
361 // a timestamp of kSkip indicates that a Read() call for that stream 451 // 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 452 // shouldn't be made on that iteration of the loop. If both streams have
363 // a kSkip then the loop will terminate. 453 // a kSkip then the loop will terminate.
364 bool ParseWebMFile(const std::string& filename, 454 bool ParseWebMFile(const std::string& filename,
365 const BufferTimestamps* timestamps, 455 const BufferTimestamps* timestamps,
366 const base::TimeDelta& duration) { 456 const base::TimeDelta& duration) {
457 return ParseWebMFile(filename, timestamps, duration, true, true);
458 }
459
460 bool ParseWebMFile(const std::string& filename,
461 const BufferTimestamps* timestamps,
462 const base::TimeDelta& duration,
463 bool has_audio, bool has_video) {
367 EXPECT_CALL(*client_, DemuxerOpened(_)); 464 EXPECT_CALL(*client_, DemuxerOpened(_));
368 demuxer_->Initialize( 465 demuxer_->Initialize(
369 &host_, CreateInitDoneCB(duration, PIPELINE_OK)); 466 &host_, CreateInitDoneCB(duration, PIPELINE_OK));
370 467
371 if (AddId() != ChunkDemuxer::kOk) 468 if (AddId(kSourceId, has_audio, has_video) != ChunkDemuxer::kOk)
372 return false; 469 return false;
373 470
374 // Read a WebM file into memory and send the data to the demuxer. 471 // Read a WebM file into memory and send the data to the demuxer.
375 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename); 472 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename);
376 if (!AppendDataInPieces(buffer->GetData(), buffer->GetDataSize(), 512)) 473 if (!AppendDataInPieces(buffer->GetData(), buffer->GetDataSize(), 512))
377 return false; 474 return false;
378 475
379 scoped_refptr<DemuxerStream> audio = 476 scoped_refptr<DemuxerStream> audio =
380 demuxer_->GetStream(DemuxerStream::AUDIO); 477 demuxer_->GetStream(DemuxerStream::AUDIO);
381 scoped_refptr<DemuxerStream> video = 478 scoped_refptr<DemuxerStream> video =
(...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after
949 struct BufferTimestamps buffer_timestamps[] = { 1046 struct BufferTimestamps buffer_timestamps[] = {
950 {kSkip, 0}, 1047 {kSkip, 0},
951 {kSkip, 3}, 1048 {kSkip, 3},
952 {kSkip, 6}, 1049 {kSkip, 6},
953 {kSkip, 9}, 1050 {kSkip, 9},
954 {kSkip, 12}, 1051 {kSkip, 12},
955 {kSkip, kSkip}, 1052 {kSkip, kSkip},
956 }; 1053 };
957 1054
958 ASSERT_TRUE(ParseWebMFile("bear-320x240-audio-only.webm", buffer_timestamps, 1055 ASSERT_TRUE(ParseWebMFile("bear-320x240-audio-only.webm", buffer_timestamps,
959 base::TimeDelta::FromMilliseconds(2744))); 1056 base::TimeDelta::FromMilliseconds(2744),
1057 true, false));
960 } 1058 }
961 1059
962 TEST_F(ChunkDemuxerTest, TestWebMFile_VideoOnly) { 1060 TEST_F(ChunkDemuxerTest, TestWebMFile_VideoOnly) {
963 struct BufferTimestamps buffer_timestamps[] = { 1061 struct BufferTimestamps buffer_timestamps[] = {
964 {0, kSkip}, 1062 {0, kSkip},
965 {33, kSkip}, 1063 {33, kSkip},
966 {67, kSkip}, 1064 {67, kSkip},
967 {100, kSkip}, 1065 {100, kSkip},
968 {133, kSkip}, 1066 {133, kSkip},
969 {kSkip, kSkip}, 1067 {kSkip, kSkip},
970 }; 1068 };
971 1069
972 ASSERT_TRUE(ParseWebMFile("bear-320x240-video-only.webm", buffer_timestamps, 1070 ASSERT_TRUE(ParseWebMFile("bear-320x240-video-only.webm", buffer_timestamps,
973 base::TimeDelta::FromMilliseconds(2703))); 1071 base::TimeDelta::FromMilliseconds(2703),
1072 false, true));
974 } 1073 }
975 1074
976 TEST_F(ChunkDemuxerTest, TestWebMFile_AltRefFrames) { 1075 TEST_F(ChunkDemuxerTest, TestWebMFile_AltRefFrames) {
977 struct BufferTimestamps buffer_timestamps[] = { 1076 struct BufferTimestamps buffer_timestamps[] = {
978 {0, 0}, 1077 {0, 0},
979 {33, 3}, 1078 {33, 3},
980 {33, 6}, 1079 {33, 6},
981 {67, 9}, 1080 {67, 9},
982 {100, 12}, 1081 {100, 12},
983 {kSkip, kSkip}, 1082 {kSkip, kSkip},
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1089 DEMUXER_ERROR_COULD_NOT_OPEN)); 1188 DEMUXER_ERROR_COULD_NOT_OPEN));
1090 1189
1091 std::vector<std::string> codecs(1); 1190 std::vector<std::string> codecs(1);
1092 codecs[0] = "vp8"; 1191 codecs[0] = "vp8";
1093 ASSERT_EQ(demuxer_->AddId(kSourceId, "video/webm", codecs), 1192 ASSERT_EQ(demuxer_->AddId(kSourceId, "video/webm", codecs),
1094 ChunkDemuxer::kOk); 1193 ChunkDemuxer::kOk);
1095 1194
1096 ASSERT_TRUE(AppendInfoTracks(true, true, false)); 1195 ASSERT_TRUE(AppendInfoTracks(true, true, false));
1097 } 1196 }
1098 1197
1198 TEST_F(ChunkDemuxerTest, TestAddSeparateSourcesForAudioAndVideo) {
1199 std::string audio_id = "audio1";
1200 std::string video_id = "video1";
1201 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1202
1203 scoped_refptr<DemuxerStream> audio =
1204 demuxer_->GetStream(DemuxerStream::AUDIO);
1205 scoped_refptr<DemuxerStream> video =
1206 demuxer_->GetStream(DemuxerStream::VIDEO);
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 GenerateExpectedReads(0, 4, audio, kAudioBlockDuration);
1217 ASSERT_TRUE(AppendData(video_id, cluster_v->data(), cluster_v->size()));
1218 GenerateExpectedReads(0, 4, video, kVideoBlockDuration);
1219 }
1220
1221 TEST_F(ChunkDemuxerTest, TestAddIdFailures) {
1222 EXPECT_CALL(*client_, DemuxerOpened(_));
1223 demuxer_->Initialize(
1224 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK));
1225
1226 std::string audio_id = "audio1";
1227 std::string video_id = "video1";
1228
1229 ASSERT_EQ(AddId(audio_id, true, false), ChunkDemuxer::kOk);
1230
1231 // Adding an id with audio/video should fail because we already added audio.
1232 ASSERT_EQ(AddId(), ChunkDemuxer::kReachedIdLimit);
1233
1234 ASSERT_TRUE(AppendInfoTracks(audio_id, true, false, false));
1235
1236 // Adding an id after append should fail.
1237 ASSERT_EQ(AddId(video_id, false, true), ChunkDemuxer::kReachedIdLimit);
1238 }
1239
1240 // Test that Read() calls after a RemoveId() return "end of stream" buffers.
1241 TEST_F(ChunkDemuxerTest, TestRemoveId) {
1242 std::string audio_id = "audio1";
1243 std::string video_id = "video1";
1244 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1245
1246 scoped_ptr<Cluster> cluster_a(
1247 GenerateSingleStreamCluster(0, 4, kAudioTrackNum, kAudioBlockDuration));
1248
1249 scoped_ptr<Cluster> cluster_v(
1250 GenerateSingleStreamCluster(0, 4, kVideoTrackNum, kVideoBlockDuration));
1251
1252 // Append audio and video data into separate source ids.
1253 ASSERT_TRUE(AppendData(audio_id, cluster_a->data(), cluster_a->size()));
1254 ASSERT_TRUE(AppendData(video_id, cluster_v->data(), cluster_v->size()));
1255
1256 // Read() from audio should return normal buffers.
1257 scoped_refptr<DemuxerStream> audio =
1258 demuxer_->GetStream(DemuxerStream::AUDIO);
1259 GenerateExpectedReads(0, 4, audio, kAudioBlockDuration);
1260
1261 // Remove the audio id.
1262 demuxer_->RemoveId(audio_id);
1263
1264 // Read() from audio should return "end of stream" buffers.
1265 bool audio_read_done = false;
1266 audio->Read(base::Bind(&OnReadDone_EOSExpected,
1267 &audio_read_done));
1268 EXPECT_TRUE(audio_read_done);
1269
1270 // Read() from video should still return normal buffers.
1271 scoped_refptr<DemuxerStream> video =
1272 demuxer_->GetStream(DemuxerStream::VIDEO);
1273 GenerateExpectedReads(0, 4, video, kVideoBlockDuration);
1274 }
1275
1276 // Test that Seek() successfully seeks to all source IDs.
1277 TEST_F(ChunkDemuxerTest, TestSeekAudioAndVideoSources) {
1278 std::string audio_id = "audio1";
1279 std::string video_id = "video1";
1280 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1281
1282 scoped_ptr<Cluster> cluster_a1(
1283 GenerateSingleStreamCluster(0, 4, kAudioTrackNum, kAudioBlockDuration));
1284
1285 scoped_ptr<Cluster> cluster_v1(
1286 GenerateSingleStreamCluster(0, 4, kVideoTrackNum, kVideoBlockDuration));
1287
1288 ASSERT_TRUE(AppendData(audio_id, cluster_a1->data(), cluster_a1->size()));
1289 ASSERT_TRUE(AppendData(video_id, cluster_v1->data(), cluster_v1->size()));
1290
1291 // Read() should return buffers at 0.
1292 bool audio_read_done = false;
1293 bool video_read_done = false;
1294 scoped_refptr<DemuxerStream> audio =
1295 demuxer_->GetStream(DemuxerStream::AUDIO);
1296 scoped_refptr<DemuxerStream> video =
1297 demuxer_->GetStream(DemuxerStream::VIDEO);
1298
1299 audio->Read(base::Bind(&OnReadDone,
1300 base::TimeDelta::FromMilliseconds(0),
1301 &audio_read_done));
1302 video->Read(base::Bind(&OnReadDone,
1303 base::TimeDelta::FromMilliseconds(0),
1304 &video_read_done));
1305 EXPECT_TRUE(audio_read_done);
1306 EXPECT_TRUE(video_read_done);
1307
1308 // Seek to 3 (an unbuffered region).
1309 demuxer_->StartWaitingForSeek();
1310 demuxer_->Seek(base::TimeDelta::FromSeconds(3),
1311 NewExpectedStatusCB(PIPELINE_OK));
1312
1313 audio_read_done = false;
1314 video_read_done = false;
1315 audio->Read(base::Bind(&OnReadDone,
1316 base::TimeDelta::FromSeconds(3),
1317 &audio_read_done));
1318 video->Read(base::Bind(&OnReadDone,
1319 base::TimeDelta::FromSeconds(3),
1320 &video_read_done));
1321
1322 // Read()s should not return until after data is appended at the Seek point.
1323 EXPECT_FALSE(audio_read_done);
1324 EXPECT_FALSE(video_read_done);
1325
1326 scoped_ptr<Cluster> cluster_a2(
1327 GenerateSingleStreamCluster(3000, 4, kAudioTrackNum,
1328 kAudioBlockDuration));
1329
1330 scoped_ptr<Cluster> cluster_v2(
1331 GenerateSingleStreamCluster(3000, 4, kVideoTrackNum,
1332 kVideoBlockDuration));
1333
1334 ASSERT_TRUE(AppendData(audio_id, cluster_a2->data(), cluster_a2->size()));
1335 ASSERT_TRUE(AppendData(video_id, cluster_v2->data(), cluster_v2->size()));
1336
1337 // Read() should return buffers at 3.
1338 EXPECT_TRUE(audio_read_done);
1339 EXPECT_TRUE(video_read_done);
1340 }
1341
1099 } // namespace media 1342 } // namespace media
OLDNEW
« media/filters/chunk_demuxer.cc ('K') | « media/filters/chunk_demuxer.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698