Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "chromecast/media/cma/backend/alsa/audio_decoder_alsa.h" | 5 #include "chromecast/media/cma/backend/alsa/audio_decoder_alsa.h" |
| 6 | 6 |
| 7 #include <time.h> | 7 #include <time.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <limits> | 10 #include <limits> |
| 11 | 11 |
| 12 #include "base/callback_helpers.h" | 12 #include "base/callback_helpers.h" |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/macros.h" | 14 #include "base/macros.h" |
| 15 #include "base/trace_event/trace_event.h" | 15 #include "base/trace_event/trace_event.h" |
| 16 #include "chromecast/base/task_runner_impl.h" | 16 #include "chromecast/base/task_runner_impl.h" |
| 17 #include "chromecast/media/cma/backend/alsa/media_pipeline_backend_alsa.h" | 17 #include "chromecast/media/cma/backend/alsa/media_pipeline_backend_alsa.h" |
| 18 #include "chromecast/media/cma/base/decoder_buffer_adapter.h" | |
| 18 #include "chromecast/media/cma/base/decoder_buffer_base.h" | 19 #include "chromecast/media/cma/base/decoder_buffer_base.h" |
| 19 #include "chromecast/public/media/cast_decoder_buffer.h" | 20 #include "chromecast/public/media/cast_decoder_buffer.h" |
| 21 #include "media/base/audio_buffer.h" | |
| 22 #include "media/base/audio_bus.h" | |
| 23 #include "media/base/channel_layout.h" | |
| 24 #include "media/base/decoder_buffer.h" | |
| 25 #include "media/base/sample_format.h" | |
| 26 #include "media/filters/audio_renderer_algorithm.h" | |
| 20 | 27 |
| 21 #define TRACE_FUNCTION_ENTRY0() TRACE_EVENT0("cma", __FUNCTION__) | 28 #define TRACE_FUNCTION_ENTRY0() TRACE_EVENT0("cma", __FUNCTION__) |
| 22 | 29 |
| 23 #define TRACE_FUNCTION_ENTRY1(arg1) \ | 30 #define TRACE_FUNCTION_ENTRY1(arg1) \ |
| 24 TRACE_EVENT1("cma", __FUNCTION__, #arg1, arg1) | 31 TRACE_EVENT1("cma", __FUNCTION__, #arg1, arg1) |
| 25 | 32 |
| 26 #define TRACE_FUNCTION_ENTRY2(arg1, arg2) \ | 33 #define TRACE_FUNCTION_ENTRY2(arg1, arg2) \ |
| 27 TRACE_EVENT2("cma", __FUNCTION__, #arg1, arg1, #arg2, arg2) | 34 TRACE_EVENT2("cma", __FUNCTION__, #arg1, arg1, #arg2, arg2) |
| 28 | 35 |
| 29 namespace chromecast { | 36 namespace chromecast { |
| 30 namespace media { | 37 namespace media { |
| 31 | 38 |
| 32 namespace { | 39 namespace { |
| 33 | 40 |
| 41 const int kNumChannels = 2; | |
| 42 const int kBitsPerSample = 32; | |
| 43 const int kDefaultFramesPerBuffer = 1024; | |
| 44 const int kSilenceBufferFrames = 2048; | |
| 45 const int kMaxOutputMs = 20; | |
| 46 const int kMillisecondsPerSecond = 1000; | |
| 47 | |
| 48 const double kPlaybackRateEpsilon = 0.001; | |
| 49 | |
| 34 const CastAudioDecoder::OutputFormat kDecoderSampleFormat = | 50 const CastAudioDecoder::OutputFormat kDecoderSampleFormat = |
| 35 CastAudioDecoder::kOutputPlanarFloat; | 51 CastAudioDecoder::kOutputPlanarFloat; |
| 36 | 52 |
| 37 const int64_t kInvalidDelayTimestamp = std::numeric_limits<int64_t>::min(); | 53 const int64_t kInvalidTimestamp = std::numeric_limits<int64_t>::min(); |
| 38 | 54 |
| 39 AudioDecoderAlsa::RenderingDelay kInvalidRenderingDelay() { | 55 const int64_t kNoPendingOutput = -1; |
| 40 AudioDecoderAlsa::RenderingDelay delay; | 56 |
| 41 delay.timestamp_microseconds = kInvalidDelayTimestamp; | 57 scoped_refptr<::media::AudioBuffer> CreateSilenceBuffer(int sample_rate) { |
|
DaleCurtis
2016/12/13 20:13:35
Just use AudioBuffer::CreateEmptyBuffer() it will
kmackay
2016/12/15 17:29:40
Done.
| |
| 42 delay.delay_microseconds = 0; | 58 scoped_refptr<::media::AudioBuffer> silence_buffer = |
| 43 return delay; | 59 ::media::AudioBuffer::CreateBuffer( |
| 60 ::media::kSampleFormatPlanarF32, ::media::CHANNEL_LAYOUT_STEREO, | |
| 61 kNumChannels, sample_rate, kSilenceBufferFrames); | |
| 62 for (uint8_t* channel : silence_buffer->channel_data()) { | |
| 63 float* real_channel = reinterpret_cast<float*>(channel); | |
| 64 std::fill_n(real_channel, kSilenceBufferFrames, 0.0f); | |
| 65 } | |
| 66 return silence_buffer; | |
| 44 } | 67 } |
| 45 | 68 |
| 46 } // namespace | 69 } // namespace |
| 47 | 70 |
| 71 AudioDecoderAlsa::RateShifterInfo::RateShifterInfo(float playback_rate) | |
| 72 : rate(playback_rate), input_frames(0), output_frames(0) {} | |
| 73 | |
| 48 AudioDecoderAlsa::AudioDecoderAlsa(MediaPipelineBackendAlsa* backend) | 74 AudioDecoderAlsa::AudioDecoderAlsa(MediaPipelineBackendAlsa* backend) |
| 49 : backend_(backend), | 75 : backend_(backend), |
| 50 task_runner_(backend->GetTaskRunner()), | 76 task_runner_(backend->GetTaskRunner()), |
| 51 delegate_(nullptr), | 77 delegate_(nullptr), |
| 52 is_eos_(false), | 78 pending_buffer_complete_(false), |
| 53 error_(false), | 79 got_eos_(false), |
| 80 pushed_eos_(false), | |
| 81 mixer_error_(false), | |
| 82 rate_shifter_output_( | |
| 83 ::media::AudioBus::Create(kNumChannels, kDefaultFramesPerBuffer)), | |
| 84 current_pts_(kInvalidTimestamp), | |
| 85 pending_output_frames_(kNoPendingOutput), | |
| 54 volume_multiplier_(1.0f), | 86 volume_multiplier_(1.0f), |
| 55 weak_factory_(this) { | 87 weak_factory_(this) { |
| 56 TRACE_FUNCTION_ENTRY0(); | 88 TRACE_FUNCTION_ENTRY0(); |
| 57 DCHECK(backend_); | 89 DCHECK(backend_); |
| 58 DCHECK(task_runner_.get()); | 90 DCHECK(task_runner_.get()); |
| 59 DCHECK(task_runner_->BelongsToCurrentThread()); | 91 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 60 } | 92 } |
| 61 | 93 |
| 62 AudioDecoderAlsa::~AudioDecoderAlsa() { | 94 AudioDecoderAlsa::~AudioDecoderAlsa() { |
| 63 TRACE_FUNCTION_ENTRY0(); | 95 TRACE_FUNCTION_ENTRY0(); |
| 64 DCHECK(task_runner_->BelongsToCurrentThread()); | 96 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 65 } | 97 } |
| 66 | 98 |
| 67 void AudioDecoderAlsa::SetDelegate( | 99 void AudioDecoderAlsa::SetDelegate( |
| 68 MediaPipelineBackend::Decoder::Delegate* delegate) { | 100 MediaPipelineBackend::Decoder::Delegate* delegate) { |
| 69 DCHECK(delegate); | 101 DCHECK(delegate); |
| 70 delegate_ = delegate; | 102 delegate_ = delegate; |
| 71 } | 103 } |
| 72 | 104 |
| 73 void AudioDecoderAlsa::Initialize() { | 105 void AudioDecoderAlsa::Initialize() { |
| 74 TRACE_FUNCTION_ENTRY0(); | 106 TRACE_FUNCTION_ENTRY0(); |
| 75 DCHECK(delegate_); | 107 DCHECK(delegate_); |
| 76 stats_ = Statistics(); | 108 stats_ = Statistics(); |
| 77 is_eos_ = false; | 109 pending_buffer_complete_ = false; |
| 78 last_buffer_pts_ = std::numeric_limits<int64_t>::min(); | 110 got_eos_ = false; |
| 111 pushed_eos_ = false; | |
| 112 current_pts_ = kInvalidTimestamp; | |
| 113 pending_output_frames_ = kNoPendingOutput; | |
| 79 | 114 |
| 80 last_known_delay_.timestamp_microseconds = kInvalidDelayTimestamp; | 115 last_mixer_delay_.timestamp_microseconds = kInvalidTimestamp; |
| 81 last_known_delay_.delay_microseconds = 0; | 116 last_mixer_delay_.delay_microseconds = 0; |
| 82 } | 117 } |
| 83 | 118 |
| 84 bool AudioDecoderAlsa::Start(int64_t start_pts) { | 119 bool AudioDecoderAlsa::Start(int64_t start_pts) { |
| 85 TRACE_FUNCTION_ENTRY0(); | 120 TRACE_FUNCTION_ENTRY0(); |
| 86 current_pts_ = start_pts; | 121 current_pts_ = start_pts; |
| 87 DCHECK(IsValidConfig(config_)); | 122 DCHECK(IsValidConfig(config_)); |
| 88 mixer_input_.reset(new StreamMixerAlsaInput( | 123 mixer_input_.reset(new StreamMixerAlsaInput( |
| 89 this, config_.samples_per_second, backend_->Primary())); | 124 this, config_.samples_per_second, backend_->Primary())); |
| 90 mixer_input_->SetVolumeMultiplier(volume_multiplier_); | 125 mixer_input_->SetVolumeMultiplier(volume_multiplier_); |
| 91 // Create decoder_ if necessary. This can happen if Stop() was called, and | 126 // Create decoder_ if necessary. This can happen if Stop() was called, and |
| 92 // SetConfig() was not called since then. | 127 // SetConfig() was not called since then. |
| 93 if (!decoder_) | 128 if (!decoder_) { |
| 94 CreateDecoder(); | 129 CreateDecoder(); |
| 130 } | |
| 131 if (!rate_shifter_) { | |
| 132 CreateRateShifter(config_.samples_per_second); | |
| 133 } | |
| 95 return true; | 134 return true; |
| 96 } | 135 } |
| 97 | 136 |
| 98 void AudioDecoderAlsa::Stop() { | 137 void AudioDecoderAlsa::Stop() { |
| 99 TRACE_FUNCTION_ENTRY0(); | 138 TRACE_FUNCTION_ENTRY0(); |
| 100 decoder_.reset(); | 139 decoder_.reset(); |
| 101 mixer_input_.reset(); | 140 mixer_input_.reset(); |
| 141 rate_shifter_.reset(); | |
| 142 weak_factory_.InvalidateWeakPtrs(); | |
| 102 | 143 |
| 103 Initialize(); | 144 Initialize(); |
| 104 } | 145 } |
| 105 | 146 |
| 106 bool AudioDecoderAlsa::Pause() { | 147 bool AudioDecoderAlsa::Pause() { |
| 107 TRACE_FUNCTION_ENTRY0(); | 148 TRACE_FUNCTION_ENTRY0(); |
| 108 DCHECK(mixer_input_); | 149 DCHECK(mixer_input_); |
| 109 mixer_input_->SetPaused(true); | 150 mixer_input_->SetPaused(true); |
| 110 return true; | 151 return true; |
| 111 } | 152 } |
| 112 | 153 |
| 113 bool AudioDecoderAlsa::Resume() { | 154 bool AudioDecoderAlsa::Resume() { |
| 114 TRACE_FUNCTION_ENTRY0(); | 155 TRACE_FUNCTION_ENTRY0(); |
| 115 DCHECK(mixer_input_); | 156 DCHECK(mixer_input_); |
| 116 mixer_input_->SetPaused(false); | 157 mixer_input_->SetPaused(false); |
| 117 return true; | 158 return true; |
| 118 } | 159 } |
| 119 | 160 |
| 161 bool AudioDecoderAlsa::SetPlaybackRate(float rate) { | |
|
DaleCurtis
2016/12/13 20:13:35
Hmmm, are you using this to actually change playba
kmackay
2016/12/13 20:39:47
We want to allow playback at eg 2x normal rate or
| |
| 162 if (std::abs(rate - 1.0) < kPlaybackRateEpsilon) { | |
| 163 // AudioRendererAlgorithm treats values close to 1 as exactly 1. | |
| 164 rate = 1.0f; | |
| 165 } | |
| 166 LOG(INFO) << "SetPlaybackRate to " << rate; | |
| 167 | |
| 168 while (!rate_shifter_info_.empty() && | |
| 169 rate_shifter_info_.back().input_frames == 0) { | |
| 170 rate_shifter_info_.pop_back(); | |
| 171 } | |
| 172 rate_shifter_info_.push_back(RateShifterInfo(rate)); | |
| 173 return true; | |
| 174 } | |
| 175 | |
| 120 AudioDecoderAlsa::BufferStatus AudioDecoderAlsa::PushBuffer( | 176 AudioDecoderAlsa::BufferStatus AudioDecoderAlsa::PushBuffer( |
| 121 CastDecoderBuffer* buffer) { | 177 CastDecoderBuffer* buffer) { |
| 122 TRACE_FUNCTION_ENTRY0(); | 178 TRACE_FUNCTION_ENTRY0(); |
| 123 DCHECK(task_runner_->BelongsToCurrentThread()); | 179 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 124 DCHECK(buffer); | 180 DCHECK(buffer); |
| 125 DCHECK(!is_eos_); | 181 DCHECK(!got_eos_); |
| 126 DCHECK(!error_); | 182 DCHECK(!mixer_error_); |
| 183 DCHECK(!pending_buffer_complete_); | |
| 127 | 184 |
| 128 uint64_t input_bytes = buffer->end_of_stream() ? 0 : buffer->data_size(); | 185 uint64_t input_bytes = buffer->end_of_stream() ? 0 : buffer->data_size(); |
| 129 scoped_refptr<DecoderBufferBase> buffer_base( | 186 scoped_refptr<DecoderBufferBase> buffer_base( |
| 130 static_cast<DecoderBufferBase*>(buffer)); | 187 static_cast<DecoderBufferBase*>(buffer)); |
| 131 if (!buffer->end_of_stream()) { | 188 if (!buffer->end_of_stream()) { |
| 132 last_buffer_pts_ = buffer->timestamp(); | 189 current_pts_ = buffer->timestamp(); |
| 133 current_pts_ = std::min(current_pts_, last_buffer_pts_); | |
| 134 } | 190 } |
| 135 | 191 |
| 136 // If the buffer is already decoded, do not attempt to decode. Call | 192 // If the buffer is already decoded, do not attempt to decode. Call |
| 137 // OnBufferDecoded asynchronously on the main thread. | 193 // OnBufferDecoded asynchronously on the main thread. |
| 138 if (BypassDecoder()) { | 194 if (BypassDecoder()) { |
| 139 DCHECK(!decoder_); | 195 DCHECK(!decoder_); |
| 140 task_runner_->PostTask( | 196 task_runner_->PostTask( |
| 141 FROM_HERE, | 197 FROM_HERE, |
| 142 base::Bind(&AudioDecoderAlsa::OnBufferDecoded, | 198 base::Bind(&AudioDecoderAlsa::OnBufferDecoded, |
| 143 weak_factory_.GetWeakPtr(), input_bytes, | 199 weak_factory_.GetWeakPtr(), input_bytes, |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 167 } | 223 } |
| 168 | 224 |
| 169 bool AudioDecoderAlsa::SetConfig(const AudioConfig& config) { | 225 bool AudioDecoderAlsa::SetConfig(const AudioConfig& config) { |
| 170 TRACE_FUNCTION_ENTRY0(); | 226 TRACE_FUNCTION_ENTRY0(); |
| 171 DCHECK(task_runner_->BelongsToCurrentThread()); | 227 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 172 if (!IsValidConfig(config)) { | 228 if (!IsValidConfig(config)) { |
| 173 LOG(ERROR) << "Invalid audio config passed to SetConfig"; | 229 LOG(ERROR) << "Invalid audio config passed to SetConfig"; |
| 174 return false; | 230 return false; |
| 175 } | 231 } |
| 176 | 232 |
| 233 if (!rate_shifter_ || | |
| 234 config.samples_per_second != config_.samples_per_second) { | |
| 235 CreateRateShifter(config.samples_per_second); | |
| 236 } | |
| 237 | |
| 177 if (mixer_input_ && config.samples_per_second != config_.samples_per_second) { | 238 if (mixer_input_ && config.samples_per_second != config_.samples_per_second) { |
| 178 // Destroy the old input first to ensure that the mixer output sample rate | 239 // Destroy the old input first to ensure that the mixer output sample rate |
| 179 // is updated. | 240 // is updated. |
| 180 mixer_input_.reset(); | 241 mixer_input_.reset(); |
| 181 mixer_input_.reset(new StreamMixerAlsaInput( | 242 mixer_input_.reset(new StreamMixerAlsaInput( |
| 182 this, config.samples_per_second, backend_->Primary())); | 243 this, config.samples_per_second, backend_->Primary())); |
| 183 mixer_input_->SetVolumeMultiplier(volume_multiplier_); | 244 mixer_input_->SetVolumeMultiplier(volume_multiplier_); |
| 245 pending_output_frames_ = kNoPendingOutput; | |
| 184 } | 246 } |
| 185 | 247 |
| 186 config_ = config; | 248 config_ = config; |
| 187 decoder_.reset(); | 249 decoder_.reset(); |
| 188 CreateDecoder(); | 250 CreateDecoder(); |
| 251 | |
| 252 if (pending_buffer_complete_ && !rate_shifter_->IsQueueFull()) { | |
| 253 pending_buffer_complete_ = false; | |
| 254 delegate_->OnPushBufferComplete(MediaPipelineBackendAlsa::kBufferSuccess); | |
| 255 } | |
| 189 return true; | 256 return true; |
| 190 } | 257 } |
| 191 | 258 |
| 192 void AudioDecoderAlsa::CreateDecoder() { | 259 void AudioDecoderAlsa::CreateDecoder() { |
| 193 DCHECK(!decoder_); | 260 DCHECK(!decoder_); |
| 194 DCHECK(IsValidConfig(config_)); | 261 DCHECK(IsValidConfig(config_)); |
| 195 | 262 |
| 196 // No need to create a decoder if the samples are already decoded. | 263 // No need to create a decoder if the samples are already decoded. |
| 197 if (BypassDecoder()) { | 264 if (BypassDecoder()) { |
| 198 LOG(INFO) << "Data is not coded. Decoder will not be used."; | 265 LOG(INFO) << "Data is not coded. Decoder will not be used."; |
| 199 return; | 266 return; |
| 200 } | 267 } |
| 201 | 268 |
| 202 // Create a decoder. | 269 // Create a decoder. |
| 203 decoder_ = CastAudioDecoder::Create( | 270 decoder_ = CastAudioDecoder::Create( |
| 204 task_runner_, | 271 task_runner_, |
| 205 config_, | 272 config_, |
| 206 kDecoderSampleFormat, | 273 kDecoderSampleFormat, |
| 207 base::Bind(&AudioDecoderAlsa::OnDecoderInitialized, | 274 base::Bind(&AudioDecoderAlsa::OnDecoderInitialized, |
| 208 weak_factory_.GetWeakPtr())); | 275 weak_factory_.GetWeakPtr())); |
| 209 } | 276 } |
| 210 | 277 |
| 278 void AudioDecoderAlsa::CreateRateShifter(int samples_per_second) { | |
| 279 rate_shifter_info_.clear(); | |
| 280 rate_shifter_info_.push_back(RateShifterInfo(1.0f)); | |
| 281 | |
| 282 rate_shifter_.reset(new ::media::AudioRendererAlgorithm()); | |
| 283 rate_shifter_->Initialize(::media::AudioParameters( | |
| 284 ::media::AudioParameters::AUDIO_PCM_LINEAR, | |
| 285 ::media::CHANNEL_LAYOUT_STEREO, samples_per_second, kBitsPerSample, | |
| 286 kDefaultFramesPerBuffer)); | |
| 287 } | |
| 288 | |
| 211 bool AudioDecoderAlsa::SetVolume(float multiplier) { | 289 bool AudioDecoderAlsa::SetVolume(float multiplier) { |
| 212 TRACE_FUNCTION_ENTRY1(multiplier); | 290 TRACE_FUNCTION_ENTRY1(multiplier); |
| 213 DCHECK(task_runner_->BelongsToCurrentThread()); | 291 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 214 volume_multiplier_ = multiplier; | 292 volume_multiplier_ = multiplier; |
| 215 if (mixer_input_) | 293 if (mixer_input_) |
| 216 mixer_input_->SetVolumeMultiplier(volume_multiplier_); | 294 mixer_input_->SetVolumeMultiplier(volume_multiplier_); |
| 217 return true; | 295 return true; |
| 218 } | 296 } |
| 219 | 297 |
| 220 AudioDecoderAlsa::RenderingDelay AudioDecoderAlsa::GetRenderingDelay() { | 298 AudioDecoderAlsa::RenderingDelay AudioDecoderAlsa::GetRenderingDelay() { |
| 221 TRACE_FUNCTION_ENTRY0(); | 299 TRACE_FUNCTION_ENTRY0(); |
| 222 return last_known_delay_; | 300 AudioDecoderAlsa::RenderingDelay delay = last_mixer_delay_; |
| 301 if (delay.timestamp_microseconds != kInvalidTimestamp) { | |
| 302 double usec_per_sample = 1000000.0 / config_.samples_per_second; | |
| 303 | |
| 304 // Account for data that has been queued in the rate shifters. | |
| 305 for (const RateShifterInfo& info : rate_shifter_info_) { | |
| 306 double queued_output_frames = | |
| 307 (info.input_frames / info.rate) - info.output_frames; | |
| 308 delay.delay_microseconds += queued_output_frames * usec_per_sample; | |
| 309 } | |
| 310 | |
| 311 // Account for data that is in the process of being pushed to the mixer. | |
| 312 if (pending_output_frames_ != kNoPendingOutput) { | |
| 313 delay.delay_microseconds += pending_output_frames_ * usec_per_sample; | |
| 314 } | |
| 315 } | |
| 316 | |
| 317 return delay; | |
| 223 } | 318 } |
| 224 | 319 |
| 225 void AudioDecoderAlsa::OnDecoderInitialized(bool success) { | 320 void AudioDecoderAlsa::OnDecoderInitialized(bool success) { |
| 226 TRACE_FUNCTION_ENTRY0(); | 321 TRACE_FUNCTION_ENTRY0(); |
| 227 DCHECK(task_runner_->BelongsToCurrentThread()); | 322 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 228 LOG(INFO) << "Decoder initialization was " | 323 LOG(INFO) << "Decoder initialization was " |
| 229 << (success ? "successful" : "unsuccessful"); | 324 << (success ? "successful" : "unsuccessful"); |
| 230 if (!success) | 325 if (!success) |
| 231 delegate_->OnDecoderError(); | 326 delegate_->OnDecoderError(); |
| 232 } | 327 } |
| 233 | 328 |
| 234 void AudioDecoderAlsa::OnBufferDecoded( | 329 void AudioDecoderAlsa::OnBufferDecoded( |
| 235 uint64_t input_bytes, | 330 uint64_t input_bytes, |
| 236 CastAudioDecoder::Status status, | 331 CastAudioDecoder::Status status, |
| 237 const scoped_refptr<DecoderBufferBase>& decoded) { | 332 const scoped_refptr<DecoderBufferBase>& decoded) { |
| 238 TRACE_FUNCTION_ENTRY0(); | 333 TRACE_FUNCTION_ENTRY0(); |
| 239 DCHECK(task_runner_->BelongsToCurrentThread()); | 334 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 240 DCHECK(!is_eos_); | 335 DCHECK(!got_eos_); |
| 241 | 336 DCHECK(!pending_buffer_complete_); |
| 242 Statistics delta = Statistics(); | 337 DCHECK(rate_shifter_); |
| 243 | 338 |
| 244 if (status == CastAudioDecoder::Status::kDecodeError) { | 339 if (status == CastAudioDecoder::Status::kDecodeError) { |
| 245 LOG(ERROR) << "Decode error"; | 340 LOG(ERROR) << "Decode error"; |
| 246 task_runner_->PostTask(FROM_HERE, | 341 delegate_->OnPushBufferComplete(MediaPipelineBackendAlsa::kBufferFailed); |
| 247 base::Bind(&AudioDecoderAlsa::OnWritePcmCompletion, | 342 return; |
| 248 weak_factory_.GetWeakPtr(), | 343 } |
| 249 MediaPipelineBackendAlsa::kBufferFailed, | 344 if (mixer_error_) { |
| 250 kInvalidRenderingDelay())); | 345 delegate_->OnPushBufferComplete(MediaPipelineBackendAlsa::kBufferFailed); |
| 251 UpdateStatistics(delta); | |
| 252 return; | 346 return; |
| 253 } | 347 } |
| 254 | 348 |
| 349 Statistics delta; | |
| 255 delta.decoded_bytes = input_bytes; | 350 delta.decoded_bytes = input_bytes; |
| 256 UpdateStatistics(delta); | 351 UpdateStatistics(delta); |
| 257 | 352 |
| 258 if (decoded->end_of_stream()) | 353 if (decoded->end_of_stream()) { |
| 259 is_eos_ = true; | 354 got_eos_ = true; |
| 355 } else { | |
| 356 int input_frames = decoded->data_size() / (kNumChannels * sizeof(float)); | |
| 260 | 357 |
| 358 DCHECK(!rate_shifter_info_.empty()); | |
| 359 RateShifterInfo* rate_info = &rate_shifter_info_.front(); | |
| 360 // Bypass rate shifter if the rate is 1.0, and there are no frames queued | |
| 361 // in the rate shifter. | |
| 362 if (rate_info->rate == 1.0 && rate_shifter_->frames_buffered() == 0 && | |
| 363 pending_output_frames_ == kNoPendingOutput) { | |
| 364 DCHECK_EQ(rate_info->output_frames, rate_info->input_frames); | |
| 365 pending_buffer_complete_ = true; | |
| 366 pending_output_frames_ = input_frames; | |
| 367 if (got_eos_) { | |
| 368 DCHECK(!pushed_eos_); | |
| 369 pushed_eos_ = true; | |
| 370 } | |
| 371 mixer_input_->WritePcm(decoded); | |
| 372 return; | |
| 373 } | |
| 374 | |
| 375 // Otherwise, queue data into the rate shifter, and then try to push the | |
| 376 // rate-shifted data. | |
| 377 const uint8_t* channels[kNumChannels] = { | |
| 378 decoded->data(), decoded->data() + input_frames * sizeof(float)}; | |
| 379 scoped_refptr<::media::AudioBuffer> buffer = ::media::AudioBuffer::CopyFrom( | |
| 380 ::media::kSampleFormatPlanarF32, ::media::CHANNEL_LAYOUT_STEREO, | |
| 381 kNumChannels, config_.samples_per_second, input_frames, channels, | |
| 382 base::TimeDelta()); | |
| 383 rate_shifter_->EnqueueBuffer(buffer); | |
| 384 rate_shifter_info_.back().input_frames += input_frames; | |
| 385 } | |
| 386 | |
| 387 PushRateShifted(); | |
| 388 DCHECK(!rate_shifter_info_.empty()); | |
| 389 // Can't check got_eos_ here, since it may have already been reset by a call | |
| 390 // to Stop(). | |
| 391 if (decoded->end_of_stream() || (!rate_shifter_->IsQueueFull() && | |
| 392 rate_shifter_info_.front().rate != 1.0)) { | |
| 393 delegate_->OnPushBufferComplete(MediaPipelineBackendAlsa::kBufferSuccess); | |
| 394 } else { | |
| 395 pending_buffer_complete_ = true; | |
| 396 } | |
| 397 } | |
| 398 | |
| 399 void AudioDecoderAlsa::PushRateShifted() { | |
| 261 DCHECK(mixer_input_); | 400 DCHECK(mixer_input_); |
| 262 mixer_input_->WritePcm(decoded); | 401 |
| 402 if (pending_output_frames_ != kNoPendingOutput) { | |
| 403 return; | |
| 404 } | |
| 405 | |
| 406 if (got_eos_) { | |
| 407 // Push some silence into the rate shifter so we can get out any remaining | |
| 408 // rate-shifted data. | |
| 409 rate_shifter_->EnqueueBuffer( | |
| 410 CreateSilenceBuffer(config_.samples_per_second)); | |
| 411 } | |
| 412 | |
| 413 DCHECK(!rate_shifter_info_.empty()); | |
| 414 RateShifterInfo* rate_info = &rate_shifter_info_.front(); | |
| 415 int64_t possible_output_frames = rate_info->input_frames / rate_info->rate; | |
| 416 DCHECK_GE(possible_output_frames, rate_info->output_frames); | |
| 417 | |
| 418 int desired_output_frames = possible_output_frames - rate_info->output_frames; | |
| 419 if (desired_output_frames == 0) { | |
| 420 if (got_eos_) { | |
| 421 DCHECK(!pushed_eos_); | |
| 422 pending_output_frames_ = 0; | |
| 423 pushed_eos_ = true; | |
| 424 | |
| 425 scoped_refptr<DecoderBufferBase> eos_buffer( | |
| 426 new DecoderBufferAdapter(::media::DecoderBuffer::CreateEOSBuffer())); | |
| 427 mixer_input_->WritePcm(eos_buffer); | |
| 428 } | |
| 429 return; | |
| 430 } | |
| 431 // Don't push too many frames at a time. | |
| 432 desired_output_frames = std::min( | |
| 433 desired_output_frames, | |
| 434 config_.samples_per_second * kMaxOutputMs / kMillisecondsPerSecond); | |
| 435 | |
| 436 if (desired_output_frames > rate_shifter_output_->frames()) { | |
| 437 rate_shifter_output_ = | |
| 438 ::media::AudioBus::Create(kNumChannels, desired_output_frames); | |
| 439 } | |
| 440 | |
| 441 int out_frames = rate_shifter_->FillBuffer( | |
| 442 rate_shifter_output_.get(), 0, desired_output_frames, rate_info->rate); | |
| 443 if (out_frames <= 0) { | |
| 444 return; | |
| 445 } | |
| 446 | |
| 447 rate_info->output_frames += out_frames; | |
| 448 DCHECK_GE(possible_output_frames, rate_info->output_frames); | |
| 449 | |
| 450 int channel_data_size = out_frames * sizeof(float); | |
| 451 scoped_refptr<DecoderBufferBase> output_buffer(new DecoderBufferAdapter( | |
| 452 new ::media::DecoderBuffer(channel_data_size * kNumChannels))); | |
| 453 for (int c = 0; c < kNumChannels; ++c) { | |
| 454 memcpy(output_buffer->writable_data() + c * channel_data_size, | |
| 455 rate_shifter_output_->channel(c), channel_data_size); | |
| 456 } | |
| 457 pending_output_frames_ = out_frames; | |
| 458 mixer_input_->WritePcm(output_buffer); | |
| 459 | |
| 460 if (rate_shifter_info_.size() > 1 && | |
| 461 possible_output_frames == rate_info->output_frames) { | |
| 462 double remaining_input_frames = | |
| 463 rate_info->input_frames - (rate_info->output_frames * rate_info->rate); | |
| 464 rate_shifter_info_.pop_front(); | |
| 465 | |
| 466 rate_info = &rate_shifter_info_.front(); | |
| 467 LOG(INFO) << "New playback rate in effect: " << rate_info->rate; | |
| 468 rate_info->input_frames += remaining_input_frames; | |
| 469 DCHECK_EQ(0, rate_info->output_frames); | |
| 470 | |
| 471 // If new playback rate is 1.0, clear out 'extra' data in the rate shifter. | |
| 472 // When doing rate shifting, the rate shifter queue holds data after it has | |
| 473 // been logically played; once we switch to passthrough mode (rate == 1.0), | |
| 474 // that old data needs to be cleared out. | |
| 475 if (rate_info->rate == 1.0) { | |
| 476 int extra_frames = rate_shifter_->frames_buffered() - | |
| 477 static_cast<int>(rate_info->input_frames); | |
| 478 if (extra_frames > 0) { | |
| 479 // Clear out extra buffered data. | |
| 480 std::unique_ptr<::media::AudioBus> dropped = | |
| 481 ::media::AudioBus::Create(kNumChannels, extra_frames); | |
| 482 int cleared_frames = | |
| 483 rate_shifter_->FillBuffer(dropped.get(), 0, extra_frames, 1.0f); | |
| 484 DCHECK_EQ(extra_frames, cleared_frames); | |
| 485 } | |
| 486 rate_info->input_frames = rate_shifter_->frames_buffered(); | |
| 487 } | |
| 488 } | |
| 263 } | 489 } |
| 264 | 490 |
| 265 bool AudioDecoderAlsa::BypassDecoder() const { | 491 bool AudioDecoderAlsa::BypassDecoder() const { |
| 266 DCHECK(task_runner_->BelongsToCurrentThread()); | 492 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 267 // The mixer input requires planar float PCM data. | 493 // The mixer input requires planar float PCM data. |
| 268 return (config_.codec == kCodecPCM && | 494 return (config_.codec == kCodecPCM && |
| 269 config_.sample_format == kSampleFormatPlanarF32); | 495 config_.sample_format == kSampleFormatPlanarF32); |
| 270 } | 496 } |
| 271 | 497 |
| 272 void AudioDecoderAlsa::OnWritePcmCompletion(BufferStatus status, | 498 void AudioDecoderAlsa::OnWritePcmCompletion(BufferStatus status, |
| 273 const RenderingDelay& delay) { | 499 const RenderingDelay& delay) { |
| 274 TRACE_FUNCTION_ENTRY0(); | 500 TRACE_FUNCTION_ENTRY0(); |
| 275 DCHECK(task_runner_->BelongsToCurrentThread()); | 501 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 276 if (status == MediaPipelineBackendAlsa::kBufferSuccess && !is_eos_) | 502 DCHECK_EQ(MediaPipelineBackendAlsa::kBufferSuccess, status); |
| 277 current_pts_ = last_buffer_pts_; | 503 pending_output_frames_ = kNoPendingOutput; |
| 278 if (delay.timestamp_microseconds != kInvalidDelayTimestamp) | 504 last_mixer_delay_ = delay; |
| 279 last_known_delay_ = delay; | 505 |
| 280 delegate_->OnPushBufferComplete(status); | 506 if (pushed_eos_) { |
| 281 if (is_eos_) | 507 if (pending_buffer_complete_) { |
| 508 pending_buffer_complete_ = false; | |
| 509 delegate_->OnPushBufferComplete(MediaPipelineBackendAlsa::kBufferSuccess); | |
| 510 } | |
| 282 delegate_->OnEndOfStream(); | 511 delegate_->OnEndOfStream(); |
| 512 } else { | |
| 513 task_runner_->PostTask(FROM_HERE, base::Bind(&AudioDecoderAlsa::PushMorePcm, | |
| 514 weak_factory_.GetWeakPtr())); | |
| 515 } | |
| 516 } | |
| 517 | |
| 518 void AudioDecoderAlsa::PushMorePcm() { | |
| 519 PushRateShifted(); | |
| 520 | |
| 521 DCHECK(!rate_shifter_info_.empty()); | |
| 522 if (pending_buffer_complete_) { | |
| 523 double rate = rate_shifter_info_.front().rate; | |
| 524 if ((rate == 1.0 && pending_output_frames_ == kNoPendingOutput) || | |
| 525 (rate != 1.0 && !rate_shifter_->IsQueueFull())) { | |
| 526 pending_buffer_complete_ = false; | |
| 527 delegate_->OnPushBufferComplete(MediaPipelineBackendAlsa::kBufferSuccess); | |
| 528 } | |
| 529 } | |
| 283 } | 530 } |
| 284 | 531 |
| 285 void AudioDecoderAlsa::OnMixerError(MixerError error) { | 532 void AudioDecoderAlsa::OnMixerError(MixerError error) { |
| 286 TRACE_FUNCTION_ENTRY0(); | 533 TRACE_FUNCTION_ENTRY0(); |
| 287 DCHECK(task_runner_->BelongsToCurrentThread()); | 534 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 288 if (error != MixerError::kInputIgnored) | 535 if (error != MixerError::kInputIgnored) |
| 289 LOG(ERROR) << "Mixer error occurred."; | 536 LOG(ERROR) << "Mixer error occurred."; |
| 290 error_ = true; | 537 mixer_error_ = true; |
| 291 delegate_->OnDecoderError(); | 538 delegate_->OnDecoderError(); |
| 292 } | 539 } |
| 293 | 540 |
| 294 } // namespace media | 541 } // namespace media |
| 295 } // namespace chromecast | 542 } // namespace chromecast |
| OLD | NEW |