Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Side by Side Diff: remoting/client/plugin/pepper_audio_player.cc

Issue 10914210: Limit audio buffer size in the audio player used by the chromoting client. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « remoting/client/plugin/pepper_audio_player.h ('k') | remoting/codec/audio_decoder_verbatim.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/client/plugin/pepper_audio_player.h" 5 #include "remoting/client/plugin/pepper_audio_player.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/stl_util.h" 9 #include "base/stl_util.h"
10 10
11 namespace { 11 namespace {
12 // Constants used to create an audio configuration resource. 12
13 // The sample count we will request from the browser. 13 // The frame size we will request from the browser.
14 const uint32_t kSampleFrameCount = 4096u; 14 const int kFrameSizeMs = 40;
15
15 // The number of channels in the audio stream (only supporting stereo audio 16 // The number of channels in the audio stream (only supporting stereo audio
16 // for now). 17 // for now).
17 const uint32_t kChannels = 2u; 18 const int kChannels = 2u;
18 const int kSampleSizeBytes = 2; 19 const int kSampleSizeBytes = 2;
19 20
21 // If queue grows bigger than 150ms we start dropping packets.
22 const int kMaxQueueLatencyMs = 150;
23
20 PP_AudioSampleRate ConvertToPepperSampleRate( 24 PP_AudioSampleRate ConvertToPepperSampleRate(
21 remoting::AudioPacket::SamplingRate sampling_rate) { 25 remoting::AudioPacket::SamplingRate sampling_rate) {
22 switch (sampling_rate) { 26 switch (sampling_rate) {
23 case remoting::AudioPacket::SAMPLING_RATE_44100: 27 case remoting::AudioPacket::SAMPLING_RATE_44100:
24 return PP_AUDIOSAMPLERATE_44100; 28 return PP_AUDIOSAMPLERATE_44100;
25 case remoting::AudioPacket::SAMPLING_RATE_48000: 29 case remoting::AudioPacket::SAMPLING_RATE_48000:
26 return PP_AUDIOSAMPLERATE_48000; 30 return PP_AUDIOSAMPLERATE_48000;
27 default: 31 default:
28 NOTREACHED(); 32 NOTREACHED();
29 } 33 }
30 return PP_AUDIOSAMPLERATE_NONE; 34 return PP_AUDIOSAMPLERATE_NONE;
31 } 35 }
32 36
33 } // namespace 37 } // namespace
34 38
35 namespace remoting { 39 namespace remoting {
36 40
37 PepperAudioPlayer::PepperAudioPlayer(pp::Instance* instance) 41 PepperAudioPlayer::PepperAudioPlayer(pp::Instance* instance)
38 : instance_(instance), 42 : instance_(instance),
39 sampling_rate_(AudioPacket::SAMPLING_RATE_INVALID), 43 sampling_rate_(AudioPacket::SAMPLING_RATE_INVALID),
40 samples_per_frame_(kSampleFrameCount), 44 samples_per_frame_(0),
41 bytes_consumed_(0), 45 start_failed_(false),
42 start_failed_(false) { 46 queued_samples_(0),
47 bytes_consumed_(0) {
43 } 48 }
44 49
45 PepperAudioPlayer::~PepperAudioPlayer() {} 50 PepperAudioPlayer::~PepperAudioPlayer() {}
46 51
47 bool PepperAudioPlayer::ResetAudioPlayer( 52 bool PepperAudioPlayer::ResetAudioPlayer(
48 AudioPacket::SamplingRate sampling_rate) { 53 AudioPacket::SamplingRate sampling_rate) {
49 sampling_rate_ = sampling_rate; 54 sampling_rate_ = sampling_rate;
50 PP_AudioSampleRate sample_rate = 55 PP_AudioSampleRate sample_rate =
51 ConvertToPepperSampleRate(sampling_rate); 56 ConvertToPepperSampleRate(sampling_rate);
52 57
53 // Ask the browser/device for an appropriate sample frame count size. 58 // Ask the browser/device for an appropriate frame size.
54 samples_per_frame_ = 59 samples_per_frame_ = pp::AudioConfig::RecommendSampleFrameCount(
55 pp::AudioConfig::RecommendSampleFrameCount(instance_, 60 instance_, sample_rate,
56 sample_rate, 61 kFrameSizeMs * sampling_rate / base::Time::kMillisecondsPerSecond);
Wez 2012/09/12 20:47:57 nit: Since you do a similar calculation based on t
Sergey Ulanov 2012/09/12 21:43:34 Done. Called the new function MsecToSamples()
57 kSampleFrameCount);
58 62
59 // Create an audio configuration resource. 63 // Create an audio configuration resource.
60 pp::AudioConfig audio_config = pp::AudioConfig(instance_, 64 pp::AudioConfig audio_config = pp::AudioConfig(
61 sample_rate, 65 instance_, sample_rate, samples_per_frame_);
62 samples_per_frame_);
63 66
64 // Create an audio resource. 67 // Create an audio resource.
65 audio_ = pp::Audio(instance_, audio_config, PepperAudioPlayerCallback, this); 68 audio_ = pp::Audio(instance_, audio_config, PepperAudioPlayerCallback, this);
66 69
67 // Immediately start the player. 70 // Immediately start the player.
68 bool success = audio_.StartPlayback(); 71 bool success = audio_.StartPlayback();
69 if (!success) 72 if (!success)
70 LOG(ERROR) << "Failed to start Pepper audio player"; 73 LOG(ERROR) << "Failed to start Pepper audio player";
71 return success; 74 return success;
72 } 75 }
73 76
74 void PepperAudioPlayer::ProcessAudioPacket(scoped_ptr<AudioPacket> packet) { 77 void PepperAudioPlayer::ProcessAudioPacket(scoped_ptr<AudioPacket> packet) {
75 // TODO(kxing): Limit the size of the queue so that latency doesn't grow
76 // too large.
77
78 CHECK_EQ(1, packet->data_size()); 78 CHECK_EQ(1, packet->data_size());
79 DCHECK_EQ(AudioPacket::ENCODING_RAW, packet->encoding()); 79 DCHECK_EQ(AudioPacket::ENCODING_RAW, packet->encoding());
80 DCHECK_NE(AudioPacket::SAMPLING_RATE_INVALID, packet->sampling_rate()); 80 DCHECK_NE(AudioPacket::SAMPLING_RATE_INVALID, packet->sampling_rate());
81 DCHECK_EQ(kSampleSizeBytes, packet->bytes_per_sample()); 81 DCHECK_EQ(kSampleSizeBytes, packet->bytes_per_sample());
82 DCHECK_EQ(static_cast<int>(kChannels), packet->channels()); 82 DCHECK_EQ(static_cast<int>(kChannels), packet->channels());
83 83 DCHECK_EQ(packet->data(0).size() % (kChannels * kSampleSizeBytes), 0u);
Wez 2012/09/12 20:47:57 Is this check correct; do we not allow splitting o
Sergey Ulanov 2012/09/12 21:43:34 Yes, it's correct. There is no way you can encode/
84 if (packet->data(0).size() % (kChannels * kSampleSizeBytes) != 0) {
85 LOG(WARNING) << "Received corrupted packet.";
86 return;
87 }
88 base::AutoLock auto_lock(lock_);
89 84
90 // No-op if the Pepper player won't start. 85 // No-op if the Pepper player won't start.
91 if (start_failed_) { 86 if (start_failed_) {
92 return; 87 return;
93 } 88 }
94 89
95 // Start the Pepper audio player if this is the first packet. 90 // Start the Pepper audio player if this is the first packet.
96 if (sampling_rate_ != packet->sampling_rate()) { 91 if (sampling_rate_ != packet->sampling_rate()) {
97 // Drop all packets currently in the queue, since they are sampled at the 92 // Drop all packets currently in the queue, since they are sampled at the
98 // wrong rate. 93 // wrong rate.
99 STLDeleteElements(&queued_packets_); 94 {
95 base::AutoLock auto_lock(lock_);
96 STLDeleteElements(&queued_packets_);
97 queued_samples_ = 0;
98 }
100 99
101 bool success = ResetAudioPlayer(packet->sampling_rate()); 100 bool success = ResetAudioPlayer(packet->sampling_rate());
102 if (!success) { 101 if (!success) {
103 start_failed_ = true; 102 start_failed_ = true;
104 return; 103 return;
105 } 104 }
106 } 105 }
107 106
107 base::AutoLock auto_lock(lock_);
108
109 if (queued_samples_ > kMaxQueueLatencyMs * sampling_rate_ /
110 base::Time::kMillisecondsPerSecond) {
111 STLDeleteElements(&queued_packets_);
112 queued_samples_ = 0;
113 }
114
115 queued_samples_ += packet->data(0).size() / (kChannels * kSampleSizeBytes);
Wez 2012/09/12 20:47:57 nit: Since you use kSampleSizeBytes * kChannels in
Sergey Ulanov 2012/09/12 21:43:34 Done. I wish there was a term for set of samples f
108 queued_packets_.push_back(packet.release()); 116 queued_packets_.push_back(packet.release());
109 } 117 }
110 118
111 // static 119 // static
112 void PepperAudioPlayer::PepperAudioPlayerCallback(void* samples, 120 void PepperAudioPlayer::PepperAudioPlayerCallback(void* samples,
113 uint32_t buffer_size, 121 uint32_t buffer_size,
114 void* data) { 122 void* data) {
115 PepperAudioPlayer* audio_player = static_cast<PepperAudioPlayer*>(data); 123 PepperAudioPlayer* audio_player = static_cast<PepperAudioPlayer*>(data);
116 audio_player->FillWithSamples(samples, buffer_size); 124 audio_player->FillWithSamples(samples, buffer_size);
117 } 125 }
(...skipping 27 matching lines...) Expand all
145 153
146 const std::string& packet_data = queued_packets_.front()->data(0); 154 const std::string& packet_data = queued_packets_.front()->data(0);
147 size_t bytes_to_copy = std::min( 155 size_t bytes_to_copy = std::min(
148 packet_data.size() - bytes_consumed_, 156 packet_data.size() - bytes_consumed_,
149 bytes_needed - bytes_extracted); 157 bytes_needed - bytes_extracted);
150 memcpy(next_sample, packet_data.data() + bytes_consumed_, bytes_to_copy); 158 memcpy(next_sample, packet_data.data() + bytes_consumed_, bytes_to_copy);
151 159
152 next_sample += bytes_to_copy; 160 next_sample += bytes_to_copy;
153 bytes_consumed_ += bytes_to_copy; 161 bytes_consumed_ += bytes_to_copy;
154 bytes_extracted += bytes_to_copy; 162 bytes_extracted += bytes_to_copy;
163 queued_samples_ -= bytes_to_copy / kSampleSizeBytes / kChannels;
164 DCHECK_GE(queued_samples_, 0);
155 } 165 }
156 } 166 }
157 167
158 } // namespace remoting 168 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/client/plugin/pepper_audio_player.h ('k') | remoting/codec/audio_decoder_verbatim.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698