| 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 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 scoped_refptr<AudioBuffer> output; | 225 scoped_refptr<AudioBuffer> output; |
| 226 | 226 |
| 227 bool config_changed = false; | 227 bool config_changed = false; |
| 228 if (frame_decoded) { | 228 if (frame_decoded) { |
| 229 const int channels = DetermineChannels(av_frame_.get()); | 229 const int channels = DetermineChannels(av_frame_.get()); |
| 230 ChannelLayout channel_layout = ChannelLayoutToChromeChannelLayout( | 230 ChannelLayout channel_layout = ChannelLayoutToChromeChannelLayout( |
| 231 codec_context_->channel_layout, codec_context_->channels); | 231 codec_context_->channel_layout, codec_context_->channels); |
| 232 | 232 |
| 233 bool is_sample_rate_change = | 233 bool is_sample_rate_change = |
| 234 av_frame_->sample_rate != config_.samples_per_second(); | 234 av_frame_->sample_rate != config_.samples_per_second(); |
| 235 bool is_config_stale = | 235 bool is_config_stale = is_sample_rate_change || |
| 236 is_sample_rate_change || | 236 channels != config_.channels() || |
| 237 channels != ChannelLayoutToChannelCount(config_.channel_layout()) || | 237 av_frame_->format != av_sample_format_; |
| 238 av_frame_->format != av_sample_format_; | |
| 239 | 238 |
| 240 // Only consider channel layout changes for AAC. | 239 // Only consider channel layout changes for AAC. |
| 241 // TODO(tguilbert, dalecurtis): Due to http://crbug.com/600538 we need to | 240 // TODO(tguilbert, dalecurtis): Due to http://crbug.com/600538 we need to |
| 242 // allow channel layout changes for the moment. See if ffmpeg is fixable. | 241 // allow channel layout changes for the moment. See if ffmpeg is fixable. |
| 243 if (config_.codec() == kCodecAAC) | 242 if (config_.codec() == kCodecAAC) |
| 244 is_config_stale |= channel_layout != config_.channel_layout(); | 243 is_config_stale |= channel_layout != config_.channel_layout(); |
| 245 | 244 |
| 246 if (is_config_stale) { | 245 if (is_config_stale) { |
| 247 // Only allow midstream configuration changes for AAC. Sample format is | 246 // Only allow midstream configuration changes for AAC. Sample format is |
| 248 // not expected to change between AAC profiles. | 247 // not expected to change between AAC profiles. |
| 249 if (config_.codec() == kCodecAAC && | 248 if (config_.codec() == kCodecAAC && |
| 250 av_frame_->format == av_sample_format_) { | 249 av_frame_->format == av_sample_format_) { |
| 251 MEDIA_LOG(DEBUG, media_log_) | 250 MEDIA_LOG(DEBUG, media_log_) |
| 252 << " Detected AAC midstream configuration change" | 251 << " Detected AAC midstream configuration change" |
| 253 << " PTS:" << buffer->timestamp().InMicroseconds() | 252 << " PTS:" << buffer->timestamp().InMicroseconds() |
| 254 << " Sample Rate: " << av_frame_->sample_rate << " vs " | 253 << " Sample Rate: " << av_frame_->sample_rate << " vs " |
| 255 << config_.samples_per_second() | 254 << config_.samples_per_second() |
| 256 << ", ChannelLayout: " << channel_layout << " vs " | 255 << ", ChannelLayout: " << channel_layout << " vs " |
| 257 << config_.channel_layout() << ", Channels: " << channels | 256 << config_.channel_layout() << ", Channels: " << channels |
| 258 << " vs " | 257 << " vs " << config_.channels(); |
| 259 << ChannelLayoutToChannelCount(config_.channel_layout()); | |
| 260 config_.Initialize(config_.codec(), config_.sample_format(), | 258 config_.Initialize(config_.codec(), config_.sample_format(), |
| 261 channel_layout, av_frame_->sample_rate, | 259 channel_layout, av_frame_->sample_rate, |
| 262 config_.extra_data(), config_.encryption_scheme(), | 260 config_.extra_data(), config_.encryption_scheme(), |
| 263 config_.seek_preroll(), config_.codec_delay()); | 261 config_.seek_preroll(), config_.codec_delay()); |
| 264 config_changed = true; | 262 config_changed = true; |
| 265 if (is_sample_rate_change) | 263 if (is_sample_rate_change) |
| 266 ResetTimestampState(config_); | 264 ResetTimestampState(config_); |
| 267 } else { | 265 } else { |
| 268 MEDIA_LOG(ERROR, media_log_) | 266 MEDIA_LOG(ERROR, media_log_) |
| 269 << "Unsupported midstream configuration change!" | 267 << "Unsupported midstream configuration change!" |
| 270 << " Sample Rate: " << av_frame_->sample_rate << " vs " | 268 << " Sample Rate: " << av_frame_->sample_rate << " vs " |
| 271 << config_.samples_per_second() << ", Channels: " << channels | 269 << config_.samples_per_second() << ", Channels: " << channels |
| 272 << " vs " << ChannelLayoutToChannelCount(config_.channel_layout()) | 270 << " vs " << config_.channels() |
| 273 << ", Sample Format: " << av_frame_->format << " vs " | 271 << ", Sample Format: " << av_frame_->format << " vs " |
| 274 << av_sample_format_; | 272 << av_sample_format_; |
| 275 // This is an unrecoverable error, so bail out. | 273 // This is an unrecoverable error, so bail out. |
| 276 av_frame_unref(av_frame_.get()); | 274 av_frame_unref(av_frame_.get()); |
| 277 return false; | 275 return false; |
| 278 } | 276 } |
| 279 } | 277 } |
| 280 | 278 |
| 281 // Get the AudioBuffer that the data was decoded into. Adjust the number | 279 // Get the AudioBuffer that the data was decoded into. Adjust the number |
| 282 // of frames, in case fewer than requested were actually decoded. | 280 // of frames, in case fewer than requested were actually decoded. |
| 283 output = reinterpret_cast<AudioBuffer*>( | 281 output = reinterpret_cast<AudioBuffer*>( |
| 284 av_buffer_get_opaque(av_frame_->buf[0])); | 282 av_buffer_get_opaque(av_frame_->buf[0])); |
| 285 | 283 |
| 286 DCHECK_EQ(ChannelLayoutToChannelCount(config_.channel_layout()), | 284 DCHECK_EQ(config_.channels(), output->channel_count()); |
| 287 output->channel_count()); | |
| 288 const int unread_frames = output->frame_count() - av_frame_->nb_samples; | 285 const int unread_frames = output->frame_count() - av_frame_->nb_samples; |
| 289 DCHECK_GE(unread_frames, 0); | 286 DCHECK_GE(unread_frames, 0); |
| 290 if (unread_frames > 0) | 287 if (unread_frames > 0) |
| 291 output->TrimEnd(unread_frames); | 288 output->TrimEnd(unread_frames); |
| 292 av_frame_unref(av_frame_.get()); | 289 av_frame_unref(av_frame_.get()); |
| 293 } | 290 } |
| 294 | 291 |
| 295 // WARNING: |av_frame_| no longer has valid data at this point. | 292 // WARNING: |av_frame_| no longer has valid data at this point. |
| 296 const int decoded_frames = frame_decoded ? output->frame_count() : 0; | 293 const int decoded_frames = frame_decoded ? output->frame_count() : 0; |
| 297 if (IsEndOfStream(result, decoded_frames, buffer)) { | 294 if (IsEndOfStream(result, decoded_frames, buffer)) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 << codec_context_->codec_id; | 339 << codec_context_->codec_id; |
| 343 ReleaseFFmpegResources(); | 340 ReleaseFFmpegResources(); |
| 344 state_ = kUninitialized; | 341 state_ = kUninitialized; |
| 345 return false; | 342 return false; |
| 346 } | 343 } |
| 347 | 344 |
| 348 // Success! | 345 // Success! |
| 349 av_frame_.reset(av_frame_alloc()); | 346 av_frame_.reset(av_frame_alloc()); |
| 350 av_sample_format_ = codec_context_->sample_fmt; | 347 av_sample_format_ = codec_context_->sample_fmt; |
| 351 | 348 |
| 352 if (codec_context_->channels != | 349 if (codec_context_->channels != config.channels()) { |
| 353 ChannelLayoutToChannelCount(config.channel_layout())) { | |
| 354 MEDIA_LOG(ERROR, media_log_) | 350 MEDIA_LOG(ERROR, media_log_) |
| 355 << "Audio configuration specified " | 351 << "Audio configuration specified " << config.channels() |
| 356 << ChannelLayoutToChannelCount(config.channel_layout()) | |
| 357 << " channels, but FFmpeg thinks the file contains " | 352 << " channels, but FFmpeg thinks the file contains " |
| 358 << codec_context_->channels << " channels"; | 353 << codec_context_->channels << " channels"; |
| 359 ReleaseFFmpegResources(); | 354 ReleaseFFmpegResources(); |
| 360 state_ = kUninitialized; | 355 state_ = kUninitialized; |
| 361 return false; | 356 return false; |
| 362 } | 357 } |
| 363 | 358 |
| 364 ResetTimestampState(config); | 359 ResetTimestampState(config); |
| 365 return true; | 360 return true; |
| 366 } | 361 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 int buffer_size_in_bytes = av_samples_get_buffer_size( | 410 int buffer_size_in_bytes = av_samples_get_buffer_size( |
| 416 &frame->linesize[0], channels, frame->nb_samples, format, | 411 &frame->linesize[0], channels, frame->nb_samples, format, |
| 417 0 /* align, use ffmpeg default */); | 412 0 /* align, use ffmpeg default */); |
| 418 // Check for errors from av_samples_get_buffer_size(). | 413 // Check for errors from av_samples_get_buffer_size(). |
| 419 if (buffer_size_in_bytes < 0) | 414 if (buffer_size_in_bytes < 0) |
| 420 return buffer_size_in_bytes; | 415 return buffer_size_in_bytes; |
| 421 int frames_required = buffer_size_in_bytes / bytes_per_channel / channels; | 416 int frames_required = buffer_size_in_bytes / bytes_per_channel / channels; |
| 422 DCHECK_GE(frames_required, frame->nb_samples); | 417 DCHECK_GE(frames_required, frame->nb_samples); |
| 423 | 418 |
| 424 ChannelLayout channel_layout = | 419 ChannelLayout channel_layout = |
| 425 ChannelLayoutToChromeChannelLayout(s->channel_layout, s->channels); | 420 config_.channel_layout() == CHANNEL_LAYOUT_DISCRETE |
| 421 ? CHANNEL_LAYOUT_DISCRETE |
| 422 : ChannelLayoutToChromeChannelLayout(s->channel_layout, s->channels); |
| 426 | 423 |
| 427 if (channel_layout == CHANNEL_LAYOUT_UNSUPPORTED) { | 424 if (config_.channel_layout() == CHANNEL_LAYOUT_UNSUPPORTED) { |
| 428 DLOG(ERROR) << "Unsupported channel layout."; | 425 DLOG(ERROR) << "Unsupported channel layout."; |
| 429 return AVERROR(EINVAL); | 426 return AVERROR(EINVAL); |
| 430 } | 427 } |
| 431 | 428 |
| 432 scoped_refptr<AudioBuffer> buffer = | 429 scoped_refptr<AudioBuffer> buffer = |
| 433 AudioBuffer::CreateBuffer(sample_format, channel_layout, channels, | 430 AudioBuffer::CreateBuffer(sample_format, channel_layout, channels, |
| 434 s->sample_rate, frames_required, pool_); | 431 s->sample_rate, frames_required, pool_); |
| 435 | 432 |
| 436 // Initialize the data[] and extended_data[] fields to point into the memory | 433 // Initialize the data[] and extended_data[] fields to point into the memory |
| 437 // allocated for AudioBuffer. |number_of_planes| will be 1 for interleaved | 434 // allocated for AudioBuffer. |number_of_planes| will be 1 for interleaved |
| (...skipping 18 matching lines...) Expand all Loading... |
| 456 // Now create an AVBufferRef for the data just allocated. It will own the | 453 // Now create an AVBufferRef for the data just allocated. It will own the |
| 457 // reference to the AudioBuffer object. | 454 // reference to the AudioBuffer object. |
| 458 AudioBuffer* opaque = buffer.get(); | 455 AudioBuffer* opaque = buffer.get(); |
| 459 opaque->AddRef(); | 456 opaque->AddRef(); |
| 460 frame->buf[0] = av_buffer_create(frame->data[0], buffer_size_in_bytes, | 457 frame->buf[0] = av_buffer_create(frame->data[0], buffer_size_in_bytes, |
| 461 ReleaseAudioBufferImpl, opaque, 0); | 458 ReleaseAudioBufferImpl, opaque, 0); |
| 462 return 0; | 459 return 0; |
| 463 } | 460 } |
| 464 | 461 |
| 465 } // namespace media | 462 } // namespace media |
| OLD | NEW |