1 /*
2 * Copyright (c) 2023, Alliance for Open Media. All rights reserved
3 *
4 * This source code is subject to the terms of the BSD 3-Clause Clear License
5 * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
6 * License was not distributed with this source code in the LICENSE file, you
7 * can obtain it at www.aomedia.org/license/software-license/bsd-3-c-c. If the
8 * Alliance for Open Media Patent License 1.0 was not distributed with this
9 * source code in the PATENTS file, you can obtain it at
10 * www.aomedia.org/license/patent.
11 */
12 #include "iamf/cli/codec/aac_decoder.h"
13
14 #include <algorithm>
15 #include <cstddef>
16 #include <cstdint>
17 #include <cstdlib>
18 #include <vector>
19
20 #include "absl/functional/any_invocable.h"
21 #include "absl/types/span.h"
22 #include "iamf/common/utils/sample_processing_utils.h"
23
24 // This symbol conflicts with `aacenc_lib.h` and `aacdecoder_lib.h`.
25 #ifdef IS_LITTLE_ENDIAN
26 #undef IS_LITTLE_ENDIAN
27 #endif
28
29 #include "absl/log/log.h"
30 #include "absl/status/status.h"
31 #include "absl/strings/str_cat.h"
32 #include "absl/strings/string_view.h"
33 #include "iamf/cli/codec/aac_utils.h"
34 #include "iamf/cli/codec/decoder_base.h"
35 #include "iamf/common/utils/macros.h"
36 #include "iamf/common/write_bit_buffer.h"
37 #include "iamf/obu/codec_config.h"
38 #include "iamf/obu/decoder_config/aac_decoder_config.h"
39 #include "libAACdec/include/aacdecoder_lib.h"
40 #include "libSYS/include/machine_type.h"
41
42 namespace iamf_tools {
43
44 namespace {
45
46 // Converts an AAC_DECODER_ERROR to an absl::Status.
AacDecoderErrorToAbslStatus(AAC_DECODER_ERROR aac_error_code,absl::string_view error_message)47 absl::Status AacDecoderErrorToAbslStatus(AAC_DECODER_ERROR aac_error_code,
48 absl::string_view error_message) {
49 absl::StatusCode status_code;
50 switch (aac_error_code) {
51 case AAC_DEC_OK:
52 return absl::OkStatus();
53 case AAC_DEC_OUT_OF_MEMORY:
54 status_code = absl::StatusCode::kResourceExhausted;
55 break;
56 case AAC_DEC_TRANSPORT_SYNC_ERROR:
57 case AAC_DEC_NOT_ENOUGH_BITS:
58 case AAC_DEC_INVALID_HANDLE:
59 case AAC_DEC_UNSUPPORTED_AOT:
60 case AAC_DEC_UNSUPPORTED_FORMAT:
61 case AAC_DEC_UNSUPPORTED_ER_FORMAT:
62 case AAC_DEC_UNSUPPORTED_EPCONFIG:
63 case AAC_DEC_UNSUPPORTED_MULTILAYER:
64 case AAC_DEC_UNSUPPORTED_CHANNELCONFIG:
65 case AAC_DEC_UNSUPPORTED_SAMPLINGRATE:
66 case AAC_DEC_INVALID_SBR_CONFIG:
67 case AAC_DEC_SET_PARAM_FAIL:
68 case AAC_DEC_OUTPUT_BUFFER_TOO_SMALL:
69 case AAC_DEC_UNSUPPORTED_EXTENSION_PAYLOAD:
70 case AAC_DEC_UNSUPPORTED_SBA:
71 case AAC_DEC_ANC_DATA_ERROR:
72 case AAC_DEC_TOO_SMALL_ANC_BUFFER:
73 case AAC_DEC_TOO_MANY_ANC_ELEMENTS:
74 status_code = absl::StatusCode::kInvalidArgument;
75 break;
76 case AAC_DEC_NEED_TO_RESTART:
77 status_code = absl::StatusCode::kFailedPrecondition;
78 break;
79 // Several error codes usually imply that the bitstream is corrupt.
80 case AAC_DEC_TRANSPORT_ERROR:
81 case AAC_DEC_PARSE_ERROR:
82 case AAC_DEC_DECODE_FRAME_ERROR:
83 case AAC_DEC_INVALID_CODE_BOOK:
84 case AAC_DEC_UNSUPPORTED_PREDICTION:
85 case AAC_DEC_UNSUPPORTED_CCE:
86 case AAC_DEC_UNSUPPORTED_LFE:
87 case AAC_DEC_UNSUPPORTED_GAIN_CONTROL_DATA:
88 case AAC_DEC_CRC_ERROR:
89 case AAC_DEC_RVLC_ERROR:
90 case AAC_DEC_TNS_READ_ERROR:
91 status_code = absl::StatusCode::kDataLoss;
92 break;
93 default:
94 status_code = absl::StatusCode::kUnknown;
95 break;
96 }
97
98 return absl::Status(
99 status_code,
100 absl::StrCat(error_message, " AAC_DECODER_ERROR= ", aac_error_code));
101 }
102
ConfigureAacDecoder(const AacDecoderConfig & raw_aac_decoder_config,int num_channels,AAC_DECODER_INSTANCE * decoder_)103 absl::Status ConfigureAacDecoder(const AacDecoderConfig& raw_aac_decoder_config,
104 int num_channels,
105 AAC_DECODER_INSTANCE* decoder_) {
106 // Configure `fdk_aac` with the audio specific config which has the correct
107 // number of channels in it. IAMF may share a decoder config for several
108 // substreams, so the raw value may not be accurate.
109 AudioSpecificConfig fdk_audio_specific_config =
110 raw_aac_decoder_config.decoder_specific_info_.audio_specific_config;
111 fdk_audio_specific_config.channel_configuration_ = num_channels;
112
113 // Serialize the modified config. Assume a reasonable default size, but let
114 // the buffer be resizable to be safe.
115 const size_t kMaxAudioSpecificConfigSize = 5;
116 WriteBitBuffer wb(kMaxAudioSpecificConfigSize);
117 const absl::Status status = fdk_audio_specific_config.ValidateAndWrite(wb);
118
119 if (status.ok() && wb.IsByteAligned()) {
120 // Transform data from `const uint_t*` to `UCHAR*` to match the `libaac`
121 // interface.
122 std::vector<UCHAR> libaac_audio_specific_config(wb.bit_buffer().size());
123 std::transform(wb.bit_buffer().begin(), wb.bit_buffer().end(),
124 libaac_audio_specific_config.begin(),
125 [](uint8_t c) { return static_cast<UCHAR>(c); });
126
127 // Configure `decoder_` with the serialized data.
128 UCHAR* conf[] = {libaac_audio_specific_config.data()};
129 const UINT length[] = {static_cast<UINT>(wb.bit_offset() / 8)};
130 aacDecoder_ConfigRaw(decoder_, conf, length);
131 } else {
132 LOG(ERROR) << "Erroring writing audio specific config: " << status
133 << " wrote " << wb.bit_offset() << " bits.";
134 }
135
136 return status;
137 }
138
139 } // namespace
140
AacDecoder(const CodecConfigObu & codec_config_obu,int num_channels)141 AacDecoder::AacDecoder(const CodecConfigObu& codec_config_obu, int num_channels)
142 : DecoderBase(num_channels,
143 static_cast<int>(codec_config_obu.GetNumSamplesPerFrame())),
144 aac_decoder_config_(std::get<AacDecoderConfig>(
145 codec_config_obu.GetCodecConfig().decoder_config)) {}
146
~AacDecoder()147 AacDecoder::~AacDecoder() {
148 if (decoder_ != nullptr) {
149 aacDecoder_Close(decoder_);
150 }
151 }
152
Initialize()153 absl::Status AacDecoder::Initialize() {
154 // Initialize the decoder.
155 decoder_ = aacDecoder_Open(GetAacTransportationType(), /*nrOfLayers=*/1);
156
157 if (decoder_ == nullptr) {
158 return absl::UnknownError("Failed to initialize AAC decoder.");
159 }
160
161 RETURN_IF_NOT_OK(
162 ConfigureAacDecoder(aac_decoder_config_, num_channels_, decoder_));
163
164 const auto* stream_info = aacDecoder_GetStreamInfo(decoder_);
165 LOG_FIRST_N(INFO, 1) << "Created an AAC encoder with "
166 << stream_info->numChannels << " channels.";
167
168 return absl::OkStatus();
169 }
170
DecodeAudioFrame(const std::vector<uint8_t> & encoded_frame)171 absl::Status AacDecoder::DecodeAudioFrame(
172 const std::vector<uint8_t>& encoded_frame) {
173 num_valid_ticks_ = 0;
174
175 // Transform the data and feed it to the decoder.
176 std::vector<UCHAR> input_data(encoded_frame.size());
177 std::transform(encoded_frame.begin(), encoded_frame.end(), input_data.begin(),
178 [](uint8_t c) { return static_cast<UCHAR>(c); });
179
180 UCHAR* in_buffer[] = {input_data.data()};
181 const UINT buffer_size[] = {static_cast<UINT>(encoded_frame.size())};
182 UINT bytes_valid = static_cast<UINT>(encoded_frame.size());
183 RETURN_IF_NOT_OK(AacDecoderErrorToAbslStatus(
184 aacDecoder_Fill(decoder_, in_buffer, buffer_size, &bytes_valid),
185 "Failed on `aacDecoder_Fill`: "));
186 if (bytes_valid != 0) {
187 return absl::InvalidArgumentError(
188 "The input frame failed to decode. It may not have been a "
189 "complete AAC frame.");
190 }
191
192 // Retrieve the decoded frame. `fdk_aac` decodes to INT_PCM (usually 16-bits)
193 // samples with channels interlaced.
194 std::vector<INT_PCM> output_pcm(num_samples_per_channel_ * num_channels_);
195 RETURN_IF_NOT_OK(AacDecoderErrorToAbslStatus(
196 aacDecoder_DecodeFrame(decoder_, output_pcm.data(), output_pcm.size(),
197 /*flags=*/0),
198 "Failed on `aacDecoder_DecodeFrame`: "));
199
200 // Arrange the interleaved data in (time, channel) axes with samples stored in
201 // the upper bytes of an `int32_t`.
202 const absl::AnyInvocable<absl::Status(INT_PCM, int32_t&) const>
203 kAacInternalTypeToInt32 = [](INT_PCM input, int32_t& output) {
204 output = static_cast<int32_t>(input) << (32 - GetFdkAacBitDepth());
205 return absl::OkStatus();
206 };
207 return ConvertInterleavedToTimeChannel(absl::MakeConstSpan(output_pcm),
208 num_channels_, kAacInternalTypeToInt32,
209 decoded_samples_, num_valid_ticks_);
210 }
211
212 } // namespace iamf_tools
213