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/audio_frame_decoder.h"
13
14 #include <memory>
15 #include <utility>
16
17 #include "absl/container/node_hash_map.h"
18 #include "absl/status/status.h"
19 #include "absl/status/statusor.h"
20 #include "absl/strings/str_cat.h"
21 #include "iamf/cli/audio_element_with_data.h"
22 #include "iamf/cli/audio_frame_with_data.h"
23 #include "iamf/cli/codec/decoder_base.h"
24 #include "iamf/cli/codec/lpcm_decoder.h"
25 #include "iamf/common/utils/macros.h"
26 #include "iamf/obu/codec_config.h"
27
28 // These defines are not part of an official API and are likely to change or be
29 // removed. Please do not depend on them.
30 // TODO(b/401063570): Remove these statements when no longer disabling FLAC/AAC.
31 #ifndef IAMF_TOOLS_DISABLE_AAC_DECODER
32 #include "iamf/cli/codec/aac_decoder.h"
33 #endif
34
35 #ifndef IAMF_TOOLS_DISABLE_FLAC_DECODER
36 #include "iamf/cli/codec/flac_decoder.h"
37 #endif
38
39 #ifndef IAMF_TOOLS_DISABLE_OPUS_DECODER
40 #include "iamf/cli/codec/opus_decoder.h"
41 #endif
42
43 namespace iamf_tools {
44
45 namespace {
46
InitializeDecoder(const CodecConfigObu & codec_config,int num_channels,std::unique_ptr<DecoderBase> & decoder)47 absl::Status InitializeDecoder(const CodecConfigObu& codec_config,
48 int num_channels,
49 std::unique_ptr<DecoderBase>& decoder) {
50 switch (codec_config.GetCodecConfig().codec_id) {
51 using enum CodecConfig::CodecId;
52 case kCodecIdLpcm:
53 decoder = std::make_unique<LpcmDecoder>(codec_config, num_channels);
54 break;
55 #ifndef IAMF_TOOLS_DISABLE_OPUS_DECODER
56 case kCodecIdOpus:
57 decoder = std::make_unique<OpusDecoder>(codec_config, num_channels);
58 break;
59 #endif
60 #ifndef IAMF_TOOLS_DISABLE_AAC_DECODER
61 case kCodecIdAacLc:
62 decoder = std::make_unique<AacDecoder>(codec_config, num_channels);
63 break;
64 #endif
65 #ifndef IAMF_TOOLS_DISABLE_FLAC_DECODER
66 case kCodecIdFlac:
67 decoder = std::make_unique<FlacDecoder>(
68 num_channels, codec_config.GetNumSamplesPerFrame());
69 break;
70 #endif
71 default:
72 return absl::InvalidArgumentError(
73 absl::StrCat("Unrecognized or disabled codec_id= ",
74 codec_config.GetCodecConfig().codec_id));
75 }
76
77 if (decoder) {
78 RETURN_IF_NOT_OK(decoder->Initialize());
79 }
80 return absl::OkStatus();
81 }
82
83 } // namespace
84
85 // Initializes all decoders and wav writers based on the corresponding Audio
86 // Element and Codec Config OBUs.
InitDecodersForSubstreams(const SubstreamIdLabelsMap & substream_id_to_labels,const CodecConfigObu & codec_config)87 absl::Status AudioFrameDecoder::InitDecodersForSubstreams(
88 const SubstreamIdLabelsMap& substream_id_to_labels,
89 const CodecConfigObu& codec_config) {
90 for (const auto& [substream_id, labels] : substream_id_to_labels) {
91 auto& decoder = substream_id_to_decoder_[substream_id];
92 if (decoder != nullptr) {
93 return absl::InvalidArgumentError(absl::StrCat(
94 "Already initialized decoder for substream ID: ", substream_id,
95 ". Maybe multiple Audio Element OBUs have the same substream ID?"));
96 }
97
98 const int num_channels = static_cast<int>(labels.size());
99
100 // Initialize the decoder based on the found Codec Config OBU and number
101 // of channels.
102 RETURN_IF_NOT_OK(InitializeDecoder(codec_config, num_channels, decoder));
103 }
104
105 return absl::OkStatus();
106 }
107
Decode(const AudioFrameWithData & audio_frame)108 absl::StatusOr<DecodedAudioFrame> AudioFrameDecoder::Decode(
109 const AudioFrameWithData& audio_frame) {
110 auto decoder_iter =
111 substream_id_to_decoder_.find(audio_frame.obu.GetSubstreamId());
112 if (decoder_iter == substream_id_to_decoder_.end() ||
113 decoder_iter->second == nullptr) {
114 return absl::InvalidArgumentError(
115 absl::StrCat("No decoder found for substream ID: ",
116 audio_frame.obu.GetSubstreamId()));
117 }
118 // Decode the samples with the specific decoder associated with this
119 // substream.
120 auto& decoder = *decoder_iter->second;
121 RETURN_IF_NOT_OK(decoder.DecodeAudioFrame(audio_frame.obu.audio_frame_));
122
123 // Return a frame. Most fields are copied from the encoded frame.
124 return DecodedAudioFrame{
125 .substream_id = audio_frame.obu.GetSubstreamId(),
126 .start_timestamp = audio_frame.start_timestamp,
127 .end_timestamp = audio_frame.end_timestamp,
128 .samples_to_trim_at_end =
129 audio_frame.obu.header_.num_samples_to_trim_at_end,
130 .samples_to_trim_at_start =
131 audio_frame.obu.header_.num_samples_to_trim_at_start,
132 .decoded_samples = decoder.ValidDecodedSamples(),
133 .down_mixing_params = audio_frame.down_mixing_params,
134 .recon_gain_info_parameter_data =
135 audio_frame.recon_gain_info_parameter_data,
136 .audio_element_with_data = audio_frame.audio_element_with_data,
137 };
138 }
139
140 } // namespace iamf_tools
141