• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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