Upload upstream chromium 108.0.5359.1
[platform/framework/web/chromium-efl.git] / media / filters / passthrough_dts_audio_decoder.cc
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.
4
5 #include "media/filters/passthrough_dts_audio_decoder.h"
6
7 #include "media/base/audio_buffer.h"
8 #include "media/base/bind_to_current_loop.h"
9 #include "media/formats/dts/dts_util.h"
10
11 namespace media {
12
13 PassthroughDTSAudioDecoder::PassthroughDTSAudioDecoder(
14     const scoped_refptr<base::SequencedTaskRunner>& task_runner,
15     MediaLog* media_log)
16     : task_runner_(task_runner),
17       media_log_(media_log),
18       pool_(new AudioBufferMemoryPool()) {
19   DETACH_FROM_SEQUENCE(sequence_checker_);
20 }
21
22 PassthroughDTSAudioDecoder::~PassthroughDTSAudioDecoder() {
23   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
24 }
25
26 AudioDecoderType PassthroughDTSAudioDecoder::GetDecoderType() const {
27   return AudioDecoderType::kPassthroughDTS;
28 }
29
30 void PassthroughDTSAudioDecoder::Initialize(const AudioDecoderConfig& config,
31                                             CdmContext* /* cdm_context */,
32                                             InitCB init_cb,
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"));
43     return;
44   }
45
46   if (config.target_output_sample_format() != kSampleFormatDts) {
47     std::move(bound_init_cb)
48         .Run(
49             DecoderStatus(DecoderStatus::Codes::kUnsupportedConfig,
50                           "PassthroughDTSAudioDecoder does not support codec"));
51     return;
52   }
53
54   // Success!
55   config_ = config;
56   output_cb_ = BindToCurrentLoop(output_cb);
57   std::move(bound_init_cb).Run(OkStatus());
58 }
59
60 void PassthroughDTSAudioDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
61                                         DecodeCB decode_cb) {
62   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
63   DCHECK(decode_cb);
64   DecodeCB decode_cb_bound = BindToCurrentLoop(std::move(decode_cb));
65
66   if (buffer->end_of_stream()) {
67     std::move(decode_cb_bound).Run(DecoderStatus::Codes::kOk);
68     return;
69   }
70
71   ProcessBuffer(*buffer, std::move(decode_cb_bound));
72 }
73
74 void PassthroughDTSAudioDecoder::Reset(base::OnceClosure closure) {
75   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
76
77   task_runner_->PostTask(FROM_HERE, std::move(closure));
78 }
79
80 void PassthroughDTSAudioDecoder::ProcessBuffer(const DecoderBuffer& buffer,
81                                                DecodeCB decode_cb) {
82   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
83
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);
89     return;
90   }
91   EncapsulateFrame(buffer);
92
93   std::move(decode_cb).Run(DecoderStatus::Codes::kOk);
94 }
95
96 void PassthroughDTSAudioDecoder::EncapsulateFrame(const DecoderBuffer& buffer) {
97   if (config_.target_output_sample_format() != kSampleFormatDts)
98     return;
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);
102
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());
107
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);
114 }
115
116 }  // namespace media