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 16 namespace remoting { 17 18 AudioScheduler::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 37 void AudioScheduler::Start() { 38 DCHECK(network_task_runner_->BelongsToCurrentThread()); 39 40 audio_task_runner_->PostTask( 41 FROM_HERE, base::Bind(&AudioScheduler::StartOnAudioThread, this)); 42 } 43 44 void 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 56 AudioScheduler::~AudioScheduler() { 57 } 58 59 void 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 67 void AudioScheduler::StopOnAudioThread() { 68 DCHECK(audio_task_runner_->BelongsToCurrentThread()); 69 audio_capturer_->Stop(); 70 } 71 72 void 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 82 void 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 100 void 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