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/codec/encoder_base.h"
13
14 #include <cstdint>
15 #include <list>
16 #include <memory>
17 #include <utility>
18 #include <vector>
19
20 #include "absl/status/status.h"
21 #include "absl/status/status_matchers.h"
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include "iamf/cli/audio_frame_with_data.h"
25 #include "iamf/obu/audio_frame.h"
26 #include "iamf/obu/codec_config.h"
27 #include "iamf/obu/obu_header.h"
28 #include "iamf/obu/types.h"
29
30 namespace iamf_tools {
31 namespace {
32
33 using ::absl_testing::IsOk;
34
35 using testing::Return;
36
37 constexpr DecodedUleb128 kCodecConfigId = 159;
38 constexpr bool kValidateCodecDelay = true;
39 constexpr bool kDontValidateCodecDelay = false;
40
41 class MockEncoder : public EncoderBase {
42 public:
MockEncoder()43 MockEncoder()
44 : EncoderBase(CodecConfigObu(ObuHeader(), kCodecConfigId, CodecConfig()),
45 0) {}
46
47 MOCK_METHOD(
48 absl::Status, EncodeAudioFrame,
49 (int input_bit_depth, const std::vector<std::vector<int32_t>>& samples,
50 std::unique_ptr<AudioFrameWithData> partial_audio_frame_with_data),
51 (override));
52
53 MOCK_METHOD(absl::Status, InitializeEncoder, (), (override));
54 MOCK_METHOD(absl::Status, SetNumberOfSamplesToDelayAtStart,
55 (bool validate_codec_delay), (override));
56 };
57
TEST(EncoderBaseTest,InitializeSucceeds)58 TEST(EncoderBaseTest, InitializeSucceeds) {
59 MockEncoder encoder;
60 EXPECT_CALL(encoder, InitializeEncoder()).WillOnce(Return(absl::OkStatus()));
61 EXPECT_CALL(encoder, SetNumberOfSamplesToDelayAtStart(kValidateCodecDelay))
62 .WillOnce(Return(absl::OkStatus()));
63
64 EXPECT_THAT(encoder.Initialize(kValidateCodecDelay), IsOk());
65 }
66
TEST(EncoderBaseTest,InitializeFailsWhenInitializeEncoderFails)67 TEST(EncoderBaseTest, InitializeFailsWhenInitializeEncoderFails) {
68 MockEncoder encoder;
69 EXPECT_CALL(encoder, InitializeEncoder())
70 .WillOnce(Return(absl::UnknownError("")));
71
72 EXPECT_EQ(encoder.Initialize(kValidateCodecDelay).code(),
73 absl::StatusCode::kUnknown);
74 }
75
TEST(EncoderBaseTest,InitializePropagatesValidatePreSkipToSetNumberOfSamplesToDelayAtStart)76 TEST(EncoderBaseTest,
77 InitializePropagatesValidatePreSkipToSetNumberOfSamplesToDelayAtStart) {
78 MockEncoder encoder;
79 EXPECT_CALL(encoder,
80 SetNumberOfSamplesToDelayAtStart(kDontValidateCodecDelay));
81
82 encoder.Initialize(kDontValidateCodecDelay).IgnoreError();
83 }
84
TEST(EncoderBaseTest,SetNumberOfSamplesToDelayAtStartDefaultsToSuccess)85 TEST(EncoderBaseTest, SetNumberOfSamplesToDelayAtStartDefaultsToSuccess) {
86 MockEncoder encoder;
87 EXPECT_CALL(encoder, SetNumberOfSamplesToDelayAtStart(kValidateCodecDelay));
88
89 EXPECT_THAT(encoder.Initialize(kValidateCodecDelay), IsOk());
90 }
91
TEST(EncoderBaseTest,InitializeFailsWhenSetNumberOfSamplesToDelayAtStartFails)92 TEST(EncoderBaseTest,
93 InitializeFailsWhenSetNumberOfSamplesToDelayAtStartFails) {
94 MockEncoder encoder;
95 EXPECT_CALL(encoder, InitializeEncoder()).WillOnce(Return(absl::OkStatus()));
96 EXPECT_CALL(encoder, SetNumberOfSamplesToDelayAtStart(kValidateCodecDelay))
97 .WillOnce(Return(absl::UnknownError("")));
98
99 EXPECT_EQ(encoder.Initialize(kValidateCodecDelay).code(),
100 absl::StatusCode::kUnknown);
101 }
102
TEST(EncoderBaseTest,FinalizeAndPopAppendNothingWhenNoFramesAvailable)103 TEST(EncoderBaseTest, FinalizeAndPopAppendNothingWhenNoFramesAvailable) {
104 MockEncoder encoder;
105
106 // Expect the returned `audio_frames` is just the same as before calling
107 // `Finalize()` and `Pop()`, because we know an empty list
108 // (`finalized_audio_frames_`) is appended at the end.
109 const DecodedUleb128 kSubstreamId = 137;
110 const int32_t kStartTimestamp = 77;
111 const int32_t kEndTimestamp = 101;
112 const std::vector<uint8_t> kAudioFrame = {1, 7, 5, 3};
113 AudioFrameObu obu(ObuHeader(), kSubstreamId, kAudioFrame);
114 std::list<AudioFrameWithData> audio_frames;
115 audio_frames.emplace_back(AudioFrameWithData{
116 .obu = std::move(obu),
117 .start_timestamp = kStartTimestamp,
118 .end_timestamp = kEndTimestamp,
119 .audio_element_with_data = nullptr,
120 });
121
122 EXPECT_THAT(encoder.Finalize(), IsOk());
123
124 // Since nothing has been added, there are no frames available.
125 EXPECT_FALSE(encoder.FramesAvailable());
126
127 // `Pop()` still works, just adding nothing.
128 EXPECT_THAT(encoder.Pop(audio_frames), IsOk());
129
130 // Expect the `audio_frames` is unaltered.
131 ASSERT_EQ(audio_frames.size(), 1);
132 const auto& only_frame = audio_frames.back();
133 EXPECT_EQ(only_frame.obu.GetSubstreamId(), kSubstreamId);
134 EXPECT_EQ(only_frame.obu.audio_frame_, kAudioFrame);
135 EXPECT_EQ(only_frame.start_timestamp, kStartTimestamp);
136 EXPECT_EQ(only_frame.end_timestamp, kEndTimestamp);
137 EXPECT_EQ(only_frame.audio_element_with_data, nullptr);
138 }
139
TEST(EncoderBaseTest,DefaultZeroNumberOfSamplesToDelayAtStart)140 TEST(EncoderBaseTest, DefaultZeroNumberOfSamplesToDelayAtStart) {
141 MockEncoder encoder;
142
143 EXPECT_EQ(encoder.GetNumberOfSamplesToDelayAtStart(), 0);
144 }
145
146 } // namespace
147 } // namespace iamf_tools
148