| 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 "base/callback_helpers.h" | 7 #include "base/callback_helpers.h" |
| 8 #include "base/single_thread_task_runner.h" | 8 #include "base/single_thread_task_runner.h" |
| 9 #include "media/base/audio_buffer.h" | 9 #include "media/base/audio_buffer.h" |
| 10 #include "media/base/audio_bus.h" | 10 #include "media/base/audio_bus.h" |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 // reference to the AudioBuffer object. | 119 // reference to the AudioBuffer object. |
| 120 void* opaque = NULL; | 120 void* opaque = NULL; |
| 121 buffer.swap(reinterpret_cast<AudioBuffer**>(&opaque)); | 121 buffer.swap(reinterpret_cast<AudioBuffer**>(&opaque)); |
| 122 frame->buf[0] = av_buffer_create( | 122 frame->buf[0] = av_buffer_create( |
| 123 frame->data[0], buffer_size_in_bytes, ReleaseAudioBufferImpl, opaque, 0); | 123 frame->data[0], buffer_size_in_bytes, ReleaseAudioBufferImpl, opaque, 0); |
| 124 return 0; | 124 return 0; |
| 125 } | 125 } |
| 126 | 126 |
| 127 FFmpegAudioDecoder::FFmpegAudioDecoder( | 127 FFmpegAudioDecoder::FFmpegAudioDecoder( |
| 128 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 128 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
| 129 const LogCB& log_cb) | 129 const scoped_refptr<MediaLog>& media_log) |
| 130 : task_runner_(task_runner), | 130 : task_runner_(task_runner), |
| 131 state_(kUninitialized), | 131 state_(kUninitialized), |
| 132 av_sample_format_(0), | 132 av_sample_format_(0), |
| 133 log_cb_(log_cb) { | 133 media_log_(media_log) { |
| 134 } | 134 } |
| 135 | 135 |
| 136 FFmpegAudioDecoder::~FFmpegAudioDecoder() { | 136 FFmpegAudioDecoder::~FFmpegAudioDecoder() { |
| 137 DCHECK(task_runner_->BelongsToCurrentThread()); | 137 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 138 | 138 |
| 139 if (state_ != kUninitialized) { | 139 if (state_ != kUninitialized) { |
| 140 ReleaseFFmpegResources(); | 140 ReleaseFFmpegResources(); |
| 141 ResetTimestampState(); | 141 ResetTimestampState(); |
| 142 } | 142 } |
| 143 } | 143 } |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 int frame_decoded = 0; | 255 int frame_decoded = 0; |
| 256 const int result = avcodec_decode_audio4( | 256 const int result = avcodec_decode_audio4( |
| 257 codec_context_.get(), av_frame_.get(), &frame_decoded, &packet); | 257 codec_context_.get(), av_frame_.get(), &frame_decoded, &packet); |
| 258 | 258 |
| 259 if (result < 0) { | 259 if (result < 0) { |
| 260 DCHECK(!buffer->end_of_stream()) | 260 DCHECK(!buffer->end_of_stream()) |
| 261 << "End of stream buffer produced an error! " | 261 << "End of stream buffer produced an error! " |
| 262 << "This is quite possibly a bug in the audio decoder not handling " | 262 << "This is quite possibly a bug in the audio decoder not handling " |
| 263 << "end of stream AVPackets correctly."; | 263 << "end of stream AVPackets correctly."; |
| 264 | 264 |
| 265 MEDIA_LOG(DEBUG, log_cb_) | 265 MEDIA_LOG(DEBUG, media_log_) |
| 266 << "Dropping audio frame which failed decode with timestamp: " | 266 << "Dropping audio frame which failed decode with timestamp: " |
| 267 << buffer->timestamp().InMicroseconds() | 267 << buffer->timestamp().InMicroseconds() |
| 268 << " us, duration: " << buffer->duration().InMicroseconds() | 268 << " us, duration: " << buffer->duration().InMicroseconds() |
| 269 << " us, packet size: " << buffer->data_size() << " bytes"; | 269 << " us, packet size: " << buffer->data_size() << " bytes"; |
| 270 | 270 |
| 271 break; | 271 break; |
| 272 } | 272 } |
| 273 | 273 |
| 274 // Update packet size and data pointer in case we need to call the decoder | 274 // Update packet size and data pointer in case we need to call the decoder |
| 275 // with the remaining bytes from this packet. | 275 // with the remaining bytes from this packet. |
| 276 packet.size -= result; | 276 packet.size -= result; |
| 277 packet.data += result; | 277 packet.data += result; |
| 278 | 278 |
| 279 scoped_refptr<AudioBuffer> output; | 279 scoped_refptr<AudioBuffer> output; |
| 280 const int channels = DetermineChannels(av_frame_.get()); | 280 const int channels = DetermineChannels(av_frame_.get()); |
| 281 if (frame_decoded) { | 281 if (frame_decoded) { |
| 282 if (av_frame_->sample_rate != config_.samples_per_second() || | 282 if (av_frame_->sample_rate != config_.samples_per_second() || |
| 283 channels != ChannelLayoutToChannelCount(config_.channel_layout()) || | 283 channels != ChannelLayoutToChannelCount(config_.channel_layout()) || |
| 284 av_frame_->format != av_sample_format_) { | 284 av_frame_->format != av_sample_format_) { |
| 285 DLOG(ERROR) << "Unsupported midstream configuration change!" | 285 DLOG(ERROR) << "Unsupported midstream configuration change!" |
| 286 << " Sample Rate: " << av_frame_->sample_rate << " vs " | 286 << " Sample Rate: " << av_frame_->sample_rate << " vs " |
| 287 << config_.samples_per_second() | 287 << config_.samples_per_second() |
| 288 << ", Channels: " << channels << " vs " | 288 << ", Channels: " << channels << " vs " |
| 289 << ChannelLayoutToChannelCount(config_.channel_layout()) | 289 << ChannelLayoutToChannelCount(config_.channel_layout()) |
| 290 << ", Sample Format: " << av_frame_->format << " vs " | 290 << ", Sample Format: " << av_frame_->format << " vs " |
| 291 << av_sample_format_; | 291 << av_sample_format_; |
| 292 | 292 |
| 293 if (config_.codec() == kCodecAAC && | 293 if (config_.codec() == kCodecAAC && |
| 294 av_frame_->sample_rate == 2 * config_.samples_per_second()) { | 294 av_frame_->sample_rate == 2 * config_.samples_per_second()) { |
| 295 MEDIA_LOG(DEBUG, log_cb_) << "Implicit HE-AAC signalling is being" | 295 MEDIA_LOG(DEBUG, media_log_) |
| 296 << " used. Please use mp4a.40.5 instead of" | 296 << "Implicit HE-AAC signalling is being" |
| 297 << " mp4a.40.2 in the mimetype."; | 297 << " used. Please use mp4a.40.5 instead of" |
| 298 << " mp4a.40.2 in the mimetype."; |
| 298 } | 299 } |
| 299 // This is an unrecoverable error, so bail out. | 300 // This is an unrecoverable error, so bail out. |
| 300 av_frame_unref(av_frame_.get()); | 301 av_frame_unref(av_frame_.get()); |
| 301 return false; | 302 return false; |
| 302 } | 303 } |
| 303 | 304 |
| 304 // Get the AudioBuffer that the data was decoded into. Adjust the number | 305 // Get the AudioBuffer that the data was decoded into. Adjust the number |
| 305 // of frames, in case fewer than requested were actually decoded. | 306 // of frames, in case fewer than requested were actually decoded. |
| 306 output = reinterpret_cast<AudioBuffer*>( | 307 output = reinterpret_cast<AudioBuffer*>( |
| 307 av_buffer_get_opaque(av_frame_->buf[0])); | 308 av_buffer_get_opaque(av_frame_->buf[0])); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 | 388 |
| 388 ResetTimestampState(); | 389 ResetTimestampState(); |
| 389 return true; | 390 return true; |
| 390 } | 391 } |
| 391 | 392 |
| 392 void FFmpegAudioDecoder::ResetTimestampState() { | 393 void FFmpegAudioDecoder::ResetTimestampState() { |
| 393 discard_helper_->Reset(config_.codec_delay()); | 394 discard_helper_->Reset(config_.codec_delay()); |
| 394 } | 395 } |
| 395 | 396 |
| 396 } // namespace media | 397 } // namespace media |
| OLD | NEW |