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 "media/filters/ffmpeg_audio_decoder.h" | 5 #include "media/filters/ffmpeg_audio_decoder.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
| 10 #include "base/single_thread_task_runner.h" | 10 #include "base/single_thread_task_runner.h" |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 71 | 71 |
| 72 int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format); | 72 int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format); |
| 73 if (frame->nb_samples <= 0) | 73 if (frame->nb_samples <= 0) |
| 74 return AVERROR(EINVAL); | 74 return AVERROR(EINVAL); |
| 75 | 75 |
| 76 if (s->channels != channels) { | 76 if (s->channels != channels) { |
| 77 DLOG(ERROR) << "AVCodecContext and AVFrame disagree on channel count."; | 77 DLOG(ERROR) << "AVCodecContext and AVFrame disagree on channel count."; |
| 78 return AVERROR(EINVAL); | 78 return AVERROR(EINVAL); |
| 79 } | 79 } |
| 80 | 80 |
| 81 if (s->sample_rate != frame->sample_rate) { | |
| 82 DLOG(ERROR) << "AVCodecContext and AVFrame disagree on sample rate." | |
| 83 << s->sample_rate << " vs " << frame->sample_rate; | |
| 84 return AVERROR(EINVAL); | |
| 85 } | |
| 86 | |
| 81 // Determine how big the buffer should be and allocate it. FFmpeg may adjust | 87 // Determine how big the buffer should be and allocate it. FFmpeg may adjust |
| 82 // how big each channel data is in order to meet the alignment policy, so | 88 // how big each channel data is in order to meet the alignment policy, so |
| 83 // we need to take this into consideration. | 89 // we need to take this into consideration. |
| 84 int buffer_size_in_bytes = | 90 int buffer_size_in_bytes = |
| 85 av_samples_get_buffer_size(&frame->linesize[0], | 91 av_samples_get_buffer_size(&frame->linesize[0], |
| 86 channels, | 92 channels, |
| 87 frame->nb_samples, | 93 frame->nb_samples, |
| 88 format, | 94 format, |
| 89 AudioBuffer::kChannelAlignment); | 95 AudioBuffer::kChannelAlignment); |
| 90 // Check for errors from av_samples_get_buffer_size(). | 96 // Check for errors from av_samples_get_buffer_size(). |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 280 | 286 |
| 281 break; | 287 break; |
| 282 } | 288 } |
| 283 | 289 |
| 284 // Update packet size and data pointer in case we need to call the decoder | 290 // Update packet size and data pointer in case we need to call the decoder |
| 285 // with the remaining bytes from this packet. | 291 // with the remaining bytes from this packet. |
| 286 packet.size -= result; | 292 packet.size -= result; |
| 287 packet.data += result; | 293 packet.data += result; |
| 288 | 294 |
| 289 scoped_refptr<AudioBuffer> output; | 295 scoped_refptr<AudioBuffer> output; |
| 290 const int channels = DetermineChannels(av_frame_.get()); | 296 |
| 297 bool config_changed = false; | |
| 291 if (frame_decoded) { | 298 if (frame_decoded) { |
| 299 const int channels = DetermineChannels(av_frame_.get()); | |
| 300 ChannelLayout channel_layout = ChannelLayoutToChromeChannelLayout( | |
| 301 codec_context_->channel_layout, codec_context_->channels); | |
| 302 | |
| 292 if (av_frame_->sample_rate != config_.samples_per_second() || | 303 if (av_frame_->sample_rate != config_.samples_per_second() || |
| 293 channels != ChannelLayoutToChannelCount(config_.channel_layout()) || | 304 channel_layout != config_.channel_layout() || |
| 305 channels != ChannelLayoutToChannelCount(config_.channel_layout()) || // IIUC, this should go. We previously allowed channel layout changes as long as the number of channels held fixed. Why? | |
|
DaleCurtis
2016/03/18 00:16:23
Needed as discussed via e-mail.
chcunningham
2016/03/25 01:41:16
Acknowledged.
| |
| 294 av_frame_->format != av_sample_format_) { | 306 av_frame_->format != av_sample_format_) { |
| 295 DLOG(ERROR) << "Unsupported midstream configuration change!" | |
| 296 << " Sample Rate: " << av_frame_->sample_rate << " vs " | |
| 297 << config_.samples_per_second() | |
| 298 << ", Channels: " << channels << " vs " | |
| 299 << ChannelLayoutToChannelCount(config_.channel_layout()) | |
| 300 << ", Sample Format: " << av_frame_->format << " vs " | |
| 301 << av_sample_format_; | |
| 302 | 307 |
| 308 // Only allow midstream configuration changes for AAC. Sample format is | |
| 309 // not expected to change between AAC profiles. | |
| 303 if (config_.codec() == kCodecAAC && | 310 if (config_.codec() == kCodecAAC && |
| 304 av_frame_->sample_rate == 2 * config_.samples_per_second()) { | 311 av_frame_->format == av_sample_format_) { |
| 305 MEDIA_LOG(DEBUG, media_log_) | 312 MEDIA_LOG(DEBUG, media_log_) |
| 306 << "Implicit HE-AAC signalling is being" | 313 << " Detected AAC midstream configuration change" |
| 307 << " used. Please use mp4a.40.5 instead of" | 314 << " PTS:" << buffer->timestamp().InMicroseconds() |
| 308 << " mp4a.40.2 in the mimetype."; | 315 << " Sample Rate: " << av_frame_->sample_rate << " vs " |
| 316 << config_.samples_per_second() | |
| 317 << ", ChannelLayout: " << channel_layout << " vs " | |
| 318 << config_.channel_layout() | |
| 319 << ", Channels: " << channels << " vs " | |
| 320 << ChannelLayoutToChannelCount(config_.channel_layout()); | |
| 321 config_.Initialize(config_.codec(), | |
| 322 config_.sample_format(), | |
| 323 channel_layout, | |
| 324 av_frame_->sample_rate, | |
| 325 config_.extra_data(), | |
| 326 config_.encryption_scheme(), | |
| 327 config_.seek_preroll(), | |
| 328 config_.codec_delay()); | |
| 329 config_changed = true; | |
| 330 ResetTimestampState(); | |
| 331 } else { | |
| 332 MEDIA_LOG(ERROR, media_log_) | |
| 333 << "Unsupported midstream configuration change!" | |
| 334 << " Sample Rate: " << av_frame_->sample_rate << " vs " | |
| 335 << config_.samples_per_second() | |
| 336 << ", Channels: " << channels << " vs " | |
| 337 << ChannelLayoutToChannelCount(config_.channel_layout()) | |
| 338 << ", Sample Format: " << av_frame_->format << " vs " | |
| 339 << av_sample_format_; | |
| 340 // This is an unrecoverable error, so bail out. | |
| 341 av_frame_unref(av_frame_.get()); | |
| 342 return false; | |
| 309 } | 343 } |
| 310 // This is an unrecoverable error, so bail out. | |
| 311 av_frame_unref(av_frame_.get()); | |
| 312 return false; | |
| 313 } | 344 } |
| 314 | 345 |
| 315 // Get the AudioBuffer that the data was decoded into. Adjust the number | 346 // Get the AudioBuffer that the data was decoded into. Adjust the number |
| 316 // of frames, in case fewer than requested were actually decoded. | 347 // of frames, in case fewer than requested were actually decoded. |
| 317 output = reinterpret_cast<AudioBuffer*>( | 348 output = reinterpret_cast<AudioBuffer*>( |
| 318 av_buffer_get_opaque(av_frame_->buf[0])); | 349 av_buffer_get_opaque(av_frame_->buf[0])); |
| 319 | 350 |
| 320 DCHECK_EQ(ChannelLayoutToChannelCount(config_.channel_layout()), | 351 DCHECK_EQ(ChannelLayoutToChannelCount(config_.channel_layout()), |
| 321 output->channel_count()); | 352 output->channel_count()); |
| 322 const int unread_frames = output->frame_count() - av_frame_->nb_samples; | 353 const int unread_frames = output->frame_count() - av_frame_->nb_samples; |
| 323 DCHECK_GE(unread_frames, 0); | 354 DCHECK_GE(unread_frames, 0); |
| 324 if (unread_frames > 0) | 355 if (unread_frames > 0) |
| 325 output->TrimEnd(unread_frames); | 356 output->TrimEnd(unread_frames); |
| 326 av_frame_unref(av_frame_.get()); | 357 av_frame_unref(av_frame_.get()); |
| 327 } | 358 } |
| 328 | 359 |
| 329 // WARNING: |av_frame_| no longer has valid data at this point. | 360 // WARNING: |av_frame_| no longer has valid data at this point. |
| 330 const int decoded_frames = frame_decoded ? output->frame_count() : 0; | 361 const int decoded_frames = frame_decoded ? output->frame_count() : 0; |
| 331 if (IsEndOfStream(result, decoded_frames, buffer)) { | 362 if (IsEndOfStream(result, decoded_frames, buffer)) { |
| 332 DCHECK_EQ(packet.size, 0); | 363 DCHECK_EQ(packet.size, 0); |
| 333 } else if (discard_helper_->ProcessBuffers(buffer, output)) { | 364 } else if (discard_helper_->ProcessBuffers(buffer, output)) { |
| 365 if (config_changed && | |
| 366 output->sample_rate() != config_.samples_per_second()) { | |
| 367 // At the boundary of the config change, FFmpeg's AAC decoder gives the | |
| 368 // previous sample rate when calling our GetAudioBuffer. Set the correct | |
| 369 // sample rate before sending the buffer along. | |
| 370 // TODO(chcunningham): Fix FFmpeg and upstream it. | |
| 371 output->AdjustSampleRate(config_.samples_per_second()); | |
| 372 } | |
| 334 *has_produced_frame = true; | 373 *has_produced_frame = true; |
| 335 output_cb_.Run(output); | 374 output_cb_.Run(output); |
| 336 } | 375 } |
| 337 } while (packet.size > 0); | 376 } while (packet.size > 0); |
| 338 | 377 |
| 339 return true; | 378 return true; |
| 340 } | 379 } |
| 341 | 380 |
| 342 void FFmpegAudioDecoder::ReleaseFFmpegResources() { | 381 void FFmpegAudioDecoder::ReleaseFFmpegResources() { |
| 343 codec_context_.reset(); | 382 codec_context_.reset(); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 387 return true; | 426 return true; |
| 388 } | 427 } |
| 389 | 428 |
| 390 void FFmpegAudioDecoder::ResetTimestampState() { | 429 void FFmpegAudioDecoder::ResetTimestampState() { |
| 391 discard_helper_.reset(new AudioDiscardHelper(config_.samples_per_second(), | 430 discard_helper_.reset(new AudioDiscardHelper(config_.samples_per_second(), |
| 392 config_.codec_delay())); | 431 config_.codec_delay())); |
| 393 discard_helper_->Reset(config_.codec_delay()); | 432 discard_helper_->Reset(config_.codec_delay()); |
| 394 } | 433 } |
| 395 | 434 |
| 396 } // namespace media | 435 } // namespace media |
| OLD | NEW |