Commit 22d7f3b7 authored by kxing@chromium.org's avatar kxing@chromium.org

Piping for audio decoding.


Review URL: https://chromiumcodereview.appspot.com/10843031

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@149990 0039d316-1c4b-4281-b951-d872f2087c98
parent f6d95185
...@@ -3,6 +3,7 @@ include_rules = [ ...@@ -3,6 +3,7 @@ include_rules = [
"+jingle/glue", "+jingle/glue",
"+net", "+net",
"+remoting/codec",
"+remoting/protocol", "+remoting/protocol",
"+remoting/jingle_glue", "+remoting/jingle_glue",
] ]
// 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/client/audio_decode_scheduler.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "remoting/client/audio_player.h"
#include "remoting/codec/audio_decoder.h"
#include "remoting/proto/audio.pb.h"
namespace remoting {
AudioDecodeScheduler::AudioDecodeScheduler(
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> audio_decode_task_runner,
scoped_ptr<AudioPlayer> audio_player)
: main_task_runner_(main_task_runner),
audio_decode_task_runner_(audio_decode_task_runner),
audio_player_(audio_player.Pass()) {
}
AudioDecodeScheduler::~AudioDecodeScheduler() {
}
void AudioDecodeScheduler::Initialize(const protocol::SessionConfig& config) {
DCHECK(main_task_runner_->BelongsToCurrentThread());
decoder_.reset(AudioDecoder::CreateAudioDecoder(config).release());
}
void AudioDecodeScheduler::ProcessAudioPacket(scoped_ptr<AudioPacket> packet,
const base::Closure& done) {
DCHECK(main_task_runner_->BelongsToCurrentThread());
audio_decode_task_runner_->PostTask(FROM_HERE, base::Bind(
&AudioDecodeScheduler::DecodePacket, base::Unretained(this),
base::Passed(&packet), done));
}
void AudioDecodeScheduler::DecodePacket(scoped_ptr<AudioPacket> packet,
const base::Closure& done) {
DCHECK(audio_decode_task_runner_->BelongsToCurrentThread());
scoped_ptr<AudioPacket> decoded_packet = decoder_->Decode(packet.Pass());
main_task_runner_->PostTask(FROM_HERE, base::Bind(
&AudioDecodeScheduler::ProcessDecodedPacket, base::Unretained(this),
base::Passed(decoded_packet.Pass()), done));
}
void AudioDecodeScheduler::ProcessDecodedPacket(scoped_ptr<AudioPacket> packet,
const base::Closure& done) {
DCHECK(main_task_runner_->BelongsToCurrentThread());
audio_player_->ProcessAudioPacket(packet.Pass());
done.Run();
}
} // namespace remoting
// 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.
#ifndef REMOTING_CLIENT_AUDIO_DECODE_SCHEDULER_H_
#define REMOTING_CLIENT_AUDIO_DECODE_SCHEDULER_H_
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "remoting/protocol/audio_stub.h"
namespace base {
class SingleThreadTaskRunner;
} // namespace base
namespace remoting {
namespace protocol {
class SessionConfig;
} // namespace protocol
class AudioDecoder;
class AudioPacket;
class AudioPlayer;
class AudioDecodeScheduler : public protocol::AudioStub {
public:
AudioDecodeScheduler(
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> audio_decode_task_runner,
scoped_ptr<AudioPlayer> audio_player);
virtual ~AudioDecodeScheduler();
// Initializes decoder with the information from the protocol config.
void Initialize(const protocol::SessionConfig& config);
// AudioStub implementation.
virtual void ProcessAudioPacket(scoped_ptr<AudioPacket> packet,
const base::Closure& done) OVERRIDE;
private:
// Called on the audio decoder thread.
void DecodePacket(scoped_ptr<AudioPacket> packet, const base::Closure& done);
// Called on the main thread.
void ProcessDecodedPacket(scoped_ptr<AudioPacket> packet,
const base::Closure& done);
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> audio_decode_task_runner_;
scoped_ptr<AudioDecoder> decoder_;
scoped_ptr<AudioPlayer> audio_player_;
DISALLOW_COPY_AND_ASSIGN(AudioDecodeScheduler);
};
} // namespace remoting
#endif // REMOTING_CLIENT_AUDIO_DECODE_SCHEDULER_H_
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "remoting/client/chromoting_client.h" #include "remoting/client/chromoting_client.h"
#include "base/bind.h" #include "base/bind.h"
#include "remoting/client/audio_decode_scheduler.h"
#include "remoting/client/audio_player.h" #include "remoting/client/audio_player.h"
#include "remoting/client/client_context.h" #include "remoting/client/client_context.h"
#include "remoting/client/client_user_interface.h" #include "remoting/client/client_user_interface.h"
...@@ -31,20 +32,23 @@ ChromotingClient::QueuedVideoPacket::~QueuedVideoPacket() { ...@@ -31,20 +32,23 @@ ChromotingClient::QueuedVideoPacket::~QueuedVideoPacket() {
ChromotingClient::ChromotingClient( ChromotingClient::ChromotingClient(
const ClientConfig& config, const ClientConfig& config,
scoped_refptr<base::SingleThreadTaskRunner> task_runner, ClientContext* client_context,
protocol::ConnectionToHost* connection, protocol::ConnectionToHost* connection,
ClientUserInterface* user_interface, ClientUserInterface* user_interface,
RectangleUpdateDecoder* rectangle_decoder, RectangleUpdateDecoder* rectangle_decoder,
AudioPlayer* audio_player) scoped_ptr<AudioPlayer> audio_player)
: config_(config), : config_(config),
task_runner_(task_runner), task_runner_(client_context->main_task_runner()),
connection_(connection), connection_(connection),
user_interface_(user_interface), user_interface_(user_interface),
rectangle_decoder_(rectangle_decoder), rectangle_decoder_(rectangle_decoder),
audio_player_(audio_player),
packet_being_processed_(false), packet_being_processed_(false),
last_sequence_number_(0), last_sequence_number_(0),
weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
audio_decode_scheduler_.reset(new AudioDecodeScheduler(
client_context->main_task_runner(),
client_context->audio_decode_task_runner(),
audio_player.Pass()));
} }
ChromotingClient::~ChromotingClient() { ChromotingClient::~ChromotingClient() {
...@@ -65,7 +69,8 @@ void ChromotingClient::Start( ...@@ -65,7 +69,8 @@ void ChromotingClient::Start(
connection_->Connect(xmpp_proxy, config_.local_jid, config_.host_jid, connection_->Connect(xmpp_proxy, config_.local_jid, config_.host_jid,
config_.host_public_key, transport_factory.Pass(), config_.host_public_key, transport_factory.Pass(),
authenticator.Pass(), this, this, this, this, this); authenticator.Pass(), this, this, this, this,
audio_decode_scheduler_.get());
} }
void ChromotingClient::Stop(const base::Closure& shutdown_task) { void ChromotingClient::Stop(const base::Closure& shutdown_task) {
...@@ -141,12 +146,6 @@ int ChromotingClient::GetPendingVideoPackets() { ...@@ -141,12 +146,6 @@ int ChromotingClient::GetPendingVideoPackets() {
return received_packets_.size(); return received_packets_.size();
} }
void ChromotingClient::ProcessAudioPacket(scoped_ptr<AudioPacket> packet,
const base::Closure& done) {
audio_player_->ProcessAudioPacket(packet.Pass());
done.Run();
}
void ChromotingClient::DispatchPacket() { void ChromotingClient::DispatchPacket() {
DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(task_runner_->BelongsToCurrentThread());
CHECK(!packet_being_processed_); CHECK(!packet_being_processed_);
...@@ -217,6 +216,8 @@ void ChromotingClient::Initialize() { ...@@ -217,6 +216,8 @@ void ChromotingClient::Initialize() {
// Initialize the decoder. // Initialize the decoder.
rectangle_decoder_->Initialize(connection_->config()); rectangle_decoder_->Initialize(connection_->config());
if (connection_->config().is_audio_enabled())
audio_decode_scheduler_->Initialize(connection_->config());
} }
} // namespace remoting } // namespace remoting
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include "base/time.h" #include "base/time.h"
#include "remoting/client/client_config.h" #include "remoting/client/client_config.h"
#include "remoting/client/chromoting_stats.h" #include "remoting/client/chromoting_stats.h"
#include "remoting/protocol/audio_stub.h"
#include "remoting/protocol/client_stub.h" #include "remoting/protocol/client_stub.h"
#include "remoting/protocol/clipboard_stub.h" #include "remoting/protocol/clipboard_stub.h"
#include "remoting/protocol/connection_to_host.h" #include "remoting/protocol/connection_to_host.h"
...@@ -33,23 +32,24 @@ namespace protocol { ...@@ -33,23 +32,24 @@ namespace protocol {
class TransportFactory; class TransportFactory;
} // namespace protocol } // namespace protocol
class AudioDecodeScheduler;
class AudioPlayer; class AudioPlayer;
class ClientContext;
class ClientUserInterface; class ClientUserInterface;
class RectangleUpdateDecoder; class RectangleUpdateDecoder;
// TODO(sergeyu): Move VideoStub implementation to RectangleUpdateDecoder. // TODO(sergeyu): Move VideoStub implementation to RectangleUpdateDecoder.
class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback, class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback,
public protocol::ClientStub, public protocol::ClientStub,
public protocol::VideoStub, public protocol::VideoStub {
public protocol::AudioStub {
public: public:
// Objects passed in are not owned by this class. // Objects passed in are not owned by this class.
ChromotingClient(const ClientConfig& config, ChromotingClient(const ClientConfig& config,
scoped_refptr<base::SingleThreadTaskRunner> task_runner, ClientContext* client_context,
protocol::ConnectionToHost* connection, protocol::ConnectionToHost* connection,
ClientUserInterface* user_interface, ClientUserInterface* user_interface,
RectangleUpdateDecoder* rectangle_decoder, RectangleUpdateDecoder* rectangle_decoder,
AudioPlayer* audio_player); scoped_ptr<AudioPlayer> audio_player);
virtual ~ChromotingClient(); virtual ~ChromotingClient();
...@@ -80,10 +80,6 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback, ...@@ -80,10 +80,6 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback,
const base::Closure& done) OVERRIDE; const base::Closure& done) OVERRIDE;
virtual int GetPendingVideoPackets() OVERRIDE; virtual int GetPendingVideoPackets() OVERRIDE;
// AudioStub implementation.
virtual void ProcessAudioPacket(scoped_ptr<AudioPacket> packet,
const base::Closure& done) OVERRIDE;
private: private:
struct QueuedVideoPacket { struct QueuedVideoPacket {
QueuedVideoPacket(scoped_ptr<VideoPacket> packet, QueuedVideoPacket(scoped_ptr<VideoPacket> packet,
...@@ -112,8 +108,10 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback, ...@@ -112,8 +108,10 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback,
scoped_refptr<base::SingleThreadTaskRunner> task_runner_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
protocol::ConnectionToHost* connection_; protocol::ConnectionToHost* connection_;
ClientUserInterface* user_interface_; ClientUserInterface* user_interface_;
// TODO(kxing): Make ChromotingClient own RectangleUpdateDecoder.
RectangleUpdateDecoder* rectangle_decoder_; RectangleUpdateDecoder* rectangle_decoder_;
AudioPlayer* audio_player_;
scoped_ptr<AudioDecodeScheduler> audio_decode_scheduler_;
// If non-NULL, this is called when the client is done. // If non-NULL, this is called when the client is done.
base::Closure client_done_; base::Closure client_done_;
......
...@@ -8,7 +8,8 @@ namespace remoting { ...@@ -8,7 +8,8 @@ namespace remoting {
ClientContext::ClientContext(base::SingleThreadTaskRunner* main_task_runner) ClientContext::ClientContext(base::SingleThreadTaskRunner* main_task_runner)
: main_task_runner_(main_task_runner), : main_task_runner_(main_task_runner),
decode_thread_("ChromotingClientDecodeThread") { decode_thread_("ChromotingClientDecodeThread"),
audio_decode_thread_("ChromotingClientAudioDecodeThread") {
} }
ClientContext::~ClientContext() { ClientContext::~ClientContext() {
...@@ -17,11 +18,13 @@ ClientContext::~ClientContext() { ...@@ -17,11 +18,13 @@ ClientContext::~ClientContext() {
void ClientContext::Start() { void ClientContext::Start() {
// Start all the threads. // Start all the threads.
decode_thread_.Start(); decode_thread_.Start();
audio_decode_thread_.Start();
} }
void ClientContext::Stop() { void ClientContext::Stop() {
// Stop all the threads. // Stop all the threads.
decode_thread_.Stop(); decode_thread_.Stop();
audio_decode_thread_.Stop();
} }
base::SingleThreadTaskRunner* ClientContext::main_task_runner() { base::SingleThreadTaskRunner* ClientContext::main_task_runner() {
...@@ -32,4 +35,8 @@ base::SingleThreadTaskRunner* ClientContext::decode_task_runner() { ...@@ -32,4 +35,8 @@ base::SingleThreadTaskRunner* ClientContext::decode_task_runner() {
return decode_thread_.message_loop_proxy(); return decode_thread_.message_loop_proxy();
} }
base::SingleThreadTaskRunner* ClientContext::audio_decode_task_runner() {
return audio_decode_thread_.message_loop_proxy();
}
} // namespace remoting } // namespace remoting
...@@ -29,13 +29,17 @@ class ClientContext { ...@@ -29,13 +29,17 @@ class ClientContext {
base::SingleThreadTaskRunner* main_task_runner(); base::SingleThreadTaskRunner* main_task_runner();
base::SingleThreadTaskRunner* decode_task_runner(); base::SingleThreadTaskRunner* decode_task_runner();
base::SingleThreadTaskRunner* audio_decode_task_runner();
private: private:
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
// A thread that handles all decode operations. // A thread that handles all video decode operations.
base::Thread decode_thread_; base::Thread decode_thread_;
// A thread that handles all audio decode operations.
base::Thread audio_decode_thread_;
DISALLOW_COPY_AND_ASSIGN(ClientContext); DISALLOW_COPY_AND_ASSIGN(ClientContext);
}; };
......
...@@ -470,11 +470,11 @@ void ChromotingInstance::Connect(const ClientConfig& config) { ...@@ -470,11 +470,11 @@ void ChromotingInstance::Connect(const ClientConfig& config) {
jingle_glue::JingleThreadWrapper::EnsureForCurrentThread(); jingle_glue::JingleThreadWrapper::EnsureForCurrentThread();
host_connection_.reset(new protocol::ConnectionToHost(true)); host_connection_.reset(new protocol::ConnectionToHost(true));
audio_player_.reset(new PepperAudioPlayer(this)); scoped_ptr<AudioPlayer> audio_player(new PepperAudioPlayer(this));
client_.reset(new ChromotingClient(config, context_.main_task_runner(), client_.reset(new ChromotingClient(config, &context_,
host_connection_.get(), this, host_connection_.get(), this,
rectangle_decoder_.get(), rectangle_decoder_.get(),
audio_player_.get())); audio_player.Pass()));
// Construct the input pipeline // Construct the input pipeline
mouse_input_filter_.reset( mouse_input_filter_.reset(
...@@ -536,7 +536,6 @@ void ChromotingInstance::Disconnect() { ...@@ -536,7 +536,6 @@ void ChromotingInstance::Disconnect() {
input_handler_.reset(); input_handler_.reset();
input_tracker_.reset(); input_tracker_.reset();
mouse_input_filter_.reset(); mouse_input_filter_.reset();
audio_player_.reset();
host_connection_.reset(); host_connection_.reset();
} }
......
...@@ -199,7 +199,6 @@ class ChromotingInstance : ...@@ -199,7 +199,6 @@ class ChromotingInstance :
#endif #endif
KeyEventMapper key_mapper_; KeyEventMapper key_mapper_;
scoped_ptr<PepperInputHandler> input_handler_; scoped_ptr<PepperInputHandler> input_handler_;
scoped_ptr<PepperAudioPlayer> audio_player_;
scoped_ptr<ChromotingClient> client_; scoped_ptr<ChromotingClient> client_;
// XmppProxy is a refcounted interface used to perform thread-switching and // XmppProxy is a refcounted interface used to perform thread-switching and
......
include_rules = [ include_rules = [
"+google/protobuf", "+google/protobuf",
"+remoting/protocol",
] ]
// 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/codec/audio_decoder.h"
#include "base/logging.h"
#include "remoting/codec/audio_decoder_verbatim.h"
#include "remoting/protocol/session_config.h"
namespace remoting {
scoped_ptr<AudioDecoder> AudioDecoder::CreateAudioDecoder(
const protocol::SessionConfig& config) {
const protocol::ChannelConfig& audio_config = config.audio_config();
if (audio_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) {
return scoped_ptr<AudioDecoder>(new AudioDecoderVerbatim());
}
NOTIMPLEMENTED();
return scoped_ptr<AudioDecoder>(NULL);
}
} // namespace remoting
// 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.
#ifndef REMOTING_CODEC_AUDIO_DECODER_H_
#define REMOTING_CODEC_AUDIO_DECODER_H_
#include "base/memory/scoped_ptr.h"
namespace remoting {
namespace protocol {
class SessionConfig;
} // namespace protocol
class AudioPacket;
class AudioDecoder {
public:
static scoped_ptr<AudioDecoder> CreateAudioDecoder(
const protocol::SessionConfig& config);
virtual ~AudioDecoder() {}
virtual scoped_ptr<AudioPacket> Decode(scoped_ptr<AudioPacket> packet) = 0;
};
} // namespace remoting
#endif // REMOTING_CODEC_AUDIO_DECODER_H_
// 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/codec/audio_decoder_verbatim.h"
#include "base/logging.h"
#include "remoting/proto/audio.pb.h"
namespace remoting {
AudioDecoderVerbatim::AudioDecoderVerbatim() {
}
AudioDecoderVerbatim::~AudioDecoderVerbatim() {
}
scoped_ptr<AudioPacket> AudioDecoderVerbatim::Decode(
scoped_ptr<AudioPacket> packet) {
DCHECK_EQ(AudioPacket::ENCODING_RAW, packet->encoding());
return packet.Pass();
}
} // namespace remoting
// 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.
#ifndef REMOTING_CODEC_AUDIO_DECODER_VERBATIM_H_
#define REMOTING_CODEC_AUDIO_DECODER_VERBATIM_H_
#include "remoting/codec/audio_decoder.h"
#include "base/memory/scoped_ptr.h"
namespace remoting {
class AudioPacket;
// The decoder for raw audio streams.
class AudioDecoderVerbatim : public AudioDecoder {
public:
AudioDecoderVerbatim();
virtual ~AudioDecoderVerbatim();
virtual scoped_ptr<AudioPacket> Decode(
scoped_ptr<AudioPacket> packet) OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(AudioDecoderVerbatim);
};
} // namespace remoting
#endif // REMOTING_CODEC_AUDIO_DECODER_VERBATIM_H_
...@@ -1194,6 +1194,10 @@ ...@@ -1194,6 +1194,10 @@
'base/util.h', 'base/util.h',
# TODO(kxing): Seperate the audio and video codec files into a separate # TODO(kxing): Seperate the audio and video codec files into a separate
# target. # target.
'codec/audio_decoder.cc',
'codec/audio_decoder.h',
'codec/audio_decoder_verbatim.cc',
'codec/audio_decoder_verbatim.h',
'codec/audio_encoder.h', 'codec/audio_encoder.h',
'codec/audio_encoder_verbatim.cc', 'codec/audio_encoder_verbatim.cc',
'codec/audio_encoder_verbatim.h', 'codec/audio_encoder_verbatim.h',
...@@ -1401,6 +1405,8 @@ ...@@ -1401,6 +1405,8 @@
'remoting_protocol', 'remoting_protocol',
], ],
'sources': [ 'sources': [
'client/audio_decode_scheduler.cc',
'client/audio_decode_scheduler.h',
'client/audio_player.h', 'client/audio_player.h',
'client/chromoting_client.cc', 'client/chromoting_client.cc',
'client/chromoting_client.h', 'client/chromoting_client.h',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment