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

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

Issue 1260193005: Fix incorrect opus seek preroll and flaky pre-skip removal. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix mojo renderer. Created 5 years, 4 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
« no previous file with comments | « media/filters/opus_audio_decoder.h ('k') | media/test/data/opus-trimming-test.ogg » ('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/opus_audio_decoder.h" 5 #include "media/filters/opus_audio_decoder.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 8
9 #include "base/single_thread_task_runner.h" 9 #include "base/single_thread_task_runner.h"
10 #include "base/sys_byteorder.h" 10 #include "base/sys_byteorder.h"
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 if (extra_data->num_streams + extra_data->num_coupled != extra_data->channels) 238 if (extra_data->num_streams + extra_data->num_coupled != extra_data->channels)
239 DVLOG(1) << "Inconsistent channel mapping."; 239 DVLOG(1) << "Inconsistent channel mapping.";
240 240
241 for (int i = 0; i < extra_data->channels; ++i) 241 for (int i = 0; i < extra_data->channels; ++i)
242 extra_data->stream_map[i] = *(data + kOpusExtraDataStreamMapOffset + i); 242 extra_data->stream_map[i] = *(data + kOpusExtraDataStreamMapOffset + i);
243 return true; 243 return true;
244 } 244 }
245 245
246 OpusAudioDecoder::OpusAudioDecoder( 246 OpusAudioDecoder::OpusAudioDecoder(
247 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) 247 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
248 : task_runner_(task_runner), 248 : task_runner_(task_runner), opus_decoder_(nullptr) {}
249 opus_decoder_(NULL),
250 start_input_timestamp_(kNoTimestamp()) {}
251 249
252 std::string OpusAudioDecoder::GetDisplayName() const { 250 std::string OpusAudioDecoder::GetDisplayName() const {
253 return "OpusAudioDecoder"; 251 return "OpusAudioDecoder";
254 } 252 }
255 253
256 void OpusAudioDecoder::Initialize(const AudioDecoderConfig& config, 254 void OpusAudioDecoder::Initialize(const AudioDecoderConfig& config,
257 const InitCB& init_cb, 255 const InitCB& init_cb,
258 const OutputCB& output_cb) { 256 const OutputCB& output_cb) {
259 DCHECK(task_runner_->BelongsToCurrentThread()); 257 DCHECK(task_runner_->BelongsToCurrentThread());
260 InitCB bound_init_cb = BindToCurrentLoop(init_cb); 258 InitCB bound_init_cb = BindToCurrentLoop(init_cb);
(...skipping 25 matching lines...) Expand all
286 task_runner_->PostTask(FROM_HERE, closure); 284 task_runner_->PostTask(FROM_HERE, closure);
287 } 285 }
288 286
289 OpusAudioDecoder::~OpusAudioDecoder() { 287 OpusAudioDecoder::~OpusAudioDecoder() {
290 DCHECK(task_runner_->BelongsToCurrentThread()); 288 DCHECK(task_runner_->BelongsToCurrentThread());
291 289
292 if (!opus_decoder_) 290 if (!opus_decoder_)
293 return; 291 return;
294 292
295 opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE); 293 opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE);
296 ResetTimestampState();
297 CloseDecoder(); 294 CloseDecoder();
298 } 295 }
299 296
300 void OpusAudioDecoder::DecodeBuffer( 297 void OpusAudioDecoder::DecodeBuffer(
301 const scoped_refptr<DecoderBuffer>& input, 298 const scoped_refptr<DecoderBuffer>& input,
302 const DecodeCB& decode_cb) { 299 const DecodeCB& decode_cb) {
303 DCHECK(task_runner_->BelongsToCurrentThread()); 300 DCHECK(task_runner_->BelongsToCurrentThread());
304 DCHECK(!decode_cb.is_null()); 301 DCHECK(!decode_cb.is_null());
305 DCHECK(input.get()); 302 DCHECK(input.get());
306 303
307 // Libopus does not buffer output. Decoding is complete when an end of stream 304 // Libopus does not buffer output. Decoding is complete when an end of stream
308 // input buffer is received. 305 // input buffer is received.
309 if (input->end_of_stream()) { 306 if (input->end_of_stream()) {
310 decode_cb.Run(kOk); 307 decode_cb.Run(kOk);
311 return; 308 return;
312 } 309 }
313 310
314 // Make sure we are notified if http://crbug.com/49709 returns. Issue also 311 // Make sure we are notified if http://crbug.com/49709 returns. Issue also
315 // occurs with some damaged files. 312 // occurs with some damaged files.
316 if (input->timestamp() == kNoTimestamp()) { 313 if (input->timestamp() == kNoTimestamp()) {
317 DLOG(ERROR) << "Received a buffer without timestamps!"; 314 DLOG(ERROR) << "Received a buffer without timestamps!";
318 decode_cb.Run(kDecodeError); 315 decode_cb.Run(kDecodeError);
319 return; 316 return;
320 } 317 }
321 318
322 // Apply the necessary codec delay.
323 if (start_input_timestamp_ == kNoTimestamp())
324 start_input_timestamp_ = input->timestamp();
325 if (!discard_helper_->initialized() &&
326 input->timestamp() == start_input_timestamp_) {
327 discard_helper_->Reset(config_.codec_delay());
328 }
329
330 scoped_refptr<AudioBuffer> output_buffer; 319 scoped_refptr<AudioBuffer> output_buffer;
331 320
332 if (!Decode(input, &output_buffer)) { 321 if (!Decode(input, &output_buffer)) {
333 decode_cb.Run(kDecodeError); 322 decode_cb.Run(kDecodeError);
334 return; 323 return;
335 } 324 }
336 325
337 if (output_buffer.get()) { 326 if (output_buffer.get()) {
338 output_cb_.Run(output_buffer); 327 output_cb_.Run(output_buffer);
339 } 328 }
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 } 402 }
414 403
415 status = opus_multistream_decoder_ctl( 404 status = opus_multistream_decoder_ctl(
416 opus_decoder_, OPUS_SET_GAIN(opus_extra_data.gain_db)); 405 opus_decoder_, OPUS_SET_GAIN(opus_extra_data.gain_db));
417 if (status != OPUS_OK) { 406 if (status != OPUS_OK) {
418 DLOG(ERROR) << "Failed to set OPUS header gain; status=" 407 DLOG(ERROR) << "Failed to set OPUS header gain; status="
419 << opus_strerror(status); 408 << opus_strerror(status);
420 return false; 409 return false;
421 } 410 }
422 411
423 discard_helper_.reset( 412 ResetTimestampState();
424 new AudioDiscardHelper(config_.samples_per_second(), 0));
425 start_input_timestamp_ = kNoTimestamp();
426 return true; 413 return true;
427 } 414 }
428 415
429 void OpusAudioDecoder::CloseDecoder() { 416 void OpusAudioDecoder::CloseDecoder() {
430 if (opus_decoder_) { 417 if (opus_decoder_) {
431 opus_multistream_decoder_destroy(opus_decoder_); 418 opus_multistream_decoder_destroy(opus_decoder_);
432 opus_decoder_ = NULL; 419 opus_decoder_ = nullptr;
433 } 420 }
434 } 421 }
435 422
436 void OpusAudioDecoder::ResetTimestampState() { 423 void OpusAudioDecoder::ResetTimestampState() {
437 discard_helper_->Reset( 424 discard_helper_.reset(
438 discard_helper_->TimeDeltaToFrames(config_.seek_preroll())); 425 new AudioDiscardHelper(config_.samples_per_second(), 0));
426 discard_helper_->Reset(config_.codec_delay());
439 } 427 }
440 428
441 bool OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& input, 429 bool OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& input,
442 scoped_refptr<AudioBuffer>* output_buffer) { 430 scoped_refptr<AudioBuffer>* output_buffer) {
443 // Allocate a buffer for the output samples. 431 // Allocate a buffer for the output samples.
444 *output_buffer = AudioBuffer::CreateBuffer( 432 *output_buffer = AudioBuffer::CreateBuffer(
445 config_.sample_format(), 433 config_.sample_format(),
446 config_.channel_layout(), 434 config_.channel_layout(),
447 ChannelLayoutToChannelCount(config_.channel_layout()), 435 ChannelLayoutToChannelCount(config_.channel_layout()),
448 config_.samples_per_second(), 436 config_.samples_per_second(),
(...skipping 23 matching lines...) Expand all
472 } 460 }
473 461
474 // Trim off any extraneous allocation. 462 // Trim off any extraneous allocation.
475 DCHECK_LE(frames_decoded, output_buffer->get()->frame_count()); 463 DCHECK_LE(frames_decoded, output_buffer->get()->frame_count());
476 const int trim_frames = output_buffer->get()->frame_count() - frames_decoded; 464 const int trim_frames = output_buffer->get()->frame_count() - frames_decoded;
477 if (trim_frames > 0) 465 if (trim_frames > 0)
478 output_buffer->get()->TrimEnd(trim_frames); 466 output_buffer->get()->TrimEnd(trim_frames);
479 467
480 // Handles discards and timestamping. Discard the buffer if more data needed. 468 // Handles discards and timestamping. Discard the buffer if more data needed.
481 if (!discard_helper_->ProcessBuffers(input, *output_buffer)) 469 if (!discard_helper_->ProcessBuffers(input, *output_buffer))
482 *output_buffer = NULL; 470 *output_buffer = nullptr;
483 471
484 return true; 472 return true;
485 } 473 }
486 474
487 } // namespace media 475 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/opus_audio_decoder.h ('k') | media/test/data/opus-trimming-test.ogg » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698