xref: /aosp_15_r20/frameworks/av/media/codec2/sfplugin/tests/FrameReassembler_test.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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,bool separateEos)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             bool separateEos) {
58         FrameReassembler frameReassembler;
59         frameReassembler.init(
60                 mPool,
61                 kUsage,
62                 encoderFrameSize,
63                 sampleRate,
64                 channelCount,
65                 encoding);
66 
67         ASSERT_TRUE(frameReassembler) << "FrameReassembler init failed";
68 
69         size_t inputIndex = 0, outputIndex = 0;
70         size_t expectCount = 0;
71         for (size_t i = 0; i < count + (separateEos ? 1 : 0); ++i) {
72             sp<MediaCodecBuffer> buffer = new MediaCodecBuffer(
73                     new AMessage, new ABuffer(inputFrameSizeInBytes));
74             buffer->setRange(0, inputFrameSizeInBytes);
75             buffer->meta()->setInt64(
76                     "timeUs",
77                     inputIndex * 1000000 / sampleRate / channelCount / BytesPerSample(encoding));
78             if (i == count - 1) {
79                 buffer->meta()->setInt32("eos", 1);
80             }
81             if (i == count && separateEos) {
82                 buffer->setRange(0, 0);
83             } else {
84                 for (size_t j = 0; j < inputFrameSizeInBytes; ++j, ++inputIndex) {
85                     buffer->base()[j] = (inputIndex & 0xFF);
86                 }
87             }
88             std::list<std::unique_ptr<C2Work>> items;
89             ASSERT_EQ(C2_OK, frameReassembler.process(buffer, &items));
90             while (!items.empty()) {
91                 std::unique_ptr<C2Work> work = std::move(*items.begin());
92                 items.erase(items.begin());
93                 // Verify timestamp
94                 uint64_t expectedTimeUs =
95                     outputIndex * 1000000 / sampleRate / channelCount / BytesPerSample(encoding);
96                 EXPECT_GE(
97                         kTimestampToleranceUs,
98                         Diff(expectedTimeUs, work->input.ordinal.timestamp))
99                     << "expected timestamp: " << expectedTimeUs
100                     << " actual timestamp: " << work->input.ordinal.timestamp.peeku()
101                     << " output index: " << outputIndex;
102 
103                 // Verify buffer
104                 ASSERT_EQ(1u, work->input.buffers.size());
105                 std::shared_ptr<C2Buffer> buffer = work->input.buffers.front();
106                 ASSERT_EQ(C2BufferData::LINEAR, buffer->data().type());
107                 ASSERT_EQ(1u, buffer->data().linearBlocks().size());
108                 C2ReadView view = buffer->data().linearBlocks().front().map().get();
109                 ASSERT_EQ(C2_OK, view.error());
110                 ASSERT_EQ(encoderFrameSize * BytesPerSample(encoding), view.capacity());
111                 for (size_t j = 0; j < view.capacity(); ++j, ++outputIndex) {
112                     ASSERT_TRUE(outputIndex < inputIndex
113                              || inputIndex == inputFrameSizeInBytes * count)
114                         << "inputIndex = " << inputIndex << " outputIndex = " << outputIndex;
115                     uint8_t expected = outputIndex < inputIndex ? (outputIndex & 0xFF) : 0;
116                     if (expectCount < 10) {
117                         ++expectCount;
118                         EXPECT_EQ(expected, view.data()[j]) << "output index = " << outputIndex;
119                     }
120                 }
121             }
122         }
123 
124         ASSERT_EQ(inputFrameSizeInBytes * count, inputIndex);
125         size_t encoderFrameSizeInBytes =
126             encoderFrameSize * channelCount * BytesPerSample(encoding);
127         ASSERT_EQ(0, outputIndex % encoderFrameSizeInBytes)
128             << "output size must be multiple of frame size: output size = " << outputIndex
129             << " frame size = " << encoderFrameSizeInBytes;
130         ASSERT_EQ(expectedOutputSize, outputIndex)
131             << "output size must be smallest multiple of frame size, "
132             << "equal to or larger than input size. output size = " << outputIndex
133             << " input size = " << inputIndex << " frame size = " << encoderFrameSizeInBytes;
134     }
135 
136 private:
137     status_t mInitStatus;
138     std::shared_ptr<C2BlockPool> mPool;
139 };
140 
141 const C2MemoryUsage FrameReassemblerTest::kUsage{C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
142 
143 // Push frames with exactly the same size as the encoder requested.
TEST_F(FrameReassemblerTest,PushExactFrameSize)144 TEST_F(FrameReassemblerTest, PushExactFrameSize) {
145     ASSERT_EQ(OK, initStatus());
146     for (bool separateEos : {false, true}) {
147         testPushSameSize(
148                 1024 /* frame size in samples */,
149                 48000 /* sample rate */,
150                 1 /* channel count */,
151                 PCM_8,
152                 1024 /* input frame size in bytes = 1024 samples * 1 channel * 1 bytes/sample */,
153                 10 /* count */,
154                 10240 /* expected output size = 10 * 1024 bytes/frame */,
155                 separateEos);
156         testPushSameSize(
157                 1024 /* frame size in samples */,
158                 48000 /* sample rate */,
159                 1 /* channel count */,
160                 PCM_16,
161                 2048 /* input frame size in bytes = 1024 samples * 1 channel * 2 bytes/sample */,
162                 10 /* count */,
163                 20480 /* expected output size = 10 * 2048 bytes/frame */,
164                 separateEos);
165         testPushSameSize(
166                 1024 /* frame size in samples */,
167                 48000 /* sample rate */,
168                 1 /* channel count */,
169                 PCM_FLOAT,
170                 4096 /* input frame size in bytes = 1024 samples * 1 channel * 4 bytes/sample */,
171                 10 /* count */,
172                 40960 /* expected output size = 10 * 4096 bytes/frame */,
173                 separateEos);
174     }
175 }
176 
177 // Push frames with half the size that the encoder requested.
TEST_F(FrameReassemblerTest,PushHalfFrameSize)178 TEST_F(FrameReassemblerTest, PushHalfFrameSize) {
179     ASSERT_EQ(OK, initStatus());
180     for (bool separateEos : {false, true}) {
181         testPushSameSize(
182                 1024 /* frame size in samples */,
183                 48000 /* sample rate */,
184                 1 /* channel count */,
185                 PCM_8,
186                 512 /* input frame size in bytes = 512 samples * 1 channel * 1 bytes/sample */,
187                 10 /* count */,
188                 5120 /* expected output size = 5 * 1024 bytes/frame */,
189                 separateEos);
190         testPushSameSize(
191                 1024 /* frame size in samples */,
192                 48000 /* sample rate */,
193                 1 /* channel count */,
194                 PCM_16,
195                 1024 /* input frame size in bytes = 512 samples * 1 channel * 2 bytes/sample */,
196                 10 /* count */,
197                 10240 /* expected output size = 5 * 2048 bytes/frame */,
198                 separateEos);
199         testPushSameSize(
200                 1024 /* frame size in samples */,
201                 48000 /* sample rate */,
202                 1 /* channel count */,
203                 PCM_FLOAT,
204                 2048 /* input frame size in bytes = 512 samples * 1 channel * 4 bytes/sample */,
205                 10 /* count */,
206                 20480 /* expected output size = 5 * 4096 bytes/frame */,
207                 separateEos);
208     }
209 }
210 
211 // Push frames with twice the size that the encoder requested.
TEST_F(FrameReassemblerTest,PushDoubleFrameSize)212 TEST_F(FrameReassemblerTest, PushDoubleFrameSize) {
213     ASSERT_EQ(OK, initStatus());
214     for (bool separateEos : {false, true}) {
215         testPushSameSize(
216                 1024 /* frame size in samples */,
217                 48000 /* sample rate */,
218                 1 /* channel count */,
219                 PCM_8,
220                 2048 /* input frame size in bytes = 2048 samples * 1 channel * 1 bytes/sample */,
221                 10 /* count */,
222                 20480 /* expected output size = 20 * 1024 bytes/frame */,
223                 separateEos);
224         testPushSameSize(
225                 1024 /* frame size in samples */,
226                 48000 /* sample rate */,
227                 1 /* channel count */,
228                 PCM_16,
229                 4096 /* input frame size in bytes = 2048 samples * 1 channel * 2 bytes/sample */,
230                 10 /* count */,
231                 40960 /* expected output size = 20 * 2048 bytes/frame */,
232                 separateEos);
233         testPushSameSize(
234                 1024 /* frame size in samples */,
235                 48000 /* sample rate */,
236                 1 /* channel count */,
237                 PCM_FLOAT,
238                 8192 /* input frame size in bytes = 2048 samples * 1 channel * 4 bytes/sample */,
239                 10 /* count */,
240                 81920 /* expected output size = 20 * 4096 bytes/frame */,
241                 separateEos);
242     }
243 }
244 
245 // Push frames with a little bit larger (+5 samples) than the requested size.
TEST_F(FrameReassemblerTest,PushLittleLargerFrameSize)246 TEST_F(FrameReassemblerTest, PushLittleLargerFrameSize) {
247     ASSERT_EQ(OK, initStatus());
248     for (bool separateEos : {false, true}) {
249         testPushSameSize(
250                 1024 /* frame size in samples */,
251                 48000 /* sample rate */,
252                 1 /* channel count */,
253                 PCM_8,
254                 1029 /* input frame size in bytes = 1029 samples * 1 channel * 1 bytes/sample */,
255                 10 /* count */,
256                 11264 /* expected output size = 11 * 1024 bytes/frame */,
257                 separateEos);
258         testPushSameSize(
259                 1024 /* frame size in samples */,
260                 48000 /* sample rate */,
261                 1 /* channel count */,
262                 PCM_16,
263                 2058 /* input frame size in bytes = 1029 samples * 1 channel * 2 bytes/sample */,
264                 10 /* count */,
265                 22528 /* expected output size = 11 * 2048 bytes/frame */,
266                 separateEos);
267         testPushSameSize(
268                 1024 /* frame size in samples */,
269                 48000 /* sample rate */,
270                 1 /* channel count */,
271                 PCM_FLOAT,
272                 4116 /* input frame size in bytes = 1029 samples * 1 channel * 4 bytes/sample */,
273                 10 /* count */,
274                 45056 /* expected output size = 11 * 4096 bytes/frame */,
275                 separateEos);
276     }
277 }
278 
279 // Push frames with a little bit smaller (-5 samples) than the requested size.
TEST_F(FrameReassemblerTest,PushLittleSmallerFrameSize)280 TEST_F(FrameReassemblerTest, PushLittleSmallerFrameSize) {
281     ASSERT_EQ(OK, initStatus());
282     for (bool separateEos : {false, true}) {
283         testPushSameSize(
284                 1024 /* frame size in samples */,
285                 48000 /* sample rate */,
286                 1 /* channel count */,
287                 PCM_8,
288                 1019 /* input frame size in bytes = 1019 samples * 1 channel * 1 bytes/sample */,
289                 10 /* count */,
290                 10240 /* expected output size = 10 * 1024 bytes/frame */,
291                 separateEos);
292         testPushSameSize(
293                 1024 /* frame size in samples */,
294                 48000 /* sample rate */,
295                 1 /* channel count */,
296                 PCM_16,
297                 2038 /* input frame size in bytes = 1019 samples * 1 channel * 2 bytes/sample */,
298                 10 /* count */,
299                 20480 /* expected output size = 10 * 2048 bytes/frame */,
300                 separateEos);
301         testPushSameSize(
302                 1024 /* frame size in samples */,
303                 48000 /* sample rate */,
304                 1 /* channel count */,
305                 PCM_FLOAT,
306                 4076 /* input frame size in bytes = 1019 samples * 1 channel * 4 bytes/sample */,
307                 10 /* count */,
308                 40960 /* expected output size = 10 * 4096 bytes/frame */,
309                 separateEos);
310     }
311 }
312 
313 // Push single-byte frames
TEST_F(FrameReassemblerTest,PushSingleByte)314 TEST_F(FrameReassemblerTest, PushSingleByte) {
315     ASSERT_EQ(OK, initStatus());
316     for (bool separateEos : {false, true}) {
317         testPushSameSize(
318                 1024 /* frame size in samples */,
319                 48000 /* sample rate */,
320                 1 /* channel count */,
321                 PCM_8,
322                 1 /* input frame size in bytes */,
323                 100000 /* count */,
324                 100352 /* expected output size = 98 * 1024 bytes/frame */,
325                 separateEos);
326         testPushSameSize(
327                 1024 /* frame size in samples */,
328                 48000 /* sample rate */,
329                 1 /* channel count */,
330                 PCM_16,
331                 1 /* input frame size in bytes */,
332                 100000 /* count */,
333                 100352 /* expected output size = 49 * 2048 bytes/frame */,
334                 separateEos);
335         testPushSameSize(
336                 1024 /* frame size in samples */,
337                 48000 /* sample rate */,
338                 1 /* channel count */,
339                 PCM_FLOAT,
340                 1 /* input frame size in bytes */,
341                 100000 /* count */,
342                 102400 /* expected output size = 25 * 4096 bytes/frame */,
343                 separateEos);
344     }
345 }
346 
347 // Push one big chunk.
TEST_F(FrameReassemblerTest,PushBigChunk)348 TEST_F(FrameReassemblerTest, PushBigChunk) {
349     ASSERT_EQ(OK, initStatus());
350     for (bool separateEos : {false, true}) {
351         testPushSameSize(
352                 1024 /* frame size in samples */,
353                 48000 /* sample rate */,
354                 1 /* channel count */,
355                 PCM_8,
356                 100000 /* input frame size in bytes */,
357                 1 /* count */,
358                 100352 /* expected output size = 98 * 1024 bytes/frame */,
359                 separateEos);
360         testPushSameSize(
361                 1024 /* frame size in samples */,
362                 48000 /* sample rate */,
363                 1 /* channel count */,
364                 PCM_16,
365                 100000 /* input frame size in bytes */,
366                 1 /* count */,
367                 100352 /* expected output size = 49 * 2048 bytes/frame */,
368                 separateEos);
369         testPushSameSize(
370                 1024 /* frame size in samples */,
371                 48000 /* sample rate */,
372                 1 /* channel count */,
373                 PCM_FLOAT,
374                 100000 /* input frame size in bytes */,
375                 1 /* count */,
376                 102400 /* expected output size = 25 * 4096 bytes/frame */,
377                 separateEos);
378     }
379 }
380 
381 } // namespace android
382