summaryrefslogtreecommitdiffstats
path: root/remoting/client/audio_decode_scheduler.cc
blob: ac006dda50d4b566c5f900874a0f09acff863b65 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// 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/macros.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