• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "iamf/cli/codec/lpcm_decoder.h"
2 
3 #include <cstdint>
4 #include <vector>
5 
6 #include "absl/log/log.h"
7 #include "absl/status/status_matchers.h"
8 #include "gmock/gmock.h"
9 #include "gtest/gtest.h"
10 #include "iamf/obu/codec_config.h"
11 #include "iamf/obu/decoder_config/lpcm_decoder_config.h"
12 #include "iamf/obu/obu_header.h"
13 
14 namespace iamf_tools {
15 namespace {
16 
17 using ::absl_testing::IsOk;
18 
19 constexpr bool kOverrideAudioRollDistance = true;
20 constexpr uint32_t kNumSamplesPerFrame = 1024;
21 constexpr uint8_t kSampleSize16 = 16;
22 constexpr bool kLittleEndian = true;
23 
CreateCodecConfigObu(LpcmDecoderConfig lpcm_decoder_config,uint32_t num_samples_per_frame)24 CodecConfigObu CreateCodecConfigObu(LpcmDecoderConfig lpcm_decoder_config,
25                                     uint32_t num_samples_per_frame) {
26   const CodecConfig codec_config = {
27       .codec_id = CodecConfig::kCodecIdLpcm,
28       .num_samples_per_frame = num_samples_per_frame,
29       .decoder_config = lpcm_decoder_config};
30 
31   CodecConfigObu codec_config_obu(ObuHeader(), 0, codec_config);
32   return codec_config_obu;
33 };
34 
TEST(LpcmDecoderTest,Construct)35 TEST(LpcmDecoderTest, Construct) {
36   LpcmDecoderConfig lpcm_decoder_config;
37   lpcm_decoder_config.sample_rate_ = 48000;
38   lpcm_decoder_config.sample_size_ = 16;
39   lpcm_decoder_config.sample_format_flags_bitmask_ =
40       LpcmDecoderConfig::LpcmFormatFlagsBitmask::kLpcmLittleEndian;
41   CodecConfigObu codec_config_obu =
42       CreateCodecConfigObu(lpcm_decoder_config, kNumSamplesPerFrame);
43   ASSERT_THAT(codec_config_obu.Initialize(kOverrideAudioRollDistance), IsOk());
44   int number_of_channels = 11;  // Arbitrary.
45 
46   LpcmDecoder lpcm_decoder(codec_config_obu, number_of_channels);
47 }
48 
TEST(LpcmDecoderTest,Initialize_InvalidConfigFails)49 TEST(LpcmDecoderTest, Initialize_InvalidConfigFails) {
50   LpcmDecoderConfig lpcm_decoder_config;
51   // The sample rate and bit depth are validated with CodecConfigObu::Initialize
52   // so if we want to test the validation in LpcmDecoderConfig::Initialize we
53   // will give an invalid sample_format_flags_bitmask_.
54   lpcm_decoder_config.sample_rate_ = 48000;
55   lpcm_decoder_config.sample_size_ = 16;
56   lpcm_decoder_config.sample_format_flags_bitmask_ =
57       LpcmDecoderConfig::LpcmFormatFlagsBitmask::kLpcmBeginReserved;
58   CodecConfigObu codec_config_obu =
59       CreateCodecConfigObu(lpcm_decoder_config, kNumSamplesPerFrame);
60   ASSERT_THAT(codec_config_obu.Initialize(kOverrideAudioRollDistance), IsOk());
61   int number_of_channels = 11;  // Arbitrary.
62 
63   LpcmDecoder lpcm_decoder(codec_config_obu, number_of_channels);
64   auto status = lpcm_decoder.Initialize();
65 
66   EXPECT_FALSE(status.ok());
67 }
68 
CreateDecoderForDecodingTest(uint8_t sample_size,bool little_endian,uint32_t num_samples_per_frame)69 LpcmDecoder CreateDecoderForDecodingTest(uint8_t sample_size,
70                                          bool little_endian,
71                                          uint32_t num_samples_per_frame) {
72   LpcmDecoderConfig lpcm_decoder_config;
73   // The sample rate and bit depth are validated with CodecConfigObu::Initialize
74   // so if we want to test the validation in LpcmDecoderConfig::Initialize we
75   // will give an invalid sample_format_flags_bitmask_.
76   lpcm_decoder_config.sample_rate_ = 48000;
77   lpcm_decoder_config.sample_size_ = sample_size;
78   using enum LpcmDecoderConfig::LpcmFormatFlagsBitmask;
79   lpcm_decoder_config.sample_format_flags_bitmask_ =
80       little_endian ? kLpcmLittleEndian : kLpcmBigEndian;
81   CodecConfigObu codec_config_obu =
82       CreateCodecConfigObu(lpcm_decoder_config, num_samples_per_frame);
83   if (!codec_config_obu.Initialize(kOverrideAudioRollDistance).ok()) {
84     LOG(ERROR) << "Failed to initialize codec config OBU";
85   }
86   constexpr int kTwoChannels = 2;  // Keep the amount of test data reasonable.
87 
88   LpcmDecoder lpcm_decoder(codec_config_obu, kTwoChannels);
89   auto status = lpcm_decoder.Initialize();
90   return lpcm_decoder;
91 }
92 
TEST(LpcmDecoderTest,DecodeAudioFrame_FailsWhenFrameIsLargerThanExpected)93 TEST(LpcmDecoderTest, DecodeAudioFrame_FailsWhenFrameIsLargerThanExpected) {
94   constexpr uint32_t kShortNumberOfSamplesPerFrame = 1;
95   LpcmDecoder lpcm_decoder = CreateDecoderForDecodingTest(
96       kSampleSize16, kLittleEndian, kShortNumberOfSamplesPerFrame);
97   const std::vector<uint8_t>& kEncodedFrameWithOneSamplesPerFrame = {
98       0x00, 0x00,  // 0
99       0x01, 0x00,  // 1
100   };
101   // The decoder is configured correctly. One sample per frame decodes fine.
102   ASSERT_THAT(
103       lpcm_decoder.DecodeAudioFrame(kEncodedFrameWithOneSamplesPerFrame),
104       IsOk());
105 
106   // But decoding two samples per frame fails, since the decoder was configured
107   // for at most one sample per frame.
108   const std::vector<uint8_t>& kEncodedFrameWithTwoSamplesPerFrame = {
109       0x00, 0x00,  // 0
110       0x01, 0x00,  // 1
111       0x00, 0x01,  // 256
112       0x80, 0xff,  // -128
113   };
114   EXPECT_FALSE(
115       lpcm_decoder.DecodeAudioFrame(kEncodedFrameWithTwoSamplesPerFrame).ok());
116 }
117 
TEST(LpcmDecoderTest,DecodeAudioFrame_LittleEndian16BitSamples)118 TEST(LpcmDecoderTest, DecodeAudioFrame_LittleEndian16BitSamples) {
119   uint8_t sample_size = 16;
120   bool little_endian = true;
121   LpcmDecoder lpcm_decoder = CreateDecoderForDecodingTest(
122       sample_size, little_endian, kNumSamplesPerFrame);
123   const std::vector<uint8_t>& encoded_frame = {
124       0x00, 0x00,  // 0
125       0x01, 0x00,  // 1
126       0x00, 0x01,  // 256
127       0x80, 0xff,  // -128
128   };
129 
130   auto status = lpcm_decoder.DecodeAudioFrame(encoded_frame);
131   const auto& decoded_samples = lpcm_decoder.ValidDecodedSamples();
132 
133   EXPECT_THAT(status, IsOk());
134   // We have two channels and four samples, so we expect two time ticks of two
135   // samples each.
136   EXPECT_EQ(decoded_samples.size(), 2);
137   EXPECT_EQ(decoded_samples[0].size(), 2);
138   EXPECT_EQ(decoded_samples[0][0], 0);
139   EXPECT_EQ(decoded_samples[0][1], 0x00010000);
140   EXPECT_EQ(decoded_samples[1].size(), 2);
141   EXPECT_EQ(decoded_samples[1][0], 0x01000000);
142   EXPECT_EQ(decoded_samples[1][1], 0xff800000);
143 }
144 
TEST(LpcmDecoderTest,DecodeAudioFrame_BigEndian24BitSamples)145 TEST(LpcmDecoderTest, DecodeAudioFrame_BigEndian24BitSamples) {
146   uint8_t sample_size = 24;
147   bool little_endian = false;
148   LpcmDecoder lpcm_decoder = CreateDecoderForDecodingTest(
149       sample_size, little_endian, kNumSamplesPerFrame);
150   const std::vector<uint8_t>& encoded_frame = {
151       0x00, 0x00, 0x00,  // 0
152       0x00, 0x00, 0x01,  // 1
153       0x00, 0x00, 0x03,  // 3
154       0x00, 0x00, 0x04,  // 4
155       0x7f, 0xff, 0xff,  // 8388607
156       0x80, 0x00, 0x00,  // -8388608
157   };
158 
159   auto status = lpcm_decoder.DecodeAudioFrame(encoded_frame);
160   const auto& decoded_samples = lpcm_decoder.ValidDecodedSamples();
161 
162   EXPECT_THAT(status, IsOk());
163   // We have two channels and six samples, so we expect three time ticks of two
164   // samples each.
165   EXPECT_EQ(decoded_samples.size(), 3);
166   EXPECT_EQ(decoded_samples[0].size(), 2);
167   EXPECT_EQ(decoded_samples[0][0], 0);
168   EXPECT_EQ(decoded_samples[0][1], 0x00000100);
169   EXPECT_EQ(decoded_samples[1].size(), 2);
170   EXPECT_EQ(decoded_samples[1][0], 0x00000300);
171   EXPECT_EQ(decoded_samples[1][1], 0x00000400);
172   EXPECT_EQ(decoded_samples[2].size(), 2);
173   EXPECT_EQ(decoded_samples[2][0], 0x7fffff00);
174   EXPECT_EQ(decoded_samples[2][1], 0x80000000);
175 }
176 
TEST(LpcmDecoderTest,DecodeAudioFrame_WillNotDecodeWrongSize)177 TEST(LpcmDecoderTest, DecodeAudioFrame_WillNotDecodeWrongSize) {
178   uint8_t sample_size = 16;
179   bool little_endian = true;
180   LpcmDecoder lpcm_decoder = CreateDecoderForDecodingTest(
181       sample_size, little_endian, kNumSamplesPerFrame);
182   // If we have 6 bytes, 16-bit samples, and two channels, we only have 3
183   // samples which doesn't divide evenly into the number of channels.
184   const std::vector<uint8_t>& encoded_frame = {0x00, 0x00, 0x00,
185                                                0x00, 0x00, 0x00};
186 
187   auto status = lpcm_decoder.DecodeAudioFrame(encoded_frame);
188   EXPECT_FALSE(status.ok());
189   EXPECT_THAT(lpcm_decoder.ValidDecodedSamples(), ::testing::IsEmpty());
190 }
191 
TEST(LpcmDecoderTest,DecodeAudioFrame_OverwritesExistingSamples)192 TEST(LpcmDecoderTest, DecodeAudioFrame_OverwritesExistingSamples) {
193   uint8_t sample_size = 16;
194   bool little_endian = true;
195   LpcmDecoder lpcm_decoder = CreateDecoderForDecodingTest(
196       sample_size, little_endian, kNumSamplesPerFrame);
197   const std::vector<uint8_t>& encoded_frame = {0x00, 0x00, 0x01, 0x00};
198 
199   auto status = lpcm_decoder.DecodeAudioFrame(encoded_frame);
200   EXPECT_THAT(status, IsOk());
201   EXPECT_EQ(lpcm_decoder.ValidDecodedSamples().size(), 1);
202 
203   status = lpcm_decoder.DecodeAudioFrame(encoded_frame);
204   EXPECT_THAT(status, IsOk());
205   EXPECT_EQ(lpcm_decoder.ValidDecodedSamples().size(), 1);
206 
207   status = lpcm_decoder.DecodeAudioFrame(encoded_frame);
208   EXPECT_THAT(status, IsOk());
209   EXPECT_EQ(lpcm_decoder.ValidDecodedSamples().size(), 1);
210 }
211 
212 }  // namespace
213 }  // namespace iamf_tools
214