Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 <string> | 5 #include <string> |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 39 // fix flaky pointer-based MDJ inequality testing. See http://crbug.com/327839. | 39 // fix flaky pointer-based MDJ inequality testing. See http://crbug.com/327839. |
| 40 | 40 |
| 41 // Mock of MediaPlayerManager for testing purpose. | 41 // Mock of MediaPlayerManager for testing purpose. |
| 42 class MockMediaPlayerManager : public MediaPlayerManager { | 42 class MockMediaPlayerManager : public MediaPlayerManager { |
| 43 public: | 43 public: |
| 44 explicit MockMediaPlayerManager(base::MessageLoop* message_loop) | 44 explicit MockMediaPlayerManager(base::MessageLoop* message_loop) |
| 45 : message_loop_(message_loop), | 45 : message_loop_(message_loop), |
| 46 playback_completed_(false), | 46 playback_completed_(false), |
| 47 num_resources_requested_(0), | 47 num_resources_requested_(0), |
| 48 num_metadata_changes_(0), | 48 num_metadata_changes_(0), |
| 49 timestamp_updated_(false) {} | 49 timestamp_updated_(false), |
| 50 is_audible_(false), | |
| 51 is_audible_idle_timeout_expired_(false) {} | |
| 50 ~MockMediaPlayerManager() override {} | 52 ~MockMediaPlayerManager() override {} |
| 51 | 53 |
| 52 // MediaPlayerManager implementation. | 54 // MediaPlayerManager implementation. |
| 53 MediaResourceGetter* GetMediaResourceGetter() override { return NULL; } | 55 MediaResourceGetter* GetMediaResourceGetter() override { return NULL; } |
| 54 MediaUrlInterceptor* GetMediaUrlInterceptor() override { return NULL; } | 56 MediaUrlInterceptor* GetMediaUrlInterceptor() override { return NULL; } |
| 55 void OnTimeUpdate(int player_id, | 57 void OnTimeUpdate(int player_id, |
| 56 base::TimeDelta current_time, | 58 base::TimeDelta current_time, |
| 57 base::TimeTicks current_time_ticks) override { | 59 base::TimeTicks current_time_ticks) override { |
| 58 timestamp_updated_ = true; | 60 timestamp_updated_ = true; |
| 59 } | 61 } |
| 60 void OnMediaMetadataChanged(int player_id, | 62 void OnMediaMetadataChanged(int player_id, |
| 61 base::TimeDelta duration, | 63 base::TimeDelta duration, |
| 62 int width, | 64 int width, |
| 63 int height, | 65 int height, |
| 64 bool success) override { | 66 bool success) override { |
| 65 num_metadata_changes_++; | 67 num_metadata_changes_++; |
| 66 } | 68 } |
| 67 void OnPlaybackComplete(int player_id) override { | 69 void OnPlaybackComplete(int player_id) override { |
| 68 playback_completed_ = true; | 70 playback_completed_ = true; |
| 69 if (message_loop_->is_running()) | 71 if (message_loop_->is_running()) |
| 70 message_loop_->Quit(); | 72 message_loop_->Quit(); |
| 71 } | 73 } |
| 72 void OnMediaInterrupted(int player_id) override {} | 74 void OnMediaInterrupted(int player_id) override {} |
| 73 void OnBufferingUpdate(int player_id, int percentage) override {} | 75 void OnBufferingUpdate(int player_id, int percentage) override {} |
| 74 void OnSeekComplete(int player_id, | 76 void OnSeekComplete(int player_id, |
| 75 const base::TimeDelta& current_time) override {} | 77 const base::TimeDelta& current_time) override {} |
| 76 void OnError(int player_id, int error) override {} | 78 void OnError(int player_id, int error) override {} |
| 77 void OnVideoSizeChanged(int player_id, int width, int height) override {} | 79 void OnVideoSizeChanged(int player_id, int width, int height) override {} |
| 78 void OnAudibleStateChanged(int player_id, bool is_audible_now) override {} | |
| 79 void OnWaitingForDecryptionKey(int player_id) override {} | 80 void OnWaitingForDecryptionKey(int player_id) override {} |
| 80 MediaPlayerAndroid* GetFullscreenPlayer() override { return NULL; } | 81 MediaPlayerAndroid* GetFullscreenPlayer() override { return NULL; } |
| 81 MediaPlayerAndroid* GetPlayer(int player_id) override { return NULL; } | 82 MediaPlayerAndroid* GetPlayer(int player_id) override { return NULL; } |
| 82 void RequestFullScreen(int player_id) override {} | 83 void RequestFullScreen(int player_id) override {} |
| 83 #if defined(VIDEO_HOLE) | 84 #if defined(VIDEO_HOLE) |
| 84 bool ShouldUseVideoOverlayForEmbeddedEncryptedVideo() override { | 85 bool ShouldUseVideoOverlayForEmbeddedEncryptedVideo() override { |
| 85 return false; | 86 return false; |
| 86 } | 87 } |
| 87 #endif // defined(VIDEO_HOLE) | 88 #endif // defined(VIDEO_HOLE) |
| 88 | 89 |
| 90 void OnAudibleStateChanged(int player_id, bool is_audible_now) override { | |
| 91 is_audible_ = is_audible_now; | |
| 92 } | |
| 93 | |
| 89 bool playback_completed() const { | 94 bool playback_completed() const { |
| 90 return playback_completed_; | 95 return playback_completed_; |
| 91 } | 96 } |
| 92 | 97 |
| 93 int num_resources_requested() const { | 98 int num_resources_requested() const { |
| 94 return num_resources_requested_; | 99 return num_resources_requested_; |
| 95 } | 100 } |
| 96 | 101 |
| 97 int num_metadata_changes() const { | 102 int num_metadata_changes() const { |
| 98 return num_metadata_changes_; | 103 return num_metadata_changes_; |
| 99 } | 104 } |
| 100 | 105 |
| 101 void OnMediaResourcesRequested(int player_id) { | 106 void OnMediaResourcesRequested(int player_id) { |
| 102 num_resources_requested_++; | 107 num_resources_requested_++; |
| 103 } | 108 } |
| 104 | 109 |
| 105 bool timestamp_updated() const { | 110 bool timestamp_updated() const { |
| 106 return timestamp_updated_; | 111 return timestamp_updated_; |
| 107 } | 112 } |
| 108 | 113 |
| 109 void ResetTimestampUpdated() { | 114 void ResetTimestampUpdated() { |
| 110 timestamp_updated_ = false; | 115 timestamp_updated_ = false; |
| 111 } | 116 } |
| 112 | 117 |
| 118 bool is_audible() const { | |
| 119 return is_audible_; | |
| 120 } | |
| 121 | |
| 122 bool is_audible_idle_timeout_expired() const { | |
| 123 return is_audible_idle_timeout_expired_; | |
| 124 } | |
| 125 | |
| 126 void SetAudibleIdleTimeoutExpired(bool value) { | |
| 127 is_audible_idle_timeout_expired_ = value; | |
| 128 } | |
| 129 | |
| 113 private: | 130 private: |
| 114 base::MessageLoop* message_loop_; | 131 base::MessageLoop* message_loop_; |
| 115 bool playback_completed_; | 132 bool playback_completed_; |
| 116 // The number of resource requests this object has seen. | 133 // The number of resource requests this object has seen. |
| 117 int num_resources_requested_; | 134 int num_resources_requested_; |
| 118 // The number of metadata changes reported by the player. | 135 // The number of metadata changes reported by the player. |
| 119 int num_metadata_changes_; | 136 int num_metadata_changes_; |
| 120 // Playback timestamp was updated. | 137 // Playback timestamp was updated. |
| 121 bool timestamp_updated_; | 138 bool timestamp_updated_; |
| 139 // Audible state of the pipeline | |
| 140 bool is_audible_; | |
| 141 // Helper flag to ensure delay before we check | |
| 142 // the audible state | |
| 143 bool is_audible_idle_timeout_expired_; | |
| 122 | 144 |
| 123 DISALLOW_COPY_AND_ASSIGN(MockMediaPlayerManager); | 145 DISALLOW_COPY_AND_ASSIGN(MockMediaPlayerManager); |
| 124 }; | 146 }; |
| 125 | 147 |
| 126 class MockDemuxerAndroid : public DemuxerAndroid { | 148 class MockDemuxerAndroid : public DemuxerAndroid { |
| 127 public: | 149 public: |
| 128 explicit MockDemuxerAndroid(base::MessageLoop* message_loop) | 150 explicit MockDemuxerAndroid(base::MessageLoop* message_loop) |
| 129 : message_loop_(message_loop), | 151 : message_loop_(message_loop), |
| 130 num_data_requests_(0), | 152 num_data_requests_(0), |
| 131 num_seek_requests_(0), | 153 num_seek_requests_(0), |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 169 MediaSourcePlayerTest() | 191 MediaSourcePlayerTest() |
| 170 : manager_(&message_loop_), | 192 : manager_(&message_loop_), |
| 171 demuxer_(new MockDemuxerAndroid(&message_loop_)), | 193 demuxer_(new MockDemuxerAndroid(&message_loop_)), |
| 172 player_(0, &manager_, | 194 player_(0, &manager_, |
| 173 base::Bind(&MockMediaPlayerManager::OnMediaResourcesRequested, | 195 base::Bind(&MockMediaPlayerManager::OnMediaResourcesRequested, |
| 174 base::Unretained(&manager_)), | 196 base::Unretained(&manager_)), |
| 175 scoped_ptr<DemuxerAndroid>(demuxer_), | 197 scoped_ptr<DemuxerAndroid>(demuxer_), |
| 176 GURL()), | 198 GURL()), |
| 177 decoder_callback_hook_executed_(false), | 199 decoder_callback_hook_executed_(false), |
| 178 surface_texture_a_is_next_(true) {} | 200 surface_texture_a_is_next_(true) {} |
| 201 | |
| 179 ~MediaSourcePlayerTest() override {} | 202 ~MediaSourcePlayerTest() override {} |
| 180 | 203 |
| 181 protected: | 204 protected: |
| 182 // Get the decoder job from the MediaSourcePlayer. The return value must not | 205 // Get the decoder job from the MediaSourcePlayer. The return value must not |
| 183 // be NULL. | 206 // be NULL. |
| 184 MediaDecoderJob* GetMediaDecoderJob(bool is_audio) { | 207 MediaDecoderJob* GetMediaDecoderJob(bool is_audio) { |
| 185 if (is_audio) { | 208 if (is_audio) { |
| 186 return reinterpret_cast<MediaDecoderJob*>( | 209 return reinterpret_cast<MediaDecoderJob*>( |
| 187 player_.audio_decoder_job_.get()); | 210 player_.audio_decoder_job_.get()); |
| 188 } | 211 } |
| (...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 835 } | 858 } |
| 836 | 859 |
| 837 bool IsRequestingDemuxerData(bool is_audio) { | 860 bool IsRequestingDemuxerData(bool is_audio) { |
| 838 return GetMediaDecoderJob(is_audio)->is_requesting_demuxer_data_; | 861 return GetMediaDecoderJob(is_audio)->is_requesting_demuxer_data_; |
| 839 } | 862 } |
| 840 | 863 |
| 841 bool IsDrainingDecoder(bool is_audio) { | 864 bool IsDrainingDecoder(bool is_audio) { |
| 842 return GetMediaDecoderJob(is_audio)->drain_decoder_; | 865 return GetMediaDecoderJob(is_audio)->drain_decoder_; |
| 843 } | 866 } |
| 844 | 867 |
| 868 protected: | |
| 845 base::MessageLoop message_loop_; | 869 base::MessageLoop message_loop_; |
| 846 MockMediaPlayerManager manager_; | 870 MockMediaPlayerManager manager_; |
| 847 MockDemuxerAndroid* demuxer_; // Owned by |player_|. | 871 MockDemuxerAndroid* demuxer_; // Owned by |player_|. |
| 848 MediaSourcePlayer player_; | 872 MediaSourcePlayer player_; |
| 849 | 873 |
| 850 // Track whether a possibly async decoder callback test hook has run. | 874 // Track whether a possibly async decoder callback test hook has run. |
| 851 bool decoder_callback_hook_executed_; | 875 bool decoder_callback_hook_executed_; |
| 852 | 876 |
| 853 // We need to keep the surface texture while the decoder is actively decoding. | 877 // We need to keep the surface texture while the decoder is actively decoding. |
| 854 // Otherwise, it may trigger unexpected crashes on some devices. To switch | 878 // Otherwise, it may trigger unexpected crashes on some devices. To switch |
| 855 // surfaces, tests need to create a new surface texture without releasing | 879 // surfaces, tests need to create a new surface texture without releasing |
| 856 // their previous one. In CreateNextTextureAndSetVideoSurface(), we toggle | 880 // their previous one. In CreateNextTextureAndSetVideoSurface(), we toggle |
| 857 // between two surface textures, only replacing the N-2 texture. Assumption is | 881 // between two surface textures, only replacing the N-2 texture. Assumption is |
| 858 // that no more than N-1 texture is in use by decoder when | 882 // that no more than N-1 texture is in use by decoder when |
| 859 // CreateNextTextureAndSetVideoSurface() is called. | 883 // CreateNextTextureAndSetVideoSurface() is called. |
| 860 scoped_refptr<gfx::SurfaceTexture> surface_texture_a_; | 884 scoped_refptr<gfx::SurfaceTexture> surface_texture_a_; |
| 861 scoped_refptr<gfx::SurfaceTexture> surface_texture_b_; | 885 scoped_refptr<gfx::SurfaceTexture> surface_texture_b_; |
| 862 bool surface_texture_a_is_next_; | 886 bool surface_texture_a_is_next_; |
| 863 int next_texture_id_; | 887 int next_texture_id_; |
| 864 | 888 |
| 889 bool verify_not_audible_is_called_; | |
| 890 | |
| 865 DISALLOW_COPY_AND_ASSIGN(MediaSourcePlayerTest); | 891 DISALLOW_COPY_AND_ASSIGN(MediaSourcePlayerTest); |
| 866 }; | 892 }; |
| 867 | 893 |
| 868 TEST_F(MediaSourcePlayerTest, StartAudioDecoderWithValidConfig) { | 894 TEST_F(MediaSourcePlayerTest, StartAudioDecoderWithValidConfig) { |
| 869 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | 895 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 870 | 896 |
| 871 // Test audio codec will be created when valid configs and data are passed to | 897 // Test audio codec will be created when valid configs and data are passed to |
| 872 // the audio decoder job. | 898 // the audio decoder job. |
| 873 StartAudioDecoderJob(); | 899 StartAudioDecoderJob(); |
| 874 EXPECT_EQ(0, demuxer_->num_seek_requests()); | 900 EXPECT_EQ(0, demuxer_->num_seek_requests()); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 886 uint8 invalid_codec_data[] = { 0x00, 0xff, 0xff, 0xff, 0xff }; | 912 uint8 invalid_codec_data[] = { 0x00, 0xff, 0xff, 0xff, 0xff }; |
| 887 configs.audio_extra_data.insert(configs.audio_extra_data.begin(), | 913 configs.audio_extra_data.insert(configs.audio_extra_data.begin(), |
| 888 invalid_codec_data, invalid_codec_data + 4); | 914 invalid_codec_data, invalid_codec_data + 4); |
| 889 Start(configs); | 915 Start(configs); |
| 890 | 916 |
| 891 // Decoder is not created after data is received. | 917 // Decoder is not created after data is received. |
| 892 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | 918 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); |
| 893 EXPECT_FALSE(GetMediaCodecBridge(true)); | 919 EXPECT_FALSE(GetMediaCodecBridge(true)); |
| 894 } | 920 } |
| 895 | 921 |
| 922 // timav | |
| 923 TEST_F(MediaSourcePlayerTest, AudioDecoderSetsAudibleState) { | |
| 924 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 925 | |
| 926 // No data arrived yet | |
| 927 EXPECT_FALSE(manager_.is_audible()); | |
| 928 | |
| 929 StartAudioDecoderJob(); | |
| 930 player_.SetVolume(1.0); | |
| 931 | |
| 932 // The first decoded frame should report the audio state | |
| 933 // to the manager | |
| 934 DecodeAudioDataUntilOutputBecomesAvailable(); | |
| 935 EXPECT_TRUE(manager_.is_audible()); | |
| 936 | |
| 937 // The player release should report a non-audible state. | |
| 938 ReleasePlayer(); | |
| 939 EXPECT_FALSE(manager_.is_audible()); | |
| 940 } | |
| 941 | |
| 942 TEST_F(MediaSourcePlayerTest, AudioDecoderRemovesAudibleStateWhenIdle) { | |
| 943 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 944 | |
| 945 // No data arrived yet | |
| 946 EXPECT_FALSE(manager_.is_audible()); | |
| 947 | |
| 948 StartAudioDecoderJob(); | |
| 949 player_.SetVolume(1.0); | |
| 950 | |
| 951 // Shorten the idle period for the test to 300 ms | |
| 952 const int kDelay = 300; // milliseconds | |
| 953 player_.SetAudibleStateIdlePeriod(base::TimeDelta::FromMilliseconds(kDelay)); | |
| 954 | |
| 955 // The first decoded frame should report the audio state | |
| 956 // to the manager | |
| 957 DecodeAudioDataUntilOutputBecomesAvailable(); | |
| 958 EXPECT_TRUE(manager_.is_audible()); | |
| 959 | |
| 960 // Wait till more than 300 ms pass (we wait 400 ms in this case) | |
| 961 manager_.SetAudibleIdleTimeoutExpired(false); | |
| 962 message_loop_.PostDelayedTask( | |
|
Tima Vaisburd
2015/03/18 01:35:02
I wanted to guarantee that this delayed task arriv
| |
| 963 FROM_HERE, | |
| 964 base::Bind(&MockMediaPlayerManager::SetAudibleIdleTimeoutExpired, | |
| 965 base::Unretained(&manager_), | |
| 966 true), | |
| 967 base::TimeDelta::FromMilliseconds(kDelay + 100)); | |
| 968 | |
| 969 while (!manager_.is_audible_idle_timeout_expired()) | |
| 970 message_loop_.RunUntilIdle(); | |
| 971 | |
| 972 // The player should have reported that there is no audio | |
| 973 // by this time. | |
| 974 EXPECT_FALSE(manager_.is_audible()); | |
| 975 | |
| 976 ReleasePlayer(); | |
| 977 } | |
| 978 | |
| 896 TEST_F(MediaSourcePlayerTest, StartVideoCodecWithValidSurface) { | 979 TEST_F(MediaSourcePlayerTest, StartVideoCodecWithValidSurface) { |
| 897 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | 980 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 898 | 981 |
| 899 // Test video codec will not be created until data is received. | 982 // Test video codec will not be created until data is received. |
| 900 StartVideoDecoderJob(); | 983 StartVideoDecoderJob(); |
| 901 | 984 |
| 902 // Set both an initial and a later video surface without receiving any | 985 // Set both an initial and a later video surface without receiving any |
| 903 // demuxed data yet. | 986 // demuxed data yet. |
| 904 CreateNextTextureAndSetVideoSurface(); | 987 CreateNextTextureAndSetVideoSurface(); |
| 905 EXPECT_FALSE(GetMediaCodecBridge(false)); | 988 EXPECT_FALSE(GetMediaCodecBridge(false)); |
| (...skipping 1449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2355 // Wait for the metadata change. | 2438 // Wait for the metadata change. |
| 2356 while(manager_.num_metadata_changes() == 1) { | 2439 while(manager_.num_metadata_changes() == 1) { |
| 2357 player_.OnDemuxerDataAvailable(data); | 2440 player_.OnDemuxerDataAvailable(data); |
| 2358 WaitForVideoDecodeDone(); | 2441 WaitForVideoDecodeDone(); |
| 2359 } | 2442 } |
| 2360 EXPECT_EQ(2, manager_.num_metadata_changes()); | 2443 EXPECT_EQ(2, manager_.num_metadata_changes()); |
| 2361 WaitForVideoDecodeDone(); | 2444 WaitForVideoDecodeDone(); |
| 2362 } | 2445 } |
| 2363 | 2446 |
| 2364 } // namespace media | 2447 } // namespace media |
| OLD | NEW |