• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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