Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(402)

Side by Side Diff: content/renderer/media/audio_renderer_sink_cache_impl.h

Issue 1942803002: Caching AudioOutputDevice instances in mixer manager (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: First round of comments addressed Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 #ifndef CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_MIXER_MANAGER_H_ 5 #include "content/renderer/media/audio_renderer_sink_cache.h"
6 #define CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_MIXER_MANAGER_H_
7 6
8 #include <map> 7 #include <map>
9 #include <string>
10 #include <utility>
11 8
12 #include "base/macros.h" 9 #include "base/single_thread_task_runner.h"
13 #include "base/synchronization/lock.h" 10 #include "base/synchronization/lock.h"
14 #include "content/common/content_export.h" 11 #include "content/common/content_export.h"
15 #include "media/audio/audio_device_description.h" 12 #include "media/audio/audio_device_description.h"
16 #include "media/base/audio_parameters.h" 13 #include "media/base/audio_renderer_sink.h"
17 #include "media/base/output_device_info.h"
18 #include "url/origin.h"
19
20 namespace media {
21 class AudioHardwareConfig;
22 class AudioRendererMixer;
23 class AudioRendererMixerInput;
24 class AudioRendererSink;
25 }
26 14
27 namespace content { 15 namespace content {
28 16
29 // Manages sharing of an AudioRendererMixer among AudioRendererMixerInputs based 17 // AudioRendererSinkCache implementation.
30 // on their AudioParameters configuration. Inputs with the same AudioParameters 18 class CONTENT_EXPORT AudioRendererSinkCacheImpl
31 // configuration will share a mixer while a new AudioRendererMixer will be 19 : public AudioRendererSinkCache {
32 // lazily created if one with the exact AudioParameters does not exist.
33 //
34 // There should only be one instance of AudioRendererMixerManager per render
35 // thread.
36 //
37 // TODO(dalecurtis): Right now we require AudioParameters to be an exact match
38 // when we should be able to ignore bits per channel since we're only dealing
39 // with floats. However, bits per channel is currently used to interleave the
40 // audio data by AudioOutputDevice::AudioThreadCallback::Process for consumption
41 // via the shared memory. See http://crbug.com/114700.
42 class CONTENT_EXPORT AudioRendererMixerManager {
43 public: 20 public:
44 AudioRendererMixerManager(); 21 // Callback to be used for AudioRendererSink creation
45 ~AudioRendererMixerManager(); 22 using CreateSinkCallback =
23 base::Callback<scoped_refptr<media::AudioRendererSink>(
24 int render_frame_id,
25 int session_id,
26 const std::string& device_id,
27 const url::Origin& security_origin)>;
46 28
47 // Creates an AudioRendererMixerInput with the proper callbacks necessary to 29 AudioRendererSinkCacheImpl(
48 // retrieve an AudioRendererMixer instance from AudioRendererMixerManager. 30 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
49 // |source_render_frame_id| refers to the RenderFrame containing the entity 31 const CreateSinkCallback& create_sink_callback,
50 // rendering the audio. Caller must ensure AudioRendererMixerManager outlives 32 int delete_timeout_ms);
51 // the returned input. |device_id|, |session_id| and |security_origin| 33
52 // identify the output device to use. If |device_id| is empty and |session_id| 34 ~AudioRendererSinkCacheImpl() final;
53 // is nonzero, output device associated with the opened input device 35
54 // designated by |session_id| is used. Otherwise, |session_id| is ignored. 36 media::OutputDeviceInfo GetSinkInfo(int source_render_frame_id,
55 media::AudioRendererMixerInput* CreateInput( 37 int session_id,
38 const std::string& device_id,
39 const url::Origin& security_origin) final;
40
41 scoped_refptr<media::AudioRendererSink> GetSink(
56 int source_render_frame_id, 42 int source_render_frame_id,
57 int session_id,
58 const std::string& device_id, 43 const std::string& device_id,
59 const url::Origin& security_origin); 44 const url::Origin& security_origin) final;
60 45
61 // Returns a mixer instance based on AudioParameters; an existing one if one 46 void ReleaseSink(int source_render_frame_id,
62 // with the provided AudioParameters exists or a new one if not.
63 media::AudioRendererMixer* GetMixer(int source_render_frame_id,
64 const media::AudioParameters& params,
65 const std::string& device_id,
66 const url::Origin& security_origin,
67 media::OutputDeviceStatus* device_status);
68
69 // Remove a mixer instance given a mixer if the only other reference is held
70 // by AudioRendererMixerManager. Every AudioRendererMixer owner must call
71 // this method when it's done with a mixer.
72 void RemoveMixer(int source_render_frame_id,
73 const media::AudioParameters& params,
74 const std::string& device_id, 47 const std::string& device_id,
75 const url::Origin& security_origin); 48 const url::Origin& security_origin,
49 const media::AudioRendererSink* sink) final;
76 50
77 private: 51 private:
78 friend class AudioRendererMixerManagerTest; 52 friend class AudioRendererSinkCacheTest;
79 53
80 // Define a key so that only those AudioRendererMixerInputs from the same 54 // The key to be used to access a cached sink (not unique,there can be
81 // RenderView, AudioParameters and output device can be mixed together. 55 // multiple sinks per device.
82 struct MixerKey { 56 struct SinkKey {
83 MixerKey(int source_render_frame_id, 57 SinkKey(int source_render_frame_id,
84 const media::AudioParameters& params, 58 const std::string& device_id,
85 const std::string& device_id, 59 const url::Origin& security_origin);
86 const url::Origin& security_origin); 60 SinkKey(const SinkKey& other);
87 MixerKey(const MixerKey& other);
88 int source_render_frame_id; 61 int source_render_frame_id;
89 media::AudioParameters params;
90 std::string device_id; 62 std::string device_id;
91 url::Origin security_origin; 63 url::Origin security_origin;
92 }; 64 };
93 65
94 // Custom compare operator for the AudioRendererMixerMap. Allows reuse of 66 // Strict weak ordering of the keys.
95 // mixers where only irrelevant keys mismatch; e.g., effects, bits per sample. 67 struct SinkKeyCompare {
96 struct MixerKeyCompare { 68 bool operator()(const SinkKey& a, const SinkKey& b) const {
97 bool operator()(const MixerKey& a, const MixerKey& b) const {
98 if (a.source_render_frame_id != b.source_render_frame_id) 69 if (a.source_render_frame_id != b.source_render_frame_id)
99 return a.source_render_frame_id < b.source_render_frame_id; 70 return a.source_render_frame_id < b.source_render_frame_id;
100 if (a.params.channels() != b.params.channels())
101 return a.params.channels() < b.params.channels();
102
103 // Ignore effects(), bits_per_sample(), format(), and frames_per_buffer(),
104 // these parameters do not affect mixer reuse. All AudioRendererMixer
105 // units disable FIFO, so frames_per_buffer() can be safely ignored.
106 if (a.params.channel_layout() != b.params.channel_layout())
107 return a.params.channel_layout() < b.params.channel_layout();
108 71
109 if (media::AudioDeviceDescription::IsDefaultDevice(a.device_id) && 72 if (media::AudioDeviceDescription::IsDefaultDevice(a.device_id) &&
110 media::AudioDeviceDescription::IsDefaultDevice(b.device_id)) { 73 media::AudioDeviceDescription::IsDefaultDevice(b.device_id)) {
111 // Both device IDs represent the same default device => do not compare 74 // Both device IDs represent the same default device => do not compare
112 // them; the default device is always authorized => ignoring security 75 // them; the default device is always authorized => ignoring security
113 // origin. 76 // origin.
114 return false; 77 return false;
115 } 78 }
116 79
117 if (a.device_id != b.device_id) 80 if (a.device_id != b.device_id)
118 return a.device_id < b.device_id; 81 return a.device_id < b.device_id;
119 82
120 return a.security_origin < b.security_origin; 83 return a.security_origin < b.security_origin;
121 } 84 }
122 }; 85 };
123 86
124 // Map of MixerKey to <AudioRendererMixer, Count>. Count allows 87 // Cached sink data.
125 // AudioRendererMixerManager to keep track explicitly (v.s. RefCounted which 88 struct AudioRendererSinkReference {
126 // is implicit) of the number of outstanding AudioRendererMixers. 89 AudioRendererSinkReference(scoped_refptr<media::AudioRendererSink> sink,
127 struct AudioRendererMixerReference { 90 bool used);
128 media::AudioRendererMixer* mixer; 91 AudioRendererSinkReference(const AudioRendererSinkReference& other);
129 int ref_count; 92 ~AudioRendererSinkReference();
93 scoped_refptr<media::AudioRendererSink> sink; // Sink instance
94 bool used; // True if in used by a client.
130 }; 95 };
131 typedef std::map<MixerKey, AudioRendererMixerReference, MixerKeyCompare>
132 AudioRendererMixerMap;
133 96
134 // Active mixers. 97 using AudioRendererSinkMap =
135 AudioRendererMixerMap mixers_; 98 std::multimap<SinkKey, AudioRendererSinkReference, SinkKeyCompare>;
136 base::Lock mixers_lock_;
137 99
138 DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerManager); 100 // Schedules a sink for deletion. Deletion will be performed on the same
101 // thread the cache is created on.
102 void DeleteLaterIfUnused(const SinkKey& key,
103 const media::AudioRendererSink* sink);
104
105 // Deletes a sink from the cache. If |force_delete_used| is set, a sink being
106 // deleted can (and should) be in use at the moment of deletion; otherwise the
107 // sink is deleted only if unused.
108 void DeleteSink(const SinkKey& key,
109 const media::AudioRendererSink* sink,
110 bool force_delete_used);
111
112 // Creates a sink with a specified |key| and |used| state and inserts it into
113 // the cache.
114 scoped_refptr<media::AudioRendererSink> InsertNewSinkWhileLockHeld(
115 const SinkKey& key,
116 bool used);
117
118 // Cached sink deletion timeout.
119 // For example: (1) sink was create and cached in GetSinkInfo(), and then (2)
120 // the same sink is requested in GetSink(), if time interval between (1) and
121 // (2) is less than |kDeleteTimeoutMs|, then sink cached in (1) is reused in
122 // (2). On the other hand, if after (1) nobody is interested in the sink
123 // within |kDeleteTimeoutMs|, it is garbage-collected.
124 const int delete_timeout_ms_;
125
126 // Task runner for scheduled sink garbage collection.
127 const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
128
129 // Callback used for sink creation.
130 const CreateSinkCallback create_sink_cb_;
131
132 // Cached sinks, protected by lock.
133 base::Lock sinks_lock_;
134 AudioRendererSinkMap sinks_;
135
136 base::WeakPtrFactory<AudioRendererSinkCacheImpl> weak_ptr_factory_;
137
138 DISALLOW_COPY_AND_ASSIGN(AudioRendererSinkCacheImpl);
139 }; 139 };
140 140
141 } // namespace content 141 } // namespace content
142
143 #endif // CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_MIXER_MANAGER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698