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