1 // Copyright 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/audio_player.h"
6 
7 #include <algorithm>
8 #include <string>
9 #include <utility>
10 
11 #include "base/callback_helpers.h"
12 #include "base/check_op.h"
13 #include "base/stl_util.h"
14 
15 // If queue grows bigger than 150ms we start dropping packets.
16 const int kMaxQueueLatencyMs = 150;
17 
18 namespace remoting {
19 
20 // TODO(nicholss): Update legacy audio player to use new audio buffer code.
AudioPlayer()21 AudioPlayer::AudioPlayer()
22     : sampling_rate_(AudioPacket::SAMPLING_RATE_INVALID),
23       start_failed_(false),
24       queued_bytes_(0),
25       bytes_consumed_(0) {}
26 
27 AudioPlayer::~AudioPlayer() = default;
28 
ProcessAudioPacket(std::unique_ptr<AudioPacket> packet,base::OnceClosure done)29 void AudioPlayer::ProcessAudioPacket(std::unique_ptr<AudioPacket> packet,
30                                      base::OnceClosure done) {
31   CHECK_EQ(1, packet->data_size());
32   DCHECK_EQ(AudioPacket::ENCODING_RAW, packet->encoding());
33   DCHECK_NE(AudioPacket::SAMPLING_RATE_INVALID, packet->sampling_rate());
34   DCHECK_EQ(kSampleSizeBytes, static_cast<int>(packet->bytes_per_sample()));
35   DCHECK_EQ(kChannels, static_cast<int>(packet->channels()));
36   DCHECK_EQ(packet->data(0).size() % (kChannels * kSampleSizeBytes), 0u);
37 
38   base::ScopedClosureRunner done_runner(std::move(done));
39 
40   // No-op if the Pepper player won't start.
41   if (start_failed_) {
42     return;
43   }
44 
45   // Start the Pepper audio player if this is the first packet.
46   if (sampling_rate_ != packet->sampling_rate()) {
47     // Drop all packets currently in the queue, since they are sampled at the
48     // wrong rate.
49     {
50       base::AutoLock auto_lock(lock_);
51       ResetQueue();
52     }
53 
54     sampling_rate_ = packet->sampling_rate();
55     bool success = ResetAudioPlayer(sampling_rate_);
56     if (!success) {
57       start_failed_ = true;
58       return;
59     }
60   }
61 
62   base::AutoLock auto_lock(lock_);
63 
64   queued_bytes_ += packet->data(0).size();
65   queued_packets_.push_back(std::move(packet));
66 
67   int max_buffer_size_ = kMaxQueueLatencyMs * sampling_rate_ *
68                          kSampleSizeBytes * kChannels /
69                          base::Time::kMillisecondsPerSecond;
70   while (queued_bytes_ > max_buffer_size_) {
71     queued_bytes_ -= queued_packets_.front()->data(0).size() - bytes_consumed_;
72     DCHECK_GE(queued_bytes_, 0);
73     queued_packets_.pop_front();
74     bytes_consumed_ = 0;
75   }
76 }
77 
78 // static
AudioPlayerCallback(void * samples,uint32_t buffer_size,void * data)79 void AudioPlayer::AudioPlayerCallback(void* samples,
80                                       uint32_t buffer_size,
81                                       void* data) {
82   AudioPlayer* audio_player = static_cast<AudioPlayer*>(data);
83   audio_player->FillWithSamples(samples, buffer_size);
84 }
85 
ResetQueue()86 void AudioPlayer::ResetQueue() {
87   lock_.AssertAcquired();
88   queued_packets_.clear();
89   queued_bytes_ = 0;
90   bytes_consumed_ = 0;
91 }
92 
FillWithSamples(void * samples,uint32_t buffer_size)93 void AudioPlayer::FillWithSamples(void* samples, uint32_t buffer_size) {
94   base::AutoLock auto_lock(lock_);
95 
96   const size_t bytes_needed =
97       kChannels * kSampleSizeBytes * GetSamplesPerFrame();
98 
99   // Make sure we don't overrun the buffer.
100   CHECK_EQ(buffer_size, bytes_needed);
101 
102   char* next_sample = static_cast<char*>(samples);
103   size_t bytes_extracted = 0;
104 
105   while (bytes_extracted < bytes_needed) {
106     // Check if we've run out of samples for this packet.
107     if (queued_packets_.empty()) {
108       memset(next_sample, 0, bytes_needed - bytes_extracted);
109       return;
110     }
111 
112     // Pop off the packet if we've already consumed all its bytes.
113     if (queued_packets_.front()->data(0).size() == bytes_consumed_) {
114       queued_packets_.pop_front();
115       bytes_consumed_ = 0;
116       continue;
117     }
118 
119     const std::string& packet_data = queued_packets_.front()->data(0);
120     size_t bytes_to_copy = std::min(packet_data.size() - bytes_consumed_,
121                                     bytes_needed - bytes_extracted);
122     memcpy(next_sample, packet_data.data() + bytes_consumed_, bytes_to_copy);
123 
124     next_sample += bytes_to_copy;
125     bytes_consumed_ += bytes_to_copy;
126     bytes_extracted += bytes_to_copy;
127     queued_bytes_ -= bytes_to_copy;
128     DCHECK_GE(queued_bytes_, 0);
129   }
130 }
131 
132 }  // namespace remoting
133