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 <stddef.h> | 5 #include <stddef.h> |
6 #include <stdint.h> | 6 #include <stdint.h> |
7 | 7 |
8 #include <algorithm> | 8 #include <algorithm> |
9 #include <deque> | 9 #include <deque> |
10 #include <string> | 10 #include <string> |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 *got_eos_buffer = false; | 76 *got_eos_buffer = false; |
77 }; | 77 }; |
78 | 78 |
79 | 79 |
80 // Fixture class to facilitate writing tests. Takes care of setting up the | 80 // Fixture class to facilitate writing tests. Takes care of setting up the |
81 // FFmpeg, pipeline and filter host mocks. | 81 // FFmpeg, pipeline and filter host mocks. |
82 class FFmpegDemuxerTest : public testing::Test { | 82 class FFmpegDemuxerTest : public testing::Test { |
83 protected: | 83 protected: |
84 FFmpegDemuxerTest() {} | 84 FFmpegDemuxerTest() {} |
85 | 85 |
86 virtual ~FFmpegDemuxerTest() { | 86 virtual ~FFmpegDemuxerTest() { Shutdown(); } |
| 87 |
| 88 void Shutdown() { |
87 if (demuxer_) | 89 if (demuxer_) |
88 demuxer_->Stop(); | 90 demuxer_->Stop(); |
89 demuxer_.reset(); | 91 demuxer_.reset(); |
90 base::RunLoop().RunUntilIdle(); | 92 base::RunLoop().RunUntilIdle(); |
| 93 data_source_.reset(); |
91 } | 94 } |
92 | 95 |
93 void CreateDemuxer(const std::string& name) { | 96 void CreateDemuxer(const std::string& name) { |
94 CHECK(!demuxer_); | 97 CHECK(!demuxer_); |
95 | 98 |
96 EXPECT_CALL(host_, OnBufferedTimeRangesChanged(_)).Times(AnyNumber()); | 99 EXPECT_CALL(host_, OnBufferedTimeRangesChanged(_)).Times(AnyNumber()); |
97 | 100 |
98 CreateDataSource(name); | 101 CreateDataSource(name); |
99 | 102 |
100 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb = base::Bind( | 103 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb = base::Bind( |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 bool got_eos_buffer = false; | 263 bool got_eos_buffer = false; |
261 const int kMaxBuffers = 170; | 264 const int kMaxBuffers = 170; |
262 for (int i = 0; !got_eos_buffer && i < kMaxBuffers; i++) { | 265 for (int i = 0; !got_eos_buffer && i < kMaxBuffers; i++) { |
263 stream->Read(base::Bind(&EosOnReadDone, &got_eos_buffer)); | 266 stream->Read(base::Bind(&EosOnReadDone, &got_eos_buffer)); |
264 base::RunLoop().Run(); | 267 base::RunLoop().Run(); |
265 } | 268 } |
266 | 269 |
267 EXPECT_TRUE(got_eos_buffer); | 270 EXPECT_TRUE(got_eos_buffer); |
268 } | 271 } |
269 | 272 |
| 273 void Seek(base::TimeDelta seek_target) { |
| 274 WaitableMessageLoopEvent event; |
| 275 demuxer_->Seek(seek_target, event.GetPipelineStatusCB()); |
| 276 event.RunAndWaitForStatus(PIPELINE_OK); |
| 277 } |
| 278 |
270 private: | 279 private: |
271 void CreateDataSource(const std::string& name) { | 280 void CreateDataSource(const std::string& name) { |
272 CHECK(!data_source_); | 281 CHECK(!data_source_); |
273 | 282 |
274 base::FilePath file_path; | 283 base::FilePath file_path; |
275 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path)); | 284 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path)); |
276 | 285 |
277 file_path = file_path.Append(FILE_PATH_LITERAL("media")) | 286 file_path = file_path.Append(FILE_PATH_LITERAL("media")) |
278 .Append(FILE_PATH_LITERAL("test")) | 287 .Append(FILE_PATH_LITERAL("test")) |
279 .Append(FILE_PATH_LITERAL("data")) | 288 .Append(FILE_PATH_LITERAL("data")) |
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
793 // must always be greater than zero. | 802 // must always be greater than zero. |
794 EXPECT_EQ(base::TimeDelta(), demuxer_->GetStartTime()); | 803 EXPECT_EQ(base::TimeDelta(), demuxer_->GetStartTime()); |
795 | 804 |
796 // Seek back to the beginning and repeat the test. | 805 // Seek back to the beginning and repeat the test. |
797 WaitableMessageLoopEvent event; | 806 WaitableMessageLoopEvent event; |
798 demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB()); | 807 demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB()); |
799 event.RunAndWaitForStatus(PIPELINE_OK); | 808 event.RunAndWaitForStatus(PIPELINE_OK); |
800 } | 809 } |
801 } | 810 } |
802 | 811 |
| 812 TEST_F(FFmpegDemuxerTest, Read_DiscardDisabledVideoStream) { |
| 813 // Verify that disabling the video stream properly marks it as AVDISCARD_ALL |
| 814 // in FFmpegDemuxer. The AVDISCARD_ALL flag allows FFmpeg to ignore key frame |
| 815 // requirements for the disabled stream and thus allows to select the seek |
| 816 // position closer to the |seek_target|, resulting in less data being read |
| 817 // from the data source. |
| 818 // The input file bear-vp8-webvtt.webm has key video frames at 1.602s and at |
| 819 // 2.002s. If we want to seek to 2.0s position while the video stream is |
| 820 // enabled, then FFmpeg is forced to start reading from 1.602s, which is the |
| 821 // earliest position guaranteed to give us key frames for all enabled streams. |
| 822 // But when the video stream is disabled, FFmpeg can start reading from 1.987s |
| 823 // which is earliest audio key frame before the 2.0s |seek_target|. |
| 824 const base::TimeDelta seek_target = base::TimeDelta::FromMilliseconds(2000); |
| 825 |
| 826 CreateDemuxer("bear-vp8-webvtt.webm"); |
| 827 InitializeDemuxer(); |
| 828 Seek(seek_target); |
| 829 GetStream(DemuxerStream::AUDIO) |
| 830 ->Read(NewReadCB(FROM_HERE, 163, 1612000, true)); |
| 831 base::RunLoop().Run(); |
| 832 auto bytes_read_with_video_enabled = data_source_->bytes_read_for_testing(); |
| 833 |
| 834 static_cast<FFmpegDemuxerStream*>(GetStream(DemuxerStream::VIDEO)) |
| 835 ->set_enabled(false, base::TimeDelta()); |
| 836 data_source_->reset_bytes_read_for_testing(); |
| 837 Seek(seek_target); |
| 838 GetStream(DemuxerStream::AUDIO) |
| 839 ->Read(NewReadCB(FROM_HERE, 156, 1987000, true)); |
| 840 base::RunLoop().Run(); |
| 841 auto bytes_read_with_video_disabled = data_source_->bytes_read_for_testing(); |
| 842 EXPECT_LT(bytes_read_with_video_disabled, bytes_read_with_video_enabled); |
| 843 } |
| 844 |
| 845 TEST_F(FFmpegDemuxerTest, Read_DiscardDisabledTextStream) { |
| 846 // This test case reads the same video frame twice, first with the text track |
| 847 // enabled, then with the text track disabled. When the text track is |
| 848 // disabled, FFmpegDemuxer sets the AVDISCARD_ALL flag on the corresponding |
| 849 // stream, which allows FFmpeg to choose the initial reading position closer |
| 850 // to the requested video frame (i.e. closer to seek_target), since it doesn't |
| 851 // need to consider key frames for the text stream. This results in less data |
| 852 // being read compared to the case with enabled text track. |
| 853 const base::TimeDelta seek_target = base::TimeDelta::FromMilliseconds(805); |
| 854 |
| 855 CreateDemuxer("bear-vp8-webvtt.webm"); |
| 856 EXPECT_CALL(host_, AddTextStream(_, _)); |
| 857 InitializeDemuxerWithText(); |
| 858 Seek(seek_target); |
| 859 GetStream(DemuxerStream::VIDEO) |
| 860 ->Read(NewReadCB(FROM_HERE, 5425, 801000, true)); |
| 861 base::RunLoop().Run(); |
| 862 auto bytes_read_with_text_enabled = data_source_->bytes_read_for_testing(); |
| 863 |
| 864 Shutdown(); |
| 865 |
| 866 CreateDemuxer("bear-vp8-webvtt.webm"); |
| 867 InitializeDemuxer(); |
| 868 Seek(seek_target); |
| 869 GetStream(DemuxerStream::VIDEO) |
| 870 ->Read(NewReadCB(FROM_HERE, 5425, 801000, true)); |
| 871 base::RunLoop().Run(); |
| 872 auto bytes_read_with_text_disabled = data_source_->bytes_read_for_testing(); |
| 873 |
| 874 EXPECT_LT(bytes_read_with_text_disabled, bytes_read_with_text_enabled); |
| 875 } |
| 876 |
803 TEST_F(FFmpegDemuxerTest, Read_EndOfStream) { | 877 TEST_F(FFmpegDemuxerTest, Read_EndOfStream) { |
804 // Verify that end of stream buffers are created. | 878 // Verify that end of stream buffers are created. |
805 CreateDemuxer("bear-320x240.webm"); | 879 CreateDemuxer("bear-320x240.webm"); |
806 InitializeDemuxer(); | 880 InitializeDemuxer(); |
807 ReadUntilEndOfStream(GetStream(DemuxerStream::AUDIO)); | 881 ReadUntilEndOfStream(GetStream(DemuxerStream::AUDIO)); |
808 } | 882 } |
809 | 883 |
810 TEST_F(FFmpegDemuxerTest, Read_EndOfStreamText) { | 884 TEST_F(FFmpegDemuxerTest, Read_EndOfStreamText) { |
811 // Verify that end of stream buffers are created. | 885 // Verify that end of stream buffers are created. |
812 CreateDemuxer("bear-vp8-webvtt.webm"); | 886 CreateDemuxer("bear-vp8-webvtt.webm"); |
(...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1518 EXPECT_EQ(astream, preferred_seeking_stream(base::TimeDelta())); | 1592 EXPECT_EQ(astream, preferred_seeking_stream(base::TimeDelta())); |
1519 | 1593 |
1520 // Now pretend that audio stream got disabled. | 1594 // Now pretend that audio stream got disabled. |
1521 astream->set_enabled(false, base::TimeDelta()); | 1595 astream->set_enabled(false, base::TimeDelta()); |
1522 // Since there's no other enabled streams, the preferred seeking stream should | 1596 // Since there's no other enabled streams, the preferred seeking stream should |
1523 // still be the audio stream. | 1597 // still be the audio stream. |
1524 EXPECT_EQ(astream, preferred_seeking_stream(base::TimeDelta())); | 1598 EXPECT_EQ(astream, preferred_seeking_stream(base::TimeDelta())); |
1525 } | 1599 } |
1526 | 1600 |
1527 } // namespace media | 1601 } // namespace media |
OLD | NEW |