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. 4 5#include "remoting/host/audio_scheduler.h" 6 7#include "base/bind.h" 8#include "base/location.h" 9#include "base/logging.h" 10#include "base/single_thread_task_runner.h" 11#include "remoting/codec/audio_encoder.h" 12#include "remoting/host/audio_capturer.h" 13#include "remoting/proto/audio.pb.h" 14#include "remoting/protocol/audio_stub.h" 15 16namespace remoting { 17 18AudioScheduler::AudioScheduler( 19 scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner, 20 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, 21 scoped_ptr<AudioCapturer> audio_capturer, 22 scoped_ptr<AudioEncoder> audio_encoder, 23 protocol::AudioStub* audio_stub) 24 : audio_task_runner_(audio_task_runner), 25 network_task_runner_(network_task_runner), 26 audio_capturer_(audio_capturer.Pass()), 27 audio_encoder_(audio_encoder.Pass()), 28 audio_stub_(audio_stub), 29 network_stopped_(false), 30 enabled_(true) { 31 DCHECK(network_task_runner_->BelongsToCurrentThread()); 32 DCHECK(audio_capturer_); 33 DCHECK(audio_encoder_); 34 DCHECK(audio_stub_); 35} 36 37void AudioScheduler::Start() { 38 DCHECK(network_task_runner_->BelongsToCurrentThread()); 39 40 audio_task_runner_->PostTask( 41 FROM_HERE, base::Bind(&AudioScheduler::StartOnAudioThread, this)); 42} 43 44void AudioScheduler::Stop() { 45 DCHECK(network_task_runner_->BelongsToCurrentThread()); 46 DCHECK(audio_stub_); 47 48 // Clear |audio_stub_| to prevent audio packets being delivered to the client. 49 audio_stub_ = NULL; 50 51 audio_task_runner_->PostTask( 52 FROM_HERE, 53 base::Bind(&AudioScheduler::StopOnAudioThread, this)); 54} 55 56AudioScheduler::~AudioScheduler() { 57} 58 59void AudioScheduler::StartOnAudioThread() { 60 DCHECK(audio_task_runner_->BelongsToCurrentThread()); 61 62 // TODO(kxing): Do something with the return value. 63 audio_capturer_->Start( 64 base::Bind(&AudioScheduler::EncodeAudioPacket, this)); 65} 66 67void AudioScheduler::StopOnAudioThread() { 68 DCHECK(audio_task_runner_->BelongsToCurrentThread()); 69 audio_capturer_->Stop(); 70} 71 72void AudioScheduler::Pause(bool pause) { 73 if (!audio_task_runner_->BelongsToCurrentThread()) { 74 audio_task_runner_->PostTask( 75 FROM_HERE, base::Bind(&AudioScheduler::Pause, this, pause)); 76 return; 77 } 78 79 enabled_ = !pause; 80} 81 82void AudioScheduler::EncodeAudioPacket(scoped_ptr<AudioPacket> packet) { 83 DCHECK(audio_task_runner_->BelongsToCurrentThread()); 84 DCHECK(packet.get()); 85 86 if (!enabled_) 87 return; 88 89 scoped_ptr<AudioPacket> encoded_packet = 90 audio_encoder_->Encode(packet.Pass()); 91 92 // The audio encoder returns a NULL audio packet if there's no audio to send. 93 if (encoded_packet.get()) { 94 network_task_runner_->PostTask( 95 FROM_HERE, base::Bind(&AudioScheduler::SendAudioPacket, 96 this, base::Passed(&encoded_packet))); 97 } 98} 99 100void AudioScheduler::SendAudioPacket(scoped_ptr<AudioPacket> packet) { 101 DCHECK(network_task_runner_->BelongsToCurrentThread()); 102 DCHECK(packet.get()); 103 104 if (!audio_stub_) 105 return; 106 107 audio_stub_->ProcessAudioPacket(packet.Pass(), base::Closure()); 108} 109 110} // namespace remoting 111