| 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" |
| 11 #include "media/base/audio_decoder_config.h" | 11 #include "media/base/audio_decoder_config.h" |
| 12 #include "media/base/audio_timestamp_helper.h" | 12 #include "media/base/audio_discard_helper.h" |
| 13 #include "media/base/bind_to_current_loop.h" | 13 #include "media/base/bind_to_current_loop.h" |
| 14 #include "media/base/decoder_buffer.h" | 14 #include "media/base/decoder_buffer.h" |
| 15 #include "media/base/limits.h" | 15 #include "media/base/limits.h" |
| 16 #include "media/base/sample_format.h" | 16 #include "media/base/sample_format.h" |
| 17 #include "media/ffmpeg/ffmpeg_common.h" | 17 #include "media/ffmpeg/ffmpeg_common.h" |
| 18 #include "media/filters/ffmpeg_glue.h" | 18 #include "media/filters/ffmpeg_glue.h" |
| 19 | 19 |
| 20 namespace media { | 20 namespace media { |
| 21 | 21 |
| 22 // Returns true if the decode result was end of stream. | 22 // Returns true if the decode result was end of stream. |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 // reference to the AudioBuffer object. | 120 // reference to the AudioBuffer object. |
| 121 void* opaque = NULL; | 121 void* opaque = NULL; |
| 122 buffer.swap(reinterpret_cast<AudioBuffer**>(&opaque)); | 122 buffer.swap(reinterpret_cast<AudioBuffer**>(&opaque)); |
| 123 frame->buf[0] = av_buffer_create( | 123 frame->buf[0] = av_buffer_create( |
| 124 frame->data[0], buffer_size_in_bytes, ReleaseAudioBufferImpl, opaque, 0); | 124 frame->data[0], buffer_size_in_bytes, ReleaseAudioBufferImpl, opaque, 0); |
| 125 return 0; | 125 return 0; |
| 126 } | 126 } |
| 127 | 127 |
| 128 FFmpegAudioDecoder::FFmpegAudioDecoder( | 128 FFmpegAudioDecoder::FFmpegAudioDecoder( |
| 129 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) | 129 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) |
| 130 : task_runner_(task_runner), | 130 : task_runner_(task_runner), state_(kUninitialized), av_sample_format_(0) { |
| 131 state_(kUninitialized), | 131 } |
| 132 av_sample_format_(0), | |
| 133 last_input_timestamp_(kNoTimestamp()), | |
| 134 output_frames_to_drop_(0) {} | |
| 135 | 132 |
| 136 FFmpegAudioDecoder::~FFmpegAudioDecoder() { | 133 FFmpegAudioDecoder::~FFmpegAudioDecoder() { |
| 137 DCHECK_EQ(state_, kUninitialized); | 134 DCHECK_EQ(state_, kUninitialized); |
| 138 DCHECK(!codec_context_); | 135 DCHECK(!codec_context_); |
| 139 DCHECK(!av_frame_); | 136 DCHECK(!av_frame_); |
| 140 } | 137 } |
| 141 | 138 |
| 142 void FFmpegAudioDecoder::Initialize(const AudioDecoderConfig& config, | 139 void FFmpegAudioDecoder::Initialize(const AudioDecoderConfig& config, |
| 143 const PipelineStatusCB& status_cb) { | 140 const PipelineStatusCB& status_cb) { |
| 144 DCHECK(task_runner_->BelongsToCurrentThread()); | 141 DCHECK(task_runner_->BelongsToCurrentThread()); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 // A decoding error occurs and decoding needs to stop. | 244 // A decoding error occurs and decoding needs to stop. |
| 248 // kFlushCodec -> kDecodeFinished: | 245 // kFlushCodec -> kDecodeFinished: |
| 249 // When avcodec_decode_audio4() returns 0 data. | 246 // When avcodec_decode_audio4() returns 0 data. |
| 250 // kFlushCodec -> kError: | 247 // kFlushCodec -> kError: |
| 251 // When avcodec_decode_audio4() errors out. | 248 // When avcodec_decode_audio4() errors out. |
| 252 // (any state) -> kNormal: | 249 // (any state) -> kNormal: |
| 253 // Any time Reset() is called. | 250 // Any time Reset() is called. |
| 254 | 251 |
| 255 // Make sure we are notified if http://crbug.com/49709 returns. Issue also | 252 // Make sure we are notified if http://crbug.com/49709 returns. Issue also |
| 256 // occurs with some damaged files. | 253 // occurs with some damaged files. |
| 257 if (!buffer->end_of_stream() && buffer->timestamp() == kNoTimestamp() && | 254 if (!buffer->end_of_stream() && buffer->timestamp() == kNoTimestamp()) { |
| 258 output_timestamp_helper_->base_timestamp() == kNoTimestamp()) { | |
| 259 DVLOG(1) << "Received a buffer without timestamps!"; | 255 DVLOG(1) << "Received a buffer without timestamps!"; |
| 260 decode_cb.Run(kDecodeError, NULL); | 256 decode_cb.Run(kDecodeError, NULL); |
| 261 return; | 257 return; |
| 262 } | 258 } |
| 263 | 259 |
| 264 if (!buffer->end_of_stream()) { | 260 if (!buffer->end_of_stream() && !discard_helper_->initialized() && |
| 265 DCHECK(buffer->timestamp() != kNoTimestamp()); | 261 codec_context_->codec_id == AV_CODEC_ID_VORBIS && |
| 266 const bool first_buffer = | 262 buffer->timestamp() < base::TimeDelta()) { |
| 267 last_input_timestamp_ == kNoTimestamp() && | 263 // Dropping frames for negative timestamps as outlined in section A.2 |
| 268 output_timestamp_helper_->base_timestamp() == kNoTimestamp(); | 264 // in the Vorbis spec. http://xiph.org/vorbis/doc/Vorbis_I_spec.html |
| 269 if (first_buffer && codec_context_->codec_id == AV_CODEC_ID_VORBIS && | 265 const int discard_frames = |
| 270 buffer->timestamp() < base::TimeDelta()) { | 266 discard_helper_->TimeDeltaToFrames(-buffer->timestamp()); |
| 271 // Dropping frames for negative timestamps as outlined in section A.2 | 267 discard_helper_->Reset(discard_frames); |
| 272 // in the Vorbis spec. http://xiph.org/vorbis/doc/Vorbis_I_spec.html | |
| 273 DCHECK_EQ(output_frames_to_drop_, 0); | |
| 274 output_frames_to_drop_ = | |
| 275 0.5 + | |
| 276 -buffer->timestamp().InSecondsF() * config_.samples_per_second(); | |
| 277 | |
| 278 // If we are dropping samples for Vorbis, the timeline always starts at 0. | |
| 279 output_timestamp_helper_->SetBaseTimestamp(base::TimeDelta()); | |
| 280 } else { | |
| 281 if (first_buffer) { | |
| 282 output_timestamp_helper_->SetBaseTimestamp(buffer->timestamp()); | |
| 283 } else if (buffer->timestamp() < last_input_timestamp_) { | |
| 284 const base::TimeDelta diff = | |
| 285 buffer->timestamp() - last_input_timestamp_; | |
| 286 DLOG(WARNING) << "Input timestamps are not monotonically increasing! " | |
| 287 << " ts " << buffer->timestamp().InMicroseconds() << " us" | |
| 288 << " diff " << diff.InMicroseconds() << " us"; | |
| 289 } | |
| 290 | |
| 291 last_input_timestamp_ = buffer->timestamp(); | |
| 292 } | |
| 293 } | 268 } |
| 294 | 269 |
| 295 // Transition to kFlushCodec on the first end of stream buffer. | 270 // Transition to kFlushCodec on the first end of stream buffer. |
| 296 if (state_ == kNormal && buffer->end_of_stream()) { | 271 if (state_ == kNormal && buffer->end_of_stream()) { |
| 297 state_ = kFlushCodec; | 272 state_ = kFlushCodec; |
| 298 } | 273 } |
| 299 | 274 |
| 300 if (!FFmpegDecode(buffer)) { | 275 if (!FFmpegDecode(buffer)) { |
| 301 state_ = kError; | 276 state_ = kError; |
| 302 decode_cb.Run(kDecodeError, NULL); | 277 decode_cb.Run(kDecodeError, NULL); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 314 decode_cb.Run(kNotEnoughData, NULL); | 289 decode_cb.Run(kNotEnoughData, NULL); |
| 315 return; | 290 return; |
| 316 } | 291 } |
| 317 | 292 |
| 318 decode_cb.Run(kOk, queued_audio_.front()); | 293 decode_cb.Run(kOk, queued_audio_.front()); |
| 319 queued_audio_.pop_front(); | 294 queued_audio_.pop_front(); |
| 320 } | 295 } |
| 321 | 296 |
| 322 bool FFmpegAudioDecoder::FFmpegDecode( | 297 bool FFmpegAudioDecoder::FFmpegDecode( |
| 323 const scoped_refptr<DecoderBuffer>& buffer) { | 298 const scoped_refptr<DecoderBuffer>& buffer) { |
| 324 | |
| 325 DCHECK(queued_audio_.empty()); | 299 DCHECK(queued_audio_.empty()); |
| 326 | 300 |
| 327 AVPacket packet; | 301 AVPacket packet; |
| 328 av_init_packet(&packet); | 302 av_init_packet(&packet); |
| 329 if (buffer->end_of_stream()) { | 303 if (buffer->end_of_stream()) { |
| 330 packet.data = NULL; | 304 packet.data = NULL; |
| 331 packet.size = 0; | 305 packet.size = 0; |
| 332 } else { | 306 } else { |
| 333 packet.data = const_cast<uint8*>(buffer->data()); | 307 packet.data = const_cast<uint8*>(buffer->data()); |
| 334 packet.size = buffer->data_size(); | 308 packet.size = buffer->data_size(); |
| 335 } | 309 } |
| 336 | 310 |
| 337 // Each audio packet may contain several frames, so we must call the decoder | 311 // Each audio packet may contain several frames, so we must call the decoder |
| 338 // until we've exhausted the packet. Regardless of the packet size we always | 312 // until we've exhausted the packet. Regardless of the packet size we always |
| 339 // want to hand it to the decoder at least once, otherwise we would end up | 313 // want to hand it to the decoder at least once, otherwise we would end up |
| 340 // skipping end of stream packets since they have a size of zero. | 314 // skipping end of stream packets since they have a size of zero. |
| 341 do { | 315 do { |
| 342 int frame_decoded = 0; | 316 int frame_decoded = 0; |
| 343 int result = avcodec_decode_audio4( | 317 const int result = avcodec_decode_audio4( |
| 344 codec_context_.get(), av_frame_.get(), &frame_decoded, &packet); | 318 codec_context_.get(), av_frame_.get(), &frame_decoded, &packet); |
| 345 | 319 |
| 346 if (result < 0) { | 320 if (result < 0) { |
| 347 DCHECK(!buffer->end_of_stream()) | 321 DCHECK(!buffer->end_of_stream()) |
| 348 << "End of stream buffer produced an error! " | 322 << "End of stream buffer produced an error! " |
| 349 << "This is quite possibly a bug in the audio decoder not handling " | 323 << "This is quite possibly a bug in the audio decoder not handling " |
| 350 << "end of stream AVPackets correctly."; | 324 << "end of stream AVPackets correctly."; |
| 351 | 325 |
| 352 DLOG(WARNING) | 326 DLOG(WARNING) |
| 353 << "Failed to decode an audio frame with timestamp: " | 327 << "Failed to decode an audio frame with timestamp: " |
| 354 << buffer->timestamp().InMicroseconds() << " us, duration: " | 328 << buffer->timestamp().InMicroseconds() << " us, duration: " |
| 355 << buffer->duration().InMicroseconds() << " us, packet size: " | 329 << buffer->duration().InMicroseconds() << " us, packet size: " |
| 356 << buffer->data_size() << " bytes"; | 330 << buffer->data_size() << " bytes"; |
| 357 | 331 |
| 358 break; | 332 break; |
| 359 } | 333 } |
| 360 | 334 |
| 361 // Update packet size and data pointer in case we need to call the decoder | 335 // Update packet size and data pointer in case we need to call the decoder |
| 362 // with the remaining bytes from this packet. | 336 // with the remaining bytes from this packet. |
| 363 packet.size -= result; | 337 packet.size -= result; |
| 364 packet.data += result; | 338 packet.data += result; |
| 365 | 339 |
| 366 scoped_refptr<AudioBuffer> output; | 340 scoped_refptr<AudioBuffer> output; |
| 367 int decoded_frames = 0; | 341 const int channels = DetermineChannels(av_frame_.get()); |
| 368 int original_frames = 0; | |
| 369 int channels = DetermineChannels(av_frame_.get()); | |
| 370 if (frame_decoded) { | 342 if (frame_decoded) { |
| 371 if (av_frame_->sample_rate != config_.samples_per_second() || | 343 if (av_frame_->sample_rate != config_.samples_per_second() || |
| 372 channels != ChannelLayoutToChannelCount(config_.channel_layout()) || | 344 channels != ChannelLayoutToChannelCount(config_.channel_layout()) || |
| 373 av_frame_->format != av_sample_format_) { | 345 av_frame_->format != av_sample_format_) { |
| 374 DLOG(ERROR) << "Unsupported midstream configuration change!" | 346 DLOG(ERROR) << "Unsupported midstream configuration change!" |
| 375 << " Sample Rate: " << av_frame_->sample_rate << " vs " | 347 << " Sample Rate: " << av_frame_->sample_rate << " vs " |
| 376 << config_.samples_per_second() | 348 << config_.samples_per_second() |
| 377 << ", Channels: " << channels << " vs " | 349 << ", Channels: " << channels << " vs " |
| 378 << ChannelLayoutToChannelCount(config_.channel_layout()) | 350 << ChannelLayoutToChannelCount(config_.channel_layout()) |
| 379 << ", Sample Format: " << av_frame_->format << " vs " | 351 << ", Sample Format: " << av_frame_->format << " vs " |
| 380 << av_sample_format_; | 352 << av_sample_format_; |
| 381 | 353 |
| 382 // This is an unrecoverable error, so bail out. | 354 // This is an unrecoverable error, so bail out. |
| 383 queued_audio_.clear(); | 355 queued_audio_.clear(); |
| 384 av_frame_unref(av_frame_.get()); | 356 av_frame_unref(av_frame_.get()); |
| 385 return false; | 357 return false; |
| 386 } | 358 } |
| 387 | 359 |
| 388 // Get the AudioBuffer that the data was decoded into. Adjust the number | 360 // Get the AudioBuffer that the data was decoded into. Adjust the number |
| 389 // of frames, in case fewer than requested were actually decoded. | 361 // of frames, in case fewer than requested were actually decoded. |
| 390 output = reinterpret_cast<AudioBuffer*>( | 362 output = reinterpret_cast<AudioBuffer*>( |
| 391 av_buffer_get_opaque(av_frame_->buf[0])); | 363 av_buffer_get_opaque(av_frame_->buf[0])); |
| 392 | 364 |
| 393 DCHECK_EQ(ChannelLayoutToChannelCount(config_.channel_layout()), | 365 DCHECK_EQ(ChannelLayoutToChannelCount(config_.channel_layout()), |
| 394 output->channel_count()); | 366 output->channel_count()); |
| 395 original_frames = av_frame_->nb_samples; | 367 const int unread_frames = output->frame_count() - av_frame_->nb_samples; |
| 396 int unread_frames = output->frame_count() - original_frames; | |
| 397 DCHECK_GE(unread_frames, 0); | 368 DCHECK_GE(unread_frames, 0); |
| 398 if (unread_frames > 0) | 369 if (unread_frames > 0) |
| 399 output->TrimEnd(unread_frames); | 370 output->TrimEnd(unread_frames); |
| 400 | 371 |
| 401 // If there are frames to drop, get rid of as many as we can. | |
| 402 if (output_frames_to_drop_ > 0) { | |
| 403 int drop = std::min(output->frame_count(), output_frames_to_drop_); | |
| 404 output->TrimStart(drop); | |
| 405 output_frames_to_drop_ -= drop; | |
| 406 } | |
| 407 | |
| 408 decoded_frames = output->frame_count(); | |
| 409 av_frame_unref(av_frame_.get()); | 372 av_frame_unref(av_frame_.get()); |
| 410 } | 373 } |
| 411 | 374 |
| 412 // WARNING: |av_frame_| no longer has valid data at this point. | 375 // WARNING: |av_frame_| no longer has valid data at this point. |
| 413 | 376 const int decoded_frames = frame_decoded ? output->frame_count() : 0; |
| 414 if (decoded_frames > 0) { | 377 if (IsEndOfStream(result, decoded_frames, buffer)) { |
| 415 // Set the timestamp/duration once all the extra frames have been | |
| 416 // discarded. | |
| 417 output->set_timestamp(output_timestamp_helper_->GetTimestamp()); | |
| 418 output->set_duration( | |
| 419 output_timestamp_helper_->GetFrameDuration(decoded_frames)); | |
| 420 output_timestamp_helper_->AddFrames(decoded_frames); | |
| 421 } else if (IsEndOfStream(result, original_frames, buffer)) { | |
| 422 DCHECK_EQ(packet.size, 0); | 378 DCHECK_EQ(packet.size, 0); |
| 423 output = AudioBuffer::CreateEOSBuffer(); | 379 queued_audio_.push_back(AudioBuffer::CreateEOSBuffer()); |
| 424 } else { | 380 } else if (discard_helper_->ProcessBuffers(buffer, output)) { |
| 425 // In case all the frames in the buffer were dropped. | 381 queued_audio_.push_back(output); |
| 426 output = NULL; | |
| 427 } | 382 } |
| 428 | |
| 429 if (output.get()) | |
| 430 queued_audio_.push_back(output); | |
| 431 | |
| 432 } while (packet.size > 0); | 383 } while (packet.size > 0); |
| 433 | 384 |
| 434 return true; | 385 return true; |
| 435 } | 386 } |
| 436 | 387 |
| 437 void FFmpegAudioDecoder::ReleaseFFmpegResources() { | 388 void FFmpegAudioDecoder::ReleaseFFmpegResources() { |
| 438 codec_context_.reset(); | 389 codec_context_.reset(); |
| 439 av_frame_.reset(); | 390 av_frame_.reset(); |
| 440 } | 391 } |
| 441 | 392 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 469 if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) { | 420 if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) { |
| 470 DLOG(ERROR) << "Could not initialize audio decoder: " | 421 DLOG(ERROR) << "Could not initialize audio decoder: " |
| 471 << codec_context_->codec_id; | 422 << codec_context_->codec_id; |
| 472 ReleaseFFmpegResources(); | 423 ReleaseFFmpegResources(); |
| 473 state_ = kUninitialized; | 424 state_ = kUninitialized; |
| 474 return false; | 425 return false; |
| 475 } | 426 } |
| 476 | 427 |
| 477 // Success! | 428 // Success! |
| 478 av_frame_.reset(av_frame_alloc()); | 429 av_frame_.reset(av_frame_alloc()); |
| 479 output_timestamp_helper_.reset( | 430 discard_helper_.reset(new AudioDiscardHelper(config_.samples_per_second())); |
| 480 new AudioTimestampHelper(config_.samples_per_second())); | |
| 481 ResetTimestampState(); | |
| 482 | |
| 483 av_sample_format_ = codec_context_->sample_fmt; | 431 av_sample_format_ = codec_context_->sample_fmt; |
| 484 | 432 |
| 485 if (codec_context_->channels != | 433 if (codec_context_->channels != |
| 486 ChannelLayoutToChannelCount(config_.channel_layout())) { | 434 ChannelLayoutToChannelCount(config_.channel_layout())) { |
| 487 DLOG(ERROR) << "Audio configuration specified " | 435 DLOG(ERROR) << "Audio configuration specified " |
| 488 << ChannelLayoutToChannelCount(config_.channel_layout()) | 436 << ChannelLayoutToChannelCount(config_.channel_layout()) |
| 489 << " channels, but FFmpeg thinks the file contains " | 437 << " channels, but FFmpeg thinks the file contains " |
| 490 << codec_context_->channels << " channels"; | 438 << codec_context_->channels << " channels"; |
| 491 ReleaseFFmpegResources(); | 439 ReleaseFFmpegResources(); |
| 492 state_ = kUninitialized; | 440 state_ = kUninitialized; |
| 493 return false; | 441 return false; |
| 494 } | 442 } |
| 495 | 443 |
| 496 output_frames_to_drop_ = config_.codec_delay(); | 444 ResetTimestampState(); |
| 497 return true; | 445 return true; |
| 498 } | 446 } |
| 499 | 447 |
| 500 void FFmpegAudioDecoder::ResetTimestampState() { | 448 void FFmpegAudioDecoder::ResetTimestampState() { |
| 501 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); | 449 discard_helper_->Reset(config_.codec_delay()); |
| 502 last_input_timestamp_ = kNoTimestamp(); | |
| 503 output_frames_to_drop_ = 0; | |
| 504 } | 450 } |
| 505 | 451 |
| 506 } // namespace media | 452 } // namespace media |
| OLD | NEW |