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
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/renderer/media/render_audiosourceprovider.h"
#include "base/basictypes.h"
#include "base/logging.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebAudioSourceProviderClient.h"
using std::vector;
using WebKit::WebVector;
RenderAudioSourceProvider::RenderAudioSourceProvider()
: is_initialized_(false),
channels_(0),
sample_rate_(0),
is_running_(false),
volume_(1.0),
renderer_(NULL),
client_(NULL) {
// We create the AudioDevice here because it must be created in the
// main thread. But we don't yet know the audio format (sample-rate, etc.)
// at this point. Later, when Initialize() is called, we have
// the audio format information and call the AudioDevice::Initialize()
// method to fully initialize it.
default_sink_ = new AudioDevice();
}
RenderAudioSourceProvider::~RenderAudioSourceProvider() {}
void RenderAudioSourceProvider::Start() {
base::AutoLock auto_lock(sink_lock_);
if (!client_)
default_sink_->Start();
is_running_ = true;
}
void RenderAudioSourceProvider::Stop() {
base::AutoLock auto_lock(sink_lock_);
if (!client_)
default_sink_->Stop();
is_running_ = false;
}
void RenderAudioSourceProvider::Play() {
base::AutoLock auto_lock(sink_lock_);
if (!client_)
default_sink_->Play();
is_running_ = true;
}
void RenderAudioSourceProvider::Pause(bool flush) {
base::AutoLock auto_lock(sink_lock_);
if (!client_)
default_sink_->Pause(flush);
is_running_ = false;
}
bool RenderAudioSourceProvider::SetVolume(double volume) {
base::AutoLock auto_lock(sink_lock_);
if (!client_)
default_sink_->SetVolume(volume);
volume_ = volume;
return true;
}
void RenderAudioSourceProvider::GetVolume(double* volume) {
if (!client_)
default_sink_->GetVolume(volume);
else if (volume)
*volume = volume_;
}
void RenderAudioSourceProvider::Initialize(
const media::AudioParameters& params, RenderCallback* renderer) {
base::AutoLock auto_lock(sink_lock_);
CHECK(!is_initialized_);
renderer_ = renderer;
default_sink_->Initialize(params, renderer);
// Keep track of the format in case the client hasn't yet been set.
channels_ = params.channels();
sample_rate_ = params.sample_rate();
if (client_) {
// Inform WebKit about the audio stream format.
client_->setFormat(channels_, sample_rate_);
}
is_initialized_ = true;
}
void RenderAudioSourceProvider::setClient(
WebKit::WebAudioSourceProviderClient* client) {
// Synchronize with other uses of client_ and default_sink_.
base::AutoLock auto_lock(sink_lock_);
if (client && client != client_) {
// Detach the audio renderer from normal playback.
default_sink_->Pause(true);
// The client will now take control by calling provideInput() periodically.
client_ = client;
if (is_initialized_) {
// The client needs to be notified of the audio format, if available.
// If the format is not yet available, we'll be notified later
// when Initialize() is called.
// Inform WebKit about the audio stream format.
client->setFormat(channels_, sample_rate_);
}
} else if (!client && client_) {
// Restore normal playback.
client_ = NULL;
// TODO(crogers): We should call default_sink_->Play() if we're
// in the playing state.
}
}
void RenderAudioSourceProvider::provideInput(
const WebVector<float*>& audio_data, size_t number_of_frames) {
DCHECK(client_);
if (renderer_ && is_initialized_ && is_running_) {
// Wrap WebVector as std::vector.
vector<float*> v(audio_data.size());
for (size_t i = 0; i < audio_data.size(); ++i)
v[i] = audio_data[i];
// TODO(crogers): figure out if we should volume scale here or in common
// WebAudio code. In any case we need to take care of volume.
renderer_->Render(v, number_of_frames, 0);
} else {
// Provide silence if the source is not running.
for (size_t i = 0; i < audio_data.size(); ++i)
memset(audio_data[i], 0, sizeof(float) * number_of_frames);
}
}
|