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_ENCODER_TEST_BASE_H_ 13 #define CLI_TESTS_ENCODER_TEST_BASE_H_ 14 15 #include <cstdint> 16 #include <list> 17 #include <memory> 18 #include <utility> 19 #include <vector> 20 21 #include "absl/memory/memory.h" 22 #include "absl/status/status.h" 23 #include "absl/status/status_matchers.h" 24 #include "gmock/gmock.h" 25 #include "gtest/gtest.h" 26 #include "iamf/cli/audio_frame_with_data.h" 27 #include "iamf/cli/codec/encoder_base.h" 28 #include "iamf/obu/audio_frame.h" 29 30 namespace iamf_tools { 31 32 using ::absl_testing::IsOk; 33 34 constexpr bool kValidateCodecDelay = true; 35 36 class EncoderTestBase { 37 public: 38 EncoderTestBase() = default; 39 virtual ~EncoderTestBase() = 0; 40 41 protected: 42 virtual void ConstructEncoder() = 0; 43 InitExpectOk()44 void InitExpectOk() { 45 ConstructEncoder(); 46 EXPECT_THAT(encoder_->Initialize(kValidateCodecDelay), IsOk()); 47 } 48 49 void EncodeAudioFrame(const std::vector<std::vector<int32_t>>& pcm_samples, 50 bool expected_encode_frame_is_ok = true) { 51 // `EncodeAudioFrame` only passes on most of the data in the input 52 // `AudioFrameWithData`. Simulate the timestamp to ensure frames are 53 // returned in the correct order, but most other fields do not matter. 54 const int32_t next_timestamp = 55 cur_timestamp_ + static_cast<int32_t>(num_samples_per_frame_); 56 auto partial_audio_frame_with_data = 57 absl::WrapUnique(new AudioFrameWithData{ 58 .obu = AudioFrameObu( 59 { 60 .obu_trimming_status_flag = false, 61 .num_samples_to_trim_at_end = 0, 62 .num_samples_to_trim_at_start = 0, 63 }, 64 0, {}), 65 .start_timestamp = cur_timestamp_, 66 .end_timestamp = next_timestamp, 67 }); 68 cur_timestamp_ = next_timestamp; 69 70 // Encode the frame as requested. 71 EXPECT_EQ(encoder_ 72 ->EncodeAudioFrame(input_sample_size_, pcm_samples, 73 std::move(partial_audio_frame_with_data)) 74 .ok(), 75 expected_encode_frame_is_ok); 76 } 77 78 // Finalizes the encoder and only validates the number and order of output 79 // frames is consistent with the input frames. Returns the output audio 80 // frames. FinalizeAndValidateOrderOnly(int expected_num_frames)81 std::list<AudioFrameWithData> FinalizeAndValidateOrderOnly( 82 int expected_num_frames) { 83 std::list<AudioFrameWithData> output_audio_frames; 84 EXPECT_THAT(encoder_->Finalize(), IsOk()); 85 86 // Pop all the frames. 87 for (int i = 0; i < expected_num_frames; i++) { 88 EXPECT_THAT(encoder_->Pop(output_audio_frames), IsOk()); 89 } 90 EXPECT_EQ(output_audio_frames.size(), expected_num_frames); 91 92 // Check that there are no more frames left. 93 EXPECT_FALSE(encoder_->FramesAvailable()); 94 95 ValidateOrder(output_audio_frames); 96 return output_audio_frames; 97 } 98 99 // Finalizes the encoder and validates the content of the `audio_frame_`s 100 // matches the expected data in the expected order. FinalizeAndValidate()101 void FinalizeAndValidate() { 102 const auto output_audio_frames = 103 FinalizeAndValidateOrderOnly(expected_audio_frames_.size()); 104 105 // Validate the `audio_frame_` data is identical to the expected data. 106 EXPECT_EQ(output_audio_frames.size(), expected_audio_frames_.size()); 107 auto output_iter = output_audio_frames.begin(); 108 auto expected_iter = expected_audio_frames_.begin(); 109 while (output_iter != output_audio_frames.end()) { 110 EXPECT_EQ(output_iter->obu.audio_frame_, *expected_iter); 111 output_iter++; 112 expected_iter++; 113 } 114 } 115 116 int num_channels_ = 1; 117 int substream_id_ = 0; 118 uint32_t num_samples_per_frame_ = 1; 119 int8_t input_sample_size_ = 16; 120 std::unique_ptr<EncoderBase> encoder_; 121 122 std::list<std::vector<uint8_t>> expected_audio_frames_ = {}; 123 124 private: ValidateOrder(const std::list<AudioFrameWithData> & output_audio_frames)125 void ValidateOrder(const std::list<AudioFrameWithData>& output_audio_frames) { 126 // Validate that the timestamps match the expected order. 127 int expected_start_timestamp_ = 0; 128 for (const auto& output_audio_frame : output_audio_frames) { 129 EXPECT_EQ(output_audio_frame.start_timestamp, expected_start_timestamp_); 130 expected_start_timestamp_ += num_samples_per_frame_; 131 } 132 } 133 134 int32_t cur_timestamp_ = 0; 135 }; 136 137 } // namespace iamf_tools 138 139 #endif // CLI_TESTS_ENCODER_TEST_BASE_H_ 140