| Index: content/browser/renderer_host/media/audio_output_impl.cc
|
| diff --git a/content/browser/renderer_host/media/audio_output_impl.cc b/content/browser/renderer_host/media/audio_output_impl.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..6cbaa808e57781ccde103b82be43fb76cb58a54d
|
| --- /dev/null
|
| +++ b/content/browser/renderer_host/media/audio_output_impl.cc
|
| @@ -0,0 +1,127 @@
|
| +// Copyright 2016 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/browser/renderer_host/media/audio_output_impl.h"
|
| +
|
| +#include <memory>
|
| +#include <utility>
|
| +
|
| +#include "base/memory/shared_memory.h"
|
| +#include "base/sync_socket.h"
|
| +#include "mojo/public/cpp/system/platform_handle.h"
|
| +
|
| +namespace content {
|
| +
|
| +AudioOutputImpl::AudioOutputImpl(
|
| + mojom::AudioOutputRequest request,
|
| + CreateDelegateCallback create_delegate_callback,
|
| + FinishedCallback finished_callback)
|
| + : binding_(this, std::move(request)),
|
| + create_delegate_callback_(std::move(create_delegate_callback)),
|
| + finished_callback_(std::move(finished_callback)) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + DCHECK(finished_callback_);
|
| + // |this| owns |binding_|, so unretained is safe.
|
| + binding_.set_connection_error_handler(
|
| + base::Bind(&AudioOutputImpl::OnError, base::Unretained(this)));
|
| +}
|
| +
|
| +AudioOutputImpl::~AudioOutputImpl() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| +}
|
| +
|
| +void AudioOutputImpl::Start(const media::AudioParameters& params,
|
| + const StartCallback& callback) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + if (delegate_) {
|
| + // Already started.
|
| + OnError();
|
| + return;
|
| + }
|
| + // Buffer up all calls from the renderer until we are done starting.
|
| + binding_.PauseIncomingMethodCallProcessing();
|
| + delegate_ = std::move(create_delegate_callback_).Run(this, params);
|
| + DCHECK(delegate_);
|
| + start_callback_ = callback;
|
| +}
|
| +
|
| +void AudioOutputImpl::Play() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + if (!delegate_) {
|
| + // Not started yet.
|
| + OnError();
|
| + return;
|
| + }
|
| + delegate_->OnPlayStream();
|
| +}
|
| +
|
| +void AudioOutputImpl::Pause() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + if (!delegate_) {
|
| + // Not started yet.
|
| + OnError();
|
| + return;
|
| + }
|
| + delegate_->OnPauseStream();
|
| +}
|
| +
|
| +void AudioOutputImpl::SetVolume(double volume) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + if (!delegate_ || volume < 0 || volume > 1) {
|
| + // Not started yet.
|
| + OnError();
|
| + return;
|
| + }
|
| + delegate_->OnSetVolume(volume);
|
| +}
|
| +
|
| +void AudioOutputImpl::OnStreamCreated(
|
| + int stream_id,
|
| + base::SharedMemory* shared_memory,
|
| + base::CancelableSyncSocket* foreign_socket) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + if (!binding_.is_bound()) {
|
| + // Already closed, make sure we are properly cleaned up.
|
| + OnError();
|
| + return;
|
| + }
|
| + DCHECK(start_callback_);
|
| + DCHECK(shared_memory);
|
| + DCHECK(foreign_socket);
|
| +
|
| + base::SharedMemoryHandle foreign_memory_handle =
|
| + base::SharedMemory::DuplicateHandle(shared_memory->handle());
|
| + DCHECK(base::SharedMemory::IsHandleValid(foreign_memory_handle));
|
| +
|
| + mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle(
|
| + foreign_memory_handle, shared_memory->requested_size(), false);
|
| + mojo::ScopedHandle socket_handle =
|
| + mojo::WrapPlatformFile(foreign_socket->handle());
|
| +
|
| + DCHECK(buffer_handle.is_valid());
|
| + DCHECK(socket_handle.is_valid());
|
| +
|
| + start_callback_.Run(std::move(buffer_handle), std::move(socket_handle));
|
| + start_callback_ = StartCallback();
|
| + binding_.ResumeIncomingMethodCallProcessing();
|
| +}
|
| +
|
| +void AudioOutputImpl::OnStreamError(int stream_id) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + OnError();
|
| +}
|
| +
|
| +void AudioOutputImpl::OnError() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + if (!finished_callback_) {
|
| + // There is already a destruction in progress.
|
| + return;
|
| + }
|
| + // Notify the renderer.
|
| + binding_.Close();
|
| + // The rest of the cleanup is done when |handler_| destructs |this|.
|
| + std::move(finished_callback_).Run(this);
|
| +}
|
| +
|
| +} // namespace content
|
|
|