| 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() || |
| 304 channel_layout != config_.channel_layout() || |
| 293 channels != ChannelLayoutToChannelCount(config_.channel_layout()) || | 305 channels != ChannelLayoutToChannelCount(config_.channel_layout()) || |
| 294 av_frame_->format != av_sample_format_) { | 306 av_frame_->format != av_sample_format_) { |
| 295 DLOG(ERROR) << "Unsupported midstream configuration change!" | 307 // Only allow midstream configuration changes for AAC. Sample format is |
| 296 << " Sample Rate: " << av_frame_->sample_rate << " vs " | 308 // not expected to change between AAC profiles. |
| 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 | |
| 303 if (config_.codec() == kCodecAAC && | 309 if (config_.codec() == kCodecAAC && |
| 304 av_frame_->sample_rate == 2 * config_.samples_per_second()) { | 310 av_frame_->format == av_sample_format_) { |
| 305 MEDIA_LOG(DEBUG, media_log_) | 311 MEDIA_LOG(DEBUG, media_log_) |
| 306 << "Implicit HE-AAC signalling is being" | 312 << " Detected AAC midstream configuration change" |
| 307 << " used. Please use mp4a.40.5 instead of" | 313 << " PTS:" << buffer->timestamp().InMicroseconds() |
| 308 << " mp4a.40.2 in the mimetype."; | 314 << " Sample Rate: " << av_frame_->sample_rate << " vs " |
| 315 << config_.samples_per_second() |
| 316 << ", ChannelLayout: " << channel_layout << " vs " |
| 317 << config_.channel_layout() << ", Channels: " << channels |
| 318 << " vs " |
| 319 << ChannelLayoutToChannelCount(config_.channel_layout()); |
| 320 config_.Initialize(config_.codec(), config_.sample_format(), |
| 321 channel_layout, av_frame_->sample_rate, |
| 322 config_.extra_data(), config_.is_encrypted(), |
| 323 config_.seek_preroll(), config_.codec_delay()); |
| 324 config_changed = true; |
| 325 ResetTimestampState(); |
| 326 } else { |
| 327 MEDIA_LOG(ERROR, media_log_) |
| 328 << "Unsupported midstream configuration change!" |
| 329 << " Sample Rate: " << av_frame_->sample_rate << " vs " |
| 330 << config_.samples_per_second() << ", Channels: " << channels |
| 331 << " vs " << ChannelLayoutToChannelCount(config_.channel_layout()) |
| 332 << ", Sample Format: " << av_frame_->format << " vs " |
| 333 << av_sample_format_; |
| 334 // This is an unrecoverable error, so bail out. |
| 335 av_frame_unref(av_frame_.get()); |
| 336 return false; |
| 309 } | 337 } |
| 310 // This is an unrecoverable error, so bail out. | |
| 311 av_frame_unref(av_frame_.get()); | |
| 312 return false; | |
| 313 } | 338 } |
| 314 | 339 |
| 315 // Get the AudioBuffer that the data was decoded into. Adjust the number | 340 // Get the AudioBuffer that the data was decoded into. Adjust the number |
| 316 // of frames, in case fewer than requested were actually decoded. | 341 // of frames, in case fewer than requested were actually decoded. |
| 317 output = reinterpret_cast<AudioBuffer*>( | 342 output = reinterpret_cast<AudioBuffer*>( |
| 318 av_buffer_get_opaque(av_frame_->buf[0])); | 343 av_buffer_get_opaque(av_frame_->buf[0])); |
| 319 | 344 |
| 320 DCHECK_EQ(ChannelLayoutToChannelCount(config_.channel_layout()), | 345 DCHECK_EQ(ChannelLayoutToChannelCount(config_.channel_layout()), |
| 321 output->channel_count()); | 346 output->channel_count()); |
| 322 const int unread_frames = output->frame_count() - av_frame_->nb_samples; | 347 const int unread_frames = output->frame_count() - av_frame_->nb_samples; |
| 323 DCHECK_GE(unread_frames, 0); | 348 DCHECK_GE(unread_frames, 0); |
| 324 if (unread_frames > 0) | 349 if (unread_frames > 0) |
| 325 output->TrimEnd(unread_frames); | 350 output->TrimEnd(unread_frames); |
| 326 av_frame_unref(av_frame_.get()); | 351 av_frame_unref(av_frame_.get()); |
| 327 } | 352 } |
| 328 | 353 |
| 329 // WARNING: |av_frame_| no longer has valid data at this point. | 354 // WARNING: |av_frame_| no longer has valid data at this point. |
| 330 const int decoded_frames = frame_decoded ? output->frame_count() : 0; | 355 const int decoded_frames = frame_decoded ? output->frame_count() : 0; |
| 331 if (IsEndOfStream(result, decoded_frames, buffer)) { | 356 if (IsEndOfStream(result, decoded_frames, buffer)) { |
| 332 DCHECK_EQ(packet.size, 0); | 357 DCHECK_EQ(packet.size, 0); |
| 333 } else if (discard_helper_->ProcessBuffers(buffer, output)) { | 358 } else if (discard_helper_->ProcessBuffers(buffer, output)) { |
| 359 if (config_changed && |
| 360 output->sample_rate() != config_.samples_per_second()) { |
| 361 // At the boundary of the config change, FFmpeg's AAC decoder gives the |
| 362 // previous sample rate when calling our GetAudioBuffer. Set the correct |
| 363 // sample rate before sending the buffer along. |
| 364 // TODO(chcunningham): Fix FFmpeg and upstream it. |
| 365 output->AdjustSampleRate(config_.samples_per_second()); |
| 366 } |
| 334 *has_produced_frame = true; | 367 *has_produced_frame = true; |
| 335 output_cb_.Run(output); | 368 output_cb_.Run(output); |
| 336 } | 369 } |
| 337 } while (packet.size > 0); | 370 } while (packet.size > 0); |
| 338 | 371 |
| 339 return true; | 372 return true; |
| 340 } | 373 } |
| 341 | 374 |
| 342 void FFmpegAudioDecoder::ReleaseFFmpegResources() { | 375 void FFmpegAudioDecoder::ReleaseFFmpegResources() { |
| 343 codec_context_.reset(); | 376 codec_context_.reset(); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 return true; | 420 return true; |
| 388 } | 421 } |
| 389 | 422 |
| 390 void FFmpegAudioDecoder::ResetTimestampState() { | 423 void FFmpegAudioDecoder::ResetTimestampState() { |
| 391 discard_helper_.reset(new AudioDiscardHelper(config_.samples_per_second(), | 424 discard_helper_.reset(new AudioDiscardHelper(config_.samples_per_second(), |
| 392 config_.codec_delay())); | 425 config_.codec_delay())); |
| 393 discard_helper_->Reset(config_.codec_delay()); | 426 discard_helper_->Reset(config_.codec_delay()); |
| 394 } | 427 } |
| 395 | 428 |
| 396 } // namespace media | 429 } // namespace media |
| OLD | NEW |