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

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: 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
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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 118
119 // Now create an AVBufferRef for the data just allocated. It will own the 119 // Now create an AVBufferRef for the data just allocated. It will own the
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 static int TimeDeltaToFrames(base::TimeDelta duration, int sample_rate) {
129 return 0.5 + duration.InSecondsF() * sample_rate;
130 }
131
128 FFmpegAudioDecoder::FFmpegAudioDecoder( 132 FFmpegAudioDecoder::FFmpegAudioDecoder(
129 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) 133 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
130 : task_runner_(task_runner), 134 : task_runner_(task_runner),
131 state_(kUninitialized), 135 state_(kUninitialized),
132 av_sample_format_(0), 136 av_sample_format_(0),
133 last_input_timestamp_(kNoTimestamp()), 137 last_input_timestamp_(kNoTimestamp()),
134 output_frames_to_drop_(0) {} 138 output_frames_to_drop_(0) {}
135 139
136 FFmpegAudioDecoder::~FFmpegAudioDecoder() { 140 FFmpegAudioDecoder::~FFmpegAudioDecoder() {
137 DCHECK_EQ(state_, kUninitialized); 141 DCHECK_EQ(state_, kUninitialized);
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 decode_cb.Run(kDecodeError, NULL); 264 decode_cb.Run(kDecodeError, NULL);
261 return; 265 return;
262 } 266 }
263 267
264 if (!buffer->end_of_stream()) { 268 if (!buffer->end_of_stream()) {
265 if (last_input_timestamp_ == kNoTimestamp() && 269 if (last_input_timestamp_ == kNoTimestamp() &&
266 codec_context_->codec_id == AV_CODEC_ID_VORBIS && 270 codec_context_->codec_id == AV_CODEC_ID_VORBIS &&
267 buffer->timestamp() < base::TimeDelta()) { 271 buffer->timestamp() < base::TimeDelta()) {
268 // Dropping frames for negative timestamps as outlined in section A.2 272 // 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 273 // in the Vorbis spec. http://xiph.org/vorbis/doc/Vorbis_I_spec.html
270 output_frames_to_drop_ = floor(0.5 + -buffer->timestamp().InSecondsF() * 274 output_frames_to_drop_ =
271 config_.samples_per_second()); 275 TimeDeltaToFrames(-buffer->timestamp(), config_.samples_per_second());
272 } else { 276 } else {
273 if (last_input_timestamp_ != kNoTimestamp() && 277 if (last_input_timestamp_ != kNoTimestamp() &&
274 buffer->timestamp() < last_input_timestamp_) { 278 buffer->timestamp() < last_input_timestamp_) {
275 const base::TimeDelta diff = 279 const base::TimeDelta diff =
276 buffer->timestamp() - last_input_timestamp_; 280 buffer->timestamp() - last_input_timestamp_;
277 DLOG(WARNING) 281 DLOG(WARNING)
278 << "Input timestamps are not monotonically increasing! " 282 << "Input timestamps are not monotonically increasing! "
279 << " ts " << buffer->timestamp().InMicroseconds() << " us" 283 << " ts " << buffer->timestamp().InMicroseconds() << " us"
280 << " diff " << diff.InMicroseconds() << " us"; 284 << " diff " << diff.InMicroseconds() << " us";
281 } 285 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 } 355 }
352 356
353 // Update packet size and data pointer in case we need to call the decoder 357 // Update packet size and data pointer in case we need to call the decoder
354 // with the remaining bytes from this packet. 358 // with the remaining bytes from this packet.
355 packet.size -= result; 359 packet.size -= result;
356 packet.data += result; 360 packet.data += result;
357 361
358 if (output_timestamp_helper_->base_timestamp() == kNoTimestamp() && 362 if (output_timestamp_helper_->base_timestamp() == kNoTimestamp() &&
359 !buffer->end_of_stream()) { 363 !buffer->end_of_stream()) {
360 DCHECK(buffer->timestamp() != kNoTimestamp()); 364 DCHECK(buffer->timestamp() != kNoTimestamp());
361 if (output_frames_to_drop_ > 0) { 365 if (output_frames_to_drop_ > 0 &&
362 // Currently Vorbis is the only codec that causes us to drop samples. 366 codec_context_->codec_id == AV_CODEC_ID_VORBIS) {
363 // If we have to drop samples it always means the timeline starts at 0. 367 // If we are dropping samples for Vorbis, it always means the timeline
364 DCHECK_EQ(codec_context_->codec_id, AV_CODEC_ID_VORBIS); 368 // starts at 0.
365 output_timestamp_helper_->SetBaseTimestamp(base::TimeDelta()); 369 output_timestamp_helper_->SetBaseTimestamp(base::TimeDelta());
366 } else { 370 } else {
367 output_timestamp_helper_->SetBaseTimestamp(buffer->timestamp()); 371 output_timestamp_helper_->SetBaseTimestamp(buffer->timestamp());
368 } 372 }
369 } 373 }
370 374
371 scoped_refptr<AudioBuffer> output; 375 scoped_refptr<AudioBuffer> output;
372 int decoded_frames = 0; 376 int decoded_frames = 0;
373 int original_frames = 0; 377 int original_frames = 0;
374 int channels = DetermineChannels(av_frame_.get()); 378 int channels = DetermineChannels(av_frame_.get());
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
489 if (codec_context_->channels != 493 if (codec_context_->channels !=
490 ChannelLayoutToChannelCount(config_.channel_layout())) { 494 ChannelLayoutToChannelCount(config_.channel_layout())) {
491 DLOG(ERROR) << "Audio configuration specified " 495 DLOG(ERROR) << "Audio configuration specified "
492 << ChannelLayoutToChannelCount(config_.channel_layout()) 496 << ChannelLayoutToChannelCount(config_.channel_layout())
493 << " channels, but FFmpeg thinks the file contains " 497 << " channels, but FFmpeg thinks the file contains "
494 << codec_context_->channels << " channels"; 498 << codec_context_->channels << " channels";
495 ReleaseFFmpegResources(); 499 ReleaseFFmpegResources();
496 state_ = kUninitialized; 500 state_ = kUninitialized;
497 return false; 501 return false;
498 } 502 }
503
504 if (config_.codec_delay() > base::TimeDelta()) {
505 output_frames_to_drop_ =
506 TimeDeltaToFrames(config_.codec_delay(), config_.samples_per_second());
507 }
508
499 return true; 509 return true;
500 } 510 }
501 511
502 void FFmpegAudioDecoder::ResetTimestampState() { 512 void FFmpegAudioDecoder::ResetTimestampState() {
503 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); 513 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp());
504 last_input_timestamp_ = kNoTimestamp(); 514 last_input_timestamp_ = kNoTimestamp();
505 output_frames_to_drop_ = 0; 515 output_frames_to_drop_ = 0;
506 } 516 }
507 517
508 } // namespace media 518 } // namespace media
OLDNEW
« no previous file with comments | « no previous file | media/filters/pipeline_integration_test.cc » ('j') | media/formats/mpeg/mpeg_audio_stream_parser_base.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698