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 <deque> | 5 #include <deque> |
6 | 6 |
7 #include "base/file_path.h" | 7 #include "base/file_path.h" |
8 #include "base/path_service.h" | 8 #include "base/path_service.h" |
9 #include "base/threading/thread.h" | 9 #include "base/threading/thread.h" |
10 #include "media/base/filters.h" | 10 #include "media/base/filters.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 using ::testing::NotNull; | 24 using ::testing::NotNull; |
25 using ::testing::Return; | 25 using ::testing::Return; |
26 using ::testing::SaveArg; | 26 using ::testing::SaveArg; |
27 using ::testing::SetArgPointee; | 27 using ::testing::SetArgPointee; |
28 using ::testing::StrictMock; | 28 using ::testing::StrictMock; |
29 using ::testing::WithArgs; | 29 using ::testing::WithArgs; |
30 using ::testing::_; | 30 using ::testing::_; |
31 | 31 |
32 namespace media { | 32 namespace media { |
33 | 33 |
| 34 MATCHER(IsEndOfStreamBuffer, |
| 35 std::string(negation ? "isn't" : "is") + " end of stream") { |
| 36 return arg->IsEndOfStream(); |
| 37 } |
| 38 |
34 // Fixture class to facilitate writing tests. Takes care of setting up the | 39 // Fixture class to facilitate writing tests. Takes care of setting up the |
35 // FFmpeg, pipeline and filter host mocks. | 40 // FFmpeg, pipeline and filter host mocks. |
36 class FFmpegDemuxerTest : public testing::Test { | 41 class FFmpegDemuxerTest : public testing::Test { |
37 protected: | 42 protected: |
38 | 43 |
39 FFmpegDemuxerTest() { | 44 FFmpegDemuxerTest() { |
40 // Create an FFmpegDemuxer. | 45 // Create an FFmpegDemuxer. |
41 demuxer_ = new FFmpegDemuxer(&message_loop_); | 46 demuxer_ = new FFmpegDemuxer(&message_loop_); |
42 demuxer_->disable_first_seek_hack_for_testing(); | 47 demuxer_->disable_first_seek_hack_for_testing(); |
43 | 48 |
44 // Inject a filter host and message loop and prepare a data source. | 49 // Inject a filter host and message loop and prepare a data source. |
45 demuxer_->set_host(&host_); | 50 demuxer_->set_host(&host_); |
46 | 51 |
47 EXPECT_CALL(host_, SetTotalBytes(_)).Times(AnyNumber()); | 52 EXPECT_CALL(host_, SetTotalBytes(_)).Times(AnyNumber()); |
48 EXPECT_CALL(host_, SetBufferedBytes(_)).Times(AnyNumber()); | 53 EXPECT_CALL(host_, SetBufferedBytes(_)).Times(AnyNumber()); |
49 EXPECT_CALL(host_, SetCurrentReadPosition(_)) | 54 EXPECT_CALL(host_, SetCurrentReadPosition(_)) |
50 .WillRepeatedly(SaveArg<0>(¤t_read_position_)); | 55 .WillRepeatedly(SaveArg<0>(¤t_read_position_)); |
51 } | 56 } |
52 | 57 |
53 virtual ~FFmpegDemuxerTest() { | 58 virtual ~FFmpegDemuxerTest() { |
54 // Call Stop() to shut down internal threads. | 59 if (demuxer_) { |
55 demuxer_->Stop(NewExpectedClosure()); | 60 // Call Stop() to shut down internal threads. |
| 61 demuxer_->Stop(NewExpectedClosure()); |
| 62 } |
56 | 63 |
57 // Finish up any remaining tasks. | 64 // Finish up any remaining tasks. |
58 message_loop_.RunAllPending(); | 65 message_loop_.RunAllPending(); |
59 // Release the reference to the demuxer. | 66 // Release the reference to the demuxer. |
60 demuxer_ = NULL; | 67 demuxer_ = NULL; |
61 } | 68 } |
62 | 69 |
63 scoped_refptr<FileDataSource> CreateDataSource(const std::string& name) { | 70 scoped_refptr<FileDataSource> CreateDataSource(const std::string& name) { |
64 return CreateDataSource(name, false); | 71 return CreateDataSource(name, false); |
65 } | 72 } |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 } | 376 } |
370 | 377 |
371 MOCK_METHOD0(OnDelete, void()); | 378 MOCK_METHOD0(OnDelete, void()); |
372 MOCK_METHOD1(Run, void(Buffer* buffer)); | 379 MOCK_METHOD1(Run, void(Buffer* buffer)); |
373 | 380 |
374 private: | 381 private: |
375 DISALLOW_COPY_AND_ASSIGN(MockReadCallback); | 382 DISALLOW_COPY_AND_ASSIGN(MockReadCallback); |
376 }; | 383 }; |
377 | 384 |
378 TEST_F(FFmpegDemuxerTest, Stop) { | 385 TEST_F(FFmpegDemuxerTest, Stop) { |
379 // Tests that calling Read() on a stopped demuxer immediately deletes the | 386 // Tests that calling Read() on a stopped demuxer stream immediately deletes |
380 // callback. | 387 // the callback. |
381 InitializeDemuxer(CreateDataSource("bear-320x240.webm")); | 388 InitializeDemuxer(CreateDataSource("bear-320x240.webm")); |
382 | 389 |
383 // Get our stream. | 390 // Get our stream. |
| 391 scoped_refptr<DemuxerStream> audio = |
| 392 demuxer_->GetStream(DemuxerStream::AUDIO); |
| 393 ASSERT_TRUE(audio); |
| 394 |
| 395 demuxer_->Stop(NewExpectedClosure()); |
| 396 |
| 397 // Expect all calls in sequence. |
| 398 InSequence s; |
| 399 |
| 400 // Create our mocked callback. The Callback created by base::Bind() will take |
| 401 // ownership of this pointer. |
| 402 StrictMock<MockReadCallback>* callback = new StrictMock<MockReadCallback>(); |
| 403 |
| 404 // The callback should be immediately deleted. We'll use a checkpoint to |
| 405 // verify that it has indeed been deleted. |
| 406 EXPECT_CALL(*callback, Run(NotNull())); |
| 407 EXPECT_CALL(*callback, OnDelete()); |
| 408 EXPECT_CALL(*this, CheckPoint(1)); |
| 409 |
| 410 // Attempt the read... |
| 411 audio->Read(base::Bind(&MockReadCallback::Run, callback)); |
| 412 |
| 413 message_loop_.RunAllPending(); |
| 414 |
| 415 // ...and verify that |callback| was deleted. |
| 416 CheckPoint(1); |
| 417 } |
| 418 |
| 419 // The streams can outlive the demuxer because the streams may still be in use |
| 420 // by the decoder when the demuxer is destroyed. |
| 421 // This test verifies that DemuxerStream::Read() does not use an invalid demuxer |
| 422 // pointer (no crash occurs) and calls the callback with an EndOfStream buffer. |
| 423 TEST_F(FFmpegDemuxerTest, StreamReadAfterStopAndDemuxerDestruction) { |
| 424 InitializeDemuxer(CreateDataSource("bear-320x240.webm")); |
| 425 |
| 426 // Get our stream. |
384 scoped_refptr<DemuxerStream> audio = | 427 scoped_refptr<DemuxerStream> audio = |
385 demuxer_->GetStream(DemuxerStream::AUDIO); | 428 demuxer_->GetStream(DemuxerStream::AUDIO); |
386 ASSERT_TRUE(audio); | 429 ASSERT_TRUE(audio); |
387 | 430 |
388 demuxer_->Stop(NewExpectedClosure()); | 431 demuxer_->Stop(NewExpectedClosure()); |
389 | 432 |
| 433 // Finish up any remaining tasks. |
| 434 message_loop_.RunAllPending(); |
| 435 |
390 // Expect all calls in sequence. | 436 // Expect all calls in sequence. |
391 InSequence s; | 437 InSequence s; |
392 | 438 |
393 // Create our mocked callback. The Callback created by base::Bind() will take | 439 // Create our mocked callback. The Callback created by base::Bind() will take |
394 // ownership of this pointer. | 440 // ownership of this pointer. |
395 StrictMock<MockReadCallback>* callback = new StrictMock<MockReadCallback>(); | 441 StrictMock<MockReadCallback>* callback = new StrictMock<MockReadCallback>(); |
396 | 442 |
397 // The callback should be immediately deleted. We'll use a checkpoint to | 443 // The callback should be immediately deleted. We'll use a checkpoint to |
398 // verify that it has indeed been deleted. | 444 // verify that it has indeed been deleted. |
| 445 EXPECT_CALL(*callback, Run(IsEndOfStreamBuffer())); |
399 EXPECT_CALL(*callback, OnDelete()); | 446 EXPECT_CALL(*callback, OnDelete()); |
400 EXPECT_CALL(*this, CheckPoint(1)); | 447 EXPECT_CALL(*this, CheckPoint(1)); |
401 | 448 |
| 449 // Release the reference to the demuxer. This should also destroy it. |
| 450 demuxer_ = NULL; |
| 451 // |audio| now has a demuxer_ pointer to invalid memory. |
| 452 |
402 // Attempt the read... | 453 // Attempt the read... |
403 audio->Read(base::Bind(&MockReadCallback::Run, callback)); | 454 audio->Read(base::Bind(&MockReadCallback::Run, callback)); |
404 | 455 |
405 message_loop_.RunAllPending(); | 456 message_loop_.RunAllPending(); |
406 | 457 |
407 // ...and verify that |callback| was deleted. | 458 // ...and verify that |callback| was deleted. |
408 CheckPoint(1); | 459 CheckPoint(1); |
409 } | 460 } |
410 | 461 |
411 TEST_F(FFmpegDemuxerTest, DisableAudioStream) { | 462 TEST_F(FFmpegDemuxerTest, DisableAudioStream) { |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
632 message_loop_.RunAllPending(); | 683 message_loop_.RunAllPending(); |
633 EXPECT_TRUE(reader->called()); | 684 EXPECT_TRUE(reader->called()); |
634 ValidateBuffer(FROM_HERE, reader->buffer(), 1740, 2436000); | 685 ValidateBuffer(FROM_HERE, reader->buffer(), 1740, 2436000); |
635 | 686 |
636 // Manually release the last reference to the buffer and verify it was freed. | 687 // Manually release the last reference to the buffer and verify it was freed. |
637 reader->Reset(); | 688 reader->Reset(); |
638 message_loop_.RunAllPending(); | 689 message_loop_.RunAllPending(); |
639 } | 690 } |
640 | 691 |
641 } // namespace media | 692 } // namespace media |
OLD | NEW |