// 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 "remoting/host/audio_scheduler.h" #include "base/bind.h" #include "base/callback.h" #include "base/location.h" #include "base/logging.h" #include "base/single_thread_task_runner.h" #include "remoting/codec/audio_encoder.h" #include "remoting/host/audio_capturer.h" #include "remoting/proto/audio.pb.h" #include "remoting/protocol/audio_stub.h" namespace remoting { AudioScheduler::AudioScheduler( scoped_refptr audio_task_runner, scoped_refptr network_task_runner, AudioCapturer* audio_capturer, scoped_ptr audio_encoder, protocol::AudioStub* audio_stub) : audio_task_runner_(audio_task_runner), network_task_runner_(network_task_runner), audio_capturer_(audio_capturer), audio_encoder_(audio_encoder.Pass()), audio_stub_(audio_stub), network_stopped_(false) { DCHECK(audio_task_runner_); DCHECK(network_task_runner_); DCHECK(audio_capturer_); DCHECK(audio_stub_); audio_task_runner_->PostTask( FROM_HERE, base::Bind(&AudioScheduler::DoStart, this)); } void AudioScheduler::Stop(const base::Closure& done_task) { DCHECK(!done_task.is_null()); if (!audio_task_runner_->BelongsToCurrentThread()) { audio_task_runner_->PostTask(FROM_HERE, base::Bind( &AudioScheduler::Stop, this, done_task)); return; } audio_capturer_->Stop(); network_task_runner_->PostTask(FROM_HERE, base::Bind( &AudioScheduler::DoStopOnNetworkThread, this, done_task)); } void AudioScheduler::OnClientDisconnected() { DCHECK(network_task_runner_->BelongsToCurrentThread()); DCHECK(audio_stub_); audio_stub_ = NULL; } AudioScheduler::~AudioScheduler() { } void AudioScheduler::NotifyAudioPacketCaptured( scoped_ptr packet) { DCHECK(packet.get()); scoped_ptr encoded_packet = audio_encoder_->Encode(packet.Pass()); // The audio encoder returns a NULL audio packet if there's no audio to send. if (encoded_packet.get()) { network_task_runner_->PostTask( FROM_HERE, base::Bind(&AudioScheduler::DoSendAudioPacket, this, base::Passed(encoded_packet.Pass()))); } } void AudioScheduler::DoStart() { DCHECK(audio_task_runner_->BelongsToCurrentThread()); // TODO(kxing): Do something with the return value. audio_capturer_->Start( base::Bind(&AudioScheduler::NotifyAudioPacketCaptured, this)); } void AudioScheduler::DoSendAudioPacket(scoped_ptr packet) { DCHECK(network_task_runner_->BelongsToCurrentThread()); DCHECK(packet.get()); if (network_stopped_ || !audio_stub_) return; audio_stub_->ProcessAudioPacket( packet.Pass(), base::Bind(&AudioScheduler::OnCaptureCallbackNotified, this)); } void AudioScheduler::OnCaptureCallbackNotified() { } void AudioScheduler::DoStopOnNetworkThread(const base::Closure& done_task) { DCHECK(network_task_runner_->BelongsToCurrentThread()); network_stopped_ = true; done_task.Run(); } } // namespace remoting