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