Home | History | Annotate | Download | only in client
      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/client/audio_decode_scheduler.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/location.h"
      9 #include "base/single_thread_task_runner.h"
     10 #include "remoting/client/audio_player.h"
     11 #include "remoting/codec/audio_decoder.h"
     12 #include "remoting/proto/audio.pb.h"
     13 
     14 namespace remoting {
     15 
     16 class AudioDecodeScheduler::Core : public base::RefCountedThreadSafe<Core> {
     17  public:
     18   Core(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
     19        scoped_refptr<base::SingleThreadTaskRunner> audio_decode_task_runner,
     20        scoped_ptr<AudioPlayer> audio_player);
     21 
     22   void Initialize(const protocol::SessionConfig& config);
     23   void ProcessAudioPacket(scoped_ptr<AudioPacket> packet,
     24                           const base::Closure& done);
     25 
     26   // Called by AudioDecodeScheduler when it is destroyed.
     27   void Detach();
     28 
     29  private:
     30   friend class base::RefCountedThreadSafe<Core>;
     31 
     32   virtual ~Core();
     33 
     34   // Called on the audio decoder thread.
     35   void DecodePacket(scoped_ptr<AudioPacket> packet, const base::Closure& done);
     36 
     37   // Called on the main thread.
     38   void ProcessDecodedPacket(scoped_ptr<AudioPacket> packet,
     39                             const base::Closure& done);
     40 
     41   scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
     42   scoped_refptr<base::SingleThreadTaskRunner> audio_decode_task_runner_;
     43   scoped_ptr<AudioDecoder> decoder_;
     44   scoped_ptr<AudioPlayer> audio_player_;
     45 
     46   DISALLOW_COPY_AND_ASSIGN(Core);
     47 };
     48 
     49 AudioDecodeScheduler::Core::Core(
     50     scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
     51     scoped_refptr<base::SingleThreadTaskRunner> audio_decode_task_runner,
     52     scoped_ptr<AudioPlayer> audio_player)
     53     : main_task_runner_(main_task_runner),
     54       audio_decode_task_runner_(audio_decode_task_runner),
     55       audio_player_(audio_player.Pass()) {
     56 }
     57 
     58 AudioDecodeScheduler::Core::~Core() {
     59 }
     60 
     61 void AudioDecodeScheduler::Core::Initialize(
     62     const protocol::SessionConfig& config) {
     63   DCHECK(main_task_runner_->BelongsToCurrentThread());
     64   decoder_.reset(AudioDecoder::CreateAudioDecoder(config).release());
     65 }
     66 
     67 void AudioDecodeScheduler::Core::ProcessAudioPacket(
     68     scoped_ptr<AudioPacket> packet,
     69     const base::Closure& done) {
     70   DCHECK(main_task_runner_->BelongsToCurrentThread());
     71   audio_decode_task_runner_->PostTask(FROM_HERE, base::Bind(
     72       &AudioDecodeScheduler::Core::DecodePacket, this,
     73       base::Passed(&packet), done));
     74 }
     75 
     76 void AudioDecodeScheduler::Core::Detach() {
     77   DCHECK(main_task_runner_->BelongsToCurrentThread());
     78   audio_player_.reset();
     79 }
     80 
     81 void AudioDecodeScheduler::Core::DecodePacket(
     82     scoped_ptr<AudioPacket> packet,
     83     const base::Closure& done) {
     84   DCHECK(audio_decode_task_runner_->BelongsToCurrentThread());
     85   scoped_ptr<AudioPacket> decoded_packet = decoder_->Decode(packet.Pass());
     86 
     87   main_task_runner_->PostTask(FROM_HERE, base::Bind(
     88       &AudioDecodeScheduler::Core::ProcessDecodedPacket, this,
     89       base::Passed(&decoded_packet), done));
     90 }
     91 
     92 void AudioDecodeScheduler::Core::ProcessDecodedPacket(
     93     scoped_ptr<AudioPacket> packet,
     94     const base::Closure& done) {
     95   DCHECK(main_task_runner_->BelongsToCurrentThread());
     96   // Only process |packet| if it is non-NULL.
     97   if (packet.get() && audio_player_.get())
     98     audio_player_->ProcessAudioPacket(packet.Pass());
     99   done.Run();
    100 }
    101 
    102 AudioDecodeScheduler::AudioDecodeScheduler(
    103     scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
    104     scoped_refptr<base::SingleThreadTaskRunner> audio_decode_task_runner,
    105     scoped_ptr<AudioPlayer> audio_player)
    106     : core_(new Core(main_task_runner, audio_decode_task_runner,
    107                      audio_player.Pass())) {
    108 }
    109 
    110 AudioDecodeScheduler::~AudioDecodeScheduler() {
    111   core_->Detach();
    112 }
    113 
    114 void AudioDecodeScheduler::Initialize(const protocol::SessionConfig& config) {
    115   core_->Initialize(config);
    116 }
    117 
    118 void AudioDecodeScheduler::ProcessAudioPacket(scoped_ptr<AudioPacket> packet,
    119                                               const base::Closure& done) {
    120   core_->ProcessAudioPacket(packet.Pass(), done);
    121 }
    122 
    123 }  // namespace remoting
    124