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/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 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 extra_data->stream_map[i] = *(data + kOpusExtraDataStreamMapOffset + i); | 246 extra_data->stream_map[i] = *(data + kOpusExtraDataStreamMapOffset + i); |
247 return true; | 247 return true; |
248 } | 248 } |
249 | 249 |
250 OpusAudioDecoder::OpusAudioDecoder( | 250 OpusAudioDecoder::OpusAudioDecoder( |
251 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) | 251 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) |
252 : task_runner_(task_runner), | 252 : task_runner_(task_runner), |
253 opus_decoder_(NULL), | 253 opus_decoder_(NULL), |
254 last_input_timestamp_(kNoTimestamp()), | 254 last_input_timestamp_(kNoTimestamp()), |
255 frames_to_discard_(0), | 255 frames_to_discard_(0), |
256 frame_delay_at_start_(0), | |
257 start_input_timestamp_(kNoTimestamp()) {} | 256 start_input_timestamp_(kNoTimestamp()) {} |
258 | 257 |
259 void OpusAudioDecoder::Initialize(const AudioDecoderConfig& config, | 258 void OpusAudioDecoder::Initialize(const AudioDecoderConfig& config, |
260 const PipelineStatusCB& status_cb) { | 259 const PipelineStatusCB& status_cb) { |
261 DCHECK(task_runner_->BelongsToCurrentThread()); | 260 DCHECK(task_runner_->BelongsToCurrentThread()); |
262 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); | 261 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); |
263 | 262 |
264 config_ = config; | 263 config_ = config; |
265 | 264 |
266 if (!ConfigureDecoder()) { | 265 if (!ConfigureDecoder()) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 << " diff " << diff.InMicroseconds() << " us"; | 329 << " diff " << diff.InMicroseconds() << " us"; |
331 decode_cb.Run(kDecodeError, NULL); | 330 decode_cb.Run(kDecodeError, NULL); |
332 return; | 331 return; |
333 } | 332 } |
334 | 333 |
335 // Apply the necessary codec delay. | 334 // Apply the necessary codec delay. |
336 if (start_input_timestamp_ == kNoTimestamp()) | 335 if (start_input_timestamp_ == kNoTimestamp()) |
337 start_input_timestamp_ = input->timestamp(); | 336 start_input_timestamp_ = input->timestamp(); |
338 if (last_input_timestamp_ == kNoTimestamp() && | 337 if (last_input_timestamp_ == kNoTimestamp() && |
339 input->timestamp() == start_input_timestamp_) { | 338 input->timestamp() == start_input_timestamp_) { |
340 frames_to_discard_ = frame_delay_at_start_; | 339 frames_to_discard_ = config_.codec_delay(); |
341 } | 340 } |
342 | 341 |
343 last_input_timestamp_ = input->timestamp(); | 342 last_input_timestamp_ = input->timestamp(); |
344 | 343 |
345 scoped_refptr<AudioBuffer> output_buffer; | 344 scoped_refptr<AudioBuffer> output_buffer; |
346 | 345 |
347 if (!Decode(input, &output_buffer)) { | 346 if (!Decode(input, &output_buffer)) { |
348 decode_cb.Run(kDecodeError, NULL); | 347 decode_cb.Run(kDecodeError, NULL); |
349 return; | 348 return; |
350 } | 349 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
384 // Clean up existing decoder if necessary. | 383 // Clean up existing decoder if necessary. |
385 CloseDecoder(); | 384 CloseDecoder(); |
386 | 385 |
387 // Parse the Opus Extra Data. | 386 // Parse the Opus Extra Data. |
388 OpusExtraData opus_extra_data; | 387 OpusExtraData opus_extra_data; |
389 if (!ParseOpusExtraData(config_.extra_data(), config_.extra_data_size(), | 388 if (!ParseOpusExtraData(config_.extra_data(), config_.extra_data_size(), |
390 config_, | 389 config_, |
391 &opus_extra_data)) | 390 &opus_extra_data)) |
392 return false; | 391 return false; |
393 | 392 |
394 // Convert from seconds to samples. | 393 if (config_.codec_delay() <= 0) { |
395 timestamp_offset_ = config_.codec_delay(); | |
396 frame_delay_at_start_ = TimeDeltaToAudioFrames(config_.codec_delay(), | |
397 config_.samples_per_second()); | |
398 if (timestamp_offset_ <= base::TimeDelta() || frame_delay_at_start_ < 0) { | |
399 DLOG(ERROR) << "Invalid file. Incorrect value for codec delay: " | 394 DLOG(ERROR) << "Invalid file. Incorrect value for codec delay: " |
400 << config_.codec_delay().InMicroseconds(); | 395 << config_.codec_delay(); |
401 return false; | 396 return false; |
402 } | 397 } |
403 | 398 |
404 if (frame_delay_at_start_ != opus_extra_data.skip_samples) { | 399 if (config_.codec_delay() != opus_extra_data.skip_samples) { |
405 DLOG(ERROR) << "Invalid file. Codec Delay in container does not match the " | 400 DLOG(ERROR) << "Invalid file. Codec Delay in container does not match the " |
406 << "value in Opus Extra Data."; | 401 << "value in Opus Extra Data."; |
407 return false; | 402 return false; |
408 } | 403 } |
409 | 404 |
410 uint8 channel_mapping[kMaxVorbisChannels] = {0}; | 405 uint8 channel_mapping[kMaxVorbisChannels] = {0}; |
411 memcpy(&channel_mapping, | 406 memcpy(&channel_mapping, |
412 kDefaultOpusChannelLayout, | 407 kDefaultOpusChannelLayout, |
413 kMaxChannelsWithDefaultLayout); | 408 kMaxChannelsWithDefaultLayout); |
414 | 409 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
489 << " timestamp: " << input->timestamp().InMicroseconds() | 484 << " timestamp: " << input->timestamp().InMicroseconds() |
490 << " us, duration: " << input->duration().InMicroseconds() | 485 << " us, duration: " << input->duration().InMicroseconds() |
491 << " us, packet size: " << input->data_size() << " bytes with" | 486 << " us, packet size: " << input->data_size() << " bytes with" |
492 << " status: " << opus_strerror(frames_decoded); | 487 << " status: " << opus_strerror(frames_decoded); |
493 return false; | 488 return false; |
494 } | 489 } |
495 | 490 |
496 if (output_timestamp_helper_->base_timestamp() == kNoTimestamp() && | 491 if (output_timestamp_helper_->base_timestamp() == kNoTimestamp() && |
497 !input->end_of_stream()) { | 492 !input->end_of_stream()) { |
498 DCHECK(input->timestamp() != kNoTimestamp()); | 493 DCHECK(input->timestamp() != kNoTimestamp()); |
| 494 // Adjust the timestamp helper so the base timestamp is corrected for frames |
| 495 // dropped due to codec delay. |
499 output_timestamp_helper_->SetBaseTimestamp(input->timestamp()); | 496 output_timestamp_helper_->SetBaseTimestamp(input->timestamp()); |
| 497 output_timestamp_helper_->SetBaseTimestamp( |
| 498 input->timestamp() - |
| 499 output_timestamp_helper_->GetFrameDuration(config_.codec_delay())); |
500 } | 500 } |
501 | 501 |
502 // Trim off any extraneous allocation. | 502 // Trim off any extraneous allocation. |
503 DCHECK_LE(frames_decoded, output_buffer->get()->frame_count()); | 503 DCHECK_LE(frames_decoded, output_buffer->get()->frame_count()); |
504 const int trim_frames = output_buffer->get()->frame_count() - frames_decoded; | 504 const int trim_frames = output_buffer->get()->frame_count() - frames_decoded; |
505 if (trim_frames > 0) | 505 if (trim_frames > 0) |
506 output_buffer->get()->TrimEnd(trim_frames); | 506 output_buffer->get()->TrimEnd(trim_frames); |
507 | 507 |
508 // Handle frame discard and trimming. | 508 // Handle frame discard and trimming. |
509 int frames_to_output = frames_decoded; | 509 int frames_to_output = frames_decoded; |
(...skipping 12 matching lines...) Expand all Loading... |
522 } | 522 } |
523 output_buffer->get()->TrimEnd(discard_padding); | 523 output_buffer->get()->TrimEnd(discard_padding); |
524 frames_to_output -= discard_padding; | 524 frames_to_output -= discard_padding; |
525 } | 525 } |
526 } else { | 526 } else { |
527 frames_to_discard_ -= frames_to_output; | 527 frames_to_discard_ -= frames_to_output; |
528 frames_to_output = 0; | 528 frames_to_output = 0; |
529 } | 529 } |
530 | 530 |
531 // Assign timestamp and duration to the buffer. | 531 // Assign timestamp and duration to the buffer. |
532 output_buffer->get()->set_timestamp( | 532 output_buffer->get()->set_timestamp(output_timestamp_helper_->GetTimestamp()); |
533 output_timestamp_helper_->GetTimestamp() - timestamp_offset_); | |
534 output_buffer->get()->set_duration( | 533 output_buffer->get()->set_duration( |
535 output_timestamp_helper_->GetFrameDuration(frames_to_output)); | 534 output_timestamp_helper_->GetFrameDuration(frames_to_output)); |
536 output_timestamp_helper_->AddFrames(frames_decoded); | 535 output_timestamp_helper_->AddFrames(frames_decoded); |
537 | 536 |
538 // Discard the buffer to indicate we need more data. | 537 // Discard the buffer to indicate we need more data. |
539 if (!frames_to_output) | 538 if (!frames_to_output) |
540 *output_buffer = NULL; | 539 *output_buffer = NULL; |
541 | 540 |
542 return true; | 541 return true; |
543 } | 542 } |
544 | 543 |
545 } // namespace media | 544 } // namespace media |
OLD | NEW |