• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024, 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 
13 #include "iamf/cli/renderer/renderer_utils.h"
14 
15 #include <cstddef>
16 #include <vector>
17 
18 #include "absl/status/status_matchers.h"
19 #include "absl/types/span.h"
20 #include "gmock/gmock.h"
21 #include "gtest/gtest.h"
22 #include "iamf/cli/channel_label.h"
23 #include "iamf/cli/demixing_module.h"
24 #include "iamf/obu/mix_presentation.h"
25 #include "iamf/obu/types.h"
26 
27 namespace iamf_tools {
28 namespace renderer_utils {
29 namespace {
30 
31 using ::absl_testing::IsOk;
32 using enum ChannelLabel::Label;
33 using testing::DoubleEq;
34 using testing::Pointwise;
35 
36 constexpr size_t kNumSamplesPerFrame = 8;
37 
TEST(ArrangeSamplesToRender,SucceedsOnEmptyFrame)38 TEST(ArrangeSamplesToRender, SucceedsOnEmptyFrame) {
39   std::vector<std::vector<InternalSampleType>> samples(
40       kNumSamplesPerFrame, std::vector<InternalSampleType>(0));
41   size_t num_valid_samples = 0;
42   EXPECT_THAT(ArrangeSamplesToRender({}, {}, samples, num_valid_samples),
43               IsOk());
44 
45   // `samples` remains the same size, but `num_valid_samples` is zero.
46   EXPECT_EQ(samples.size(), kNumSamplesPerFrame);
47   EXPECT_EQ(num_valid_samples, 0);
48 }
49 
TEST(ArrangeSamplesToRender,ArrangesSamplesInTimeChannelAxes)50 TEST(ArrangeSamplesToRender, ArrangesSamplesInTimeChannelAxes) {
51   const LabeledFrame kStereoLabeledFrame = {
52       .label_to_samples = {{kL2, {0, 1, 2}}, {kR2, {10, 11, 12}}}};
53   const std::vector<ChannelLabel::Label> kStereoArrangement = {kL2, kR2};
54 
55   std::vector<std::vector<InternalSampleType>> samples(
56       kNumSamplesPerFrame,
57       std::vector<InternalSampleType>(kStereoArrangement.size()));
58   size_t num_valid_samples = 0;
59   EXPECT_THAT(ArrangeSamplesToRender(kStereoLabeledFrame, kStereoArrangement,
60                                      samples, num_valid_samples),
61               IsOk());
62   EXPECT_THAT(absl::MakeConstSpan(samples).first(num_valid_samples),
63               testing::ElementsAreArray({Pointwise(DoubleEq(), {0.0, 10.0}),
64                                          Pointwise(DoubleEq(), {1.0, 11.0}),
65                                          Pointwise(DoubleEq(), {2.0, 12.0})}));
66 }
67 
TEST(ArrangeSamplesToRender,FindsDemixedLabels)68 TEST(ArrangeSamplesToRender, FindsDemixedLabels) {
69   const LabeledFrame kDemixedTwoLayerStereoFrame = {
70       .label_to_samples = {{kMono, {75}}, {kL2, {50}}, {kDemixedR2, {100}}}};
71   const std::vector<ChannelLabel::Label> kStereoArrangement = {kL2, kR2};
72 
73   std::vector<std::vector<InternalSampleType>> samples(
74       kNumSamplesPerFrame,
75       std::vector<InternalSampleType>(kStereoArrangement.size()));
76   size_t num_valid_samples = 0;
77   EXPECT_THAT(
78       ArrangeSamplesToRender(kDemixedTwoLayerStereoFrame, kStereoArrangement,
79                              samples, num_valid_samples),
80       IsOk());
81   EXPECT_THAT(
82       absl::MakeConstSpan(samples).first(num_valid_samples),
83       testing::ElementsAreArray({Pointwise(DoubleEq(), {50.0, 100.0})}));
84 }
85 
TEST(ArrangeSamplesToRender,IgnoresExtraLabels)86 TEST(ArrangeSamplesToRender, IgnoresExtraLabels) {
87   const LabeledFrame kStereoLabeledFrameWithExtraLabel = {
88       .label_to_samples = {{kL2, {0}}, {kR2, {10}}, {kLFE, {999}}}};
89   const std::vector<ChannelLabel::Label> kStereoArrangement = {kL2, kR2};
90 
91   std::vector<std::vector<InternalSampleType>> samples(
92       kNumSamplesPerFrame,
93       std::vector<InternalSampleType>(kStereoArrangement.size()));
94   size_t num_valid_samples = 0;
95   EXPECT_THAT(
96       ArrangeSamplesToRender(kStereoLabeledFrameWithExtraLabel,
97                              kStereoArrangement, samples, num_valid_samples),
98       IsOk());
99   EXPECT_THAT(absl::MakeConstSpan(samples).first(num_valid_samples),
100               testing::ElementsAreArray({Pointwise(DoubleEq(), {0.0, 10.0})}));
101 }
102 
TEST(ArrangeSamplesToRender,LeavesOmittedLabelsZeroForMixedOrderAmbisonics)103 TEST(ArrangeSamplesToRender, LeavesOmittedLabelsZeroForMixedOrderAmbisonics) {
104   const LabeledFrame kMixedFirstOrderAmbisonicsFrame = {
105       .label_to_samples = {
106           {kA0, {1, 2}}, {kA2, {201, 202}}, {kA3, {301, 302}}}};
107   const std::vector<ChannelLabel::Label> kMixedFirstOrderAmbisonicsArrangement =
108       {kA0, kOmitted, kA2, kA3};
109 
110   std::vector<std::vector<InternalSampleType>> samples(
111       kNumSamplesPerFrame, std::vector<InternalSampleType>(
112                                kMixedFirstOrderAmbisonicsArrangement.size()));
113   size_t num_valid_samples = 0;
114   EXPECT_THAT(ArrangeSamplesToRender(kMixedFirstOrderAmbisonicsFrame,
115                                      kMixedFirstOrderAmbisonicsArrangement,
116                                      samples, num_valid_samples),
117               IsOk());
118   EXPECT_THAT(absl::MakeConstSpan(samples).first(num_valid_samples),
119               testing::ElementsAreArray(
120                   {Pointwise(DoubleEq(), {1.0, 0.0, 201.0, 301.0}),
121                    Pointwise(DoubleEq(), {2.0, 0.0, 202.0, 302.0})}));
122 }
123 
TEST(ArrangeSamplesToRender,LeavesOmittedLabelsZeroForChannelBasedLayout)124 TEST(ArrangeSamplesToRender, LeavesOmittedLabelsZeroForChannelBasedLayout) {
125   const LabeledFrame kLFEOnlyFrame = {.label_to_samples = {{kLFE, {1, 2}}}};
126   const std::vector<ChannelLabel::Label> kLFEAsSecondChannelArrangement = {
127       kOmitted, kOmitted, kLFE, kOmitted};
128 
129   std::vector<std::vector<InternalSampleType>> samples(
130       kNumSamplesPerFrame,
131       std::vector<InternalSampleType>(kLFEAsSecondChannelArrangement.size()));
132   size_t num_valid_samples = 0;
133   EXPECT_THAT(
134       ArrangeSamplesToRender(kLFEOnlyFrame, kLFEAsSecondChannelArrangement,
135                              samples, num_valid_samples),
136       IsOk());
137   EXPECT_THAT(
138       absl::MakeConstSpan(samples).first(num_valid_samples),
139       testing::ElementsAreArray({Pointwise(DoubleEq(), {0.0, 0.0, 1.0, 0.0}),
140                                  Pointwise(DoubleEq(), {0.0, 0.0, 2.0, 0.0})}));
141 }
142 
TEST(ArrangeSamplesToRender,ExcludesSamplesToBeTrimmed)143 TEST(ArrangeSamplesToRender, ExcludesSamplesToBeTrimmed) {
144   const LabeledFrame kMonoLabeledFrameWithSamplesToTrim = {
145       .samples_to_trim_at_end = 2,
146       .samples_to_trim_at_start = 1,
147       .label_to_samples = {{kMono, {999, 100, 999, 999}}}};
148   const std::vector<ChannelLabel::Label> kMonoArrangement = {kMono};
149 
150   std::vector<std::vector<InternalSampleType>> samples(
151       kNumSamplesPerFrame,
152       std::vector<InternalSampleType>(kMonoArrangement.size()));
153   size_t num_valid_samples = 0;
154   EXPECT_THAT(
155       ArrangeSamplesToRender(kMonoLabeledFrameWithSamplesToTrim,
156                              kMonoArrangement, samples, num_valid_samples),
157       IsOk());
158   EXPECT_THAT(absl::MakeConstSpan(samples).first(num_valid_samples),
159               testing::ElementsAreArray({Pointwise(DoubleEq(), {100.0})}));
160 }
161 
TEST(ArrangeSamplesToRender,OverwritesInputVector)162 TEST(ArrangeSamplesToRender, OverwritesInputVector) {
163   const LabeledFrame kMonoLabeledFrame = {
164       .label_to_samples = {{kMono, {1, 2}}}};
165   const std::vector<ChannelLabel::Label> kMonoArrangement = {kMono};
166 
167   std::vector<std::vector<InternalSampleType>> samples = {{999}, {999}};
168   size_t num_valid_samples = 0;
169   EXPECT_THAT(ArrangeSamplesToRender(kMonoLabeledFrame, kMonoArrangement,
170                                      samples, num_valid_samples),
171               IsOk());
172   EXPECT_THAT(absl::MakeConstSpan(samples).first(num_valid_samples),
173               testing::ElementsAreArray({Pointwise(DoubleEq(), {1.0}),
174                                          Pointwise(DoubleEq(), {2.0})}));
175 }
176 
TEST(ArrangeSamplesToRender,TrimmingAllFramesFromStartIsResultsInEmptyOutput)177 TEST(ArrangeSamplesToRender, TrimmingAllFramesFromStartIsResultsInEmptyOutput) {
178   const LabeledFrame kMonoLabeledFrameWithSamplesToTrim = {
179       .samples_to_trim_at_end = 0,
180       .samples_to_trim_at_start = 4,
181       .label_to_samples = {{kMono, {999, 999, 999, 999}}}};
182   const std::vector<ChannelLabel::Label> kMonoArrangement = {kMono};
183 
184   std::vector<std::vector<InternalSampleType>> samples(
185       kNumSamplesPerFrame,
186       std::vector<InternalSampleType>(kMonoArrangement.size()));
187   size_t num_valid_samples = 0;
188   EXPECT_THAT(
189       ArrangeSamplesToRender(kMonoLabeledFrameWithSamplesToTrim,
190                              kMonoArrangement, samples, num_valid_samples),
191       IsOk());
192   EXPECT_TRUE(absl::MakeConstSpan(samples).first(num_valid_samples).empty());
193 }
194 
TEST(ArrangeSamplesToRender,InvalidWhenRequestedLabelsHaveDifferentNumberOfSamples)195 TEST(ArrangeSamplesToRender,
196      InvalidWhenRequestedLabelsHaveDifferentNumberOfSamples) {
197   const LabeledFrame kStereoLabeledFrameWithMissingSample = {
198       .label_to_samples = {{kL2, {0, 1}}, {kR2, {10}}}};
199   const std::vector<ChannelLabel::Label> kStereoArrangement = {kL2, kR2};
200 
201   std::vector<std::vector<InternalSampleType>> samples(
202       kNumSamplesPerFrame,
203       std::vector<InternalSampleType>(kStereoArrangement.size()));
204   size_t num_valid_samples = 0;
205   EXPECT_FALSE(ArrangeSamplesToRender(kStereoLabeledFrameWithMissingSample,
206                                       kStereoArrangement, samples,
207                                       num_valid_samples)
208                    .ok());
209 }
210 
TEST(ArrangeSamplesToRender,InvalidWhenTrimIsImplausible)211 TEST(ArrangeSamplesToRender, InvalidWhenTrimIsImplausible) {
212   const LabeledFrame kFrameWithExcessSamplesTrimmed = {
213       .samples_to_trim_at_end = 1,
214       .samples_to_trim_at_start = 2,
215       .label_to_samples = {{kL2, {0, 1}}, {kR2, {10, 11}}}};
216   const std::vector<ChannelLabel::Label> kStereoArrangement = {kL2, kR2};
217 
218   std::vector<std::vector<InternalSampleType>> samples(
219       kNumSamplesPerFrame,
220       std::vector<InternalSampleType>(kStereoArrangement.size()));
221   size_t num_valid_samples = 0;
222   EXPECT_FALSE(ArrangeSamplesToRender(kFrameWithExcessSamplesTrimmed,
223                                       kStereoArrangement, samples,
224                                       num_valid_samples)
225                    .ok());
226 }
227 
TEST(ArrangeSamplesToRender,InvalidMissingLabel)228 TEST(ArrangeSamplesToRender, InvalidMissingLabel) {
229   const LabeledFrame kStereoLabeledFrame = {
230       .label_to_samples = {{kL2, {0}}, {kR2, {10}}}};
231   const std::vector<ChannelLabel::Label> kMonoArrangement = {kMono};
232 
233   std::vector<std::vector<InternalSampleType>> unused_samples(
234       kNumSamplesPerFrame,
235       std::vector<InternalSampleType>(kMonoArrangement.size()));
236   size_t num_valid_samples = 0;
237   EXPECT_FALSE(ArrangeSamplesToRender(kStereoLabeledFrame, kMonoArrangement,
238                                       unused_samples, num_valid_samples)
239                    .ok());
240 }
241 
TEST(LookupOutputKeyFromPlaybackLayout,SucceedsForChannelBasedLayout)242 TEST(LookupOutputKeyFromPlaybackLayout, SucceedsForChannelBasedLayout) {
243   EXPECT_THAT(
244       LookupOutputKeyFromPlaybackLayout(
245           {.layout_type = Layout::kLayoutTypeLoudspeakersSsConvention,
246            .specific_layout =
247                LoudspeakersSsConventionLayout{
248                    .sound_system =
249                        LoudspeakersSsConventionLayout::kSoundSystemA_0_2_0}}),
250       IsOk());
251 }
252 
TEST(LookupOutputKeyFromPlaybackLayout,SucceedsFor9_1_6)253 TEST(LookupOutputKeyFromPlaybackLayout, SucceedsFor9_1_6) {
254   EXPECT_THAT(
255       LookupOutputKeyFromPlaybackLayout(
256           {.layout_type = Layout::kLayoutTypeLoudspeakersSsConvention,
257            .specific_layout =
258                LoudspeakersSsConventionLayout{
259                    .sound_system =
260                        LoudspeakersSsConventionLayout::kSoundSystem13_6_9_0}}),
261       IsOk());
262 }
TEST(LookupOutputKeyFromPlaybackLayout,FailsOnBinauralBasedLayout)263 TEST(LookupOutputKeyFromPlaybackLayout, FailsOnBinauralBasedLayout) {
264   EXPECT_FALSE(LookupOutputKeyFromPlaybackLayout(
265                    {.layout_type = Layout::kLayoutTypeBinaural,
266                     .specific_layout = LoudspeakersReservedOrBinauralLayout{}})
267                    .ok());
268 }
269 
TEST(LookupOutputKeyFromPlaybackLayout,FailsOnReservedLayout)270 TEST(LookupOutputKeyFromPlaybackLayout, FailsOnReservedLayout) {
271   EXPECT_FALSE(LookupOutputKeyFromPlaybackLayout(
272                    {.layout_type = Layout::kLayoutTypeReserved0,
273                     .specific_layout = LoudspeakersReservedOrBinauralLayout{}})
274                    .ok());
275 }
276 
277 }  // namespace
278 }  // namespace renderer_utils
279 }  // namespace iamf_tools
280