| // 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 { |
| |
| class AudioDecodeScheduler::Core : public base::RefCountedThreadSafe<Core> { |
| public: |
| Core(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
| scoped_refptr<base::SingleThreadTaskRunner> audio_decode_task_runner, |
| scoped_ptr<AudioPlayer> audio_player); |
| |
| void Initialize(const protocol::SessionConfig& config); |
| void ProcessAudioPacket(scoped_ptr<AudioPacket> packet, |
| const base::Closure& done); |
| |
| // Called by AudioDecodeScheduler when it is destroyed. |
| void Detach(); |
| |
| private: |
| friend class base::RefCountedThreadSafe<Core>; |
| |
| virtual ~Core(); |
| |
| // 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(Core); |
| }; |
| |
| AudioDecodeScheduler::Core::Core( |
| 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::Core::~Core() { |
| } |
| |
| void AudioDecodeScheduler::Core::Initialize( |
| const protocol::SessionConfig& config) { |
| DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| decoder_.reset(AudioDecoder::CreateAudioDecoder(config).release()); |
| } |
| |
| void AudioDecodeScheduler::Core::ProcessAudioPacket( |
| scoped_ptr<AudioPacket> packet, |
| const base::Closure& done) { |
| DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| audio_decode_task_runner_->PostTask(FROM_HERE, base::Bind( |
| &AudioDecodeScheduler::Core::DecodePacket, this, |
| base::Passed(&packet), done)); |
| } |
| |
| void AudioDecodeScheduler::Core::Detach() { |
| DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| audio_player_.reset(); |
| } |
| |
| void AudioDecodeScheduler::Core::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::Core::ProcessDecodedPacket, this, |
| base::Passed(&decoded_packet), done)); |
| } |
| |
| void AudioDecodeScheduler::Core::ProcessDecodedPacket( |
| scoped_ptr<AudioPacket> packet, |
| const base::Closure& done) { |
| DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| // Only process |packet| if it is non-NULL. |
| if (packet.get() && audio_player_.get()) |
| audio_player_->ProcessAudioPacket(packet.Pass()); |
| done.Run(); |
| } |
| |
| AudioDecodeScheduler::AudioDecodeScheduler( |
| scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
| scoped_refptr<base::SingleThreadTaskRunner> audio_decode_task_runner, |
| scoped_ptr<AudioPlayer> audio_player) |
| : core_(new Core(main_task_runner, audio_decode_task_runner, |
| audio_player.Pass())) { |
| } |
| |
| AudioDecodeScheduler::~AudioDecodeScheduler() { |
| core_->Detach(); |
| } |
| |
| void AudioDecodeScheduler::Initialize(const protocol::SessionConfig& config) { |
| core_->Initialize(config); |
| } |
| |
| void AudioDecodeScheduler::ProcessAudioPacket(scoped_ptr<AudioPacket> packet, |
| const base::Closure& done) { |
| core_->ProcessAudioPacket(packet.Pass(), done); |
| } |
| |
| } // namespace remoting |