• 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 #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