| 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 "content/renderer/pepper/ppb_audio_impl.h" | 5 #include "content/renderer/pepper/ppb_audio_impl.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "content/renderer/pepper/pepper_platform_audio_output.h" | 8 #include "content/renderer/pepper/pepper_platform_audio_output.h" |
| 9 #include "content/renderer/pepper/pepper_plugin_instance_impl.h" | 9 #include "content/renderer/pepper/pepper_plugin_instance_impl.h" |
| 10 #include "content/renderer/pepper/plugin_instance_throttler_impl.h" | 10 #include "content/renderer/pepper/plugin_instance_throttler_impl.h" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 using ppapi::thunk::EnterResourceNoLock; | 23 using ppapi::thunk::EnterResourceNoLock; |
| 24 using ppapi::thunk::PPB_Audio_API; | 24 using ppapi::thunk::PPB_Audio_API; |
| 25 using ppapi::thunk::PPB_AudioConfig_API; | 25 using ppapi::thunk::PPB_AudioConfig_API; |
| 26 using ppapi::TrackedCallback; | 26 using ppapi::TrackedCallback; |
| 27 | 27 |
| 28 namespace content { | 28 namespace content { |
| 29 | 29 |
| 30 // PPB_Audio_Impl -------------------------------------------------------------- | 30 // PPB_Audio_Impl -------------------------------------------------------------- |
| 31 | 31 |
| 32 PPB_Audio_Impl::PPB_Audio_Impl(PP_Instance instance) | 32 PPB_Audio_Impl::PPB_Audio_Impl(PP_Instance instance) |
| 33 : Resource(ppapi::OBJECT_IS_IMPL, instance), audio_(NULL) {} | 33 : Resource(ppapi::OBJECT_IS_IMPL, instance), |
| 34 audio_(NULL), |
| 35 playback_throttled_(false) { |
| 36 PepperPluginInstanceImpl* plugin_instance = |
| 37 static_cast<PepperPluginInstanceImpl*>( |
| 38 PepperPluginInstance::Get(pp_instance())); |
| 39 if (plugin_instance && plugin_instance->throttler()) { |
| 40 plugin_instance->throttler()->AddObserver(this); |
| 41 } |
| 42 } |
| 34 | 43 |
| 35 PPB_Audio_Impl::~PPB_Audio_Impl() { | 44 PPB_Audio_Impl::~PPB_Audio_Impl() { |
| 45 PepperPluginInstanceImpl* instance = static_cast<PepperPluginInstanceImpl*>( |
| 46 PepperPluginInstance::Get(pp_instance())); |
| 47 if (instance && instance->throttler()) { |
| 48 instance->throttler()->RemoveObserver(this); |
| 49 } |
| 50 |
| 36 // Calling ShutDown() makes sure StreamCreated cannot be called anymore and | 51 // Calling ShutDown() makes sure StreamCreated cannot be called anymore and |
| 37 // releases the audio data associated with the pointer. Note however, that | 52 // releases the audio data associated with the pointer. Note however, that |
| 38 // until ShutDown returns, StreamCreated may still be called. This will be | 53 // until ShutDown returns, StreamCreated may still be called. This will be |
| 39 // OK since we'll just immediately clean up the data it stored later in this | 54 // OK since we'll just immediately clean up the data it stored later in this |
| 40 // destructor. | 55 // destructor. |
| 41 if (audio_) { | 56 if (audio_) { |
| 42 audio_->ShutDown(); | 57 audio_->ShutDown(); |
| 43 audio_ = NULL; | 58 audio_ = NULL; |
| 44 } | 59 } |
| 45 } | 60 } |
| 46 | 61 |
| 47 PPB_Audio_API* PPB_Audio_Impl::AsPPB_Audio_API() { return this; } | 62 PPB_Audio_API* PPB_Audio_Impl::AsPPB_Audio_API() { return this; } |
| 48 | 63 |
| 49 PP_Resource PPB_Audio_Impl::GetCurrentConfig() { | 64 PP_Resource PPB_Audio_Impl::GetCurrentConfig() { |
| 50 // AddRef on behalf of caller, while keeping a ref for ourselves. | 65 // AddRef on behalf of caller, while keeping a ref for ourselves. |
| 51 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(config_); | 66 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(config_); |
| 52 return config_; | 67 return config_; |
| 53 } | 68 } |
| 54 | 69 |
| 55 PP_Bool PPB_Audio_Impl::StartPlayback() { | 70 PP_Bool PPB_Audio_Impl::StartPlayback() { |
| 56 if (!audio_) | 71 if (!audio_) |
| 57 return PP_FALSE; | 72 return PP_FALSE; |
| 58 if (playing()) | 73 if (playing()) |
| 59 return PP_TRUE; | 74 return PP_TRUE; |
| 75 |
| 76 // If plugin is in power saver mode, defer audio IPC communication. |
| 77 PepperPluginInstanceImpl* instance = static_cast<PepperPluginInstanceImpl*>( |
| 78 PepperPluginInstance::Get(pp_instance())); |
| 79 if (instance && instance->throttler() && |
| 80 instance->throttler()->power_saver_enabled()) { |
| 81 instance->throttler()->NotifyAudioThrottled(); |
| 82 playback_throttled_ = true; |
| 83 return PP_TRUE; |
| 84 } |
| 85 |
| 60 SetStartPlaybackState(); | 86 SetStartPlaybackState(); |
| 61 return PP_FromBool(audio_->StartPlayback()); | 87 return PP_FromBool(audio_->StartPlayback()); |
| 62 } | 88 } |
| 63 | 89 |
| 64 PP_Bool PPB_Audio_Impl::StopPlayback() { | 90 PP_Bool PPB_Audio_Impl::StopPlayback() { |
| 65 if (!audio_) | 91 if (!audio_) |
| 66 return PP_FALSE; | 92 return PP_FALSE; |
| 93 |
| 94 if (playback_throttled_) { |
| 95 // If a start playback request is still deferred, we must fulfill it first |
| 96 // to shut down the audio thread correctly. |
| 97 StartDeferredPlayback(); |
| 98 } |
| 99 |
| 67 if (!playing()) | 100 if (!playing()) |
| 68 return PP_TRUE; | 101 return PP_TRUE; |
| 69 if (!audio_->StopPlayback()) | 102 if (!audio_->StopPlayback()) |
| 70 return PP_FALSE; | 103 return PP_FALSE; |
| 71 SetStopPlaybackState(); | 104 SetStopPlaybackState(); |
| 105 |
| 72 return PP_TRUE; | 106 return PP_TRUE; |
| 73 } | 107 } |
| 74 | 108 |
| 75 int32_t PPB_Audio_Impl::Open(PP_Resource config, | 109 int32_t PPB_Audio_Impl::Open(PP_Resource config, |
| 76 scoped_refptr<TrackedCallback> create_callback) { | 110 scoped_refptr<TrackedCallback> create_callback) { |
| 77 // Validate the config and keep a reference to it. | 111 // Validate the config and keep a reference to it. |
| 78 EnterResourceNoLock<PPB_AudioConfig_API> enter(config, true); | 112 EnterResourceNoLock<PPB_AudioConfig_API> enter(config, true); |
| 79 if (enter.failed()) | 113 if (enter.failed()) |
| 80 return PP_ERROR_FAILED; | 114 return PP_ERROR_FAILED; |
| 81 config_ = config; | 115 config_ = config; |
| 82 | 116 |
| 83 PepperPluginInstanceImpl* instance = static_cast<PepperPluginInstanceImpl*>( | 117 PepperPluginInstanceImpl* instance = static_cast<PepperPluginInstanceImpl*>( |
| 84 PepperPluginInstance::Get(pp_instance())); | 118 PepperPluginInstance::Get(pp_instance())); |
| 85 if (!instance) | 119 if (!instance) |
| 86 return PP_ERROR_FAILED; | 120 return PP_ERROR_FAILED; |
| 87 | 121 |
| 88 // Prevent any throttling since we are playing audio. This stopgap prevents | |
| 89 // video from appearing 'frozen' while the audio track plays. | |
| 90 if (instance->throttler() && instance->throttler()->power_saver_enabled()) { | |
| 91 instance->throttler()->MarkPluginEssential( | |
| 92 PluginInstanceThrottler::UNTHROTTLE_METHOD_BY_AUDIO); | |
| 93 } | |
| 94 | |
| 95 // When the stream is created, we'll get called back on StreamCreated(). | 122 // When the stream is created, we'll get called back on StreamCreated(). |
| 96 DCHECK(!audio_); | 123 DCHECK(!audio_); |
| 97 audio_ = PepperPlatformAudioOutput::Create( | 124 audio_ = PepperPlatformAudioOutput::Create( |
| 98 static_cast<int>(enter.object()->GetSampleRate()), | 125 static_cast<int>(enter.object()->GetSampleRate()), |
| 99 static_cast<int>(enter.object()->GetSampleFrameCount()), | 126 static_cast<int>(enter.object()->GetSampleFrameCount()), |
| 100 instance->GetRenderView()->GetRoutingID(), | 127 instance->GetRenderView()->GetRoutingID(), |
| 101 instance->render_frame()->GetRoutingID(), | 128 instance->render_frame()->GetRoutingID(), |
| 102 this); | 129 this); |
| 103 if (!audio_) | 130 if (!audio_) |
| 104 return PP_ERROR_FAILED; | 131 return PP_ERROR_FAILED; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 125 base::SyncSocket::Handle socket_handle) { | 152 base::SyncSocket::Handle socket_handle) { |
| 126 EnterResourceNoLock<PPB_AudioConfig_API> enter(config_, true); | 153 EnterResourceNoLock<PPB_AudioConfig_API> enter(config_, true); |
| 127 SetStreamInfo(pp_instance(), | 154 SetStreamInfo(pp_instance(), |
| 128 shared_memory_handle, | 155 shared_memory_handle, |
| 129 shared_memory_size, | 156 shared_memory_size, |
| 130 socket_handle, | 157 socket_handle, |
| 131 enter.object()->GetSampleRate(), | 158 enter.object()->GetSampleRate(), |
| 132 enter.object()->GetSampleFrameCount()); | 159 enter.object()->GetSampleFrameCount()); |
| 133 } | 160 } |
| 134 | 161 |
| 162 void PPB_Audio_Impl::OnThrottleStateChange() { |
| 163 PepperPluginInstanceImpl* instance = static_cast<PepperPluginInstanceImpl*>( |
| 164 PepperPluginInstance::Get(pp_instance())); |
| 165 if (playback_throttled_ && instance && instance->throttler() && |
| 166 !instance->throttler()->power_saver_enabled()) { |
| 167 // If we have become unthrottled, and we have a pending playback, start it. |
| 168 StartDeferredPlayback(); |
| 169 } |
| 170 } |
| 171 |
| 172 void PPB_Audio_Impl::StartDeferredPlayback() { |
| 173 DCHECK(playback_throttled_); |
| 174 playback_throttled_ = false; |
| 175 |
| 176 SetStartPlaybackState(); |
| 177 audio_->StartPlayback(); |
| 178 } |
| 179 |
| 135 } // namespace content | 180 } // namespace content |
| OLD | NEW |