Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 #include "remoting/proto/audio.pb.h" | |
| 11 | 10 |
| 12 namespace { | 11 namespace { |
| 13 // Constants used to create an audio configuration resource. | 12 // Constants used to create an audio configuration resource. |
| 14 // The sample count we will request from the browser. | 13 // The sample count we will request from the browser. |
| 15 const uint32_t kSampleFrameCount = 4096u; | 14 const uint32_t kSampleFrameCount = 4096u; |
| 16 // The number of channels in the audio stream (only supporting stereo audio | 15 // The number of channels in the audio stream (only supporting stereo audio |
| 17 // for now). | 16 // for now). |
| 18 const uint32_t kChannels = 2u; | 17 const uint32_t kChannels = 2u; |
| 19 const int kSampleSizeBytes = 2; | 18 const int kSampleSizeBytes = 2; |
| 20 } // namespace | 19 } // namespace |
| 21 | 20 |
| 22 namespace remoting { | 21 namespace remoting { |
| 23 | 22 |
| 24 bool PepperAudioPlayer::IsRunning() const { | 23 bool PepperAudioPlayer::IsRunning() const { |
| 25 return running_; | 24 return running_; |
| 26 } | 25 } |
| 27 | 26 |
| 28 PepperAudioPlayer::PepperAudioPlayer(pp::Instance* instance) | 27 PepperAudioPlayer::PepperAudioPlayer(pp::Instance* instance) |
| 29 : samples_per_frame_(kSampleFrameCount), | 28 : instance_(instance), |
| 30 bytes_consumed_(0), | 29 sampling_rate_(AudioPacket::SAMPLING_RATE_INVALID), |
| 31 running_(false) { | 30 samples_per_frame_(kSampleFrameCount), |
| 31 bytes_consumed_(0), | |
| 32 running_(false) { | |
| 33 } | |
| 34 | |
| 35 PepperAudioPlayer::~PepperAudioPlayer() { | |
| 36 if (running_ && !audio_.is_null()) | |
| 37 DoStop(); | |
|
Sergey Ulanov
2012/07/23 22:01:47
Do we really need to call this explicitly? Doesn't
kxing
2012/07/23 22:58:47
Done.
| |
| 38 } | |
| 39 | |
| 40 bool PepperAudioPlayer::Start() { | |
| 41 running_ = true; | |
|
Sergey Ulanov
2012/07/23 22:01:47
Do we want to do that even when we fail to start?
kxing
2012/07/23 22:58:47
Done.
| |
| 42 if (!audio_.is_null()) | |
| 43 return DoStart(); | |
|
Sergey Ulanov
2012/07/23 22:01:47
That's going to fail if audio_ is null. I wonder w
kxing
2012/07/23 22:58:47
Done.
| |
| 44 return true; | |
| 45 } | |
| 46 | |
| 47 bool PepperAudioPlayer::DoStart() { | |
|
Sergey Ulanov
2012/07/23 22:01:47
Doesn't seem like a good name given that it called
kxing
2012/07/23 22:58:47
Done.
| |
| 48 bool success = audio_.StartPlayback(); | |
| 49 if (!success) | |
| 50 LOG(ERROR) << "Failed to start Pepper audio player"; | |
| 51 return success; | |
| 52 } | |
| 53 | |
| 54 void PepperAudioPlayer::DoStop() { | |
| 55 bool success = audio_.StopPlayback(); | |
| 56 if (!success) | |
| 57 LOG(ERROR) << "Failed to stop Pepper audio player"; | |
| 58 } | |
| 59 | |
| 60 // static | |
| 61 PP_AudioSampleRate PepperAudioPlayer::ConvertToPepperSampleRate( | |
|
Sergey Ulanov
2012/07/23 22:01:47
Doesn't need to be a class member. Just make it a
kxing
2012/07/23 22:58:47
Done.
| |
| 62 AudioPacket::SamplingRate sampling_rate) { | |
| 63 switch (sampling_rate) { | |
| 64 case AudioPacket::SAMPLING_RATE_44100: | |
| 65 return PP_AUDIOSAMPLERATE_44100; | |
| 66 case AudioPacket::SAMPLING_RATE_48000: | |
| 67 return PP_AUDIOSAMPLERATE_48000; | |
| 68 default: | |
| 69 NOTREACHED(); | |
| 70 } | |
| 71 return PP_AUDIOSAMPLERATE_NONE; | |
| 72 } | |
| 73 | |
| 74 void PepperAudioPlayer::ResetAudioPlayer( | |
| 75 AudioPacket::SamplingRate sampling_rate) { | |
| 76 sampling_rate_ = sampling_rate; | |
| 77 PP_AudioSampleRate sample_rate = | |
| 78 ConvertToPepperSampleRate(sampling_rate); | |
| 79 | |
| 32 // Ask the browser/device for an appropriate sample frame count size. | 80 // Ask the browser/device for an appropriate sample frame count size. |
| 33 samples_per_frame_ = | 81 samples_per_frame_ = |
| 34 pp::AudioConfig::RecommendSampleFrameCount(instance, | 82 pp::AudioConfig::RecommendSampleFrameCount(instance_, |
| 35 PP_AUDIOSAMPLERATE_44100, | 83 sample_rate, |
| 36 kSampleFrameCount); | 84 kSampleFrameCount); |
| 37 | 85 |
| 38 // Create an audio configuration resource. | 86 // Create an audio configuration resource. |
| 39 pp::AudioConfig audio_config = pp::AudioConfig(instance, | 87 pp::AudioConfig audio_config = pp::AudioConfig(instance_, |
| 40 PP_AUDIOSAMPLERATE_44100, | 88 sample_rate, |
| 41 samples_per_frame_); | 89 samples_per_frame_); |
| 42 | 90 |
| 43 // Create an audio resource. | 91 // Create an audio resource. |
| 44 audio_ = pp::Audio(instance, audio_config, PepperAudioPlayerCallback, this); | 92 audio_ = pp::Audio(instance_, audio_config, PepperAudioPlayerCallback, this); |
| 45 } | |
| 46 | |
| 47 PepperAudioPlayer::~PepperAudioPlayer() { } | |
| 48 | |
| 49 bool PepperAudioPlayer::Start() { | |
| 50 running_ = audio_.StartPlayback(); | |
| 51 return running_; | |
| 52 } | 93 } |
| 53 | 94 |
| 54 void PepperAudioPlayer::ProcessAudioPacket(scoped_ptr<AudioPacket> packet) { | 95 void PepperAudioPlayer::ProcessAudioPacket(scoped_ptr<AudioPacket> packet) { |
| 55 // TODO(kxing): Limit the size of the queue so that latency doesn't grow | 96 // TODO(kxing): Limit the size of the queue so that latency doesn't grow |
| 56 // too large. | 97 // too large. |
| 57 if (packet->data().size() % (kChannels * kSampleSizeBytes) != 0) { | 98 if (packet->data().size() % (kChannels * kSampleSizeBytes) != 0) { |
| 58 LOG(WARNING) << "Received corrupted packet."; | 99 LOG(WARNING) << "Received corrupted packet."; |
| 59 return; | 100 return; |
| 60 } | 101 } |
| 61 base::AutoLock auto_lock(lock_); | 102 base::AutoLock auto_lock(lock_); |
| 62 | 103 |
| 104 // Start the Pepper audio player if this is the first packet. | |
| 105 if (sampling_rate_ != packet->sampling_rate()) { | |
| 106 if (running_ && !audio_.is_null()) | |
| 107 DoStop(); | |
|
Sergey Ulanov
2012/07/23 22:01:47
ResetAudioPlayer() creates new pp::Audio object an
kxing
2012/07/23 22:58:47
Done.
| |
| 108 ResetAudioPlayer(packet->sampling_rate()); | |
| 109 if (running_) | |
| 110 DoStart(); | |
| 111 } | |
| 112 | |
| 63 queued_packets_.push_back(packet.release()); | 113 queued_packets_.push_back(packet.release()); |
| 64 } | 114 } |
| 65 | 115 |
| 66 // static | 116 // static |
| 67 void PepperAudioPlayer::PepperAudioPlayerCallback(void* samples, | 117 void PepperAudioPlayer::PepperAudioPlayerCallback(void* samples, |
| 68 uint32_t buffer_size, | 118 uint32_t buffer_size, |
| 69 void* data) { | 119 void* data) { |
| 70 PepperAudioPlayer* audio_player = static_cast<PepperAudioPlayer*>(data); | 120 PepperAudioPlayer* audio_player = static_cast<PepperAudioPlayer*>(data); |
| 71 audio_player->FillWithSamples(samples, buffer_size); | 121 audio_player->FillWithSamples(samples, buffer_size); |
| 72 } | 122 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 104 bytes_needed - bytes_extracted); | 154 bytes_needed - bytes_extracted); |
| 105 memcpy(next_sample, packet_data.data() + bytes_consumed_, bytes_to_copy); | 155 memcpy(next_sample, packet_data.data() + bytes_consumed_, bytes_to_copy); |
| 106 | 156 |
| 107 next_sample += bytes_to_copy; | 157 next_sample += bytes_to_copy; |
| 108 bytes_consumed_ += bytes_to_copy; | 158 bytes_consumed_ += bytes_to_copy; |
| 109 bytes_extracted += bytes_to_copy; | 159 bytes_extracted += bytes_to_copy; |
| 110 } | 160 } |
| 111 } | 161 } |
| 112 | 162 |
| 113 } // namespace remoting | 163 } // namespace remoting |
| OLD | NEW |