Move media/audio files into media namespace
[chromium-blink-merge.git] / content / renderer / media / audio_device.cc
blob60e36a729b91b5450e97548a561f6f976415aa05
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
3 // found in the LICENSE file.
5 #include "content/renderer/media/audio_device.h"
7 #include "base/debug/trace_event.h"
8 #include "base/message_loop.h"
9 #include "base/threading/thread_restrictions.h"
10 #include "base/time.h"
11 #include "content/common/child_process.h"
12 #include "content/common/media/audio_messages.h"
13 #include "content/common/view_messages.h"
14 #include "content/renderer/render_thread_impl.h"
15 #include "media/audio/audio_output_controller.h"
16 #include "media/audio/audio_util.h"
18 using media::AudioRendererSink;
20 // Takes care of invoking the render callback on the audio thread.
21 // An instance of this class is created for each capture stream in
22 // OnStreamCreated().
23 class AudioDevice::AudioThreadCallback
24 : public AudioDeviceThread::Callback {
25 public:
26 AudioThreadCallback(const media::AudioParameters& audio_parameters,
27 base::SharedMemoryHandle memory,
28 int memory_length,
29 AudioRendererSink::RenderCallback* render_callback);
30 virtual ~AudioThreadCallback();
32 virtual void MapSharedMemory() OVERRIDE;
34 // Called whenever we receive notifications about pending data.
35 virtual void Process(int pending_data) OVERRIDE;
37 private:
38 AudioRendererSink::RenderCallback* render_callback_;
39 DISALLOW_COPY_AND_ASSIGN(AudioThreadCallback);
42 AudioDevice::AudioDevice()
43 : ScopedLoopObserver(ChildProcess::current()->io_message_loop()),
44 callback_(NULL),
45 volume_(1.0),
46 stream_id_(0),
47 play_on_start_(true),
48 is_started_(false) {
49 filter_ = RenderThreadImpl::current()->audio_message_filter();
52 AudioDevice::AudioDevice(const media::AudioParameters& params,
53 RenderCallback* callback)
54 : ScopedLoopObserver(ChildProcess::current()->io_message_loop()),
55 audio_parameters_(params),
56 callback_(callback),
57 volume_(1.0),
58 stream_id_(0),
59 play_on_start_(true),
60 is_started_(false) {
61 filter_ = RenderThreadImpl::current()->audio_message_filter();
64 void AudioDevice::Initialize(const media::AudioParameters& params,
65 RenderCallback* callback) {
66 CHECK_EQ(0, stream_id_) <<
67 "AudioDevice::Initialize() must be called before Start()";
69 CHECK(!callback_); // Calling Initialize() twice?
71 audio_parameters_ = params;
72 // TODO(xians): We have to hard code the sample format to 16 since the
73 // current audio path does not support sample formats rather than 16bits per
74 // channel. Remove it if the problem is fixed.
75 audio_parameters_.Reset(
76 params.format(),
77 params.channel_layout(), params.sample_rate(), 16,
78 params.frames_per_buffer());
79 callback_ = callback;
82 AudioDevice::~AudioDevice() {
83 // The current design requires that the user calls Stop() before deleting
84 // this class.
85 CHECK_EQ(0, stream_id_);
88 void AudioDevice::Start() {
89 DCHECK(callback_) << "Initialize hasn't been called";
90 message_loop()->PostTask(FROM_HERE,
91 base::Bind(&AudioDevice::InitializeOnIOThread, this, audio_parameters_));
94 void AudioDevice::Stop() {
96 base::AutoLock auto_lock(audio_thread_lock_);
97 audio_thread_.Stop(MessageLoop::current());
100 message_loop()->PostTask(FROM_HERE,
101 base::Bind(&AudioDevice::ShutDownOnIOThread, this));
104 void AudioDevice::Play() {
105 message_loop()->PostTask(FROM_HERE,
106 base::Bind(&AudioDevice::PlayOnIOThread, this));
109 void AudioDevice::Pause(bool flush) {
110 message_loop()->PostTask(FROM_HERE,
111 base::Bind(&AudioDevice::PauseOnIOThread, this, flush));
114 bool AudioDevice::SetVolume(double volume) {
115 if (volume < 0 || volume > 1.0)
116 return false;
118 if (!message_loop()->PostTask(FROM_HERE,
119 base::Bind(&AudioDevice::SetVolumeOnIOThread, this, volume))) {
120 return false;
123 volume_ = volume;
125 return true;
128 void AudioDevice::GetVolume(double* volume) {
129 // Return a locally cached version of the current scaling factor.
130 *volume = volume_;
133 void AudioDevice::InitializeOnIOThread(const media::AudioParameters& params) {
134 DCHECK(message_loop()->BelongsToCurrentThread());
135 // Make sure we don't create the stream more than once.
136 DCHECK_EQ(0, stream_id_);
137 if (stream_id_)
138 return;
140 stream_id_ = filter_->AddDelegate(this);
141 Send(new AudioHostMsg_CreateStream(stream_id_, params));
144 void AudioDevice::PlayOnIOThread() {
145 DCHECK(message_loop()->BelongsToCurrentThread());
146 if (stream_id_ && is_started_)
147 Send(new AudioHostMsg_PlayStream(stream_id_));
148 else
149 play_on_start_ = true;
152 void AudioDevice::PauseOnIOThread(bool flush) {
153 DCHECK(message_loop()->BelongsToCurrentThread());
154 if (stream_id_ && is_started_) {
155 Send(new AudioHostMsg_PauseStream(stream_id_));
156 if (flush)
157 Send(new AudioHostMsg_FlushStream(stream_id_));
158 } else {
159 // Note that |flush| isn't relevant here since this is the case where
160 // the stream is first starting.
161 play_on_start_ = false;
165 void AudioDevice::ShutDownOnIOThread() {
166 DCHECK(message_loop()->BelongsToCurrentThread());
168 // Make sure we don't call shutdown more than once.
169 if (stream_id_) {
170 is_started_ = false;
172 filter_->RemoveDelegate(stream_id_);
173 Send(new AudioHostMsg_CloseStream(stream_id_));
174 stream_id_ = 0;
177 // We can run into an issue where ShutDownOnIOThread is called right after
178 // OnStreamCreated is called in cases where Start/Stop are called before we
179 // get the OnStreamCreated callback. To handle that corner case, we call
180 // Stop(). In most cases, the thread will already be stopped.
181 // Another situation is when the IO thread goes away before Stop() is called
182 // in which case, we cannot use the message loop to close the thread handle
183 // and can't not rely on the main thread existing either.
184 base::ThreadRestrictions::ScopedAllowIO allow_io;
185 audio_thread_.Stop(NULL);
186 audio_callback_.reset();
189 void AudioDevice::SetVolumeOnIOThread(double volume) {
190 DCHECK(message_loop()->BelongsToCurrentThread());
191 if (stream_id_)
192 Send(new AudioHostMsg_SetVolume(stream_id_, volume));
195 void AudioDevice::OnStateChanged(AudioStreamState state) {
196 DCHECK(message_loop()->BelongsToCurrentThread());
198 // Do nothing if the stream has been closed.
199 if (!stream_id_)
200 return;
202 if (state == kAudioStreamError) {
203 DLOG(WARNING) << "AudioDevice::OnStateChanged(kError)";
204 // Don't dereference the callback object if the audio thread
205 // is stopped or stopping. That could mean that the callback
206 // object has been deleted.
207 // TODO(tommi): Add an explicit contract for clearing the callback
208 // object. Possibly require calling Initialize again or provide
209 // a callback object via Start() and clear it in Stop().
210 if (!audio_thread_.IsStopped())
211 callback_->OnRenderError();
215 void AudioDevice::OnStreamCreated(
216 base::SharedMemoryHandle handle,
217 base::SyncSocket::Handle socket_handle,
218 uint32 length) {
219 DCHECK(message_loop()->BelongsToCurrentThread());
220 DCHECK_GE(length,
221 audio_parameters_.frames_per_buffer() * sizeof(int16) *
222 audio_parameters_.channels());
223 #if defined(OS_WIN)
224 DCHECK(handle);
225 DCHECK(socket_handle);
226 #else
227 DCHECK_GE(handle.fd, 0);
228 DCHECK_GE(socket_handle, 0);
229 #endif
231 base::AutoLock auto_lock(audio_thread_lock_);
233 // Takes care of the case when Stop() is called before OnStreamCreated().
234 if (!stream_id_) {
235 base::SharedMemory::CloseHandle(handle);
236 // Close the socket handler.
237 base::SyncSocket socket(socket_handle);
238 return;
241 DCHECK(audio_thread_.IsStopped());
242 audio_callback_.reset(new AudioDevice::AudioThreadCallback(audio_parameters_,
243 handle, length, callback_));
244 audio_thread_.Start(audio_callback_.get(), socket_handle, "AudioDevice");
246 // We handle the case where Play() and/or Pause() may have been called
247 // multiple times before OnStreamCreated() gets called.
248 is_started_ = true;
249 if (play_on_start_)
250 PlayOnIOThread();
253 void AudioDevice::Send(IPC::Message* message) {
254 filter_->Send(message);
257 void AudioDevice::WillDestroyCurrentMessageLoop() {
258 LOG(ERROR) << "IO loop going away before the audio device has been stopped";
259 ShutDownOnIOThread();
262 // AudioDevice::AudioThreadCallback
264 AudioDevice::AudioThreadCallback::AudioThreadCallback(
265 const media::AudioParameters& audio_parameters,
266 base::SharedMemoryHandle memory,
267 int memory_length,
268 media::AudioRendererSink::RenderCallback* render_callback)
269 : AudioDeviceThread::Callback(audio_parameters, memory, memory_length),
270 render_callback_(render_callback) {
273 AudioDevice::AudioThreadCallback::~AudioThreadCallback() {
276 void AudioDevice::AudioThreadCallback::MapSharedMemory() {
277 shared_memory_.Map(media::TotalSharedMemorySizeInBytes(memory_length_));
280 // Called whenever we receive notifications about pending data.
281 void AudioDevice::AudioThreadCallback::Process(int pending_data) {
282 if (pending_data == media::AudioOutputController::kPauseMark) {
283 memset(shared_memory_.memory(), 0, memory_length_);
284 media::SetActualDataSizeInBytes(&shared_memory_, memory_length_, 0);
285 return;
288 // Convert the number of pending bytes in the render buffer
289 // into milliseconds.
290 int audio_delay_milliseconds = pending_data / bytes_per_ms_;
292 TRACE_EVENT0("audio", "AudioDevice::FireRenderCallback");
294 // Update the audio-delay measurement then ask client to render audio.
295 size_t num_frames = render_callback_->Render(audio_data_,
296 audio_parameters_.frames_per_buffer(), audio_delay_milliseconds);
298 // Interleave, scale, and clip to int16.
299 // TODO(crogers): avoid converting to integer here, and pass the data
300 // to the browser process as float, so we don't lose precision for
301 // audio hardware which has better than 16bit precision.
302 int16* data = reinterpret_cast<int16*>(shared_memory_.memory());
303 media::InterleaveFloatToInt16(audio_data_, data,
304 audio_parameters_.frames_per_buffer());
306 // Let the host know we are done.
307 media::SetActualDataSizeInBytes(&shared_memory_, memory_length_,
308 num_frames * audio_parameters_.channels() * sizeof(data[0]));