• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 //#define LOG_NDEBUG 0
6 #define LOG_TAG "C2VDACompIntf_test"
7 
8 #include <C2VDAAllocatorStore.h>
9 #include <C2VDAComponent.h>
10 
11 #include <C2PlatformSupport.h>
12 
13 #include <gtest/gtest.h>
14 #include <utils/Log.h>
15 
16 #include <inttypes.h>
17 #include <stdio.h>
18 #include <limits>
19 
20 #define UNUSED(expr)  \
21     do {              \
22         (void)(expr); \
23     } while (0)
24 
25 namespace android {
26 
27 const C2String testCompName = "c2.vda.avc.decoder";
28 const c2_node_id_t testCompNodeId = 12345;
29 
30 const char* MEDIA_MIMETYPE_VIDEO_RAW = "video/raw";
31 const char* MEDIA_MIMETYPE_VIDEO_AVC = "video/avc";
32 
33 const C2Allocator::id_t kInputAllocators[] = {C2PlatformAllocatorStore::ION};
34 const C2Allocator::id_t kOutputAllocators[] = {C2VDAAllocatorStore::V4L2_BUFFERQUEUE};
35 const C2BlockPool::local_id_t kDefaultOutputBlockPool = C2BlockPool::BASIC_GRAPHIC;
36 
37 class C2VDACompIntfTest : public ::testing::Test {
38 protected:
C2VDACompIntfTest()39     C2VDACompIntfTest() {
40         mReflector = std::make_shared<C2ReflectorHelper>();
41         mIntf = std::shared_ptr<C2ComponentInterface>(new SimpleInterface<C2VDAComponent::IntfImpl>(
42                 testCompName.c_str(), testCompNodeId,
43                 std::make_shared<C2VDAComponent::IntfImpl>(testCompName, mReflector)));
44     }
~C2VDACompIntfTest()45     ~C2VDACompIntfTest() override {}
46 
47     template <typename T>
48     void testReadOnlyParam(const T* expected, T* invalid);
49 
50     template <typename T>
51     void checkReadOnlyFailureOnConfig(T* param);
52 
53     template <typename T>
54     void testReadOnlyParamOnStack(const T* expected, T* invalid);
55 
56     template <typename T>
57     void testReadOnlyParamOnHeap(const T* expected, T* invalid);
58 
59     template <typename T>
60     void testWritableParam(T* newParam);
61 
62     template <typename T>
63     void testInvalidWritableParam(T* invalidParam);
64 
65     template <typename T>
66     void testWritableVideoSizeParam(int32_t widthMin, int32_t widthMax, int32_t widthStep,
67                                     int32_t heightMin, int32_t heightMax, int32_t heightStep);
68 
69     std::shared_ptr<C2ComponentInterface> mIntf;
70     std::shared_ptr<C2ReflectorHelper> mReflector;
71 };
72 
73 template <typename T>
testReadOnlyParam(const T * expected,T * invalid)74 void C2VDACompIntfTest::testReadOnlyParam(const T* expected, T* invalid) {
75     testReadOnlyParamOnStack(expected, invalid);
76     testReadOnlyParamOnHeap(expected, invalid);
77 }
78 
79 template <typename T>
checkReadOnlyFailureOnConfig(T * param)80 void C2VDACompIntfTest::checkReadOnlyFailureOnConfig(T* param) {
81     std::vector<C2Param*> params{param};
82     std::vector<std::unique_ptr<C2SettingResult>> failures;
83 
84     // TODO: do not assert on checking return value since it is not consistent for
85     //       C2InterfaceHelper now. (b/79720928)
86     //   1) if config same value, it returns C2_OK
87     //   2) if config different value, it returns C2_CORRUPTED. But when you config again, it
88     //      returns C2_OK
89     //ASSERT_EQ(C2_BAD_VALUE, mIntf->config_vb(params, C2_DONT_BLOCK, &failures));
90     mIntf->config_vb(params, C2_DONT_BLOCK, &failures);
91 
92     // TODO: failure is not yet supported for C2InterfaceHelper
93     //ASSERT_EQ(1u, failures.size());
94     //EXPECT_EQ(C2SettingResult::READ_ONLY, failures[0]->failure);
95 }
96 
97 template <typename T>
testReadOnlyParamOnStack(const T * expected,T * invalid)98 void C2VDACompIntfTest::testReadOnlyParamOnStack(const T* expected, T* invalid) {
99     T param;
100     std::vector<C2Param*> stackParams{&param};
101     ASSERT_EQ(C2_OK, mIntf->query_vb(stackParams, {}, C2_DONT_BLOCK, nullptr));
102     EXPECT_EQ(*expected, param);
103 
104     checkReadOnlyFailureOnConfig(&param);
105     checkReadOnlyFailureOnConfig(invalid);
106 
107     // The param must not change after failed config.
108     ASSERT_EQ(C2_OK, mIntf->query_vb(stackParams, {}, C2_DONT_BLOCK, nullptr));
109     EXPECT_EQ(*expected, param);
110 }
111 
112 template <typename T>
testReadOnlyParamOnHeap(const T * expected,T * invalid)113 void C2VDACompIntfTest::testReadOnlyParamOnHeap(const T* expected, T* invalid) {
114     std::vector<std::unique_ptr<C2Param>> heapParams;
115 
116     uint32_t index = expected->index();
117 
118     ASSERT_EQ(C2_OK, mIntf->query_vb({}, {index}, C2_DONT_BLOCK, &heapParams));
119     ASSERT_EQ(1u, heapParams.size());
120     EXPECT_EQ(*expected, *heapParams[0]);
121 
122     checkReadOnlyFailureOnConfig(heapParams[0].get());
123     checkReadOnlyFailureOnConfig(invalid);
124 
125     // The param must not change after failed config.
126     heapParams.clear();
127     ASSERT_EQ(C2_OK, mIntf->query_vb({}, {index}, C2_DONT_BLOCK, &heapParams));
128     ASSERT_EQ(1u, heapParams.size());
129     EXPECT_EQ(*expected, *heapParams[0]);
130 }
131 
132 template <typename T>
testWritableParam(T * newParam)133 void C2VDACompIntfTest::testWritableParam(T* newParam) {
134     std::vector<C2Param*> params{newParam};
135     std::vector<std::unique_ptr<C2SettingResult>> failures;
136     ASSERT_EQ(C2_OK, mIntf->config_vb(params, C2_DONT_BLOCK, &failures));
137     EXPECT_EQ(0u, failures.size());
138 
139     // The param must change to newParam
140     // Check like param on stack
141     T param;
142     std::vector<C2Param*> stackParams{&param};
143     ASSERT_EQ(C2_OK, mIntf->query_vb(stackParams, {}, C2_DONT_BLOCK, nullptr));
144     EXPECT_EQ(*newParam, param);
145 
146     // Check also like param on heap
147     std::vector<std::unique_ptr<C2Param>> heapParams;
148     ASSERT_EQ(C2_OK, mIntf->query_vb({}, {newParam->index()}, C2_DONT_BLOCK, &heapParams));
149     ASSERT_EQ(1u, heapParams.size());
150     EXPECT_EQ(*newParam, *heapParams[0]);
151 }
152 
153 template <typename T>
testInvalidWritableParam(T * invalidParam)154 void C2VDACompIntfTest::testInvalidWritableParam(T* invalidParam) {
155     // Get the current parameter info
156     T preParam;
157     std::vector<C2Param*> stackParams{&preParam};
158     ASSERT_EQ(C2_OK, mIntf->query_vb(stackParams, {}, C2_DONT_BLOCK, nullptr));
159 
160     // Config invalid value. The failure is expected
161     std::vector<C2Param*> params{invalidParam};
162     std::vector<std::unique_ptr<C2SettingResult>> failures;
163     ASSERT_EQ(C2_BAD_VALUE, mIntf->config_vb(params, C2_DONT_BLOCK, &failures));
164     EXPECT_EQ(1u, failures.size());
165 
166     //The param must not change after config failed
167     T param;
168     std::vector<C2Param*> stackParams2{&param};
169     ASSERT_EQ(C2_OK, mIntf->query_vb(stackParams2, {}, C2_DONT_BLOCK, nullptr));
170     EXPECT_EQ(preParam, param);
171 
172     // Check also like param on heap
173     std::vector<std::unique_ptr<C2Param>> heapParams;
174     ASSERT_EQ(C2_OK, mIntf->query_vb({}, {invalidParam->index()}, C2_DONT_BLOCK, &heapParams));
175     ASSERT_EQ(1u, heapParams.size());
176     EXPECT_EQ(preParam, *heapParams[0]);
177 }
178 
isUnderflowSubstract(int32_t a,int32_t b)179 bool isUnderflowSubstract(int32_t a, int32_t b) {
180     return a < 0 && b > a - std::numeric_limits<int32_t>::min();
181 }
182 
isOverflowAdd(int32_t a,int32_t b)183 bool isOverflowAdd(int32_t a, int32_t b) {
184     return a > 0 && b > std::numeric_limits<int32_t>::max() - a;
185 }
186 
187 template <typename T>
testWritableVideoSizeParam(int32_t widthMin,int32_t widthMax,int32_t widthStep,int32_t heightMin,int32_t heightMax,int32_t heightStep)188 void C2VDACompIntfTest::testWritableVideoSizeParam(int32_t widthMin, int32_t widthMax,
189                                                    int32_t widthStep, int32_t heightMin,
190                                                    int32_t heightMax, int32_t heightStep) {
191     // Test supported values of video size
192     T valid;
193     for (int32_t h = heightMin; h <= heightMax; h += heightStep) {
194         for (int32_t w = widthMin; w <= widthMax; w += widthStep) {
195             valid.width = w;
196             valid.height = h;
197             {
198                 SCOPED_TRACE("testWritableParam");
199                 testWritableParam(&valid);
200                 if (HasFailure()) {
201                     printf("Failed while config width = %d, height = %d\n", valid.width,
202                            valid.height);
203                 }
204                 if (HasFatalFailure()) return;
205             }
206         }
207     }
208 
209     // TODO: validate possible values in C2InterfaceHelper is not implemented yet.
210     //// Test invalid values video size
211     //T invalid;
212     //// Width or height is smaller than min values
213     //if (!isUnderflowSubstract(widthMin, widthStep)) {
214     //    invalid.width = widthMin - widthStep;
215     //    invalid.height = heightMin;
216     //    testInvalidWritableParam(&invalid);
217     //}
218     //if (!isUnderflowSubstract(heightMin, heightStep)) {
219     //    invalid.width = widthMin;
220     //    invalid.height = heightMin - heightStep;
221     //    testInvalidWritableParam(&invalid);
222     //}
223 
224     //// Width or height is bigger than max values
225     //if (!isOverflowAdd(widthMax, widthStep)) {
226     //    invalid.width = widthMax + widthStep;
227     //    invalid.height = heightMax;
228     //    testInvalidWritableParam(&invalid);
229     //}
230     //if (!isOverflowAdd(heightMax, heightStep)) {
231     //    invalid.width = widthMax;
232     //    invalid.height = heightMax + heightStep;
233     //    testInvalidWritableParam(&invalid);
234     //}
235 
236     //// Invalid width/height within the range
237     //if (widthStep != 1) {
238     //    invalid.width = widthMin + 1;
239     //    invalid.height = heightMin;
240     //    testInvalidWritableParam(&invalid);
241     //}
242     //if (heightStep != 1) {
243     //    invalid.width = widthMin;
244     //    invalid.height = heightMin + 1;
245     //    testInvalidWritableParam(&invalid);
246     //}
247 }
248 
249 #define TRACED_FAILURE(func)                            \
250     do {                                                \
251         SCOPED_TRACE(#func);                            \
252         func;                                           \
253         if (::testing::Test::HasFatalFailure()) return; \
254     } while (false)
255 
TEST_F(C2VDACompIntfTest,CreateInstance)256 TEST_F(C2VDACompIntfTest, CreateInstance) {
257     auto name = mIntf->getName();
258     auto id = mIntf->getId();
259     printf("name = %s\n", name.c_str());
260     printf("node_id = %u\n", id);
261     EXPECT_STREQ(name.c_str(), testCompName.c_str());
262     EXPECT_EQ(id, testCompNodeId);
263 }
264 
TEST_F(C2VDACompIntfTest,TestInputFormat)265 TEST_F(C2VDACompIntfTest, TestInputFormat) {
266     C2StreamBufferTypeSetting::input expected(0u, C2FormatCompressed);
267     expected.setStream(0);  // only support single stream
268     C2StreamBufferTypeSetting::input invalid(0u, C2FormatVideo);
269     invalid.setStream(0);  // only support single stream
270     TRACED_FAILURE(testReadOnlyParam(&expected, &invalid));
271 }
272 
TEST_F(C2VDACompIntfTest,TestOutputFormat)273 TEST_F(C2VDACompIntfTest, TestOutputFormat) {
274     C2StreamBufferTypeSetting::output expected(0u, C2FormatVideo);
275     expected.setStream(0);  // only support single stream
276     C2StreamBufferTypeSetting::output invalid(0u, C2FormatCompressed);
277     invalid.setStream(0);  // only support single stream
278     TRACED_FAILURE(testReadOnlyParam(&expected, &invalid));
279 }
280 
TEST_F(C2VDACompIntfTest,TestInputPortMime)281 TEST_F(C2VDACompIntfTest, TestInputPortMime) {
282     std::shared_ptr<C2PortMediaTypeSetting::input> expected(
283             AllocSharedString<C2PortMediaTypeSetting::input>(MEDIA_MIMETYPE_VIDEO_AVC));
284     std::shared_ptr<C2PortMediaTypeSetting::input> invalid(
285             AllocSharedString<C2PortMediaTypeSetting::input>(MEDIA_MIMETYPE_VIDEO_RAW));
286     TRACED_FAILURE(testReadOnlyParamOnHeap(expected.get(), invalid.get()));
287 }
288 
TEST_F(C2VDACompIntfTest,TestOutputPortMime)289 TEST_F(C2VDACompIntfTest, TestOutputPortMime) {
290     std::shared_ptr<C2PortMediaTypeSetting::output> expected(
291             AllocSharedString<C2PortMediaTypeSetting::output>(MEDIA_MIMETYPE_VIDEO_RAW));
292     std::shared_ptr<C2PortMediaTypeSetting::output> invalid(
293             AllocSharedString<C2PortMediaTypeSetting::output>(MEDIA_MIMETYPE_VIDEO_AVC));
294     TRACED_FAILURE(testReadOnlyParamOnHeap(expected.get(), invalid.get()));
295 }
296 
TEST_F(C2VDACompIntfTest,TestVideoSize)297 TEST_F(C2VDACompIntfTest, TestVideoSize) {
298     C2StreamPictureSizeInfo::output videoSize;
299     videoSize.setStream(0);  // only support single stream
300     std::vector<C2FieldSupportedValuesQuery> widthC2FSV = {
301             {C2ParamField(&videoSize, &C2StreamPictureSizeInfo::width),
302              C2FieldSupportedValuesQuery::CURRENT},
303     };
304     ASSERT_EQ(C2_OK, mIntf->querySupportedValues_vb(widthC2FSV, C2_DONT_BLOCK));
305     std::vector<C2FieldSupportedValuesQuery> heightC2FSV = {
306             {C2ParamField(&videoSize, &C2StreamPictureSizeInfo::height),
307              C2FieldSupportedValuesQuery::CURRENT},
308     };
309     ASSERT_EQ(C2_OK, mIntf->querySupportedValues_vb(heightC2FSV, C2_DONT_BLOCK));
310     ASSERT_EQ(1u, widthC2FSV.size());
311     ASSERT_EQ(C2_OK, widthC2FSV[0].status);
312     ASSERT_EQ(C2FieldSupportedValues::RANGE, widthC2FSV[0].values.type);
313     auto& widthFSVRange = widthC2FSV[0].values.range;
314     int32_t widthMin = widthFSVRange.min.i32;
315     int32_t widthMax = widthFSVRange.max.i32;
316     int32_t widthStep = widthFSVRange.step.i32;
317 
318     ASSERT_EQ(1u, heightC2FSV.size());
319     ASSERT_EQ(C2_OK, heightC2FSV[0].status);
320     ASSERT_EQ(C2FieldSupportedValues::RANGE, heightC2FSV[0].values.type);
321     auto& heightFSVRange = heightC2FSV[0].values.range;
322     int32_t heightMin = heightFSVRange.min.i32;
323     int32_t heightMax = heightFSVRange.max.i32;
324     int32_t heightStep = heightFSVRange.step.i32;
325 
326     // test updating valid and invalid values
327     TRACED_FAILURE(testWritableVideoSizeParam<C2StreamPictureSizeInfo::output>(
328             widthMin, widthMax, widthStep, heightMin, heightMax, heightStep));
329 }
330 
TEST_F(C2VDACompIntfTest,TestInputAllocatorIds)331 TEST_F(C2VDACompIntfTest, TestInputAllocatorIds) {
332     std::shared_ptr<C2PortAllocatorsTuning::input> expected(
333             C2PortAllocatorsTuning::input::AllocShared(kInputAllocators));
334     std::shared_ptr<C2PortAllocatorsTuning::input> invalid(
335             C2PortAllocatorsTuning::input::AllocShared(kOutputAllocators));
336     TRACED_FAILURE(testReadOnlyParamOnHeap(expected.get(), invalid.get()));
337 }
338 
TEST_F(C2VDACompIntfTest,TestOutputAllocatorIds)339 TEST_F(C2VDACompIntfTest, TestOutputAllocatorIds) {
340     std::shared_ptr<C2PortAllocatorsTuning::output> expected(
341             C2PortAllocatorsTuning::output::AllocShared(kOutputAllocators));
342     std::shared_ptr<C2PortAllocatorsTuning::output> invalid(
343             C2PortAllocatorsTuning::output::AllocShared(kInputAllocators));
344     TRACED_FAILURE(testReadOnlyParamOnHeap(expected.get(), invalid.get()));
345 }
346 
TEST_F(C2VDACompIntfTest,TestOutputBlockPoolIds)347 TEST_F(C2VDACompIntfTest, TestOutputBlockPoolIds) {
348     std::vector<std::unique_ptr<C2Param>> heapParams;
349     C2Param::Index index = C2PortBlockPoolsTuning::output::PARAM_TYPE;
350 
351     // Query the param and check the default value.
352     ASSERT_EQ(C2_OK, mIntf->query_vb({}, {index}, C2_DONT_BLOCK, &heapParams));
353     ASSERT_EQ(1u, heapParams.size());
354     C2BlockPool::local_id_t value = ((C2PortBlockPoolsTuning*)heapParams[0].get())->m.values[0];
355     ASSERT_EQ(kDefaultOutputBlockPool, value);
356 
357     // Configure the param.
358     C2BlockPool::local_id_t configBlockPools[] = {C2BlockPool::PLATFORM_START + 1};
359     std::shared_ptr<C2PortBlockPoolsTuning::output> newParam(
360             C2PortBlockPoolsTuning::output::AllocShared(configBlockPools));
361 
362     std::vector<C2Param*> params{newParam.get()};
363     std::vector<std::unique_ptr<C2SettingResult>> failures;
364     ASSERT_EQ(C2_OK, mIntf->config_vb(params, C2_DONT_BLOCK, &failures));
365     EXPECT_EQ(0u, failures.size());
366 
367     // Query the param again and check the value is as configured
368     heapParams.clear();
369     ASSERT_EQ(C2_OK, mIntf->query_vb({}, {index}, C2_DONT_BLOCK, &heapParams));
370     ASSERT_EQ(1u, heapParams.size());
371     value = ((C2PortBlockPoolsTuning*)heapParams[0].get())->m.values[0];
372     ASSERT_EQ(configBlockPools[0], value);
373 }
374 
TEST_F(C2VDACompIntfTest,TestUnsupportedParam)375 TEST_F(C2VDACompIntfTest, TestUnsupportedParam) {
376     C2ComponentTemporalInfo unsupportedParam;
377     std::vector<C2Param*> stackParams{&unsupportedParam};
378     ASSERT_EQ(C2_BAD_INDEX, mIntf->query_vb(stackParams, {}, C2_DONT_BLOCK, nullptr));
379     EXPECT_EQ(0u, unsupportedParam.size());  // invalidated
380 }
381 
dumpType(const C2FieldDescriptor::type_t type)382 void dumpType(const C2FieldDescriptor::type_t type) {
383     switch (type) {
384     case C2FieldDescriptor::INT32:
385         printf("int32_t");
386         break;
387     case C2FieldDescriptor::UINT32:
388         printf("uint32_t");
389         break;
390     case C2FieldDescriptor::INT64:
391         printf("int64_t");
392         break;
393     case C2FieldDescriptor::UINT64:
394         printf("uint64_t");
395         break;
396     case C2FieldDescriptor::FLOAT:
397         printf("float");
398         break;
399     default:
400         printf("<flex>");
401         break;
402     }
403 }
404 
dumpStruct(const C2StructDescriptor & sd)405 void dumpStruct(const C2StructDescriptor& sd) {
406     printf("  struct: { ");
407     for (const C2FieldDescriptor& f : sd) {
408         printf("%s:", f.name().c_str());
409         dumpType(f.type());
410         printf(", ");
411     }
412     printf("}\n");
413 }
414 
TEST_F(C2VDACompIntfTest,ParamReflector)415 TEST_F(C2VDACompIntfTest, ParamReflector) {
416     std::vector<std::shared_ptr<C2ParamDescriptor>> params;
417 
418     ASSERT_EQ(mIntf->querySupportedParams_nb(&params), C2_OK);
419     for (const auto& paramDesc : params) {
420         printf("name: %s\n", paramDesc->name().c_str());
421         printf("  required: %s\n", paramDesc->isRequired() ? "yes" : "no");
422         printf("  type: %x\n", paramDesc->index().type());
423         std::unique_ptr<C2StructDescriptor> desc{mReflector->describe(paramDesc->index().type())};
424         if (desc.get()) dumpStruct(*desc);
425     }
426 }
427 }  // namespace android
428