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