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 22 AudioPlayer::AudioPlayer() 23 : sampling_rate_(AudioPacket::SAMPLING_RATE_INVALID), 24 start_failed_(false), 25 queued_bytes_(0), 26 bytes_consumed_(0) { 27 } 28 29 AudioPlayer::~AudioPlayer() { 30 base::AutoLock auto_lock(lock_); 31 ResetQueue(); 32 } 33 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 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 89 void AudioPlayer::ResetQueue() { 90 lock_.AssertAcquired(); 91 STLDeleteElements(&queued_packets_); 92 queued_bytes_ = 0; 93 bytes_consumed_ = 0; 94 } 95 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