• 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 <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