OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/base_paths.h" | 5 #include "base/base_paths.h" |
6 #include "base/bind.h" | 6 #include "base/bind.h" |
7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
8 #include "base/message_loop.h" | |
8 #include "base/path_service.h" | 9 #include "base/path_service.h" |
9 #include "media/base/media.h" | 10 #include "media/base/media.h" |
10 #include "media/base/mock_callback.h" | 11 #include "media/base/mock_callback.h" |
11 #include "media/base/mock_ffmpeg.h" | 12 #include "media/base/mock_ffmpeg.h" |
13 #include "media/base/mock_filter_host.h" | |
12 #include "media/filters/chunk_demuxer.h" | 14 #include "media/filters/chunk_demuxer.h" |
13 #include "media/filters/chunk_demuxer_client.h" | 15 #include "media/filters/chunk_demuxer_client.h" |
14 #include "media/webm/cluster_builder.h" | 16 #include "media/webm/cluster_builder.h" |
15 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
16 | 18 |
19 using ::testing::AnyNumber; | |
17 using ::testing::InSequence; | 20 using ::testing::InSequence; |
18 using ::testing::Return; | 21 using ::testing::Return; |
19 using ::testing::SetArgumentPointee; | 22 using ::testing::SetArgumentPointee; |
20 using ::testing::NiceMock; | 23 using ::testing::NiceMock; |
21 using ::testing::_; | 24 using ::testing::_; |
22 | 25 |
23 namespace media { | 26 namespace media { |
24 | 27 |
25 static const uint8 kTracksHeader[] = { | 28 static const uint8 kTracksHeader[] = { |
26 0x16, 0x54, 0xAE, 0x6B, // Tracks ID | 29 0x16, 0x54, 0xAE, 0x6B, // Tracks ID |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
65 codecs_[VIDEO].width = 320; | 68 codecs_[VIDEO].width = 320; |
66 codecs_[VIDEO].height = 240; | 69 codecs_[VIDEO].height = 240; |
67 | 70 |
68 codecs_[AUDIO].codec_type = AVMEDIA_TYPE_AUDIO; | 71 codecs_[AUDIO].codec_type = AVMEDIA_TYPE_AUDIO; |
69 codecs_[AUDIO].codec_id = CODEC_ID_VORBIS; | 72 codecs_[AUDIO].codec_id = CODEC_ID_VORBIS; |
70 codecs_[AUDIO].channels = 2; | 73 codecs_[AUDIO].channels = 2; |
71 codecs_[AUDIO].sample_rate = 44100; | 74 codecs_[AUDIO].sample_rate = 44100; |
72 } | 75 } |
73 | 76 |
74 virtual ~ChunkDemuxerTest() { | 77 virtual ~ChunkDemuxerTest() { |
78 message_loop_.RunAllPending(); | |
Ami GONE FROM CHROMIUM
2011/08/03 21:06:02
This makes me worry. Why do you have it?
acolwell GONE FROM CHROMIUM
2011/08/03 22:08:11
It was just catching the error on EndOfStream() ca
| |
75 ShutdownDemuxer(); | 79 ShutdownDemuxer(); |
76 } | 80 } |
77 | 81 |
78 void ReadFile(const std::string& name, scoped_array<uint8>* buffer, | 82 void ReadFile(const std::string& name, scoped_array<uint8>* buffer, |
79 int* size) { | 83 int* size) { |
80 FilePath file_path; | 84 FilePath file_path; |
81 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path)); | 85 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path)); |
82 file_path = file_path.Append(FILE_PATH_LITERAL("media")) | 86 file_path = file_path.Append(FILE_PATH_LITERAL("media")) |
83 .Append(FILE_PATH_LITERAL("test")) | 87 .Append(FILE_PATH_LITERAL("test")) |
84 .Append(FILE_PATH_LITERAL("data")) | 88 .Append(FILE_PATH_LITERAL("data")) |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
142 memcpy(buf, audio_track_entry.get(), audio_track_entry_size); | 146 memcpy(buf, audio_track_entry.get(), audio_track_entry_size); |
143 buf += audio_track_entry_size; | 147 buf += audio_track_entry_size; |
144 } | 148 } |
145 | 149 |
146 if (has_video) { | 150 if (has_video) { |
147 memcpy(buf, video_track_entry.get(), video_track_entry_size); | 151 memcpy(buf, video_track_entry.get(), video_track_entry_size); |
148 buf += video_track_entry_size; | 152 buf += video_track_entry_size; |
149 } | 153 } |
150 } | 154 } |
151 | 155 |
156 void AppendData(const uint8* data, unsigned length) { | |
157 EXPECT_CALL(mock_filter_host_, SetBufferedBytes(_)).Times(AnyNumber()); | |
158 EXPECT_CALL(mock_filter_host_, SetBufferedTime(_)).Times(AnyNumber()); | |
159 EXPECT_CALL(mock_filter_host_, SetNetworkActivity(true)).Times(AnyNumber()); | |
Ami GONE FROM CHROMIUM
2011/08/03 21:06:02
Ugh to the above three lines, and the other green
acolwell GONE FROM CHROMIUM
2011/08/03 22:08:11
Yes. Yes I can...These are on the must die list al
| |
160 EXPECT_TRUE(demuxer_->AppendData(data, length)); | |
161 message_loop_.RunAllPending(); | |
162 } | |
163 | |
152 void AppendInfoTracks(bool has_audio, bool has_video) { | 164 void AppendInfoTracks(bool has_audio, bool has_video) { |
153 EXPECT_CALL(mock_ffmpeg_, AVOpenInputFile(_, _, NULL, 0, NULL)) | 165 EXPECT_CALL(mock_ffmpeg_, AVOpenInputFile(_, _, NULL, 0, NULL)) |
154 .WillOnce(DoAll(SetArgumentPointee<0>(&format_context_), | 166 .WillOnce(DoAll(SetArgumentPointee<0>(&format_context_), |
155 Return(0))); | 167 Return(0))); |
156 | 168 |
157 EXPECT_CALL(mock_ffmpeg_, AVFindStreamInfo(&format_context_)) | 169 EXPECT_CALL(mock_ffmpeg_, AVFindStreamInfo(&format_context_)) |
158 .WillOnce(Return(0)); | 170 .WillOnce(Return(0)); |
159 | 171 |
160 EXPECT_CALL(mock_ffmpeg_, AVCloseInputFile(&format_context_)); | 172 EXPECT_CALL(mock_ffmpeg_, AVCloseInputFile(&format_context_)); |
161 | 173 |
162 EXPECT_CALL(mock_ffmpeg_, AVRegisterLockManager(_)) | 174 EXPECT_CALL(mock_ffmpeg_, AVRegisterLockManager(_)) |
163 .WillRepeatedly(Return(0)); | 175 .WillRepeatedly(Return(0)); |
164 | 176 |
165 scoped_array<uint8> info_tracks; | 177 scoped_array<uint8> info_tracks; |
166 int info_tracks_size = 0; | 178 int info_tracks_size = 0; |
167 CreateInfoTracks(has_audio, has_video, &info_tracks, &info_tracks_size); | 179 CreateInfoTracks(has_audio, has_video, &info_tracks, &info_tracks_size); |
168 | 180 |
169 SetupAVFormatContext(has_audio, has_video); | 181 SetupAVFormatContext(has_audio, has_video); |
170 | 182 |
171 demuxer_->AppendData(info_tracks.get(), info_tracks_size); | 183 AppendData(info_tracks.get(), info_tracks_size); |
172 } | 184 } |
173 | 185 |
174 static void InitDoneCalled(bool* was_called, PipelineStatus expectedStatus, | 186 static void InitDoneCalled(bool* was_called, PipelineStatus expectedStatus, |
175 PipelineStatus status) { | 187 PipelineStatus status) { |
176 EXPECT_EQ(status, expectedStatus); | 188 EXPECT_EQ(status, expectedStatus); |
177 *was_called = true; | 189 *was_called = true; |
178 } | 190 } |
179 | 191 |
180 void InitDemuxer(bool has_audio, bool has_video) { | 192 void InitDemuxer(bool has_audio, bool has_video) { |
181 bool init_done_called = false; | 193 bool init_done_called = false; |
182 PipelineStatus expectedStatus = | 194 PipelineStatus expectedStatus = |
183 (has_audio || has_video) ? PIPELINE_OK : DEMUXER_ERROR_COULD_NOT_OPEN; | 195 (has_audio || has_video) ? PIPELINE_OK : DEMUXER_ERROR_COULD_NOT_OPEN; |
184 | 196 |
185 EXPECT_CALL(*client_, DemuxerOpened(_)); | 197 EXPECT_CALL(*client_, DemuxerOpened(_)); |
186 demuxer_->Init(base::Bind(&ChunkDemuxerTest::InitDoneCalled, | 198 demuxer_->Init(base::Bind(&ChunkDemuxerTest::InitDoneCalled, |
187 &init_done_called, | 199 &init_done_called, |
188 expectedStatus)); | 200 expectedStatus)); |
189 | 201 |
190 EXPECT_FALSE(init_done_called); | 202 EXPECT_FALSE(init_done_called); |
191 | 203 |
192 AppendInfoTracks(has_audio, has_video); | 204 AppendInfoTracks(has_audio, has_video); |
193 | 205 |
194 EXPECT_TRUE(init_done_called); | 206 EXPECT_TRUE(init_done_called); |
207 EXPECT_CALL(mock_filter_host_, SetDuration(_)); | |
208 EXPECT_CALL(mock_filter_host_, SetCurrentReadPosition(_)); | |
209 demuxer_->set_host(&mock_filter_host_); | |
195 } | 210 } |
196 | 211 |
197 void ShutdownDemuxer() { | 212 void ShutdownDemuxer() { |
198 if (demuxer_) { | 213 if (demuxer_) { |
199 EXPECT_CALL(*client_, DemuxerClosed()); | 214 EXPECT_CALL(*client_, DemuxerClosed()); |
200 demuxer_->Shutdown(); | 215 demuxer_->Shutdown(); |
201 } | 216 } |
202 | 217 |
203 if (format_context_.streams) { | 218 if (format_context_.streams) { |
204 delete[] format_context_.streams; | 219 delete[] format_context_.streams; |
205 format_context_.streams = NULL; | 220 format_context_.streams = NULL; |
206 format_context_.nb_streams = 0; | 221 format_context_.nb_streams = 0; |
207 } | 222 } |
208 } | 223 } |
209 | 224 |
210 void AddSimpleBlock(ClusterBuilder* cb, int track_num, int64 timecode) { | 225 void AddSimpleBlock(ClusterBuilder* cb, int track_num, int64 timecode) { |
211 uint8 data[] = { 0x00 }; | 226 uint8 data[] = { 0x00 }; |
212 cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data)); | 227 cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data)); |
213 } | 228 } |
214 | 229 |
215 MOCK_METHOD1(Checkpoint, void(int id)); | 230 MOCK_METHOD1(Checkpoint, void(int id)); |
216 | 231 |
232 MessageLoop message_loop_; | |
Ami GONE FROM CHROMIUM
2011/08/03 21:06:02
I don't get where this is populated, only drained.
acolwell GONE FROM CHROMIUM
2011/08/03 22:08:11
The constructor is magical and initializes the thr
Ami GONE FROM CHROMIUM
2011/08/03 23:41:35
Per offline convo, I think you can avoid ML entire
acolwell GONE FROM CHROMIUM
2011/08/04 00:22:16
Removed
| |
217 MockFFmpeg mock_ffmpeg_; | 233 MockFFmpeg mock_ffmpeg_; |
234 MockFilterHost mock_filter_host_; | |
218 | 235 |
219 AVFormatContext format_context_; | 236 AVFormatContext format_context_; |
220 AVCodecContext codecs_[MAX_CODECS_INDEX]; | 237 AVCodecContext codecs_[MAX_CODECS_INDEX]; |
221 AVStream streams_[MAX_CODECS_INDEX]; | 238 AVStream streams_[MAX_CODECS_INDEX]; |
222 | 239 |
223 scoped_ptr<MockChunkDemuxerClient> client_; | 240 scoped_ptr<MockChunkDemuxerClient> client_; |
224 scoped_refptr<ChunkDemuxer> demuxer_; | 241 scoped_refptr<ChunkDemuxer> demuxer_; |
225 | 242 |
226 private: | 243 private: |
227 void SetupAVFormatContext(bool has_audio, bool has_video) { | 244 void SetupAVFormatContext(bool has_audio, bool has_video) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
292 | 309 |
293 EXPECT_CALL(*this, Checkpoint(2)); | 310 EXPECT_CALL(*this, Checkpoint(2)); |
294 | 311 |
295 ClusterBuilder cb; | 312 ClusterBuilder cb; |
296 cb.SetClusterTimecode(0); | 313 cb.SetClusterTimecode(0); |
297 AddSimpleBlock(&cb, kVideoTrackNum, 0); | 314 AddSimpleBlock(&cb, kVideoTrackNum, 0); |
298 scoped_ptr<Cluster> cluster(cb.Finish()); | 315 scoped_ptr<Cluster> cluster(cb.Finish()); |
299 | 316 |
300 Checkpoint(1); | 317 Checkpoint(1); |
301 | 318 |
302 EXPECT_TRUE(demuxer_->AppendData(cluster->data(), cluster->size())); | 319 AppendData(cluster->data(), cluster->size()); |
303 | 320 |
304 Checkpoint(2); | 321 Checkpoint(2); |
305 } | 322 } |
306 | 323 |
307 // Test the case where AppendData() is called before Init(). | 324 // Test the case where AppendData() is called before Init(). |
308 TEST_F(ChunkDemuxerTest, TestAppendDataBeforeInit) { | 325 TEST_F(ChunkDemuxerTest, TestAppendDataBeforeInit) { |
309 scoped_array<uint8> info_tracks; | 326 scoped_array<uint8> info_tracks; |
310 int info_tracks_size = 0; | 327 int info_tracks_size = 0; |
311 CreateInfoTracks(true, true, &info_tracks, &info_tracks_size); | 328 CreateInfoTracks(true, true, &info_tracks, &info_tracks_size); |
312 | 329 |
(...skipping 25 matching lines...) Expand all Loading... | |
338 video->Read(base::Bind(&OnReadDone, | 355 video->Read(base::Bind(&OnReadDone, |
339 base::TimeDelta::FromMilliseconds(123), | 356 base::TimeDelta::FromMilliseconds(123), |
340 &video_read_done)); | 357 &video_read_done)); |
341 | 358 |
342 ClusterBuilder cb; | 359 ClusterBuilder cb; |
343 cb.SetClusterTimecode(0); | 360 cb.SetClusterTimecode(0); |
344 AddSimpleBlock(&cb, kAudioTrackNum, 32); | 361 AddSimpleBlock(&cb, kAudioTrackNum, 32); |
345 AddSimpleBlock(&cb, kVideoTrackNum, 123); | 362 AddSimpleBlock(&cb, kVideoTrackNum, 123); |
346 scoped_ptr<Cluster> cluster(cb.Finish()); | 363 scoped_ptr<Cluster> cluster(cb.Finish()); |
347 | 364 |
348 EXPECT_TRUE(demuxer_->AppendData(cluster->data(), cluster->size())); | 365 AppendData(cluster->data(), cluster->size()); |
349 | 366 |
350 EXPECT_TRUE(audio_read_done); | 367 EXPECT_TRUE(audio_read_done); |
351 EXPECT_TRUE(video_read_done); | 368 EXPECT_TRUE(video_read_done); |
352 } | 369 } |
353 | 370 |
354 TEST_F(ChunkDemuxerTest, TestOutOfOrderClusters) { | 371 TEST_F(ChunkDemuxerTest, TestOutOfOrderClusters) { |
355 InitDemuxer(true, true); | 372 InitDemuxer(true, true); |
356 | 373 |
357 ClusterBuilder cb; | 374 ClusterBuilder cb; |
358 | 375 |
359 cb.SetClusterTimecode(10); | 376 cb.SetClusterTimecode(10); |
360 AddSimpleBlock(&cb, kAudioTrackNum, 10); | 377 AddSimpleBlock(&cb, kAudioTrackNum, 10); |
361 AddSimpleBlock(&cb, kVideoTrackNum, 10); | 378 AddSimpleBlock(&cb, kVideoTrackNum, 10); |
362 AddSimpleBlock(&cb, kAudioTrackNum, 33); | 379 AddSimpleBlock(&cb, kAudioTrackNum, 33); |
363 AddSimpleBlock(&cb, kVideoTrackNum, 43); | 380 AddSimpleBlock(&cb, kVideoTrackNum, 43); |
364 scoped_ptr<Cluster> clusterA(cb.Finish()); | 381 scoped_ptr<Cluster> clusterA(cb.Finish()); |
365 | 382 |
366 EXPECT_TRUE(demuxer_->AppendData(clusterA->data(), clusterA->size())); | 383 AppendData(clusterA->data(), clusterA->size()); |
367 | 384 |
368 // Cluster B starts before clusterA and has data | 385 // Cluster B starts before clusterA and has data |
369 // that overlaps. | 386 // that overlaps. |
370 cb.SetClusterTimecode(5); | 387 cb.SetClusterTimecode(5); |
371 AddSimpleBlock(&cb, kAudioTrackNum, 5); | 388 AddSimpleBlock(&cb, kAudioTrackNum, 5); |
372 AddSimpleBlock(&cb, kVideoTrackNum, 7); | 389 AddSimpleBlock(&cb, kVideoTrackNum, 7); |
373 AddSimpleBlock(&cb, kAudioTrackNum, 28); | 390 AddSimpleBlock(&cb, kAudioTrackNum, 28); |
374 AddSimpleBlock(&cb, kVideoTrackNum, 40); | 391 AddSimpleBlock(&cb, kVideoTrackNum, 40); |
375 scoped_ptr<Cluster> clusterB(cb.Finish()); | 392 scoped_ptr<Cluster> clusterB(cb.Finish()); |
376 | 393 |
377 // Make sure that AppendData() fails because this cluster data | 394 // Make sure that AppendData() fails because this cluster data |
378 // is before previous data. | 395 // is before previous data. |
379 EXPECT_FALSE(demuxer_->AppendData(clusterB->data(), clusterB->size())); | 396 EXPECT_CALL(mock_filter_host_, SetError(PIPELINE_ERROR_DECODE)); |
397 AppendData(clusterB->data(), clusterB->size()); | |
380 | 398 |
381 // Cluster C starts after clusterA. | 399 // Verify that AppendData() doesn't accept more data now. |
382 cb.SetClusterTimecode(56); | 400 cb.SetClusterTimecode(45); |
383 AddSimpleBlock(&cb, kAudioTrackNum, 56); | 401 AddSimpleBlock(&cb, kAudioTrackNum, 45); |
384 AddSimpleBlock(&cb, kVideoTrackNum, 76); | 402 AddSimpleBlock(&cb, kVideoTrackNum, 45); |
385 AddSimpleBlock(&cb, kAudioTrackNum, 79); | |
386 AddSimpleBlock(&cb, kVideoTrackNum, 109); | |
387 scoped_ptr<Cluster> clusterC(cb.Finish()); | 403 scoped_ptr<Cluster> clusterC(cb.Finish()); |
388 | 404 EXPECT_FALSE(demuxer_->AppendData(clusterC->data(), clusterC->size())); |
389 // Verify that clusterC is accepted. | |
390 EXPECT_TRUE(demuxer_->AppendData(clusterC->data(), clusterC->size())); | |
391 | |
392 // Flush and try clusterB again. | |
393 demuxer_->FlushData(); | |
394 EXPECT_TRUE(demuxer_->AppendData(clusterB->data(), clusterB->size())); | |
395 | |
396 // Following that with clusterC should work too since it doesn't | |
397 // overlap with clusterB. | |
398 EXPECT_TRUE(demuxer_->AppendData(clusterC->data(), clusterC->size())); | |
399 } | 405 } |
400 | 406 |
401 TEST_F(ChunkDemuxerTest, TestInvalidBlockSequences) { | 407 TEST_F(ChunkDemuxerTest, TestNonMonotonicButAboveClusterTimecode) { |
402 InitDemuxer(true, true); | 408 InitDemuxer(true, true); |
403 | 409 |
404 ClusterBuilder cb; | 410 ClusterBuilder cb; |
405 | 411 |
406 // Test the case where timecode is not monotonically | 412 // Test the case where block timecodes are not monotonically |
407 // increasing but stays above the cluster timecode. | 413 // increasing but stay above the cluster timecode. |
408 cb.SetClusterTimecode(5); | 414 cb.SetClusterTimecode(5); |
409 AddSimpleBlock(&cb, kAudioTrackNum, 5); | 415 AddSimpleBlock(&cb, kAudioTrackNum, 5); |
410 AddSimpleBlock(&cb, kVideoTrackNum, 10); | 416 AddSimpleBlock(&cb, kVideoTrackNum, 10); |
411 AddSimpleBlock(&cb, kAudioTrackNum, 7); | 417 AddSimpleBlock(&cb, kAudioTrackNum, 7); |
412 AddSimpleBlock(&cb, kVideoTrackNum, 15); | 418 AddSimpleBlock(&cb, kVideoTrackNum, 15); |
413 scoped_ptr<Cluster> clusterA(cb.Finish()); | 419 scoped_ptr<Cluster> clusterA(cb.Finish()); |
414 | 420 |
415 EXPECT_FALSE(demuxer_->AppendData(clusterA->data(), clusterA->size())); | 421 EXPECT_CALL(mock_filter_host_, SetError(PIPELINE_ERROR_DECODE)); |
422 AppendData(clusterA->data(), clusterA->size()); | |
416 | 423 |
417 // Test timecodes going backwards before cluster timecode. | 424 // Verify that AppendData() doesn't accept more data now. |
425 cb.SetClusterTimecode(20); | |
426 AddSimpleBlock(&cb, kAudioTrackNum, 20); | |
427 AddSimpleBlock(&cb, kVideoTrackNum, 20); | |
428 scoped_ptr<Cluster> clusterB(cb.Finish()); | |
429 EXPECT_FALSE(demuxer_->AppendData(clusterB->data(), clusterB->size())); | |
430 } | |
431 | |
432 TEST_F(ChunkDemuxerTest, TestBackwardsAndBeforeClusterTimecode) { | |
433 InitDemuxer(true, true); | |
434 | |
435 ClusterBuilder cb; | |
436 | |
437 // Test timecodes going backwards and including values less than the cluster | |
438 // timecode. | |
418 cb.SetClusterTimecode(5); | 439 cb.SetClusterTimecode(5); |
419 AddSimpleBlock(&cb, kAudioTrackNum, 5); | 440 AddSimpleBlock(&cb, kAudioTrackNum, 5); |
420 AddSimpleBlock(&cb, kVideoTrackNum, 5); | 441 AddSimpleBlock(&cb, kVideoTrackNum, 5); |
421 AddSimpleBlock(&cb, kAudioTrackNum, 3); | 442 AddSimpleBlock(&cb, kAudioTrackNum, 3); |
422 AddSimpleBlock(&cb, kVideoTrackNum, 3); | 443 AddSimpleBlock(&cb, kVideoTrackNum, 3); |
444 scoped_ptr<Cluster> clusterA(cb.Finish()); | |
445 | |
446 EXPECT_CALL(mock_filter_host_, SetError(PIPELINE_ERROR_DECODE)); | |
447 AppendData(clusterA->data(), clusterA->size()); | |
448 | |
449 // Verify that AppendData() doesn't accept more data now. | |
450 cb.SetClusterTimecode(6); | |
451 AddSimpleBlock(&cb, kAudioTrackNum, 6); | |
452 AddSimpleBlock(&cb, kVideoTrackNum, 6); | |
423 scoped_ptr<Cluster> clusterB(cb.Finish()); | 453 scoped_ptr<Cluster> clusterB(cb.Finish()); |
454 EXPECT_FALSE(demuxer_->AppendData(clusterB->data(), clusterB->size())); | |
455 } | |
424 | 456 |
425 EXPECT_FALSE(demuxer_->AppendData(clusterB->data(), clusterB->size())); | 457 |
458 TEST_F(ChunkDemuxerTest, TestPerStreamMonotonicallyIncreasingTimestamps) { | |
459 InitDemuxer(true, true); | |
460 | |
461 ClusterBuilder cb; | |
426 | 462 |
427 // Test strict monotonic increasing timestamps on a per stream | 463 // Test strict monotonic increasing timestamps on a per stream |
428 // basis. | 464 // basis. |
429 cb.SetClusterTimecode(5); | 465 cb.SetClusterTimecode(5); |
430 AddSimpleBlock(&cb, kAudioTrackNum, 5); | 466 AddSimpleBlock(&cb, kAudioTrackNum, 5); |
431 AddSimpleBlock(&cb, kVideoTrackNum, 5); | 467 AddSimpleBlock(&cb, kVideoTrackNum, 5); |
432 AddSimpleBlock(&cb, kAudioTrackNum, 5); | 468 AddSimpleBlock(&cb, kAudioTrackNum, 5); |
433 AddSimpleBlock(&cb, kVideoTrackNum, 7); | 469 AddSimpleBlock(&cb, kVideoTrackNum, 7); |
434 scoped_ptr<Cluster> clusterC(cb.Finish()); | 470 scoped_ptr<Cluster> cluster(cb.Finish()); |
435 | 471 |
436 EXPECT_FALSE(demuxer_->AppendData(clusterC->data(), clusterC->size())); | 472 EXPECT_CALL(mock_filter_host_, SetError(PIPELINE_ERROR_DECODE)); |
473 AppendData(cluster->data(), cluster->size()); | |
474 } | |
475 | |
476 TEST_F(ChunkDemuxerTest, TestMonotonicallyIncreasingTimestampsAcrossClusters) { | |
477 InitDemuxer(true, true); | |
478 | |
479 ClusterBuilder cb; | |
437 | 480 |
438 // Test strict monotonic increasing timestamps on a per stream | 481 // Test strict monotonic increasing timestamps on a per stream |
439 // basis across clusters. | 482 // basis across clusters. |
440 cb.SetClusterTimecode(5); | 483 cb.SetClusterTimecode(5); |
441 AddSimpleBlock(&cb, kAudioTrackNum, 5); | 484 AddSimpleBlock(&cb, kAudioTrackNum, 5); |
442 AddSimpleBlock(&cb, kVideoTrackNum, 5); | 485 AddSimpleBlock(&cb, kVideoTrackNum, 5); |
443 scoped_ptr<Cluster> clusterD(cb.Finish()); | 486 scoped_ptr<Cluster> clusterA(cb.Finish()); |
444 | 487 |
445 EXPECT_TRUE(demuxer_->AppendData(clusterD->data(), clusterD->size())); | 488 AppendData(clusterA->data(), clusterA->size()); |
446 | 489 |
447 cb.SetClusterTimecode(5); | 490 cb.SetClusterTimecode(5); |
448 AddSimpleBlock(&cb, kAudioTrackNum, 5); | 491 AddSimpleBlock(&cb, kAudioTrackNum, 5); |
449 AddSimpleBlock(&cb, kVideoTrackNum, 7); | 492 AddSimpleBlock(&cb, kVideoTrackNum, 7); |
450 scoped_ptr<Cluster> clusterE(cb.Finish()); | 493 scoped_ptr<Cluster> clusterB(cb.Finish()); |
451 | 494 |
452 EXPECT_FALSE(demuxer_->AppendData(clusterE->data(), clusterE->size())); | 495 EXPECT_CALL(mock_filter_host_, SetError(PIPELINE_ERROR_DECODE)); |
496 AppendData(clusterB->data(), clusterB->size()); | |
497 | |
498 // Verify that AppendData() doesn't accept more data now. | |
499 cb.SetClusterTimecode(10); | |
500 AddSimpleBlock(&cb, kAudioTrackNum, 10); | |
501 AddSimpleBlock(&cb, kVideoTrackNum, 10); | |
502 scoped_ptr<Cluster> clusterC(cb.Finish()); | |
503 EXPECT_FALSE(demuxer_->AppendData(clusterC->data(), clusterC->size())); | |
453 } | 504 } |
454 | 505 |
455 // Test the case where a cluster is passed to AppendData() before | 506 // Test the case where a cluster is passed to AppendData() before |
456 // INFO & TRACKS data. | 507 // INFO & TRACKS data. |
457 TEST_F(ChunkDemuxerTest, TestClusterBeforeInfoTracks) { | 508 TEST_F(ChunkDemuxerTest, TestClusterBeforeInfoTracks) { |
458 EXPECT_CALL(*client_, DemuxerOpened(_)); | 509 EXPECT_CALL(*client_, DemuxerOpened(_)); |
459 demuxer_->Init(NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); | 510 demuxer_->Init(NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); |
460 | 511 |
461 ClusterBuilder cb; | 512 ClusterBuilder cb; |
462 cb.SetClusterTimecode(0); | 513 cb.SetClusterTimecode(0); |
463 AddSimpleBlock(&cb, kVideoTrackNum, 0); | 514 AddSimpleBlock(&cb, kVideoTrackNum, 0); |
464 scoped_ptr<Cluster> cluster(cb.Finish()); | 515 scoped_ptr<Cluster> cluster(cb.Finish()); |
465 | 516 |
466 EXPECT_FALSE(demuxer_->AppendData(cluster->data(), cluster->size())); | 517 AppendData(cluster->data(), cluster->size()); |
467 } | 518 } |
468 | 519 |
469 | |
470 // Test cases where we get an EndOfStream() call during initialization. | 520 // Test cases where we get an EndOfStream() call during initialization. |
471 TEST_F(ChunkDemuxerTest, TestEOSDuringInit) { | 521 TEST_F(ChunkDemuxerTest, TestEOSDuringInit) { |
472 EXPECT_CALL(*client_, DemuxerOpened(_)); | 522 EXPECT_CALL(*client_, DemuxerOpened(_)); |
473 demuxer_->Init(NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); | 523 demuxer_->Init(NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); |
474 demuxer_->EndOfStream(PIPELINE_OK); | 524 demuxer_->EndOfStream(PIPELINE_OK); |
475 } | 525 } |
526 | |
527 TEST_F(ChunkDemuxerTest, TestDecodeErrorEndOfStream) { | |
528 InitDemuxer(true, true); | |
529 | |
530 ClusterBuilder cb; | |
531 cb.SetClusterTimecode(0); | |
532 AddSimpleBlock(&cb, kAudioTrackNum, 0); | |
533 AddSimpleBlock(&cb, kVideoTrackNum, 0); | |
534 AddSimpleBlock(&cb, kAudioTrackNum, 23); | |
535 AddSimpleBlock(&cb, kVideoTrackNum, 33); | |
536 scoped_ptr<Cluster> cluster(cb.Finish()); | |
537 AppendData(cluster->data(), cluster->size()); | |
538 | |
539 EXPECT_CALL(mock_filter_host_, SetError(PIPELINE_ERROR_DECODE)); | |
540 demuxer_->EndOfStream(PIPELINE_ERROR_DECODE); | |
541 } | |
542 | |
543 TEST_F(ChunkDemuxerTest, TestNetworkErrorEndOfStream) { | |
544 InitDemuxer(true, true); | |
545 | |
546 ClusterBuilder cb; | |
547 cb.SetClusterTimecode(0); | |
548 AddSimpleBlock(&cb, kAudioTrackNum, 0); | |
549 AddSimpleBlock(&cb, kVideoTrackNum, 0); | |
550 AddSimpleBlock(&cb, kAudioTrackNum, 23); | |
551 AddSimpleBlock(&cb, kVideoTrackNum, 33); | |
552 scoped_ptr<Cluster> cluster(cb.Finish()); | |
553 AppendData(cluster->data(), cluster->size()); | |
554 | |
555 EXPECT_CALL(mock_filter_host_, SetError(PIPELINE_ERROR_NETWORK)); | |
556 demuxer_->EndOfStream(PIPELINE_ERROR_NETWORK); | |
557 } | |
558 | |
476 } // namespace media | 559 } // namespace media |
OLD | NEW |