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