blob: b8bf7ef07d8e74339214864e3d0e509db0b9e956 [file] [log] [blame]
// 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/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<base::SingleThreadTaskRunner> audio_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
scoped_ptr<AudioCapturer> audio_capturer,
scoped_ptr<AudioEncoder> audio_encoder,
protocol::AudioStub* audio_stub)
: audio_task_runner_(audio_task_runner),
network_task_runner_(network_task_runner),
audio_capturer_(audio_capturer.Pass()),
audio_encoder_(audio_encoder.Pass()),
audio_stub_(audio_stub),
network_stopped_(false),
enabled_(true) {
DCHECK(network_task_runner_->BelongsToCurrentThread());
DCHECK(audio_capturer_);
DCHECK(audio_encoder_);
DCHECK(audio_stub_);
}
void AudioScheduler::Start() {
DCHECK(network_task_runner_->BelongsToCurrentThread());
audio_task_runner_->PostTask(
FROM_HERE, base::Bind(&AudioScheduler::StartOnAudioThread, this));
}
void AudioScheduler::Stop() {
DCHECK(network_task_runner_->BelongsToCurrentThread());
DCHECK(audio_stub_);
// Clear |audio_stub_| to prevent audio packets being delivered to the client.
audio_stub_ = NULL;
audio_task_runner_->PostTask(
FROM_HERE,
base::Bind(&AudioScheduler::StopOnAudioThread, this));
}
AudioScheduler::~AudioScheduler() {
}
void AudioScheduler::StartOnAudioThread() {
DCHECK(audio_task_runner_->BelongsToCurrentThread());
// TODO(kxing): Do something with the return value.
audio_capturer_->Start(
base::Bind(&AudioScheduler::EncodeAudioPacket, this));
}
void AudioScheduler::StopOnAudioThread() {
DCHECK(audio_task_runner_->BelongsToCurrentThread());
audio_capturer_->Stop();
}
void AudioScheduler::Pause(bool pause) {
if (!audio_task_runner_->BelongsToCurrentThread()) {
audio_task_runner_->PostTask(
FROM_HERE, base::Bind(&AudioScheduler::Pause, this, pause));
return;
}
enabled_ = !pause;
}
void AudioScheduler::EncodeAudioPacket(scoped_ptr<AudioPacket> packet) {
DCHECK(audio_task_runner_->BelongsToCurrentThread());
DCHECK(packet.get());
if (!enabled_)
return;
scoped_ptr<AudioPacket> 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::SendAudioPacket,
this, base::Passed(&encoded_packet)));
}
}
void AudioScheduler::SendAudioPacket(scoped_ptr<AudioPacket> packet) {
DCHECK(network_task_runner_->BelongsToCurrentThread());
DCHECK(packet.get());
if (!audio_stub_)
return;
audio_stub_->ProcessAudioPacket(packet.Pass(), base::Closure());
}
} // namespace remoting