Chromium Code Reviews| Index: content/renderer/media/audio_renderer_sink_cache_impl.cc |
| diff --git a/content/renderer/media/audio_renderer_sink_cache_impl.cc b/content/renderer/media/audio_renderer_sink_cache_impl.cc |
| index 26b2ba5a31b4e53a3a78ef4858910b12d2623398..d1c2fc382b351c4f9d9c252c93013574b1fc0dc8 100644 |
| --- a/content/renderer/media/audio_renderer_sink_cache_impl.cc |
| +++ b/content/renderer/media/audio_renderer_sink_cache_impl.cc |
| @@ -37,6 +37,11 @@ enum GetOutputDeviceInfoCacheUtilization { |
| SINK_CACHE_LAST_ENTRY |
| }; |
| +bool SinkIsHealthy(media::AudioRendererSink* sink) { |
| + return sink->GetOutputDeviceInfo().device_status() == |
| + media::OUTPUT_DEVICE_STATUS_OK; |
| +} |
| + |
| } // namespace |
| // Cached sink data. |
| @@ -81,71 +86,51 @@ media::OutputDeviceInfo AudioRendererSinkCacheImpl::GetSinkInfo( |
| int session_id, |
| const std::string& device_id, |
| const url::Origin& security_origin) { |
| - CacheEntry cache_entry = {source_render_frame_id, |
| - std::string() /* device_id */, security_origin, |
| - nullptr /* sink */, false /* not used */}; |
| + scoped_refptr<media::AudioRendererSink> sink(nullptr); |
|
Guido Urdaneta
2016/11/25 22:13:17
nit: use default constructor? (up to you)
o1ka
2016/11/30 15:15:03
Done.
|
| if (media::AudioDeviceDescription::UseSessionIdToSelectDevice(session_id, |
| device_id)) { |
| // We are provided with session id instead of device id. Session id is |
| // unique, so we can't find any matching sink. Creating a new one. |
| - cache_entry.sink = create_sink_cb_.Run(source_render_frame_id, session_id, |
| - device_id, security_origin); |
| - cache_entry.device_id = cache_entry.sink->GetOutputDeviceInfo().device_id(); |
| - |
| - DVLOG(1) << "GetSinkInfo: address: " << cache_entry.sink.get() |
| - << " - used session to create new sink."; |
| + sink = create_sink_cb_.Run(source_render_frame_id, session_id, device_id, |
| + security_origin); |
| - // Cache a newly-created sink. |
| - base::AutoLock auto_lock(cache_lock_); |
| - cache_.push_back(cache_entry); |
| + CacheUnusedSinkIfHealthy(source_render_frame_id, |
| + sink->GetOutputDeviceInfo().device_id(), |
| + security_origin, sink); |
| UMA_HISTOGRAM_ENUMERATION( |
| "Media.Audio.Render.SinkCache.GetOutputDeviceInfoCacheUtilization", |
| SINK_CACHE_MISS_CANNOT_LOOKUP_BY_SESSION_ID, SINK_CACHE_LAST_ENTRY); |
| } else { |
| // Ignore session id. |
| - base::AutoLock auto_lock(cache_lock_); |
| - |
| - auto cache_iter = |
| - FindCacheEntry_Locked(source_render_frame_id, device_id, |
| - security_origin, false /* unused_only */); |
| - |
| - if (cache_iter != cache_.end()) { |
| - // A matching cached sink is found. |
| - DVLOG(1) << "GetSinkInfo: address: " << cache_iter->sink.get() |
| - << " - reused a cached sink."; |
| - |
| - UMA_HISTOGRAM_ENUMERATION( |
| - "Media.Audio.Render.SinkCache.GetOutputDeviceInfoCacheUtilization", |
| - SINK_CACHE_HIT, SINK_CACHE_LAST_ENTRY); |
| - return cache_iter->sink->GetOutputDeviceInfo(); |
| + { |
| + base::AutoLock auto_lock(cache_lock_); |
| + auto cache_iter = FindHealthyCacheEntry_Locked(source_render_frame_id, |
|
Guido Urdaneta
2016/11/25 22:13:17
nit: if only healthy entries are cached there is n
o1ka
2016/11/30 15:15:04
Changed so that the cached sinks are always health
|
| + device_id, security_origin, |
| + false /* unused_only */); |
| + if (cache_iter != cache_.end()) { |
| + // A matching cached sink is found. |
| + UMA_HISTOGRAM_ENUMERATION( |
| + "Media.Audio.Render.SinkCache.GetOutputDeviceInfoCacheUtilization", |
| + SINK_CACHE_HIT, SINK_CACHE_LAST_ENTRY); |
| + return cache_iter->sink->GetOutputDeviceInfo(); |
| + } |
| } |
| // No matching sink found, create a new one. |
| - cache_entry.device_id = device_id; |
| - cache_entry.sink = create_sink_cb_.Run( |
| - source_render_frame_id, 0 /* session_id */, device_id, security_origin); |
| - |
| - DVLOG(1) << "GetSinkInfo: address: " << cache_entry.sink.get() |
| - << " - no matching cached sink found, created a new one."; |
| - |
| - // Cache a newly-created sink. |
| - cache_.push_back(cache_entry); |
| + sink = create_sink_cb_.Run(source_render_frame_id, 0 /* session_id */, |
| + device_id, security_origin); |
| + CacheUnusedSinkIfHealthy(source_render_frame_id, device_id, security_origin, |
| + sink); |
| UMA_HISTOGRAM_ENUMERATION( |
| "Media.Audio.Render.SinkCache.GetOutputDeviceInfoCacheUtilization", |
| SINK_CACHE_MISS_NO_SINK, SINK_CACHE_LAST_ENTRY); |
| } |
| - // Schedule it for deletion. |
| - DeleteLaterIfUnused(cache_entry.sink.get()); |
| - |
| - DVLOG(1) << "GetSinkInfo: address: " << cache_entry.sink.get() |
| - << " created. source_render_frame_id: " << source_render_frame_id |
| - << " session_id: " << session_id << " device_id: " << device_id |
| - << " security_origin: " << security_origin; |
| - |
| - return cache_entry.sink->GetOutputDeviceInfo(); |
| + //|sink| is ref-counted, so it's ok if it is grabage-collected before we get |
|
Guido Urdaneta
2016/11/25 22:13:17
typo: grabage -> garbage.
I think the comment is w
o1ka
2016/11/30 15:15:04
Done.
|
| + // here. |
| + return sink->GetOutputDeviceInfo(); |
| } |
| scoped_refptr<media::AudioRendererSink> AudioRendererSinkCacheImpl::GetSink( |
| @@ -157,15 +142,12 @@ scoped_refptr<media::AudioRendererSink> AudioRendererSinkCacheImpl::GetSink( |
| base::AutoLock auto_lock(cache_lock_); |
| - auto cache_iter = |
| - FindCacheEntry_Locked(source_render_frame_id, device_id, security_origin, |
| - true /* unused sink only */); |
| + auto cache_iter = FindHealthyCacheEntry_Locked(source_render_frame_id, |
| + device_id, security_origin, |
| + true /* unused sink only */); |
| if (cache_iter != cache_.end()) { |
| // Found unused sink; mark it as used and return. |
| - DVLOG(1) << "GetSink: address: " << cache_iter->sink.get() |
| - << " - found unused cached sink, reusing it."; |
| - |
| cache_iter->used = true; |
| UMA_HISTOGRAM_BOOLEAN( |
| "Media.Audio.Render.SinkCache.InfoSinkReusedForOutput", true); |
| @@ -178,14 +160,7 @@ scoped_refptr<media::AudioRendererSink> AudioRendererSinkCacheImpl::GetSink( |
| create_sink_cb_.Run(source_render_frame_id, 0 /* session_id */, device_id, |
| security_origin), |
| true /* used */}; |
| - |
| cache_.push_back(cache_entry); |
| - |
| - DVLOG(1) << "GetSink: address: " << cache_entry.sink.get() |
| - << " - no unused cached sink found, created a new one." |
| - << " source_render_frame_id: " << source_render_frame_id |
| - << " device_id: " << device_id |
| - << " security_origin: " << security_origin; |
| return cache_entry.sink; |
| } |
| @@ -225,9 +200,6 @@ void AudioRendererSinkCacheImpl::DeleteSink( |
| DCHECK(!force_delete_used) |
| << "DeleteSink: address: " << sink_ptr |
| << " could not find a sink which is supposed to be in use"; |
| - |
| - DVLOG(1) << "DeleteSink: address: " << sink_ptr |
| - << " force_delete_used = false - already deleted."; |
| return; |
| } |
| @@ -236,11 +208,8 @@ void AudioRendererSinkCacheImpl::DeleteSink( |
| DCHECK((!force_delete_used) || (force_delete_used && cache_iter->used)) |
| << "Attempt to delete a non-aquired sink."; |
| - if (!force_delete_used && cache_iter->used) { |
| - DVLOG(1) << "DeleteSink: address: " << sink_ptr |
| - << " sink in use, skipping deletion."; |
| + if (!force_delete_used && cache_iter->used) |
| return; |
| - } |
| // To stop the sink before deletion if it's not used, we need to hold |
| // a ref to it. |
| @@ -251,19 +220,17 @@ void AudioRendererSinkCacheImpl::DeleteSink( |
| } |
| cache_.erase(cache_iter); |
| - DVLOG(1) << "DeleteSink: address: " << sink_ptr; |
| } // Lock scope; |
| // Stop the sink out of the lock scope. |
| if (sink_to_stop.get()) { |
| DCHECK_EQ(sink_ptr, sink_to_stop.get()); |
| sink_to_stop->Stop(); |
| - DVLOG(1) << "DeleteSink: address: " << sink_ptr << " stopped."; |
| } |
| } |
| AudioRendererSinkCacheImpl::CacheContainer::iterator |
| -AudioRendererSinkCacheImpl::FindCacheEntry_Locked( |
| +AudioRendererSinkCacheImpl::FindHealthyCacheEntry_Locked( |
| int source_render_frame_id, |
| const std::string& device_id, |
| const url::Origin& security_origin, |
| @@ -281,13 +248,37 @@ AudioRendererSinkCacheImpl::FindCacheEntry_Locked( |
| // Both device IDs represent the same default device => do not compare |
| // them; the default device is always authorized => ignore security |
| // origin. |
| - return true; |
| + return SinkIsHealthy(val.sink.get()); |
|
Guido Urdaneta
2016/11/25 22:13:17
Can a healthy sink become unhealthy? If not, why c
DaleCurtis
2016/11/28 19:00:37
Yes, OnError() may be fired by the browser side.
o1ka
2016/11/30 15:15:03
It does not change device status though. We don't
|
| } |
| return val.device_id == device_id && |
| - val.security_origin == security_origin; |
| + val.security_origin == security_origin && |
| + SinkIsHealthy(val.sink.get()); |
|
Guido Urdaneta
2016/11/25 22:13:17
ditto
o1ka
2016/11/30 15:15:04
Done.
|
| }); |
| }; |
| +void AudioRendererSinkCacheImpl::CacheUnusedSinkIfHealthy( |
| + int source_render_frame_id, |
| + const std::string& device_id, |
| + const url::Origin& security_origin, |
| + scoped_refptr<media::AudioRendererSink> sink) { |
| + if (!SinkIsHealthy(sink.get())) { |
| + UMA_HISTOGRAM_BOOLEAN("Media.Audio.Render.SinkCache.HealthySinkCached", |
| + false); |
| + return; |
| + } |
| + |
| + CacheEntry cache_entry = {source_render_frame_id, device_id, security_origin, |
| + sink, false /* not used */}; |
| + |
| + { |
| + base::AutoLock auto_lock(cache_lock_); |
| + cache_.push_back(cache_entry); |
| + } |
| + |
| + UMA_HISTOGRAM_BOOLEAN("Media.Audio.Render.SinkCache.HealthySinkCached", true); |
| + DeleteLaterIfUnused(cache_entry.sink.get()); |
| +} |
| + |
| int AudioRendererSinkCacheImpl::GetCacheSizeForTesting() { |
| return cache_.size(); |
| } |