-
Notifications
You must be signed in to change notification settings - Fork 0
/
audio_renderer_host.cc
157 lines (135 loc) · 5.27 KB
/
audio_renderer_host.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
//
#include "chromium_media_lib/audio_renderer_host.h"
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "chromium_media_lib/audio_output_delegate_impl.h"
#include "chromium_media_lib/media_context.h"
#include "chromium_media_lib/media_internals.h"
#include "media/audio/audio_device_description.h"
#include "media/audio/audio_system.h"
namespace media {
void AudioRendererHost::SetClient(AudioRendererHostClient* client) {
client_ = client;
}
AudioRendererHost::AudioRendererHost(AudioManager* audio_manager,
AudioSystem* audio_system,
AudioRendererHostClient* client)
: audio_manager_(audio_manager),
audio_system_(audio_system),
client_(client) {
DCHECK(audio_manager_);
}
AudioRendererHost::~AudioRendererHost() {}
void AudioRendererHost::RequestDeviceAuthorization(
int stream_id,
int render_frame_id,
int session_id,
const std::string& device_id,
const url::Origin& security_origin,
AuthorizationCompletedCallback cb) {
if (AudioDeviceDescription::IsDefaultDevice(device_id)) {
// Default device doesn't need authorization.
authorizations_.insert(std::make_pair(
stream_id,
std::make_pair(true, AudioDeviceDescription::kDefaultDeviceId)));
audio_system_->GetOutputStreamParameters(
AudioDeviceDescription::kDefaultDeviceId,
base::Bind(&AudioRendererHost::DeviceParametersReceived,
base::Unretained(this), stream_id, std::move(cb),
AudioDeviceDescription::kDefaultDeviceId));
return;
}
assert(false);
}
void AudioRendererHost::CreateStream(int stream_id,
int render_frame_id,
const AudioParameters& params) {
const auto& auth_data = authorizations_.find(stream_id);
std::string device_unique_id;
if (auth_data != authorizations_.end()) {
if (!auth_data->second.first) {
OnStreamError(stream_id);
return;
}
device_unique_id.swap(auth_data->second.second);
authorizations_.erase(auth_data);
}
MediaInternals* const media_internals = MediaInternals::GetInstance();
std::unique_ptr<AudioLog> audio_log =
media_internals->CreateAudioLog(AudioLogFactory::AUDIO_OUTPUT_CONTROLLER);
delegates_.push_back(
base::WrapUnique<AudioOutputDelegate>(new AudioOutputDelegateImpl(
this, audio_manager_, std::move(audio_log), stream_id,
render_frame_id, params, device_unique_id,
MediaContext::Get()->io_task_runner())));
}
void AudioRendererHost::PlayStream(int stream_id) {
media::AudioOutputDelegate* delegate = LookupById(stream_id);
if (!delegate) {
OnStreamError(stream_id);
return;
}
delegate->OnPlayStream();
}
void AudioRendererHost::DeviceParametersReceived(
int stream_id,
AuthorizationCompletedCallback cb,
const std::string& raw_device_id,
const AudioParameters& output_params) const {
DCHECK(!raw_device_id.empty());
cb.Run(stream_id, OUTPUT_DEVICE_STATUS_OK,
output_params.IsValid() ? output_params
: AudioParameters::UnavailableDeviceParams(),
raw_device_id);
}
void AudioRendererHost::OnStreamCreated(
int stream_id,
const base::SharedMemory* shared_memory,
std::unique_ptr<base::CancelableSyncSocket> foreign_socket) {
base::SyncSocket::TransitDescriptor socket_descriptor;
size_t shared_memory_size = shared_memory->requested_size();
base::SharedMemoryHandle foreign_memory_handle =
shared_memory->handle().Duplicate();
base::ProcessHandle handle = base::GetCurrentProcessHandle();
if (!(foreign_memory_handle.IsValid() &&
foreign_socket->PrepareTransitDescriptor(handle,
&socket_descriptor))) {
// Something went wrong in preparing the IPC handles.
client_->OnStreamError(stream_id);
return;
}
// NOTE: It is important to release handle otherwise the socket_descriptor
// will be invalide after foreign_socket destroy
foreign_socket->Release();
client_->OnStreamCreated(stream_id, foreign_memory_handle, socket_descriptor,
base::checked_cast<uint32_t>(shared_memory_size));
}
void AudioRendererHost::OnStreamError(int stream_id) {
if (client_)
client_->OnStreamError(stream_id);
}
AudioRendererHost::AudioOutputDelegateVector::iterator
AudioRendererHost::LookupIteratorById(int stream_id) {
return std::find_if(
delegates_.begin(), delegates_.end(),
[stream_id](const std::unique_ptr<AudioOutputDelegate>& d) {
return d->GetStreamId() == stream_id;
});
}
void AudioRendererHost::OnCloseStream(int stream_id) {
authorizations_.erase(stream_id);
auto i = LookupIteratorById(stream_id);
// Prevent oustanding callbacks from attempting to close/delete the same
// AudioOutputDelegate twice.
if (i == delegates_.end())
return;
std::swap(*i, delegates_.back());
delegates_.pop_back();
}
media::AudioOutputDelegate* AudioRendererHost::LookupById(int stream_id) {
auto i = LookupIteratorById(stream_id);
return i != delegates_.end() ? i->get() : nullptr;
}
} // namespace media