| 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 "media/audio/null_audio_sink.h" | 5 #include "media/audio/null_audio_sink.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/stringprintf.h" | 8 #include "base/stringprintf.h" |
| 9 #include "base/sys_byteorder.h" | 9 #include "base/sys_byteorder.h" |
| 10 #include "base/threading/platform_thread.h" | 10 #include "base/threading/platform_thread.h" |
| 11 | 11 |
| 12 namespace media { | 12 namespace media { |
| 13 | 13 |
| 14 NullAudioSink::NullAudioSink() | 14 NullAudioSink::NullAudioSink() |
| 15 : initialized_(false), | 15 : initialized_(false), |
| 16 playing_(false), | 16 playing_(false), |
| 17 callback_(NULL), | 17 callback_(NULL), |
| 18 thread_("NullAudioThread"), | 18 thread_("NullAudioThread"), |
| 19 hash_audio_for_testing_(false) { | 19 hash_audio_for_testing_(false) { |
| 20 } | 20 } |
| 21 | 21 |
| 22 void NullAudioSink::Initialize(const AudioParameters& params, | 22 void NullAudioSink::Initialize(const AudioParameters& params, |
| 23 RenderCallback* callback) { | 23 RenderCallback* callback) { |
| 24 DCHECK(!initialized_); | 24 DCHECK(!initialized_); |
| 25 params_ = params; | 25 params_ = params; |
| 26 | 26 |
| 27 audio_data_.reserve(params.channels()); | 27 audio_bus_ = AudioBus::Create(params_); |
| 28 for (int i = 0; i < params.channels(); ++i) { | |
| 29 float* channel_data = new float[params.frames_per_buffer()]; | |
| 30 audio_data_.push_back(channel_data); | |
| 31 } | |
| 32 | 28 |
| 33 if (hash_audio_for_testing_) { | 29 if (hash_audio_for_testing_) { |
| 34 md5_channel_contexts_.reset(new base::MD5Context[params.channels()]); | 30 md5_channel_contexts_.reset(new base::MD5Context[params_.channels()]); |
| 35 for (int i = 0; i < params.channels(); i++) | 31 for (int i = 0; i < params_.channels(); i++) |
| 36 base::MD5Init(&md5_channel_contexts_[i]); | 32 base::MD5Init(&md5_channel_contexts_[i]); |
| 37 } | 33 } |
| 38 | 34 |
| 39 callback_ = callback; | 35 callback_ = callback; |
| 40 initialized_ = true; | 36 initialized_ = true; |
| 41 } | 37 } |
| 42 | 38 |
| 43 void NullAudioSink::Start() { | 39 void NullAudioSink::Start() { |
| 44 if (!thread_.Start()) | 40 if (!thread_.Start()) |
| 45 return; | 41 return; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 66 return volume == 0.0; | 62 return volume == 0.0; |
| 67 } | 63 } |
| 68 | 64 |
| 69 void NullAudioSink::SetPlaying(bool is_playing) { | 65 void NullAudioSink::SetPlaying(bool is_playing) { |
| 70 base::AutoLock auto_lock(lock_); | 66 base::AutoLock auto_lock(lock_); |
| 71 playing_ = is_playing; | 67 playing_ = is_playing; |
| 72 } | 68 } |
| 73 | 69 |
| 74 NullAudioSink::~NullAudioSink() { | 70 NullAudioSink::~NullAudioSink() { |
| 75 DCHECK(!thread_.IsRunning()); | 71 DCHECK(!thread_.IsRunning()); |
| 76 for (size_t i = 0; i < audio_data_.size(); ++i) | |
| 77 delete [] audio_data_[i]; | |
| 78 } | 72 } |
| 79 | 73 |
| 80 void NullAudioSink::FillBufferTask() { | 74 void NullAudioSink::FillBufferTask() { |
| 81 base::AutoLock auto_lock(lock_); | 75 base::AutoLock auto_lock(lock_); |
| 82 | 76 |
| 83 base::TimeDelta delay; | 77 base::TimeDelta delay; |
| 84 // Only consume buffers when actually playing. | 78 // Only consume buffers when actually playing. |
| 85 if (playing_) { | 79 if (playing_) { |
| 86 int requested_frames = params_.frames_per_buffer(); | 80 int frames_received = callback_->Render( |
| 87 int frames_received = callback_->Render(audio_data_, requested_frames, 0); | 81 audio_bus_.get(), audio_bus_->frames(), 0); |
| 88 int frames_per_millisecond = | 82 int frames_per_millisecond = |
| 89 params_.sample_rate() / base::Time::kMillisecondsPerSecond; | 83 params_.sample_rate() / base::Time::kMillisecondsPerSecond; |
| 90 | 84 |
| 91 if (hash_audio_for_testing_ && frames_received > 0) { | 85 if (hash_audio_for_testing_ && frames_received > 0) { |
| 92 DCHECK_EQ(sizeof(float), sizeof(uint32)); | 86 DCHECK_EQ(sizeof(float), sizeof(uint32)); |
| 93 int channels = audio_data_.size(); | 87 int channels = audio_bus_->channels(); |
| 94 for (int channel_idx = 0; channel_idx < channels; ++channel_idx) { | 88 for (int channel_idx = 0; channel_idx < channels; ++channel_idx) { |
| 95 float* channel = audio_data_[channel_idx]; | 89 float* channel = audio_bus_->channel(channel_idx); |
| 96 for (int frame_idx = 0; frame_idx < frames_received; frame_idx++) { | 90 for (int frame_idx = 0; frame_idx < frames_received; frame_idx++) { |
| 97 // Convert float to uint32 w/o conversion loss. | 91 // Convert float to uint32 w/o conversion loss. |
| 98 uint32 frame = base::ByteSwapToLE32( | 92 uint32 frame = base::ByteSwapToLE32( |
| 99 bit_cast<uint32>(channel[frame_idx])); | 93 bit_cast<uint32>(channel[frame_idx])); |
| 100 base::MD5Update( | 94 base::MD5Update( |
| 101 &md5_channel_contexts_[channel_idx], base::StringPiece( | 95 &md5_channel_contexts_[channel_idx], base::StringPiece( |
| 102 reinterpret_cast<char*>(&frame), sizeof(frame))); | 96 reinterpret_cast<char*>(&frame), sizeof(frame))); |
| 103 } | 97 } |
| 104 } | 98 } |
| 105 } | 99 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 128 DCHECK(hash_audio_for_testing_); | 122 DCHECK(hash_audio_for_testing_); |
| 129 | 123 |
| 130 // If initialize failed or was never called, ensure we return an empty hash. | 124 // If initialize failed or was never called, ensure we return an empty hash. |
| 131 if (!initialized_) { | 125 if (!initialized_) { |
| 132 md5_channel_contexts_.reset(new base::MD5Context[1]); | 126 md5_channel_contexts_.reset(new base::MD5Context[1]); |
| 133 base::MD5Init(&md5_channel_contexts_[0]); | 127 base::MD5Init(&md5_channel_contexts_[0]); |
| 134 } | 128 } |
| 135 | 129 |
| 136 // Hash all channels into the first channel. | 130 // Hash all channels into the first channel. |
| 137 base::MD5Digest digest; | 131 base::MD5Digest digest; |
| 138 for (size_t i = 1; i < audio_data_.size(); i++) { | 132 for (int i = 1; i < audio_bus_->channels(); i++) { |
| 139 base::MD5Final(&digest, &md5_channel_contexts_[i]); | 133 base::MD5Final(&digest, &md5_channel_contexts_[i]); |
| 140 base::MD5Update(&md5_channel_contexts_[0], base::StringPiece( | 134 base::MD5Update(&md5_channel_contexts_[0], base::StringPiece( |
| 141 reinterpret_cast<char*>(&digest), sizeof(base::MD5Digest))); | 135 reinterpret_cast<char*>(&digest), sizeof(base::MD5Digest))); |
| 142 } | 136 } |
| 143 | 137 |
| 144 base::MD5Final(&digest, &md5_channel_contexts_[0]); | 138 base::MD5Final(&digest, &md5_channel_contexts_[0]); |
| 145 return base::MD5DigestToBase16(digest); | 139 return base::MD5DigestToBase16(digest); |
| 146 } | 140 } |
| 147 | 141 |
| 148 } // namespace media | 142 } // namespace media |
| OLD | NEW |