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

Side by Side Diff: media/audio/pulse/pulse_util.cc

Issue 2784433002: Ensures that audio tasks cannot run after AudioManager is deleted. (Closed)
Patch Set: rebase Created 3 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
« no previous file with comments | « media/audio/pulse/pulse_util.h ('k') | media/audio/sounds/audio_stream_handler_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "media/audio/pulse/pulse_util.h" 5 #include "media/audio/pulse/pulse_util.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include "base/files/file_path.h"
9 #include "base/logging.h" 10 #include "base/logging.h"
10 #include "base/macros.h" 11 #include "base/macros.h"
12 #include "base/memory/ptr_util.h"
11 #include "media/audio/audio_device_description.h" 13 #include "media/audio/audio_device_description.h"
12 #include "media/base/audio_parameters.h" 14 #include "media/base/audio_parameters.h"
13 #include "media/base/audio_timestamp_helper.h" 15 #include "media/base/audio_timestamp_helper.h"
14 16
17 #if defined(DLOPEN_PULSEAUDIO)
18 #include "media/audio/pulse/pulse_stubs.h"
19
20 using media_audio_pulse::kModulePulse;
21 using media_audio_pulse::InitializeStubs;
22 using media_audio_pulse::StubPathMap;
23 #endif // defined(DLOPEN_PULSEAUDIO)
24
15 namespace media { 25 namespace media {
16 26
17 namespace pulse { 27 namespace pulse {
18 28
19 namespace { 29 namespace {
20 30
21 #if defined(GOOGLE_CHROME_BUILD) 31 #if defined(GOOGLE_CHROME_BUILD)
22 static const char kBrowserDisplayName[] = "google-chrome"; 32 static const char kBrowserDisplayName[] = "google-chrome";
23 #else 33 #else
24 static const char kBrowserDisplayName[] = "chromium-browser"; 34 static const char kBrowserDisplayName[] = "chromium-browser";
25 #endif 35 #endif
26 36
37 #if defined(DLOPEN_PULSEAUDIO)
38 static const base::FilePath::CharType kPulseLib[] =
39 FILE_PATH_LITERAL("libpulse.so.0");
40 #endif
41
42 void DestroyMainloop(pa_threaded_mainloop* mainloop) {
43 pa_threaded_mainloop_stop(mainloop);
44 pa_threaded_mainloop_free(mainloop);
45 }
46
47 void DestroyContext(pa_context* context) {
48 pa_context_set_state_callback(context, NULL, NULL);
49 pa_context_disconnect(context);
50 pa_context_unref(context);
51 }
52
27 pa_channel_position ChromiumToPAChannelPosition(Channels channel) { 53 pa_channel_position ChromiumToPAChannelPosition(Channels channel) {
28 switch (channel) { 54 switch (channel) {
29 // PulseAudio does not differentiate between left/right and 55 // PulseAudio does not differentiate between left/right and
30 // stereo-left/stereo-right, both translate to front-left/front-right. 56 // stereo-left/stereo-right, both translate to front-left/front-right.
31 case LEFT: 57 case LEFT:
32 return PA_CHANNEL_POSITION_FRONT_LEFT; 58 return PA_CHANNEL_POSITION_FRONT_LEFT;
33 case RIGHT: 59 case RIGHT:
34 return PA_CHANNEL_POSITION_FRONT_RIGHT; 60 return PA_CHANNEL_POSITION_FRONT_RIGHT;
35 case CENTER: 61 case CENTER:
36 return PA_CHANNEL_POSITION_FRONT_CENTER; 62 return PA_CHANNEL_POSITION_FRONT_CENTER;
(...skipping 26 matching lines...) Expand all
63 89
64 pa_proplist* get() const { return property_list_; } 90 pa_proplist* get() const { return property_list_; }
65 91
66 private: 92 private:
67 pa_proplist* property_list_; 93 pa_proplist* property_list_;
68 DISALLOW_COPY_AND_ASSIGN(ScopedPropertyList); 94 DISALLOW_COPY_AND_ASSIGN(ScopedPropertyList);
69 }; 95 };
70 96
71 } // namespace 97 } // namespace
72 98
99 bool InitPulse(pa_threaded_mainloop** mainloop, pa_context** context) {
100 #if defined(DLOPEN_PULSEAUDIO)
101 StubPathMap paths;
102
103 // Check if the pulse library is avialbale.
104 paths[kModulePulse].push_back(kPulseLib);
105 if (!InitializeStubs(paths)) {
106 VLOG(1) << "Failed on loading the Pulse library and symbols";
107 return false;
108 }
109 #endif // defined(DLOPEN_PULSEAUDIO)
110
111 // Create a mainloop API and connect to the default server.
112 // The mainloop is the internal asynchronous API event loop.
113 pa_threaded_mainloop* pa_mainloop = pa_threaded_mainloop_new();
114 if (!pa_mainloop)
115 return false;
116
117 // Start the threaded mainloop.
118 if (pa_threaded_mainloop_start(pa_mainloop)) {
119 pa_threaded_mainloop_free(pa_mainloop);
120 return false;
121 }
122
123 // Lock the event loop object, effectively blocking the event loop thread
124 // from processing events. This is necessary.
125 auto mainloop_lock = base::MakeUnique<AutoPulseLock>(pa_mainloop);
126
127 pa_mainloop_api* pa_mainloop_api = pa_threaded_mainloop_get_api(pa_mainloop);
128 pa_context* pa_context = pa_context_new(pa_mainloop_api, "Chrome input");
129 if (!pa_context) {
130 mainloop_lock.reset();
131 DestroyMainloop(pa_mainloop);
132 return false;
133 }
134
135 pa_context_set_state_callback(pa_context, &pulse::ContextStateCallback,
136 pa_mainloop);
137 if (pa_context_connect(pa_context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL)) {
138 VLOG(1) << "Failed to connect to the context. Error: "
139 << pa_strerror(pa_context_errno(pa_context));
140 pa_context_set_state_callback(pa_context, NULL, NULL);
141 pa_context_unref(pa_context);
142 mainloop_lock.reset();
143 DestroyMainloop(pa_mainloop);
144 return false;
145 }
146
147 // Wait until |pa_context| is ready. pa_threaded_mainloop_wait() must be
148 // called after pa_context_get_state() in case the context is already ready,
149 // otherwise pa_threaded_mainloop_wait() will hang indefinitely.
150 while (true) {
151 pa_context_state_t context_state = pa_context_get_state(pa_context);
152 if (!PA_CONTEXT_IS_GOOD(context_state)) {
153 DestroyContext(pa_context);
154 mainloop_lock.reset();
155 DestroyMainloop(pa_mainloop);
156 return false;
157 }
158 if (context_state == PA_CONTEXT_READY)
159 break;
160 pa_threaded_mainloop_wait(pa_mainloop);
161 }
162
163 *mainloop = pa_mainloop;
164 *context = pa_context;
165 return true;
166 }
167
168 void DestroyPulse(pa_threaded_mainloop* mainloop, pa_context* context) {
169 DCHECK(mainloop);
170 DCHECK(context);
171
172 {
173 AutoPulseLock auto_lock(mainloop);
174 DestroyContext(context);
175 }
176
177 DestroyMainloop(mainloop);
178 }
179
73 // static, pa_stream_success_cb_t 180 // static, pa_stream_success_cb_t
74 void StreamSuccessCallback(pa_stream* s, int error, void* mainloop) { 181 void StreamSuccessCallback(pa_stream* s, int error, void* mainloop) {
75 pa_threaded_mainloop* pa_mainloop = 182 pa_threaded_mainloop* pa_mainloop =
76 static_cast<pa_threaded_mainloop*>(mainloop); 183 static_cast<pa_threaded_mainloop*>(mainloop);
77 pa_threaded_mainloop_signal(pa_mainloop, 0); 184 pa_threaded_mainloop_signal(pa_mainloop, 0);
78 } 185 }
79 186
80 // |pa_context| and |pa_stream| state changed cb. 187 // |pa_context| and |pa_stream| state changed cb.
81 void ContextStateCallback(pa_context* context, void* mainloop) { 188 void ContextStateCallback(pa_context* context, void* mainloop) {
82 pa_threaded_mainloop* pa_mainloop = 189 pa_threaded_mainloop* pa_mainloop =
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 } 465 }
359 466
360 return true; 467 return true;
361 } 468 }
362 469
363 #undef RETURN_ON_FAILURE 470 #undef RETURN_ON_FAILURE
364 471
365 } // namespace pulse 472 } // namespace pulse
366 473
367 } // namespace media 474 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/pulse/pulse_util.h ('k') | media/audio/sounds/audio_stream_handler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698