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 <array>
15 #include <cstdint>
16 #include <vector>
17
18 #include "absl/container/flat_hash_map.h"
19 #include "absl/status/status_matchers.h"
20 #include "gmock/gmock.h"
21 #include "gtest/gtest.h"
22 #include "iamf/cli/audio_element_with_data.h"
23 #include "iamf/cli/audio_frame_with_data.h"
24 #include "iamf/cli/channel_label.h"
25 #include "iamf/cli/tests/cli_test_utils.h"
26 #include "iamf/obu/audio_frame.h"
27 #include "iamf/obu/codec_config.h"
28 #include "iamf/obu/demixing_info_parameter_data.h"
29 #include "iamf/obu/obu_header.h"
30 #include "iamf/obu/types.h"
31
32 namespace iamf_tools {
33 namespace {
34
35 using ::absl_testing::IsOk;
36
37 constexpr DecodedUleb128 kCodecConfigId = 44;
38 constexpr uint32_t kSampleRate = 16000;
39 constexpr DecodedUleb128 kAudioElementId = 13;
40 constexpr DecodedUleb128 kSubstreamId = 0;
41 constexpr DownMixingParams kDownMixingParams = {.alpha = 0.5, .beta = 0.5};
42 const int kNumChannels = 1;
43 const int kNumSamplesPerFrame = 8;
44 const int kBytesPerSample = 2;
45 constexpr std::array<uint8_t, 22> kFlacEncodedFrame = {
46 0xff, 0xf8, 0x6a, 0xa8, 0x00, 0x0f, 0x42, 0x00, 0x00, 0x00, 0x13,
47 0x80, 0x00, 0x80, 0x04, 0x92, 0x49, 0x00, 0x01, 0xfe, 0x81, 0xee};
48
PrepareEncodedAudioFrame(absl::flat_hash_map<uint32_t,CodecConfigObu> & codec_config_obus,absl::flat_hash_map<DecodedUleb128,AudioElementWithData> & audio_elements,CodecConfig::CodecId codec_id_type=CodecConfig::kCodecIdLpcm,std::vector<uint8_t> encoded_audio_frame_payload={})49 AudioFrameWithData PrepareEncodedAudioFrame(
50 absl::flat_hash_map<uint32_t, CodecConfigObu>& codec_config_obus,
51 absl::flat_hash_map<DecodedUleb128, AudioElementWithData>& audio_elements,
52 CodecConfig::CodecId codec_id_type = CodecConfig::kCodecIdLpcm,
53 std::vector<uint8_t> encoded_audio_frame_payload = {}) {
54 if (codec_id_type == CodecConfig::kCodecIdLpcm) {
55 AddLpcmCodecConfigWithIdAndSampleRate(kCodecConfigId, kSampleRate,
56 codec_config_obus);
57 } else if (codec_id_type == CodecConfig::kCodecIdFlac) {
58 AddFlacCodecConfigWithId(kCodecConfigId, codec_config_obus);
59 }
60 AddAmbisonicsMonoAudioElementWithSubstreamIds(
61 kAudioElementId, kCodecConfigId, {kSubstreamId}, codec_config_obus,
62 audio_elements);
63
64 if (encoded_audio_frame_payload.empty()) {
65 encoded_audio_frame_payload =
66 std::vector<uint8_t>(kNumSamplesPerFrame * kBytesPerSample, 0);
67 }
68 return AudioFrameWithData({
69 .obu = AudioFrameObu(ObuHeader(), kSubstreamId,
70 /*audio_frame=*/
71 encoded_audio_frame_payload),
72 .start_timestamp = 0,
73 .end_timestamp = kNumSamplesPerFrame,
74 .down_mixing_params = kDownMixingParams,
75 .audio_element_with_data = &audio_elements.at(kAudioElementId),
76 });
77 }
78
TEST(Decode,RequiresSubstreamsAreInitialized)79 TEST(Decode, RequiresSubstreamsAreInitialized) {
80 AudioFrameDecoder decoder;
81 // Encoded frames.
82 absl::flat_hash_map<uint32_t, CodecConfigObu> codec_config_obus;
83 absl::flat_hash_map<DecodedUleb128, AudioElementWithData> audio_elements;
84 const AudioFrameWithData encoded_audio_frame =
85 PrepareEncodedAudioFrame(codec_config_obus, audio_elements);
86
87 // Decoding fails before substreams are initialized.
88 EXPECT_FALSE(decoder.Decode(encoded_audio_frame).ok());
89 const auto& audio_element = audio_elements.at(kAudioElementId);
90 // Decoding succeeds after substreams are initialized.
91 EXPECT_THAT(
92 decoder.InitDecodersForSubstreams(audio_element.substream_id_to_labels,
93 *audio_element.codec_config),
94 IsOk());
95 EXPECT_THAT(decoder.Decode(encoded_audio_frame), IsOk());
96 }
97
TEST(InitDecodersForSubstreams,ShouldNotBeCalledTwiceWithTheSameSubstreamIdForStatefulEncoders)98 TEST(InitDecodersForSubstreams,
99 ShouldNotBeCalledTwiceWithTheSameSubstreamIdForStatefulEncoders) {
100 absl::flat_hash_map<uint32_t, CodecConfigObu> codec_config_obus;
101 AddOpusCodecConfigWithId(kCodecConfigId, codec_config_obus);
102 const auto& codec_config = codec_config_obus.at(kCodecConfigId);
103
104 AudioFrameDecoder decoder;
105 const SubstreamIdLabelsMap kLabelsForSubstreamZero = {
106 {kSubstreamId, {ChannelLabel::kMono}}};
107 EXPECT_THAT(
108 decoder.InitDecodersForSubstreams(kLabelsForSubstreamZero, codec_config),
109 IsOk());
110 EXPECT_FALSE(
111 decoder.InitDecodersForSubstreams(kLabelsForSubstreamZero, codec_config)
112 .ok());
113
114 const SubstreamIdLabelsMap kLabelsForSubstreamOne = {
115 {kSubstreamId + 1, {ChannelLabel::kMono}}};
116 EXPECT_THAT(
117 decoder.InitDecodersForSubstreams(kLabelsForSubstreamOne, codec_config),
118 IsOk());
119 }
120
InitAllAudioElements(const absl::flat_hash_map<DecodedUleb128,AudioElementWithData> & audio_elements,AudioFrameDecoder & decoder)121 void InitAllAudioElements(
122 const absl::flat_hash_map<DecodedUleb128, AudioElementWithData>&
123 audio_elements,
124 AudioFrameDecoder& decoder) {
125 for (const auto& [audio_element_id, audio_element_with_data] :
126 audio_elements) {
127 EXPECT_THAT(decoder.InitDecodersForSubstreams(
128 audio_element_with_data.substream_id_to_labels,
129 *audio_element_with_data.codec_config),
130 IsOk());
131 }
132 }
133
TEST(Decode,DecodesLpcmFrame)134 TEST(Decode, DecodesLpcmFrame) {
135 AudioFrameDecoder decoder;
136
137 // Encoded frames.
138 absl::flat_hash_map<uint32_t, CodecConfigObu> codec_config_obus;
139 absl::flat_hash_map<DecodedUleb128, AudioElementWithData> audio_elements;
140 const AudioFrameWithData encoded_audio_frame =
141 PrepareEncodedAudioFrame(codec_config_obus, audio_elements);
142 InitAllAudioElements(audio_elements, decoder);
143
144 // Decode.
145 const auto decoded_audio_frame = decoder.Decode(encoded_audio_frame);
146
147 // Validate.
148 ASSERT_THAT(decoded_audio_frame, IsOk());
149 EXPECT_EQ(decoded_audio_frame->substream_id, kSubstreamId);
150 EXPECT_EQ(decoded_audio_frame->start_timestamp, 0);
151 EXPECT_EQ(decoded_audio_frame->end_timestamp, kNumSamplesPerFrame);
152 EXPECT_EQ(decoded_audio_frame->down_mixing_params, kDownMixingParams);
153 EXPECT_EQ(decoded_audio_frame->audio_element_with_data,
154 &audio_elements.at(kAudioElementId));
155
156 // For LPCM, the input bytes are all zeros, but we expect the decoder to
157 // combine kBytesPerSample bytes each into one int32_t sample.
158 // There are kNumSamplesPerFrame samples in the frame.
159 EXPECT_EQ(decoded_audio_frame->decoded_samples.size(), kNumSamplesPerFrame);
160 for (const std::vector<int32_t>& samples_for_one_time_tick :
161 decoded_audio_frame->decoded_samples) {
162 EXPECT_EQ(samples_for_one_time_tick.size(), kNumChannels);
163 for (int32_t sample : samples_for_one_time_tick) {
164 EXPECT_EQ(sample, 0);
165 }
166 }
167 }
168
TEST(Decode,DecodesFlacFrame)169 TEST(Decode, DecodesFlacFrame) {
170 AudioFrameDecoder decoder;
171
172 // Encoded frames.
173 absl::flat_hash_map<uint32_t, CodecConfigObu> codec_config_obus;
174 absl::flat_hash_map<DecodedUleb128, AudioElementWithData> audio_elements;
175 std::vector<uint8_t> encoded_audio_frame_payload = {kFlacEncodedFrame.begin(),
176 kFlacEncodedFrame.end()};
177 const AudioFrameWithData encoded_audio_frame = PrepareEncodedAudioFrame(
178 codec_config_obus, audio_elements, CodecConfig::kCodecIdFlac,
179 encoded_audio_frame_payload);
180 InitAllAudioElements(audio_elements, decoder);
181
182 // Decode.
183 const auto decoded_audio_frame = decoder.Decode(encoded_audio_frame);
184
185 // Validate.
186 ASSERT_THAT(decoded_audio_frame, IsOk());
187 EXPECT_EQ(decoded_audio_frame->substream_id, kSubstreamId);
188 EXPECT_EQ(decoded_audio_frame->start_timestamp, 0);
189 EXPECT_EQ(decoded_audio_frame->end_timestamp, kNumSamplesPerFrame);
190 EXPECT_EQ(decoded_audio_frame->down_mixing_params, kDownMixingParams);
191 EXPECT_EQ(decoded_audio_frame->audio_element_with_data,
192 &audio_elements.at(kAudioElementId));
193 const std::vector<std::vector<int32_t>> kExpectedDecodedSamples = {
194 {0x00010000, static_cast<int32_t>(0xffff0000)},
195 {0x00020000, static_cast<int32_t>(0xfffe0000)},
196 {0x00030000, static_cast<int32_t>(0xfffd0000)},
197 {0x00040000, static_cast<int32_t>(0xfffc0000)},
198 {0x00050000, static_cast<int32_t>(0xfffb0000)},
199 {0x00060000, static_cast<int32_t>(0xfffa0000)},
200 {0x00070000, static_cast<int32_t>(0xfff90000)},
201 {0x00080000, static_cast<int32_t>(0xfff80000)},
202 {0x00000000, 0x00000000},
203 {0x00000000, 0x00000000},
204 {0x00000000, 0x00000000},
205 {0x00000000, 0x00000000},
206 {0x00000000, 0x00000000},
207 {0x00000000, 0x00000000},
208 {0x00000000, 0x00000000},
209 {0x00000000, 0x00000000}};
210 EXPECT_EQ(decoded_audio_frame->decoded_samples, kExpectedDecodedSamples);
211 }
212
TEST(Decode,DecodesMultipleFlacFrames)213 TEST(Decode, DecodesMultipleFlacFrames) {
214 AudioFrameDecoder decoder;
215
216 // Encoded frames.
217 absl::flat_hash_map<uint32_t, CodecConfigObu> codec_config_obus;
218 absl::flat_hash_map<DecodedUleb128, AudioElementWithData> audio_elements;
219 std::vector<uint8_t> encoded_audio_frame_payload = {kFlacEncodedFrame.begin(),
220 kFlacEncodedFrame.end()};
221 const AudioFrameWithData encoded_audio_frame = PrepareEncodedAudioFrame(
222 codec_config_obus, audio_elements, CodecConfig::kCodecIdFlac,
223 encoded_audio_frame_payload);
224 InitAllAudioElements(audio_elements, decoder);
225
226 // Decode the same frame twice.
227 EXPECT_THAT(decoder.Decode(encoded_audio_frame), IsOk());
228 EXPECT_THAT(decoder.Decode(encoded_audio_frame), IsOk());
229 }
230 // TODO(b/308073716): Add tests for more kinds of decoders.
231
232 } // namespace
233 } // namespace iamf_tools
234