1 /*
2 * Copyright 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "FrameReassembler.h"
18
19 #include <gtest/gtest.h>
20
21 #include <C2PlatformSupport.h>
22
23 #include <media/stagefright/foundation/ABuffer.h>
24 #include <media/stagefright/foundation/AMessage.h>
25
26 namespace android {
27
BytesPerSample(C2Config::pcm_encoding_t encoding)28 static size_t BytesPerSample(C2Config::pcm_encoding_t encoding) {
29 return encoding == PCM_8 ? 1
30 : encoding == PCM_16 ? 2
31 : encoding == PCM_FLOAT ? 4 : 0;
32 }
33
Diff(c2_cntr64_t a,c2_cntr64_t b)34 static uint64_t Diff(c2_cntr64_t a, c2_cntr64_t b) {
35 return std::abs((a - b).peek());
36 }
37
38 class FrameReassemblerTest : public ::testing::Test {
39 public:
40 static const C2MemoryUsage kUsage;
41 static constexpr uint64_t kTimestampToleranceUs = 100;
42
FrameReassemblerTest()43 FrameReassemblerTest() {
44 mInitStatus = GetCodec2BlockPool(C2BlockPool::BASIC_LINEAR, nullptr, &mPool);
45 }
46
initStatus() const47 status_t initStatus() const { return mInitStatus; }
48
testPushSameSize(size_t encoderFrameSize,size_t sampleRate,size_t channelCount,C2Config::pcm_encoding_t encoding,size_t inputFrameSizeInBytes,size_t count,size_t expectedOutputSize)49 void testPushSameSize(
50 size_t encoderFrameSize,
51 size_t sampleRate,
52 size_t channelCount,
53 C2Config::pcm_encoding_t encoding,
54 size_t inputFrameSizeInBytes,
55 size_t count,
56 size_t expectedOutputSize) {
57 FrameReassembler frameReassembler;
58 frameReassembler.init(
59 mPool,
60 kUsage,
61 encoderFrameSize,
62 sampleRate,
63 channelCount,
64 encoding);
65
66 ASSERT_TRUE(frameReassembler) << "FrameReassembler init failed";
67
68 size_t inputIndex = 0, outputIndex = 0;
69 size_t expectCount = 0;
70 for (size_t i = 0; i < count; ++i) {
71 sp<MediaCodecBuffer> buffer = new MediaCodecBuffer(
72 new AMessage, new ABuffer(inputFrameSizeInBytes));
73 buffer->setRange(0, inputFrameSizeInBytes);
74 buffer->meta()->setInt64(
75 "timeUs",
76 inputIndex * 1000000 / sampleRate / channelCount / BytesPerSample(encoding));
77 if (i == count - 1) {
78 buffer->meta()->setInt32("eos", 1);
79 }
80 for (size_t j = 0; j < inputFrameSizeInBytes; ++j, ++inputIndex) {
81 buffer->base()[j] = (inputIndex & 0xFF);
82 }
83 std::list<std::unique_ptr<C2Work>> items;
84 ASSERT_EQ(C2_OK, frameReassembler.process(buffer, &items));
85 while (!items.empty()) {
86 std::unique_ptr<C2Work> work = std::move(*items.begin());
87 items.erase(items.begin());
88 // Verify timestamp
89 uint64_t expectedTimeUs =
90 outputIndex * 1000000 / sampleRate / channelCount / BytesPerSample(encoding);
91 EXPECT_GE(
92 kTimestampToleranceUs,
93 Diff(expectedTimeUs, work->input.ordinal.timestamp))
94 << "expected timestamp: " << expectedTimeUs
95 << " actual timestamp: " << work->input.ordinal.timestamp.peeku()
96 << " output index: " << outputIndex;
97
98 // Verify buffer
99 ASSERT_EQ(1u, work->input.buffers.size());
100 std::shared_ptr<C2Buffer> buffer = work->input.buffers.front();
101 ASSERT_EQ(C2BufferData::LINEAR, buffer->data().type());
102 ASSERT_EQ(1u, buffer->data().linearBlocks().size());
103 C2ReadView view = buffer->data().linearBlocks().front().map().get();
104 ASSERT_EQ(C2_OK, view.error());
105 ASSERT_EQ(encoderFrameSize * BytesPerSample(encoding), view.capacity());
106 for (size_t j = 0; j < view.capacity(); ++j, ++outputIndex) {
107 ASSERT_TRUE(outputIndex < inputIndex
108 || inputIndex == inputFrameSizeInBytes * count);
109 uint8_t expected = outputIndex < inputIndex ? (outputIndex & 0xFF) : 0;
110 if (expectCount < 10) {
111 ++expectCount;
112 EXPECT_EQ(expected, view.data()[j]) << "output index = " << outputIndex;
113 }
114 }
115 }
116 }
117
118 ASSERT_EQ(inputFrameSizeInBytes * count, inputIndex);
119 size_t encoderFrameSizeInBytes =
120 encoderFrameSize * channelCount * BytesPerSample(encoding);
121 ASSERT_EQ(0, outputIndex % encoderFrameSizeInBytes)
122 << "output size must be multiple of frame size: output size = " << outputIndex
123 << " frame size = " << encoderFrameSizeInBytes;
124 ASSERT_EQ(expectedOutputSize, outputIndex)
125 << "output size must be smallest multiple of frame size, "
126 << "equal to or larger than input size. output size = " << outputIndex
127 << " input size = " << inputIndex << " frame size = " << encoderFrameSizeInBytes;
128 }
129
130 private:
131 status_t mInitStatus;
132 std::shared_ptr<C2BlockPool> mPool;
133 };
134
135 const C2MemoryUsage FrameReassemblerTest::kUsage{C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
136
137 // Push frames with exactly the same size as the encoder requested.
TEST_F(FrameReassemblerTest,PushExactFrameSize)138 TEST_F(FrameReassemblerTest, PushExactFrameSize) {
139 ASSERT_EQ(OK, initStatus());
140 testPushSameSize(
141 1024 /* frame size in samples */,
142 48000 /* sample rate */,
143 1 /* channel count */,
144 PCM_8,
145 1024 /* input frame size in bytes = 1024 samples * 1 channel * 1 bytes/sample */,
146 10 /* count */,
147 10240 /* expected output size = 10 * 1024 bytes/frame */);
148 testPushSameSize(
149 1024 /* frame size in samples */,
150 48000 /* sample rate */,
151 1 /* channel count */,
152 PCM_16,
153 2048 /* input frame size in bytes = 1024 samples * 1 channel * 2 bytes/sample */,
154 10 /* count */,
155 20480 /* expected output size = 10 * 2048 bytes/frame */);
156 testPushSameSize(
157 1024 /* frame size in samples */,
158 48000 /* sample rate */,
159 1 /* channel count */,
160 PCM_FLOAT,
161 4096 /* input frame size in bytes = 1024 samples * 1 channel * 4 bytes/sample */,
162 10 /* count */,
163 40960 /* expected output size = 10 * 4096 bytes/frame */);
164 }
165
166 // Push frames with half the size that the encoder requested.
TEST_F(FrameReassemblerTest,PushHalfFrameSize)167 TEST_F(FrameReassemblerTest, PushHalfFrameSize) {
168 ASSERT_EQ(OK, initStatus());
169 testPushSameSize(
170 1024 /* frame size in samples */,
171 48000 /* sample rate */,
172 1 /* channel count */,
173 PCM_8,
174 512 /* input frame size in bytes = 512 samples * 1 channel * 1 bytes per sample */,
175 10 /* count */,
176 5120 /* expected output size = 5 * 1024 bytes/frame */);
177 testPushSameSize(
178 1024 /* frame size in samples */,
179 48000 /* sample rate */,
180 1 /* channel count */,
181 PCM_16,
182 1024 /* input frame size in bytes = 512 samples * 1 channel * 2 bytes per sample */,
183 10 /* count */,
184 10240 /* expected output size = 5 * 2048 bytes/frame */);
185 testPushSameSize(
186 1024 /* frame size in samples */,
187 48000 /* sample rate */,
188 1 /* channel count */,
189 PCM_FLOAT,
190 2048 /* input frame size in bytes = 512 samples * 1 channel * 4 bytes per sample */,
191 10 /* count */,
192 20480 /* expected output size = 5 * 4096 bytes/frame */);
193 }
194
195 // Push frames with twice the size that the encoder requested.
TEST_F(FrameReassemblerTest,PushDoubleFrameSize)196 TEST_F(FrameReassemblerTest, PushDoubleFrameSize) {
197 ASSERT_EQ(OK, initStatus());
198 testPushSameSize(
199 1024 /* frame size in samples */,
200 48000 /* sample rate */,
201 1 /* channel count */,
202 PCM_8,
203 2048 /* input frame size in bytes = 2048 samples * 1 channel * 1 bytes per sample */,
204 10 /* count */,
205 20480 /* expected output size = 20 * 1024 bytes/frame */);
206 testPushSameSize(
207 1024 /* frame size in samples */,
208 48000 /* sample rate */,
209 1 /* channel count */,
210 PCM_16,
211 4096 /* input frame size in bytes = 2048 samples * 1 channel * 2 bytes per sample */,
212 10 /* count */,
213 40960 /* expected output size = 20 * 2048 bytes/frame */);
214 testPushSameSize(
215 1024 /* frame size in samples */,
216 48000 /* sample rate */,
217 1 /* channel count */,
218 PCM_FLOAT,
219 8192 /* input frame size in bytes = 2048 samples * 1 channel * 4 bytes per sample */,
220 10 /* count */,
221 81920 /* expected output size = 20 * 4096 bytes/frame */);
222 }
223
224 // Push frames with a little bit larger (+5 samples) than the requested size.
TEST_F(FrameReassemblerTest,PushLittleLargerFrameSize)225 TEST_F(FrameReassemblerTest, PushLittleLargerFrameSize) {
226 ASSERT_EQ(OK, initStatus());
227 testPushSameSize(
228 1024 /* frame size in samples */,
229 48000 /* sample rate */,
230 1 /* channel count */,
231 PCM_8,
232 1029 /* input frame size in bytes = 1029 samples * 1 channel * 1 bytes per sample */,
233 10 /* count */,
234 11264 /* expected output size = 11 * 1024 bytes/frame */);
235 testPushSameSize(
236 1024 /* frame size in samples */,
237 48000 /* sample rate */,
238 1 /* channel count */,
239 PCM_16,
240 2058 /* input frame size in bytes = 1029 samples * 1 channel * 2 bytes per sample */,
241 10 /* count */,
242 22528 /* expected output size = 11 * 2048 bytes/frame */);
243 testPushSameSize(
244 1024 /* frame size in samples */,
245 48000 /* sample rate */,
246 1 /* channel count */,
247 PCM_FLOAT,
248 4116 /* input frame size in bytes = 1029 samples * 1 channel * 4 bytes per sample */,
249 10 /* count */,
250 45056 /* expected output size = 11 * 4096 bytes/frame */);
251 }
252
253 // Push frames with a little bit smaller (-5 samples) than the requested size.
TEST_F(FrameReassemblerTest,PushLittleSmallerFrameSize)254 TEST_F(FrameReassemblerTest, PushLittleSmallerFrameSize) {
255 ASSERT_EQ(OK, initStatus());
256 testPushSameSize(
257 1024 /* frame size in samples */,
258 48000 /* sample rate */,
259 1 /* channel count */,
260 PCM_8,
261 1019 /* input frame size in bytes = 1019 samples * 1 channel * 1 bytes per sample */,
262 10 /* count */,
263 10240 /* expected output size = 10 * 1024 bytes/frame */);
264 testPushSameSize(
265 1024 /* frame size in samples */,
266 48000 /* sample rate */,
267 1 /* channel count */,
268 PCM_16,
269 2038 /* input frame size in bytes = 1019 samples * 1 channel * 2 bytes per sample */,
270 10 /* count */,
271 20480 /* expected output size = 10 * 2048 bytes/frame */);
272 testPushSameSize(
273 1024 /* frame size in samples */,
274 48000 /* sample rate */,
275 1 /* channel count */,
276 PCM_FLOAT,
277 4076 /* input frame size in bytes = 1019 samples * 1 channel * 4 bytes per sample */,
278 10 /* count */,
279 40960 /* expected output size = 10 * 4096 bytes/frame */);
280 }
281
282 // Push single-byte frames
TEST_F(FrameReassemblerTest,PushSingleByte)283 TEST_F(FrameReassemblerTest, PushSingleByte) {
284 ASSERT_EQ(OK, initStatus());
285 testPushSameSize(
286 1024 /* frame size in samples */,
287 48000 /* sample rate */,
288 1 /* channel count */,
289 PCM_8,
290 1 /* input frame size in bytes */,
291 100000 /* count */,
292 100352 /* expected output size = 98 * 1024 bytes/frame */);
293 testPushSameSize(
294 1024 /* frame size in samples */,
295 48000 /* sample rate */,
296 1 /* channel count */,
297 PCM_16,
298 1 /* input frame size in bytes */,
299 100000 /* count */,
300 100352 /* expected output size = 49 * 2048 bytes/frame */);
301 testPushSameSize(
302 1024 /* frame size in samples */,
303 48000 /* sample rate */,
304 1 /* channel count */,
305 PCM_FLOAT,
306 1 /* input frame size in bytes */,
307 100000 /* count */,
308 102400 /* expected output size = 25 * 4096 bytes/frame */);
309 }
310
311 // Push one big chunk.
TEST_F(FrameReassemblerTest,PushBigChunk)312 TEST_F(FrameReassemblerTest, PushBigChunk) {
313 ASSERT_EQ(OK, initStatus());
314 testPushSameSize(
315 1024 /* frame size in samples */,
316 48000 /* sample rate */,
317 1 /* channel count */,
318 PCM_8,
319 100000 /* input frame size in bytes */,
320 1 /* count */,
321 100352 /* expected output size = 98 * 1024 bytes/frame */);
322 testPushSameSize(
323 1024 /* frame size in samples */,
324 48000 /* sample rate */,
325 1 /* channel count */,
326 PCM_16,
327 100000 /* input frame size in bytes */,
328 1 /* count */,
329 100352 /* expected output size = 49 * 2048 bytes/frame */);
330 testPushSameSize(
331 1024 /* frame size in samples */,
332 48000 /* sample rate */,
333 1 /* channel count */,
334 PCM_FLOAT,
335 100000 /* input frame size in bytes */,
336 1 /* count */,
337 102400 /* expected output size = 25 * 4096 bytes/frame */);
338 }
339
340 } // namespace android
341