1 // Copyright 2022 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/filters/passthrough_dts_audio_decoder.h"
7 #include "media/base/audio_buffer.h"
8 #include "media/base/bind_to_current_loop.h"
9 #include "media/formats/dts/dts_util.h"
13 PassthroughDTSAudioDecoder::PassthroughDTSAudioDecoder(
14 const scoped_refptr<base::SequencedTaskRunner>& task_runner,
16 : task_runner_(task_runner),
17 media_log_(media_log),
18 pool_(new AudioBufferMemoryPool()) {
19 DETACH_FROM_SEQUENCE(sequence_checker_);
22 PassthroughDTSAudioDecoder::~PassthroughDTSAudioDecoder() {
23 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
26 AudioDecoderType PassthroughDTSAudioDecoder::GetDecoderType() const {
27 return AudioDecoderType::kPassthroughDTS;
30 void PassthroughDTSAudioDecoder::Initialize(const AudioDecoderConfig& config,
31 CdmContext* /* cdm_context */,
33 const OutputCB& output_cb,
34 const WaitingCB& /* waiting_cb */) {
35 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
36 DCHECK(config.IsValidConfig());
37 InitCB bound_init_cb = BindToCurrentLoop(std::move(init_cb));
38 if (config.is_encrypted()) {
39 std::move(bound_init_cb)
40 .Run(DecoderStatus(DecoderStatus::Codes::kUnsupportedEncryptionMode,
41 "PassthroughDTSAudioDecoder does not support "
42 "encrypted content"));
46 if (config.target_output_sample_format() != kSampleFormatDts) {
47 std::move(bound_init_cb)
49 DecoderStatus(DecoderStatus::Codes::kUnsupportedConfig,
50 "PassthroughDTSAudioDecoder does not support codec"));
56 output_cb_ = BindToCurrentLoop(output_cb);
57 std::move(bound_init_cb).Run(OkStatus());
60 void PassthroughDTSAudioDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
62 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
64 DecodeCB decode_cb_bound = BindToCurrentLoop(std::move(decode_cb));
66 if (buffer->end_of_stream()) {
67 std::move(decode_cb_bound).Run(DecoderStatus::Codes::kOk);
71 ProcessBuffer(*buffer, std::move(decode_cb_bound));
74 void PassthroughDTSAudioDecoder::Reset(base::OnceClosure closure) {
75 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
77 task_runner_->PostTask(FROM_HERE, std::move(closure));
80 void PassthroughDTSAudioDecoder::ProcessBuffer(const DecoderBuffer& buffer,
82 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
84 // Make sure we are notified if http://crbug.com/49709 returns. Issue also
85 // occurs with some damaged files.
86 if (!buffer.end_of_stream() && buffer.timestamp() == kNoTimestamp) {
87 DVLOG(1) << "Received a buffer without timestamps!";
88 std::move(decode_cb).Run(DecoderStatus::Codes::kFailed);
91 EncapsulateFrame(buffer);
93 std::move(decode_cb).Run(DecoderStatus::Codes::kOk);
96 void PassthroughDTSAudioDecoder::EncapsulateFrame(const DecoderBuffer& buffer) {
97 if (config_.target_output_sample_format() != kSampleFormatDts)
99 const size_t samples_per_frame = dts::GetDTSSamplesPerFrame(config_.codec());
100 const size_t dts_frame_size = 2 * 2 * samples_per_frame;
101 std::vector<uint8_t> output_buffer(dts_frame_size);
103 // Encapsulated a compressed DTS frame per IEC61937
104 base::span<const uint8_t> input_data;
105 input_data = base::span<const uint8_t>(buffer.data(), buffer.data_size());
106 dts::WrapDTSWithIEC61937(input_data, output_buffer, config_.codec());
108 // Create a mono channel "buffer" to hold IEC encapsulated bitstream
109 uint8_t* output_channels[1] = {output_buffer.data()};
110 scoped_refptr<AudioBuffer> output = AudioBuffer::CopyBitstreamFrom(
111 kSampleFormatIECDts, CHANNEL_LAYOUT_MONO, 1, config_.samples_per_second(),
112 samples_per_frame, output_channels, dts_frame_size, buffer.timestamp());
113 output_cb_.Run(output);