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