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 #ifndef CLI_TESTS_CLI_TEST_UTILS_H_
13 #define CLI_TESTS_CLI_TEST_UTILS_H_
14
15 #include <algorithm>
16 #include <cstddef>
17 #include <cstdint>
18 #include <filesystem>
19 #include <list>
20 #include <memory>
21 #include <optional>
22 #include <string>
23 #include <vector>
24
25 #include "absl/container/flat_hash_map.h"
26 #include "absl/status/status.h"
27 #include "absl/status/statusor.h"
28 #include "absl/strings/string_view.h"
29 #include "absl/types/span.h"
30 #include "gmock/gmock.h"
31 #include "gtest/gtest.h"
32 #include "iamf/cli/audio_element_with_data.h"
33 #include "iamf/cli/audio_frame_with_data.h"
34 #include "iamf/cli/demixing_module.h"
35 #include "iamf/cli/loudness_calculator_base.h"
36 #include "iamf/cli/loudness_calculator_factory_base.h"
37 #include "iamf/cli/obu_sequencer_base.h"
38 #include "iamf/cli/parameter_block_with_data.h"
39 #include "iamf/cli/proto/user_metadata.pb.h"
40 #include "iamf/cli/renderer/audio_element_renderer_base.h"
41 #include "iamf/cli/sample_processor_base.h"
42 #include "iamf/cli/user_metadata_builder/iamf_input_layout.h"
43 #include "iamf/cli/wav_reader.h"
44 #include "iamf/common/leb_generator.h"
45 #include "iamf/common/read_bit_buffer.h"
46 #include "iamf/common/utils/numeric_utils.h"
47 #include "iamf/obu/audio_element.h"
48 #include "iamf/obu/codec_config.h"
49 #include "iamf/obu/ia_sequence_header.h"
50 #include "iamf/obu/mix_presentation.h"
51 #include "iamf/obu/obu_base.h"
52 #include "iamf/obu/param_definitions.h"
53 #include "iamf/obu/types.h"
54
55 namespace iamf_tools {
56
57 /*!\brief Processes the input standalone IAMF Sequence to output containers.
58 *
59 * This function is useful for testing whether a generated IAMF Sequence
60 * contains expected OBUs.
61 *
62 * \param read_bit_buffer Buffer reader that reads the IAMF bitstream. The
63 * reader's position will be moved past the first IA sequence.
64 * \param sequence_header Output IA sequence header.
65 * \param codec_config_obus Output codec configs.
66 * \param audio_elements Output audio elements.
67 * \param mix_presentations Output mix presentations.
68 * \param audio_frames Output audio frames.
69 * \param parameter_blocks Output parameter blocks.
70 * \return `absl::OkStatus()` if the process is successful. A specific status
71 * on failure.
72 */
73 absl::Status CollectObusFromIaSequence(
74 ReadBitBuffer& read_bit_buffer, IASequenceHeaderObu& ia_sequence_header,
75 absl::flat_hash_map<DecodedUleb128, CodecConfigObu>& codec_config_obus,
76 absl::flat_hash_map<DecodedUleb128, AudioElementWithData>& audio_elements,
77 std::list<MixPresentationObu>& mix_presentations,
78 std::list<AudioFrameWithData>& audio_frames,
79 std::list<ParameterBlockWithData>& parameter_blocks);
80
81 // A specification for a decode request. Currently used in the context of
82 // extracting the relevant metadata from the UserMetadata proto associated
83 // with a given test vector.
84 struct DecodeSpecification {
85 uint32_t mix_presentation_id;
86 uint32_t sub_mix_index;
87 LoudspeakersSsConventionLayout::SoundSystem sound_system;
88 uint32_t layout_index;
89 };
90
91 /*!\brief Adds a configurable LPCM `CodecConfigObu` to the output argument.
92 *
93 * \param codec_config_id `codec_config_id` of the OBU to create.
94 * \param num_samples_per_frame Number of samples per frame.
95 * \param sample_size Sample size.
96 * \param sample_rate `sample_rate` of the OBU to create.
97 * \param codec_config_obus Map to add the OBU to keyed by `codec_config_id`.
98 */
99 void AddLpcmCodecConfig(
100 DecodedUleb128 codec_config_id, uint32_t num_samples_per_frame,
101 uint8_t sample_size, uint32_t sample_rate,
102 absl::flat_hash_map<uint32_t, CodecConfigObu>& codec_config_obus);
103
104 /*!\brief Adds a configurable LPCM `CodecConfigObu` to the output argument.
105 *
106 * \param codec_config_id `codec_config_id` of the OBU to create.
107 * \param sample_rate `sample_rate` of the OBU to create.
108 * \param codec_config_obus Map to add the OBU to keyed by `codec_config_id`.
109 */
110 void AddLpcmCodecConfigWithIdAndSampleRate(
111 uint32_t codec_config_id, uint32_t sample_rate,
112 absl::flat_hash_map<uint32_t, CodecConfigObu>& codec_config_obus);
113
114 /*!\brief Adds a configurable Opus `CodecConfigObu` to the output argument.
115 *
116 * \param codec_config_id `codec_config_id` of the OBU to create.
117 * \param codec_config_obus Map to add the OBU to keyed by `codec_config_id`.
118 */
119 void AddOpusCodecConfigWithId(
120 uint32_t codec_config_id,
121 absl::flat_hash_map<uint32_t, CodecConfigObu>& codec_config_obus);
122
123 /*!\brief Adds a configurable Flac `CodecConfigObu` to the output argument.
124 *
125 * \param codec_config_id `codec_config_id` of the OBU to create.
126 * \param codec_config_obus Map to add the OBU to keyed by `codec_config_id`.
127 */
128 void AddFlacCodecConfigWithId(
129 uint32_t codec_config_id,
130 absl::flat_hash_map<uint32_t, CodecConfigObu>& codec_config_obus);
131
132 /*!\brief Adds a configurable AAC `CodecConfigObu` to the output argument.
133 *
134 * \param codec_config_id `codec_config_id` of the OBU to create.
135 * \param codec_config_obus Map to add the OBU to keyed by `codec_config_id`.
136 */
137 void AddAacCodecConfigWithId(
138 uint32_t codec_config_id,
139 absl::flat_hash_map<uint32_t, CodecConfigObu>& codec_config_obus);
140
141 /*!\brief Adds a configurable ambisonics `AudioElementObu` to the output.
142 *
143 * \param audio_element_id `audio_element_id` of the OBU to create.
144 * \param codec_config_id `codec_config_id` of the OBU to create.
145 * \param substream_ids `substream_ids` of the OBU to create.
146 * \param codec_config_obus Codec Config OBUs containing the associated OBU.
147 * \param audio_elements Map to add the OBU to keyed by `audio_element_id`.
148 */
149 void AddAmbisonicsMonoAudioElementWithSubstreamIds(
150 DecodedUleb128 audio_element_id, uint32_t codec_config_id,
151 absl::Span<const DecodedUleb128> substream_ids,
152 const absl::flat_hash_map<uint32_t, CodecConfigObu>& codec_config_obus,
153 absl::flat_hash_map<DecodedUleb128, AudioElementWithData>& audio_elements);
154
155 /*!\brief Adds a configurable scalable `AudioElementObu` to the output argument.
156 *
157 * \param input_layout `input_layout` of the OBU to create.
158 * \param audio_element_id `audio_element_id` of the OBU to create.
159 * \param codec_config_id `codec_config_id` of the OBU to create.
160 * \param substream_ids `substream_ids` of the OBU to create.
161 * \param codec_config_obus Codec Config OBUs containing the associated OBU.
162 * \param audio_elements Map to add the OBU to keyed by `audio_element_id`.
163 */
164 void AddScalableAudioElementWithSubstreamIds(
165 IamfInputLayout input_layout, DecodedUleb128 audio_element_id,
166 uint32_t codec_config_id, absl::Span<const DecodedUleb128> substream_ids,
167 const absl::flat_hash_map<uint32_t, CodecConfigObu>& codec_config_obus,
168 absl::flat_hash_map<DecodedUleb128, AudioElementWithData>& audio_elements);
169
170 /*!\brief Adds a configurable `MixPresentationObu` to the output argument.
171 *
172 * \param mix_presentation_id `mix_presentation_id` of the OBU to create.
173 * \param audio_element_ids `audio_element_id`s of the OBU to create.
174 * \param common_parameter_id `parameter_id` of all parameters within the
175 * created OBU.
176 * \param common_parameter_rate `parameter_rate` of all parameters within the
177 * created OBU.
178 * \param output_mix_presentations List to add OBU to.
179 */
180 void AddMixPresentationObuWithAudioElementIds(
181 DecodedUleb128 mix_presentation_id,
182 const std::vector<DecodedUleb128>& audio_element_id,
183 DecodedUleb128 common_parameter_id, DecodedUleb128 common_parameter_rate,
184 std::list<MixPresentationObu>& output_mix_presentations);
185
186 /*!\brief Adds a configurable `MixPresentationObu` to the output argument.
187 *
188 * \param mix_presentation_id `mix_presentation_id` of the OBU to create.
189 * \param audio_element_ids `audio_element_id`s of the OBU to create.
190 * \param common_parameter_id `parameter_id` of all parameters within the
191 * created OBU.
192 * \param common_parameter_rate `parameter_rate` of all parameters within the
193 * created OBU.
194 * \param sound_system_layouts `sound_system`s of the OBU to create.
195 * \param output_mix_presentations List to add OBU to.
196 */
197 void AddMixPresentationObuWithConfigurableLayouts(
198 DecodedUleb128 mix_presentation_id,
199 const std::vector<DecodedUleb128>& audio_element_id,
200 DecodedUleb128 common_parameter_id, DecodedUleb128 common_parameter_rate,
201 const std::vector<LoudspeakersSsConventionLayout::SoundSystem>&
202 sound_system_layouts,
203 std::list<MixPresentationObu>& output_mix_presentations);
204
205 /*!\brief Adds a configurable mix gain param definition to the output argument.
206 *
207 * \param parameter_id `parameter_id` of the param definition to create.
208 * \param parameter_rate `parameter_rate` of the param definition to
209 * create.
210 * \param duration `duration` and `constant_subblock_duration` of the
211 * param definition to create.
212 * \param param_definitions Map to add the param definition to keyed by
213 * `parameter_id`.
214 */
215 void AddParamDefinitionWithMode0AndOneSubblock(
216 DecodedUleb128 parameter_id, DecodedUleb128 parameter_rate,
217 DecodedUleb128 duration,
218 absl::flat_hash_map<DecodedUleb128, MixGainParamDefinition>&
219 param_definitions);
220
221 /*!\brief Adds a demixing parameter definition to an Audio Element OBU.
222 *
223 * \param parameter_id `parameter_id` of the param definition to add.
224 * \param parameter_rate `parameter_rate` of the param definition to add.
225 * \param duration `duration` and `constant_subblock_duration` of the
226 * param definition to add.
227 * \param audio_element_obu Audio Element OBU to add the param definition to.
228 */
229 void AddDemixingParamDefinition(DecodedUleb128 parameter_id,
230 DecodedUleb128 parameter_rate,
231 DecodedUleb128 duration,
232 AudioElementObu& audio_element_obu);
233
234 /*!\brief Adds a recon gain parameter definition to an Audio Element OBU.
235 *
236 * \param parameter_id `parameter_id` of the param definition to add.
237 * \param parameter_rate `parameter_rate` of the param definition to add.
238 * \param duration `duration` and `constant_subblock_duration` of the
239 * param definition to add.
240 * \param audio_element_obu Audio Element OBU to add the param definition to.
241 */
242 void AddReconGainParamDefinition(DecodedUleb128 parameter_id,
243 DecodedUleb128 parameter_rate,
244 DecodedUleb128 duration,
245 AudioElementObu& audio_element_obu);
246
247 /*!\brief Calls `CreateWavReader` and unwraps the `StatusOr`.
248 *
249 * \param filename Filename to forward to `CreateWavReader`.
250 * \param num_samples_per_frame Number of samples per frame to forward to
251 * `CreateWavReader`.
252 * \return Unwrapped `WavReader` created by `CreateWavReader`.
253 */
254 WavReader CreateWavReaderExpectOk(const std::string& filename,
255 int num_samples_per_frame = 1);
256
257 /*!\brief Renders the `LabeledFrame` flushes to the output vector.
258 *
259 * \param labeled_frame Labeled frame to render.
260 * \param renderer Renderer to use.
261 * \param output_samples Vector to flush to.
262 */
263 void RenderAndFlushExpectOk(const LabeledFrame& labeled_frame,
264 AudioElementRendererBase* renderer,
265 std::vector<InternalSampleType>& output_samples);
266
267 /*!\brief Gets and cleans up unique file name based on the specified suffix.
268 *
269 * Useful when testing components that write to a single file.
270 *
271 * \param suffix Suffix to append to the file path.
272 * \return Unique file path based on the current unit test info.
273 */
274 std::string GetAndCleanupOutputFileName(absl::string_view suffix);
275
276 /*!\brief Gets and creates a unique directory based on the specified suffix.
277 *
278 * Useful when testing components that write several files to a single
279 * directory.
280 *
281 * \param suffix Suffix to append to the directory.
282 * \return Unique file path based on the current unit test info.
283 */
284 std::string GetAndCreateOutputDirectory(absl::string_view suffix);
285
286 /*!\brief Serializes a list of OBUs.
287 *
288 * \param obus OBUs to serialize.
289 * \param leb_generator Leb generator to use.
290 * \return Vector of serialized OBU data.
291 */
292 std::vector<uint8_t> SerializeObusExpectOk(
293 const std::list<const ObuBase*>& obus,
294 const LebGenerator& leb_generator = *LebGenerator::Create());
295
296 /*!\brief Parses a textproto file into a `UserMetadata` proto.
297 *
298 * This function also asserts that the file exists and is readable.
299 *
300 * \param textproto_filename File to parse.
301 * \param user_metadata Proto to populate.
302 */
303 void ParseUserMetadataAssertSuccess(
304 const std::string& textproto_filename,
305 iamf_tools_cli_proto::UserMetadata& user_metadata);
306
307 /*!\brief Computes the log-spectral distance (LSD) between two spectra.
308 *
309 * The log-spectral distance (LSD) is a distance measure (expressed in dB)
310 * between two spectra.
311 *
312 * \param first_log_spectrum First log-spectrum to compare.
313 * \param second_log_spectrum Second log-spectrum to compare.
314 * \return Log-spectral distance between the two spectra.
315 */
316 double GetLogSpectralDistance(
317 const absl::Span<const InternalSampleType>& first_log_spectrum,
318 const absl::Span<const InternalSampleType>& second_log_spectrum);
319
320 /*!\brief Extracts the relevant metadata for a given test case.
321 *
322 * This is used to properly associate gold-standard wav files with the output of
323 * the decoder.
324 *
325 * \param user_metadata Proto associated with a given test vector.
326 * \return `DecodeSpecification`(s) for the given test case.
327 */
328 std::vector<DecodeSpecification> GetDecodeSpecifications(
329 const iamf_tools_cli_proto::UserMetadata& user_metadata);
330
331 /*!\brief Converts a span of `int32_t` to a span of `InternalSampleType`.
332 *
333 * Useful because some test data is more readable as `int32_t`s, than in the
334 * canonical `InternalSampleType` format.
335 *
336 * \param samples Span of `int32_t`s to convert.
337 * \param result Span of `InternalSampleType`s to write to.
338 */
Int32ToInternalSampleType(absl::Span<const int32_t> samples,absl::Span<InternalSampleType> result)339 constexpr void Int32ToInternalSampleType(
340 absl::Span<const int32_t> samples, absl::Span<InternalSampleType> result) {
341 std::transform(samples.begin(), samples.end(), result.begin(),
342 Int32ToNormalizedFloatingPoint<InternalSampleType>);
343 }
344
345 /*!\brief Converts a span of `int32_t` to a span of `InternalSampleType`.
346 *
347 * Useful because some test data is more readable as `int32_t`s, than in the
348 * canonical `InternalSampleType` format.
349 *
350 * \param samples Span of `int32_t`s to convert.
351 * \return Output vector of `InternalSampleType`s.
352 */
353 std::vector<InternalSampleType> Int32ToInternalSampleType(
354 absl::Span<const int32_t> samples);
355
356 /*!\brief Returns samples representing a sine wave.
357 *
358 * \param start_tick Tick to start sampling at. I.e. each tick represents
359 * `1.0 / sample_rate_hz` seconds.
360 * \param num_samples Number of samples to generate.
361 * \param sample_rate_hz Sample rate of the generated samples in Hz.
362 * \param frequency_hz Frequency of the sine wave in Hz.
363 * \param amplitude Amplitude of the sine wave. Recommended to be in [-1.0,
364 * 1.0] to agree with the canonical `InternalSampleType`
365 * convention.
366 * \return Output vector of `InternalSampleType`s.
367 */
368 std::vector<InternalSampleType> GenerateSineWav(uint64_t start_tick,
369 uint32_t num_samples,
370 uint32_t sample_rate_hz,
371 double frequency_hz,
372 double amplitude);
373
374 /*!\brief Counts the zero crossings for each channel.
375 *
376 * The first time a user calls this, the `zero_crossing_states` and
377 * `zero_crossing_counts` may be empty. In subsequent calls, the user should
378 * pass the previous state of each channel.
379 *
380 * This pattern allows the user to accumulate the zero crossings for a
381 * single audio channel, while allowing data to be processed in chunks (i.e.
382 * frames).
383 *
384 * \param tick_channel_samples Samples arranged in (time, channel) axes.
385 * \param zero_crossing_states Initial state for each channel. Used between
386 * subsequence calls to `CountZeroCrossings` to track the state of each
387 * channel.
388 * \param zero_crossing_counts Accumulates the number of zero crossings
389 * detected.
390 */
391 enum class ZeroCrossingState { kUnknown, kPositive, kNegative };
392 void AccumulateZeroCrossings(
393 absl::Span<const std::vector<int32_t>> tick_channel_samples,
394 std::vector<ZeroCrossingState>& zero_crossing_states,
395 std::vector<int>& zero_crossing_counts);
396 /*!\brief Reads the contents of the file and appends it to `buffer`.
397 *
398 * \param file_path Path of file to read.
399 * \param buffer Buffer to append the contents of the file to.
400 * \return `absl::OkStatus()` on success. A specific error code on failure.
401 */
402 absl::Status ReadFileToBytes(const std::filesystem::path& file_path,
403 std::vector<uint8_t>& buffer);
404
405 /*!\brief Matches an `InternalSampleType` to an `int32_t`..
406 *
407 * Used with a tuple of `InternalSampleType` and `int32_t`.
408 *
409 * For example:
410 * std::vector<InternalSampleType> samples;
411 * std::vector<int32_t> expected_samples;
412 * EXPECT_THAT(samples,
413 * Pointwise(InternalSampleMatchesIntegralSample(),
414 * expected_samples));
415 */
416 MATCHER(InternalSampleMatchesIntegralSample, "") {
417 int32_t equivalent_integral_sample;
418 return NormalizedFloatingPointToInt32(testing::get<0>(arg),
419 equivalent_integral_sample)
420 .ok() &&
421 equivalent_integral_sample == testing::get<1>(arg);
422 }
423
424 /*!\brief Matches a tag that is the build information of the IAMF encoder.
425 *
426 * A matcher that checks that the tag name is "iamf_encoder" and the tag value
427 * starts with the prefix of the build information of the IAMF encoder. In the
428 * future we may add a suffix, such as the commit hash, to the tag value. This
429 * matcher will match both the old and new formats.
430 *
431 * For example:
432 * const MixPresentationTags::Tag tag{.tag_name = "iamf_encoder",
433 * .tag_value = "GitHub/iamf-tools"};
434 * EXPECT_THAT(tag, TagMatchesBuildInformation());
435 */
436 MATCHER(TagMatchesBuildInformation, "") {
437 constexpr absl::string_view kIamfEncoderBuildInformationPrefix =
438 "GitHub/iamf-tools";
439 return arg.tag_name == "iamf_encoder" &&
440 ExplainMatchResult(
441 ::testing::StartsWith(kIamfEncoderBuildInformationPrefix),
442 arg.tag_value, result_listener);
443 }
444
445 /*!\brief A mock sample processor. */
446 class MockSampleProcessor : public SampleProcessorBase {
447 public:
MockSampleProcessor(uint32_t max_input_samples_per_frame,size_t num_channels,uint32_t max_output_samples_per_frame)448 MockSampleProcessor(uint32_t max_input_samples_per_frame, size_t num_channels,
449 uint32_t max_output_samples_per_frame)
450 : SampleProcessorBase(max_input_samples_per_frame, num_channels,
451 max_output_samples_per_frame) {}
452
453 MOCK_METHOD(absl::Status, PushFrameDerived,
454 (absl::Span<const std::vector<int32_t>> time_channel_samples),
455 (override));
456
457 MOCK_METHOD(absl::Status, FlushDerived, (), (override));
458 };
459
460 /*!\brief A simple processor which resamples the output to every second tick.
461 */
462 class EverySecondTickResampler : public SampleProcessorBase {
463 public:
EverySecondTickResampler(uint32_t max_input_num_samples_per_frame,size_t num_channels)464 EverySecondTickResampler(uint32_t max_input_num_samples_per_frame,
465 size_t num_channels)
466 : SampleProcessorBase(max_input_num_samples_per_frame, num_channels,
467 /*max_output_samples_per_frame=*/
468 max_input_num_samples_per_frame / 2) {}
469
470 private:
471 /*!\brief Pushes a frame of samples to be resampled.
472 *
473 * \param time_channel_samples Samples to push arranged in (time, channel).
474 * \return `absl::OkStatus()` on success. A specific status on failure.
475 */
476 absl::Status PushFrameDerived(
477 absl::Span<const std::vector<int32_t>> time_channel_samples) override;
478
479 /*!\brief Signals to close the resampler and flush any remaining samples.
480 *
481 * It is bad practice to reuse the resampler after calling this function.
482 *
483 * \return `absl::OkStatus()` on success. A specific status on failure.
484 */
485 absl::Status FlushDerived() override;
486 };
487
488 /*!\brief A simple processor which delays the output by one frame.
489 *
490 * Useful for tests which want to verify that an abstract `SampleProcessorBase`
491 * is properly being used when it has delayed output.
492 *
493 * In real-world use cases, resamplers and loudness limiters often will have a
494 * short delay in their output, which `SampleProcessorBase` permits. This is
495 * just simple implementation of a delayer which helps ensure that any delayed
496 * samples are not lost.
497 */
498 class OneFrameDelayer : public SampleProcessorBase {
499 public:
500 /*!\brief Constructor.
501 *
502 * \param max_input_samples_per_frame Maximum number of samples per frame in
503 * the input timescale. Later calls to `PushFrame()` must contain at
504 * most this many samples.
505 * \param num_channels Number of channels. Later calls to `PushFrame()` must
506 * contain this many channels.
507 */
OneFrameDelayer(uint32_t max_input_num_samples_per_frame,size_t num_channels)508 OneFrameDelayer(uint32_t max_input_num_samples_per_frame, size_t num_channels)
509 : SampleProcessorBase(max_input_num_samples_per_frame, num_channels,
510 /*max_output_samples_per_frame=*/
511 max_input_num_samples_per_frame),
512 delayed_samples_(max_input_num_samples_per_frame,
513 std::vector<int32_t>(num_channels)) {}
514
515 private:
516 /*!\brief Pushes a frame of samples to be resampled.
517 *
518 * \param time_channel_samples Samples to push arranged in (time, channel).
519 * \return `absl::OkStatus()` on success. A specific status on failure.
520 */
521 absl::Status PushFrameDerived(
522 absl::Span<const std::vector<int32_t>> time_channel_samples) override;
523
524 /*!\brief Signals to close the resampler and flush any remaining samples.
525 *
526 * \return `absl::OkStatus()` on success. A specific status on failure.
527 */
528 absl::Status FlushDerived() override;
529
530 // Buffer to track the delayed samples.
531 std::vector<std::vector<int32_t>> delayed_samples_;
532 size_t num_delayed_ticks_ = 0;
533 };
534
535 /*!\brief A mock loudness calculator factory. */
536 class MockLoudnessCalculatorFactory : public LoudnessCalculatorFactoryBase {
537 public:
MockLoudnessCalculatorFactory()538 MockLoudnessCalculatorFactory() : LoudnessCalculatorFactoryBase() {}
539
540 MOCK_METHOD(std::unique_ptr<LoudnessCalculatorBase>, CreateLoudnessCalculator,
541 (const MixPresentationLayout& layout,
542 uint32_t num_samples_per_frame, int32_t rendered_sample_rate,
543 int32_t rendered_bit_depth),
544 (const, override));
545 };
546
547 /*!\brief A mock loudness calculator. */
548 class MockLoudnessCalculator : public LoudnessCalculatorBase {
549 public:
MockLoudnessCalculator()550 MockLoudnessCalculator() : LoudnessCalculatorBase() {}
551
552 MOCK_METHOD(absl::Status, AccumulateLoudnessForSamples,
553 (absl::Span<const std::vector<int32_t>> time_channel_samples),
554 (override));
555
556 MOCK_METHOD(absl::StatusOr<LoudnessInfo>, QueryLoudness, (),
557 (const, override));
558 };
559
560 /*!\brief A mock sample processor factory. */
561 typedef testing::MockFunction<std::unique_ptr<SampleProcessorBase>(
562 DecodedUleb128 mix_presentation_id, int sub_mix_index, int layout_index,
563 const Layout& layout, int num_channels, int sample_rate, int bit_depth,
564 size_t num_samples_per_frame)>
565 MockSampleProcessorFactory;
566
567 /*!\brief A mock OBU sequencer. */
568 class MockObuSequencer : public ObuSequencerBase {
569 public:
570 /*!\brief Constructor.
571 *
572 * \param leb_generator Leb generator to use when writing OBUs.
573 * \param include_temporal_delimiters Whether the serialized data should
574 * include a temporal delimiter.
575 * \param delay_descriptors_until_first_untrimmed_sample Whether the
576 * descriptor OBUs should be delayed until the first untrimmed frame
577 * is known.
578 */
MockObuSequencer(const LebGenerator & leb_generator,bool include_temporal_delimiters,bool delay_descriptors_until_first_untrimmed_sample)579 MockObuSequencer(const LebGenerator& leb_generator,
580 bool include_temporal_delimiters,
581 bool delay_descriptors_until_first_untrimmed_sample)
582 : ObuSequencerBase(leb_generator, include_temporal_delimiters,
583 delay_descriptors_until_first_untrimmed_sample) {}
584
585 MOCK_METHOD(void, AbortDerived, (), (override));
586
587 MOCK_METHOD(absl::Status, PushSerializedDescriptorObus,
588 (uint32_t common_samples_per_frame, uint32_t common_sample_rate,
589 uint8_t common_bit_depth,
590 std::optional<int64_t> first_untrimmed_timestamp,
591 int num_channels, absl::Span<const uint8_t> descriptor_obus),
592 (override));
593
594 MOCK_METHOD(absl::Status, PushSerializedTemporalUnit,
595 (int64_t timestamp, int num_samples,
596 absl::Span<const uint8_t> temporal_unit),
597 (override));
598
599 MOCK_METHOD(absl::Status, PushFinalizedDescriptorObus,
600 (absl::Span<const uint8_t> descriptor_obus), (override));
601
602 MOCK_METHOD(void, CloseDerived, (), (override));
603 };
604
605 } // namespace iamf_tools
606
607 #endif // CLI_TESTS_CLI_TEST_UTILS_H_
608