• 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/proto_conversion/proto_to_obu/arbitrary_obu_generator.h"
13 
14 #include <cstdint>
15 #include <list>
16 #include <optional>
17 #include <vector>
18 
19 #include "absl/status/status.h"
20 #include "absl/status/status_matchers.h"
21 #include "gmock/gmock.h"
22 #include "gtest/gtest.h"
23 #include "iamf/cli/proto/arbitrary_obu.pb.h"
24 #include "iamf/obu/arbitrary_obu.h"
25 #include "iamf/obu/obu_header.h"
26 #include "src/google/protobuf/repeated_ptr_field.h"
27 #include "src/google/protobuf/text_format.h"
28 
29 namespace iamf_tools {
30 namespace {
31 
32 using ::absl_testing::IsOk;
33 
34 typedef ::google::protobuf::RepeatedPtrField<
35     iamf_tools_cli_proto::ArbitraryObuMetadata>
36     ArbitraryObuMetadatas;
37 
38 constexpr int64_t kInsertionTick = 123;
39 
FillArbitraryObu(iamf_tools_cli_proto::ArbitraryObuMetadata * arbitrary_obu_metadata)40 void FillArbitraryObu(
41     iamf_tools_cli_proto::ArbitraryObuMetadata* arbitrary_obu_metadata) {
42   ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(
43       R"pb(
44         insertion_hook: INSERTION_HOOK_BEFORE_DESCRIPTORS
45         obu_type: OBU_IA_RESERVED_24
46         obu_header {
47           obu_redundant_copy: false
48           obu_trimming_status_flag: false
49           obu_extension_flag: false
50         }
51         payload: ""
52       )pb",
53       arbitrary_obu_metadata));
54 }
55 
TEST(Generate,CopiesInsertionHookBeforeDescriptors)56 TEST(Generate, CopiesInsertionHookBeforeDescriptors) {
57   ArbitraryObuMetadatas arbitrary_obu_metadatas;
58   FillArbitraryObu(arbitrary_obu_metadatas.Add());
59   arbitrary_obu_metadatas.at(0).set_insertion_hook(
60       iamf_tools_cli_proto::INSERTION_HOOK_BEFORE_DESCRIPTORS);
61 
62   ArbitraryObuGenerator generator(arbitrary_obu_metadatas);
63   std::list<ArbitraryObu> arbitrary_obus;
64   EXPECT_THAT(generator.Generate(arbitrary_obus), IsOk());
65 
66   EXPECT_EQ(arbitrary_obus.front().insertion_hook_,
67             ArbitraryObu::kInsertionHookBeforeDescriptors);
68   EXPECT_EQ(arbitrary_obus.front().insertion_tick_, std::nullopt);
69 }
70 
TEST(Generate,CopiesInsertionHookAfterDescriptors)71 TEST(Generate, CopiesInsertionHookAfterDescriptors) {
72   ArbitraryObuMetadatas arbitrary_obu_metadatas;
73   FillArbitraryObu(arbitrary_obu_metadatas.Add());
74   arbitrary_obu_metadatas.at(0).set_insertion_hook(
75       iamf_tools_cli_proto::INSERTION_HOOK_AFTER_DESCRIPTORS);
76 
77   ArbitraryObuGenerator generator(arbitrary_obu_metadatas);
78   std::list<ArbitraryObu> arbitrary_obus;
79   EXPECT_THAT(generator.Generate(arbitrary_obus), IsOk());
80 
81   EXPECT_EQ(arbitrary_obus.front().insertion_hook_,
82             ArbitraryObu::kInsertionHookAfterDescriptors);
83   EXPECT_EQ(arbitrary_obus.front().insertion_tick_, std::nullopt);
84 }
85 
TEST(Generate,CopiesInsertionHookAfterCodecConfigs)86 TEST(Generate, CopiesInsertionHookAfterCodecConfigs) {
87   ArbitraryObuMetadatas arbitrary_obu_metadatas;
88   FillArbitraryObu(arbitrary_obu_metadatas.Add());
89   arbitrary_obu_metadatas.at(0).set_insertion_hook(
90       iamf_tools_cli_proto::INSERTION_HOOK_AFTER_CODEC_CONFIGS);
91 
92   ArbitraryObuGenerator generator(arbitrary_obu_metadatas);
93   std::list<ArbitraryObu> arbitrary_obus;
94   EXPECT_THAT(generator.Generate(arbitrary_obus), IsOk());
95 
96   EXPECT_EQ(arbitrary_obus.front().insertion_hook_,
97             ArbitraryObu::kInsertionHookAfterCodecConfigs);
98   EXPECT_EQ(arbitrary_obus.front().insertion_tick_, std::nullopt);
99 }
100 
TEST(Generate,InsertionTickDefaultsToZeroForTimeBasedInsertionHooks)101 TEST(Generate, InsertionTickDefaultsToZeroForTimeBasedInsertionHooks) {
102   ArbitraryObuMetadatas arbitrary_obu_metadatas;
103   FillArbitraryObu(arbitrary_obu_metadatas.Add());
104   arbitrary_obu_metadatas.at(0).set_insertion_hook(
105       iamf_tools_cli_proto::INSERTION_HOOK_BEFORE_PARAMETER_BLOCKS_AT_TICK);
106 
107   ArbitraryObuGenerator generator(arbitrary_obu_metadatas);
108   std::list<ArbitraryObu> arbitrary_obus;
109   EXPECT_THAT(generator.Generate(arbitrary_obus), IsOk());
110 
111   EXPECT_EQ(arbitrary_obus.front().insertion_hook_,
112             ArbitraryObu::kInsertionHookBeforeParameterBlocksAtTick);
113   ASSERT_TRUE(arbitrary_obus.front().insertion_tick_.has_value());
114   EXPECT_EQ(arbitrary_obus.front().insertion_tick_, 0);
115 }
116 
TEST(Generate,CopiesInsertionTickForTimeBasedInsertionHooks)117 TEST(Generate, CopiesInsertionTickForTimeBasedInsertionHooks) {
118   ArbitraryObuMetadatas arbitrary_obu_metadatas;
119   FillArbitraryObu(arbitrary_obu_metadatas.Add());
120   arbitrary_obu_metadatas.at(0).set_insertion_hook(
121       iamf_tools_cli_proto::INSERTION_HOOK_BEFORE_PARAMETER_BLOCKS_AT_TICK);
122   arbitrary_obu_metadatas.at(0).set_insertion_tick(kInsertionTick);
123 
124   ArbitraryObuGenerator generator(arbitrary_obu_metadatas);
125   std::list<ArbitraryObu> arbitrary_obus;
126   EXPECT_THAT(generator.Generate(arbitrary_obus), IsOk());
127 
128   EXPECT_EQ(arbitrary_obus.front().insertion_hook_,
129             ArbitraryObu::kInsertionHookBeforeParameterBlocksAtTick);
130   ASSERT_TRUE(arbitrary_obus.front().insertion_tick_.has_value());
131   EXPECT_EQ(arbitrary_obus.front().insertion_tick_, kInsertionTick);
132 }
133 
TEST(Generate,CopiesInsertionHookAfterParameterBlocksAtTime)134 TEST(Generate, CopiesInsertionHookAfterParameterBlocksAtTime) {
135   ArbitraryObuMetadatas arbitrary_obu_metadatas;
136   FillArbitraryObu(arbitrary_obu_metadatas.Add());
137   arbitrary_obu_metadatas.at(0).set_insertion_hook(
138       iamf_tools_cli_proto::INSERTION_HOOK_AFTER_PARAMETER_BLOCKS_AT_TICK);
139   arbitrary_obu_metadatas.at(0).set_insertion_tick(kInsertionTick);
140 
141   ArbitraryObuGenerator generator(arbitrary_obu_metadatas);
142   std::list<ArbitraryObu> arbitrary_obus;
143   EXPECT_THAT(generator.Generate(arbitrary_obus), IsOk());
144 
145   EXPECT_EQ(arbitrary_obus.front().insertion_hook_,
146             ArbitraryObu::kInsertionHookAfterParameterBlocksAtTick);
147   ASSERT_TRUE(arbitrary_obus.front().insertion_tick_.has_value());
148   EXPECT_EQ(arbitrary_obus.front().insertion_tick_, kInsertionTick);
149 }
150 
TEST(Generate,CopiesInsertionHookAfterAudioFramesAtTime)151 TEST(Generate, CopiesInsertionHookAfterAudioFramesAtTime) {
152   ArbitraryObuMetadatas arbitrary_obu_metadatas;
153   FillArbitraryObu(arbitrary_obu_metadatas.Add());
154   arbitrary_obu_metadatas.at(0).set_insertion_hook(
155       iamf_tools_cli_proto::INSERTION_HOOK_AFTER_AUDIO_FRAMES_AT_TICK);
156   arbitrary_obu_metadatas.at(0).set_insertion_tick(kInsertionTick);
157 
158   ArbitraryObuGenerator generator(arbitrary_obu_metadatas);
159   std::list<ArbitraryObu> arbitrary_obus;
160   EXPECT_THAT(generator.Generate(arbitrary_obus), IsOk());
161 
162   EXPECT_EQ(arbitrary_obus.front().insertion_hook_,
163             ArbitraryObu::kInsertionHookAfterAudioFramesAtTick);
164   ASSERT_TRUE(arbitrary_obus.front().insertion_tick_.has_value());
165   EXPECT_EQ(arbitrary_obus.front().insertion_tick_, kInsertionTick);
166 }
167 
TEST(Generate,FailsOnInvalidInsertionHook)168 TEST(Generate, FailsOnInvalidInsertionHook) {
169   ArbitraryObuMetadatas arbitrary_obu_metadatas;
170   FillArbitraryObu(arbitrary_obu_metadatas.Add());
171   arbitrary_obu_metadatas.at(0).set_insertion_hook(
172       iamf_tools_cli_proto::INSERTION_HOOK_INVALID);
173 
174   ArbitraryObuGenerator generator(arbitrary_obu_metadatas);
175   std::list<ArbitraryObu> arbitrary_obus;
176 
177   EXPECT_FALSE(generator.Generate(arbitrary_obus).ok());
178   EXPECT_TRUE(arbitrary_obus.empty());
179 }
180 
TEST(Generate,CopiesInvalidatesBitstreamFalse)181 TEST(Generate, CopiesInvalidatesBitstreamFalse) {
182   ArbitraryObuMetadatas arbitrary_obu_metadatas;
183   FillArbitraryObu(arbitrary_obu_metadatas.Add());
184   arbitrary_obu_metadatas.at(0).set_invalidates_bitstream(false);
185 
186   ArbitraryObuGenerator generator(arbitrary_obu_metadatas);
187   std::list<ArbitraryObu> arbitrary_obus;
188   EXPECT_THAT(generator.Generate(arbitrary_obus), IsOk());
189 
190   EXPECT_EQ(arbitrary_obus.front().invalidates_bitstream_, false);
191 }
192 
TEST(Generate,CopiesInvalidatesBitstreamTrue)193 TEST(Generate, CopiesInvalidatesBitstreamTrue) {
194   ArbitraryObuMetadatas arbitrary_obu_metadatas;
195   FillArbitraryObu(arbitrary_obu_metadatas.Add());
196   arbitrary_obu_metadatas.at(0).set_invalidates_bitstream(true);
197 
198   ArbitraryObuGenerator generator(arbitrary_obu_metadatas);
199   std::list<ArbitraryObu> arbitrary_obus;
200   EXPECT_THAT(generator.Generate(arbitrary_obus), IsOk());
201 
202   EXPECT_EQ(arbitrary_obus.front().invalidates_bitstream_, true);
203 }
204 
TEST(Generate,GeneratesEmptyListForEmptyInput)205 TEST(Generate, GeneratesEmptyListForEmptyInput) {
206   ArbitraryObuMetadatas arbitrary_obu_metadatas = {};
207 
208   ArbitraryObuGenerator generator(arbitrary_obu_metadatas);
209   std::list<ArbitraryObu> arbitrary_obus;
210   EXPECT_THAT(generator.Generate(arbitrary_obus), IsOk());
211 
212   EXPECT_TRUE(arbitrary_obus.empty());
213 }
214 
215 class ArbitraryObuGeneratorTest : public testing::Test {
216  public:
ArbitraryObuGeneratorTest()217   ArbitraryObuGeneratorTest() {}
218 
InitAndTestGenerateExpectOk()219   void InitAndTestGenerateExpectOk() {
220     // Generate the OBUs.
221     std::list<ArbitraryObu> output_obus;
222     ArbitraryObuGenerator generator(arbitrary_obu_metadata_);
223     EXPECT_THAT(generator.Generate(output_obus), IsOk());
224 
225     EXPECT_EQ(output_obus, expected_obus_);
226   }
227 
228  protected:
229   ArbitraryObuMetadatas arbitrary_obu_metadata_;
230 
231   std::list<ArbitraryObu> expected_obus_;
232 };
233 
TEST_F(ArbitraryObuGeneratorTest,ReservedObu)234 TEST_F(ArbitraryObuGeneratorTest, ReservedObu) {
235   ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(
236       R"pb(
237         insertion_hook: INSERTION_HOOK_BEFORE_DESCRIPTORS
238         obu_type: OBU_IA_RESERVED_24
239         obu_header {
240           obu_redundant_copy: false
241           obu_trimming_status_flag: false
242           obu_extension_flag: false
243         }
244         payload: "abc"
245       )pb",
246       arbitrary_obu_metadata_.Add()));
247 
248   expected_obus_.emplace_back(kObuIaReserved24, ObuHeader(),
249                               std::vector<uint8_t>({'a', 'b', 'c'}),
250                               ArbitraryObu::kInsertionHookBeforeDescriptors);
251   InitAndTestGenerateExpectOk();
252 }
253 
TEST_F(ArbitraryObuGeneratorTest,ObuWithExtensionHeader)254 TEST_F(ArbitraryObuGeneratorTest, ObuWithExtensionHeader) {
255   ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(
256       R"pb(
257         insertion_hook: INSERTION_HOOK_AFTER_DESCRIPTORS
258         obu_type: OBU_IA_SEQUENCE_HEADER
259         obu_header {
260           obu_redundant_copy: false
261           obu_trimming_status_flag: false
262           obu_extension_flag: true
263           extension_header_size: 5
264           extension_header_bytes: "extra"
265         }
266         payload: "iamf\x00\x00"
267       )pb",
268       arbitrary_obu_metadata_.Add()));
269 
270   expected_obus_.emplace_back(
271       kObuIaSequenceHeader,
272       ObuHeader{.obu_extension_flag = true,
273                 .extension_header_size = 5,
274                 .extension_header_bytes = {'e', 'x', 't', 'r', 'a'}},
275       std::vector<uint8_t>({'i', 'a', 'm', 'f', '\0', '\0'}),
276       ArbitraryObu::kInsertionHookAfterDescriptors);
277   InitAndTestGenerateExpectOk();
278 }
279 
TEST_F(ArbitraryObuGeneratorTest,InvalidObuType)280 TEST_F(ArbitraryObuGeneratorTest, InvalidObuType) {
281   ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(
282       R"pb(
283         insertion_hook: INSERTION_HOOK_AFTER_DESCRIPTORS
284         obu_type: OBU_IA_INVALID
285         obu_header {
286           obu_redundant_copy: false
287           obu_trimming_status_flag: false
288           obu_extension_flag: false
289         }
290         payload: ""
291       )pb",
292       arbitrary_obu_metadata_.Add()));
293   std::list<ArbitraryObu> output_obus;
294   ArbitraryObuGenerator generator(arbitrary_obu_metadata_);
295 
296   EXPECT_FALSE(generator.Generate(output_obus).ok());
297 }
298 
299 }  // namespace
300 }  // namespace iamf_tools
301