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