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 |