Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1003)

Side by Side Diff: media/filters/ffmpeg_audio_decoder.cc

Issue 239423005: Wire up codec_delay() to MP3StreamParser and FFmpegAudioDecoder. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: ResetTimestampState() on config change. Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/filters/decrypting_demuxer_stream.cc ('k') | media/filters/opus_audio_decoder.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 // Make sure we are notified if http://crbug.com/49709 returns. Issue also 255 // Make sure we are notified if http://crbug.com/49709 returns. Issue also
256 // occurs with some damaged files. 256 // occurs with some damaged files.
257 if (!buffer->end_of_stream() && buffer->timestamp() == kNoTimestamp() && 257 if (!buffer->end_of_stream() && buffer->timestamp() == kNoTimestamp() &&
258 output_timestamp_helper_->base_timestamp() == kNoTimestamp()) { 258 output_timestamp_helper_->base_timestamp() == kNoTimestamp()) {
259 DVLOG(1) << "Received a buffer without timestamps!"; 259 DVLOG(1) << "Received a buffer without timestamps!";
260 decode_cb.Run(kDecodeError, NULL); 260 decode_cb.Run(kDecodeError, NULL);
261 return; 261 return;
262 } 262 }
263 263
264 if (!buffer->end_of_stream()) { 264 if (!buffer->end_of_stream()) {
265 if (last_input_timestamp_ == kNoTimestamp() && 265 DCHECK(buffer->timestamp() != kNoTimestamp());
266 codec_context_->codec_id == AV_CODEC_ID_VORBIS && 266 const bool first_buffer =
267 last_input_timestamp_ == kNoTimestamp() &&
268 output_timestamp_helper_->base_timestamp() == kNoTimestamp();
269 if (first_buffer && codec_context_->codec_id == AV_CODEC_ID_VORBIS &&
267 buffer->timestamp() < base::TimeDelta()) { 270 buffer->timestamp() < base::TimeDelta()) {
268 // Dropping frames for negative timestamps as outlined in section A.2 271 // Dropping frames for negative timestamps as outlined in section A.2
269 // in the Vorbis spec. http://xiph.org/vorbis/doc/Vorbis_I_spec.html 272 // in the Vorbis spec. http://xiph.org/vorbis/doc/Vorbis_I_spec.html
270 output_frames_to_drop_ = floor(0.5 + -buffer->timestamp().InSecondsF() * 273 DCHECK_EQ(output_frames_to_drop_, 0);
271 config_.samples_per_second()); 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());
272 } else { 280 } else {
273 if (last_input_timestamp_ != kNoTimestamp() && 281 if (first_buffer) {
274 buffer->timestamp() < last_input_timestamp_) { 282 output_timestamp_helper_->SetBaseTimestamp(buffer->timestamp());
283 } else if (buffer->timestamp() < last_input_timestamp_) {
275 const base::TimeDelta diff = 284 const base::TimeDelta diff =
276 buffer->timestamp() - last_input_timestamp_; 285 buffer->timestamp() - last_input_timestamp_;
277 DLOG(WARNING) 286 DLOG(WARNING) << "Input timestamps are not monotonically increasing! "
278 << "Input timestamps are not monotonically increasing! " 287 << " ts " << buffer->timestamp().InMicroseconds() << " us"
279 << " ts " << buffer->timestamp().InMicroseconds() << " us" 288 << " diff " << diff.InMicroseconds() << " us";
280 << " diff " << diff.InMicroseconds() << " us";
281 } 289 }
282 290
283 last_input_timestamp_ = buffer->timestamp(); 291 last_input_timestamp_ = buffer->timestamp();
284 } 292 }
285 } 293 }
286 294
287 // Transition to kFlushCodec on the first end of stream buffer. 295 // Transition to kFlushCodec on the first end of stream buffer.
288 if (state_ == kNormal && buffer->end_of_stream()) { 296 if (state_ == kNormal && buffer->end_of_stream()) {
289 state_ = kFlushCodec; 297 state_ = kFlushCodec;
290 } 298 }
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 << buffer->data_size() << " bytes"; 356 << buffer->data_size() << " bytes";
349 357
350 break; 358 break;
351 } 359 }
352 360
353 // Update packet size and data pointer in case we need to call the decoder 361 // Update packet size and data pointer in case we need to call the decoder
354 // with the remaining bytes from this packet. 362 // with the remaining bytes from this packet.
355 packet.size -= result; 363 packet.size -= result;
356 packet.data += result; 364 packet.data += result;
357 365
358 if (output_timestamp_helper_->base_timestamp() == kNoTimestamp() &&
359 !buffer->end_of_stream()) {
360 DCHECK(buffer->timestamp() != kNoTimestamp());
361 if (output_frames_to_drop_ > 0) {
362 // Currently Vorbis is the only codec that causes us to drop samples.
363 // If we have to drop samples it always means the timeline starts at 0.
364 DCHECK_EQ(codec_context_->codec_id, AV_CODEC_ID_VORBIS);
365 output_timestamp_helper_->SetBaseTimestamp(base::TimeDelta());
366 } else {
367 output_timestamp_helper_->SetBaseTimestamp(buffer->timestamp());
368 }
369 }
370
371 scoped_refptr<AudioBuffer> output; 366 scoped_refptr<AudioBuffer> output;
372 int decoded_frames = 0; 367 int decoded_frames = 0;
373 int original_frames = 0; 368 int original_frames = 0;
374 int channels = DetermineChannels(av_frame_.get()); 369 int channels = DetermineChannels(av_frame_.get());
375 if (frame_decoded) { 370 if (frame_decoded) {
376 if (av_frame_->sample_rate != config_.samples_per_second() || 371 if (av_frame_->sample_rate != config_.samples_per_second() ||
377 channels != ChannelLayoutToChannelCount(config_.channel_layout()) || 372 channels != ChannelLayoutToChannelCount(config_.channel_layout()) ||
378 av_frame_->format != av_sample_format_) { 373 av_frame_->format != av_sample_format_) {
379 DLOG(ERROR) << "Unsupported midstream configuration change!" 374 DLOG(ERROR) << "Unsupported midstream configuration change!"
380 << " Sample Rate: " << av_frame_->sample_rate << " vs " 375 << " Sample Rate: " << av_frame_->sample_rate << " vs "
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 << codec_context_->codec_id; 471 << codec_context_->codec_id;
477 ReleaseFFmpegResources(); 472 ReleaseFFmpegResources();
478 state_ = kUninitialized; 473 state_ = kUninitialized;
479 return false; 474 return false;
480 } 475 }
481 476
482 // Success! 477 // Success!
483 av_frame_.reset(av_frame_alloc()); 478 av_frame_.reset(av_frame_alloc());
484 output_timestamp_helper_.reset( 479 output_timestamp_helper_.reset(
485 new AudioTimestampHelper(config_.samples_per_second())); 480 new AudioTimestampHelper(config_.samples_per_second()));
481 ResetTimestampState();
486 482
487 av_sample_format_ = codec_context_->sample_fmt; 483 av_sample_format_ = codec_context_->sample_fmt;
488 484
489 if (codec_context_->channels != 485 if (codec_context_->channels !=
490 ChannelLayoutToChannelCount(config_.channel_layout())) { 486 ChannelLayoutToChannelCount(config_.channel_layout())) {
491 DLOG(ERROR) << "Audio configuration specified " 487 DLOG(ERROR) << "Audio configuration specified "
492 << ChannelLayoutToChannelCount(config_.channel_layout()) 488 << ChannelLayoutToChannelCount(config_.channel_layout())
493 << " channels, but FFmpeg thinks the file contains " 489 << " channels, but FFmpeg thinks the file contains "
494 << codec_context_->channels << " channels"; 490 << codec_context_->channels << " channels";
495 ReleaseFFmpegResources(); 491 ReleaseFFmpegResources();
496 state_ = kUninitialized; 492 state_ = kUninitialized;
497 return false; 493 return false;
498 } 494 }
495
496 output_frames_to_drop_ = config_.codec_delay();
499 return true; 497 return true;
500 } 498 }
501 499
502 void FFmpegAudioDecoder::ResetTimestampState() { 500 void FFmpegAudioDecoder::ResetTimestampState() {
503 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); 501 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp());
504 last_input_timestamp_ = kNoTimestamp(); 502 last_input_timestamp_ = kNoTimestamp();
505 output_frames_to_drop_ = 0; 503 output_frames_to_drop_ = 0;
506 } 504 }
507 505
508 } // namespace media 506 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/decrypting_demuxer_stream.cc ('k') | media/filters/opus_audio_decoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698