Chromium Code Reviews| 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 // droped due to codec delay. | |
|
acolwell GONE FROM CHROMIUM
2014/04/17 21:11:24
nit: s/droped/dropped/
DaleCurtis
2014/04/17 21:42:49
Done.
| |
| 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 |