• 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/codec/lpcm_encoder.h"
13 
14 #include <cstdint>
15 #include <memory>
16 #include <vector>
17 
18 #include "absl/status/status_matchers.h"
19 #include "gmock/gmock.h"
20 #include "gtest/gtest.h"
21 #include "iamf/cli/codec/tests/encoder_test_base.h"
22 #include "iamf/obu/codec_config.h"
23 #include "iamf/obu/decoder_config/lpcm_decoder_config.h"
24 #include "iamf/obu/obu_header.h"
25 
26 namespace iamf_tools {
27 namespace {
28 
29 using ::absl_testing::IsOk;
30 
31 constexpr bool kOverrideAudioRollDistance = true;
32 
33 class LpcmEncoderTest : public EncoderTestBase, public testing::Test {
34  public:
LpcmEncoderTest()35   LpcmEncoderTest() { input_sample_size_ = 32; }
36   ~LpcmEncoderTest() = default;
37 
38  protected:
ConstructEncoder()39   void ConstructEncoder() override {
40     // Construct a Codec Config OBU. The only fields that should affect the
41     // output are `num_samples_per_frame` and `decoder_config`.
42     const CodecConfig temp = {.codec_id = CodecConfig::kCodecIdLpcm,
43                               .num_samples_per_frame = num_samples_per_frame_,
44                               .decoder_config = lpcm_decoder_config_};
45     CodecConfigObu codec_config(ObuHeader(), 0, temp);
46     EXPECT_THAT(codec_config.Initialize(kOverrideAudioRollDistance), IsOk());
47 
48     encoder_ = std::make_unique<LpcmEncoder>(codec_config, num_channels_);
49   }
50 
51   LpcmDecoderConfig lpcm_decoder_config_ = {
52       .sample_format_flags_bitmask_ = LpcmDecoderConfig::kLpcmLittleEndian,
53       .sample_size_ = 32,
54       .sample_rate_ = 48000};
55 };  // namespace iamf_tools
56 
TEST_F(LpcmEncoderTest,LittleEndian32bit)57 TEST_F(LpcmEncoderTest, LittleEndian32bit) {
58   InitExpectOk();
59 
60   EncodeAudioFrame({{0x01234567}});
61   expected_audio_frames_.push_back({0x67, 0x45, 0x23, 0x01});
62   FinalizeAndValidate();
63 }
64 
TEST_F(LpcmEncoderTest,BigEndian32bit)65 TEST_F(LpcmEncoderTest, BigEndian32bit) {
66   lpcm_decoder_config_.sample_format_flags_bitmask_ =
67       LpcmDecoderConfig::kLpcmBigEndian;
68   InitExpectOk();
69 
70   EncodeAudioFrame({{0x01234567}});
71   expected_audio_frames_.push_back({0x01, 0x23, 0x45, 0x67});
72   FinalizeAndValidate();
73 }
74 
TEST_F(LpcmEncoderTest,MultipleFrames)75 TEST_F(LpcmEncoderTest, MultipleFrames) {
76   InitExpectOk();
77 
78   EncodeAudioFrame({{0x01234567}});
79   expected_audio_frames_.push_back({0x67, 0x45, 0x23, 0x01});
80   EncodeAudioFrame({{0x77665544}});
81   expected_audio_frames_.push_back({0x44, 0x55, 0x66, 0x77});
82   FinalizeAndValidate();
83 }
84 
TEST_F(LpcmEncoderTest,LittleEndian16bit)85 TEST_F(LpcmEncoderTest, LittleEndian16bit) {
86   lpcm_decoder_config_.sample_size_ = 16;
87   input_sample_size_ = 16;
88   InitExpectOk();
89 
90   EncodeAudioFrame({{0x12340000}});
91   expected_audio_frames_.push_back({0x34, 0x12});
92   FinalizeAndValidate();
93 }
94 
TEST_F(LpcmEncoderTest,BigEndian16bit)95 TEST_F(LpcmEncoderTest, BigEndian16bit) {
96   lpcm_decoder_config_.sample_size_ = 16;
97   lpcm_decoder_config_.sample_format_flags_bitmask_ =
98       LpcmDecoderConfig::kLpcmBigEndian;
99 
100   input_sample_size_ = 16;
101   InitExpectOk();
102 
103   EncodeAudioFrame({{0x12340000}});
104   expected_audio_frames_.push_back({0x12, 0x34});
105   FinalizeAndValidate();
106 }
107 
TEST_F(LpcmEncoderTest,LittleEndian24bit)108 TEST_F(LpcmEncoderTest, LittleEndian24bit) {
109   lpcm_decoder_config_.sample_size_ = 24;
110   input_sample_size_ = 24;
111   InitExpectOk();
112 
113   EncodeAudioFrame({{0x12345600}});
114   expected_audio_frames_.push_back({0x56, 0x34, 0x12});
115   FinalizeAndValidate();
116 }
117 
TEST_F(LpcmEncoderTest,BigEndian24bit)118 TEST_F(LpcmEncoderTest, BigEndian24bit) {
119   lpcm_decoder_config_.sample_size_ = 24;
120   lpcm_decoder_config_.sample_format_flags_bitmask_ =
121       LpcmDecoderConfig::kLpcmBigEndian;
122   input_sample_size_ = 24;
123   InitExpectOk();
124 
125   EncodeAudioFrame({{0x12345600}});
126   expected_audio_frames_.push_back({0x12, 0x34, 0x56});
127   FinalizeAndValidate();
128 }
129 
TEST_F(LpcmEncoderTest,MultipleSamplesPerFrame)130 TEST_F(LpcmEncoderTest, MultipleSamplesPerFrame) {
131   num_samples_per_frame_ = 3;
132   InitExpectOk();
133 
134   EncodeAudioFrame({{0x11111111}, {0x22222222}, {0x33333333}});
135   expected_audio_frames_.push_back(
136       {0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x33, 0x33, 0x33, 0x33});
137   FinalizeAndValidate();
138 }
139 
TEST_F(LpcmEncoderTest,EncodeAudioFrameFailsWhenThereAreNoSamples)140 TEST_F(LpcmEncoderTest, EncodeAudioFrameFailsWhenThereAreNoSamples) {
141   InitExpectOk();
142   const std::vector<std::vector<int32_t>> kInputFrameWithNoSamples = {};
143 
144   EncodeAudioFrame(kInputFrameWithNoSamples,
145                    /*expected_encode_frame_is_ok=*/false);
146 }
147 
TEST_F(LpcmEncoderTest,DoesNotSupportPartialFrames)148 TEST_F(LpcmEncoderTest, DoesNotSupportPartialFrames) {
149   constexpr bool kExpectEncodeFrameIsNotOk = false;
150   num_samples_per_frame_ = 3;
151   InitExpectOk();
152 
153   EncodeAudioFrame({{0x11111111}, {0x22222222}}, kExpectEncodeFrameIsNotOk);
154 }
155 
TEST_F(LpcmEncoderTest,TwoChannels)156 TEST_F(LpcmEncoderTest, TwoChannels) {
157   num_channels_ = 2;
158   InitExpectOk();
159 
160   EncodeAudioFrame({{0x11111111, 0x22222222}});
161   expected_audio_frames_.push_back(
162       {0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22});
163   FinalizeAndValidate();
164 }
165 
TEST_F(LpcmEncoderTest,EncodeAudioFrameFailsWhenNumChannelsIsInconsitentWithInputFrame)166 TEST_F(LpcmEncoderTest,
167        EncodeAudioFrameFailsWhenNumChannelsIsInconsitentWithInputFrame) {
168   num_channels_ = 1;
169   const std::vector<std::vector<int32_t>> kInputFrameWithTwoChannels = {
170       {0x11111111, 0x22222222}};
171   InitExpectOk();
172 
173   EncodeAudioFrame(kInputFrameWithTwoChannels,
174                    /*expected_encode_frame_is_ok=*/false);
175 }
176 
TEST_F(LpcmEncoderTest,FramesAreInOrder)177 TEST_F(LpcmEncoderTest, FramesAreInOrder) {
178   InitExpectOk();
179 
180   // Encode several frames and ensure the correct number of frames are output in
181   // the same order as the input.
182   const int kNumFrames = 100;
183   for (int i = 0; i < kNumFrames; i++) {
184     EncodeAudioFrame(std::vector<std::vector<int32_t>>(
185         num_samples_per_frame_, std::vector<int32_t>(num_channels_, i)));
186   }
187   FinalizeAndValidateOrderOnly(kNumFrames);
188 }
189 
190 }  // namespace
191 }  // namespace iamf_tools
192