• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Core(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,scoped_refptr<base::SingleThreadTaskRunner> audio_decode_task_runner,scoped_ptr<AudioPlayer> audio_player)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 
~Core()58 AudioDecodeScheduler::Core::~Core() {
59 }
60 
Initialize(const protocol::SessionConfig & config)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 
ProcessAudioPacket(scoped_ptr<AudioPacket> packet,const base::Closure & done)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 
Detach()76 void AudioDecodeScheduler::Core::Detach() {
77   DCHECK(main_task_runner_->BelongsToCurrentThread());
78   audio_player_.reset();
79 }
80 
DecodePacket(scoped_ptr<AudioPacket> packet,const base::Closure & done)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 
ProcessDecodedPacket(scoped_ptr<AudioPacket> packet,const base::Closure & done)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 
AudioDecodeScheduler(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,scoped_refptr<base::SingleThreadTaskRunner> audio_decode_task_runner,scoped_ptr<AudioPlayer> audio_player)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 
~AudioDecodeScheduler()110 AudioDecodeScheduler::~AudioDecodeScheduler() {
111   core_->Detach();
112 }
113 
Initialize(const protocol::SessionConfig & config)114 void AudioDecodeScheduler::Initialize(const protocol::SessionConfig& config) {
115   core_->Initialize(config);
116 }
117 
ProcessAudioPacket(scoped_ptr<AudioPacket> packet,const base::Closure & done)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