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 |