summaryrefslogtreecommitdiffstats
path: root/remoting/host/audio_scheduler.cc
blob: b8bf7ef07d8e74339214864e3d0e509db0b9e956 (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
// 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/host/audio_scheduler.h"

#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
#include "remoting/codec/audio_encoder.h"
#include "remoting/host/audio_capturer.h"
#include "remoting/proto/audio.pb.h"
#include "remoting/protocol/audio_stub.h"

namespace remoting {

AudioScheduler::AudioScheduler(
    scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
    scoped_ptr<AudioCapturer> audio_capturer,
    scoped_ptr<AudioEncoder> audio_encoder,
    protocol::AudioStub* audio_stub)
    : audio_task_runner_(audio_task_runner),
      network_task_runner_(network_task_runner),
      audio_capturer_(audio_capturer.Pass()),
      audio_encoder_(audio_encoder.Pass()),
      audio_stub_(audio_stub),
      network_stopped_(false),
      enabled_(true) {
  DCHECK(network_task_runner_->BelongsToCurrentThread());
  DCHECK(audio_capturer_);
  DCHECK(audio_encoder_);
  DCHECK(audio_stub_);
}

void AudioScheduler::Start() {
  DCHECK(network_task_runner_->BelongsToCurrentThread());

  audio_task_runner_->PostTask(
      FROM_HERE, base::Bind(&AudioScheduler::StartOnAudioThread, this));
}

void AudioScheduler::Stop() {
  DCHECK(network_task_runner_->BelongsToCurrentThread());
  DCHECK(audio_stub_);

  // Clear |audio_stub_| to prevent audio packets being delivered to the client.
  audio_stub_ = NULL;

  audio_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&AudioScheduler::StopOnAudioThread, this));
}

AudioScheduler::~AudioScheduler() {
}

void AudioScheduler::StartOnAudioThread() {
  DCHECK(audio_task_runner_->BelongsToCurrentThread());

  // TODO(kxing): Do something with the return value.
  audio_capturer_->Start(
      base::Bind(&AudioScheduler::EncodeAudioPacket, this));
}

void AudioScheduler::StopOnAudioThread() {
  DCHECK(audio_task_runner_->BelongsToCurrentThread());
  audio_capturer_->Stop();
}

void AudioScheduler::Pause(bool pause) {
  if (!audio_task_runner_->BelongsToCurrentThread()) {
    audio_task_runner_->PostTask(
        FROM_HERE, base::Bind(&AudioScheduler::Pause, this, pause));
    return;
  }

  enabled_ = !pause;
}

void AudioScheduler::EncodeAudioPacket(scoped_ptr<AudioPacket> packet) {
  DCHECK(audio_task_runner_->BelongsToCurrentThread());
  DCHECK(packet.get());

  if (!enabled_)
    return;

  scoped_ptr<AudioPacket> encoded_packet =
      audio_encoder_->Encode(packet.Pass());

  // The audio encoder returns a NULL audio packet if there's no audio to send.
  if (encoded_packet.get()) {
    network_task_runner_->PostTask(
        FROM_HERE, base::Bind(&AudioScheduler::SendAudioPacket,
                              this, base::Passed(&encoded_packet)));
  }
}

void AudioScheduler::SendAudioPacket(scoped_ptr<AudioPacket> packet) {
  DCHECK(network_task_runner_->BelongsToCurrentThread());
  DCHECK(packet.get());

  if (!audio_stub_)
    return;

  audio_stub_->ProcessAudioPacket(packet.Pass(), base::Closure());
}

}  // namespace remoting