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 |