From be7fd2fa4a152b8c6a3d03512d27595321e1e2f2 Mon Sep 17 00:00:00 2001 From: zhangguorong Date: Sun, 8 May 2022 22:06:35 +0800 Subject: [PATCH] feat: add hdi 1.0 demo and unittest Signed-off-by: zhangguorong --- .../codec_test/unittest/codec_proxy_test.cpp | 352 --------- codec/test/BUILD.gn | 12 +- codec/test/demo/v1.0/BUILD.gn | 131 ++++ codec/test/demo/v1.0/codec_decode_test_ipc.c | 575 ++++++++++++++ codec/test/demo/v1.0/codec_encode_test_ipc.c | 725 ++++++++++++++++++ codec/test/demo/v1.0/codec_utils.c | 133 ++++ codec/test/demo/v1.0/codec_utils.h | 37 + codec/test/unittest/BUILD.gn | 5 +- .../unittest/hdi_v1.0}/BUILD.gn | 29 +- .../unittest/hdi_v1.0/codec_proxy_test.cpp | 282 +++++++ 10 files changed, 1913 insertions(+), 368 deletions(-) delete mode 100644 codec/hdi_service/codec_test/unittest/codec_proxy_test.cpp create mode 100644 codec/test/demo/v1.0/BUILD.gn create mode 100644 codec/test/demo/v1.0/codec_decode_test_ipc.c create mode 100644 codec/test/demo/v1.0/codec_encode_test_ipc.c create mode 100644 codec/test/demo/v1.0/codec_utils.c create mode 100644 codec/test/demo/v1.0/codec_utils.h rename codec/{hdi_service/codec_test => test/unittest/hdi_v1.0}/BUILD.gn (61%) create mode 100644 codec/test/unittest/hdi_v1.0/codec_proxy_test.cpp diff --git a/codec/hdi_service/codec_test/unittest/codec_proxy_test.cpp b/codec/hdi_service/codec_test/unittest/codec_proxy_test.cpp deleted file mode 100644 index 112a159582..0000000000 --- a/codec/hdi_service/codec_test/unittest/codec_proxy_test.cpp +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "icodec.h" -#include -#include -#include -#include "codec_callback_stub.h" - -using namespace std; -using namespace testing::ext; - -namespace { -constexpr const char *TEST_SERVICE_NAME = "codec_hdi_service"; -ICodecCallback *g_callback = nullptr; - -class CodecObjCTest : public testing::Test { -public: - static void SetUpTestCase(){} - static void TearDownTestCase(){} - void SetUp(){} - void TearDown(){} -}; - -HWTEST_F(CodecObjCTest, CodecObjCTest_001, TestSize.Level0) -{ - struct ICodec *codecObj = HdiCodecGet(TEST_SERVICE_NAME); - ASSERT_TRUE(codecObj != nullptr); - - int32_t ec = codecObj->CodecInit(codecObj); - - ASSERT_EQ(ec, HDF_SUCCESS); - - HdiCodecRelease(codecObj); -} - -HWTEST_F(CodecObjCTest, CodecObjCTest_002, TestSize.Level0) -{ - struct ICodec *codecObj = HdiCodecGet(TEST_SERVICE_NAME); - ASSERT_TRUE(codecObj != nullptr); - - int32_t ec = codecObj->CodecDeinit(codecObj); - - ASSERT_EQ(ec, HDF_SUCCESS); - - HdiCodecRelease(codecObj); -} - -HWTEST_F(CodecObjCTest, CodecObjCTest_003, TestSize.Level0) -{ - struct ICodec *codecObj = HdiCodecGet(TEST_SERVICE_NAME); - ASSERT_TRUE(codecObj != nullptr); - - uint32_t index = 2; - CodecCapbility cap; - - int32_t ec = codecObj->CodecEnumerateCapbility(codecObj, index, &cap); - - ASSERT_EQ(ec, HDF_SUCCESS); - - HdiCodecRelease(codecObj); -} - -HWTEST_F(CodecObjCTest, CodecObjCTest_004, TestSize.Level0) -{ - struct ICodec *codecObj = HdiCodecGet(TEST_SERVICE_NAME); - ASSERT_TRUE(codecObj != nullptr); - - uint32_t flags = 1; - AvCodecMime mime = MEDIA_MIMETYPE_VIDEO_AVC; - CodecType type = AUDIO_DECODER; - CodecCapbility cap; - - int32_t ec = codecObj->CodecGetCapbility(codecObj, mime, type, flags, &cap); - - ASSERT_EQ(ec, HDF_SUCCESS); - ASSERT_EQ(cap.mime, MEDIA_MIMETYPE_VIDEO_AVC); - ASSERT_EQ(cap.type, AUDIO_DECODER); - ASSERT_EQ(cap.whAlignment.widthAlignment, 10); - ASSERT_EQ(cap.supportLevels.actualLen, 3); - - HdiCodecRelease(codecObj); -} - -HWTEST_F(CodecObjCTest, CodecObjCTest_005, TestSize.Level0) -{ - struct ICodec *codecObj = HdiCodecGet(TEST_SERVICE_NAME); - ASSERT_TRUE(codecObj != nullptr); - int num = 10; - const char* name = "codec.avc.hardware.decoder"; - Param params; - params.key = KEY_CODEC_TYPE; - params.val = (void *)# - params.size = 20; - int len = 3; - uint32_t handle = 5; - - int32_t ec = codecObj->CodecCreate(codecObj, name, ¶ms, len, (CODEC_HANDLETYPE *)&handle); - - ASSERT_EQ(ec, HDF_SUCCESS); - ASSERT_EQ(params.key, KEY_CODEC_TYPE); - ASSERT_EQ(params.size, 20); - ASSERT_EQ(len, 3); - - HdiCodecRelease(codecObj); -} - -HWTEST_F(CodecObjCTest, CodecObjCTest_006, TestSize.Level0) -{ - struct ICodec *codecObj = HdiCodecGet(TEST_SERVICE_NAME); - ASSERT_TRUE(codecObj != nullptr); - - uint32_t handle = 5; - - int32_t ec = codecObj->CodecDestroy(codecObj, (CODEC_HANDLETYPE *)&handle); - - ASSERT_EQ(ec, HDF_SUCCESS); - - HdiCodecRelease(codecObj); -} - -HWTEST_F(CodecObjCTest, CodecObjCTest_007, TestSize.Level0) -{ - struct ICodec *codecObj = HdiCodecGet(TEST_SERVICE_NAME); - ASSERT_TRUE(codecObj != nullptr); - - uint32_t handle = 5; - DirectionType type = OUTPUT_TYPE; - BufferMode mode = EXTERNAL; - - int32_t ec = codecObj->CodecSetPortMode(codecObj, (CODEC_HANDLETYPE *)&handle, type, mode); - - ASSERT_EQ(ec, HDF_SUCCESS); - ASSERT_EQ(type, OUTPUT_TYPE); - ASSERT_EQ(mode, EXTERNAL); - - HdiCodecRelease(codecObj); -} - -HWTEST_F(CodecObjCTest, CodecObjCTest_008, TestSize.Level0) -{ - struct ICodec *codecObj = HdiCodecGet(TEST_SERVICE_NAME); - ASSERT_TRUE(codecObj != nullptr); - - uint32_t handle = 5; - Param params; - params.key = KEY_CODEC_TYPE; - params.val = 0; - params.size = 20; - - int paramCnt = 3; - - int32_t ec = codecObj->CodecSetParameter(codecObj, (CODEC_HANDLETYPE *)&handle, ¶ms, paramCnt); - - ASSERT_EQ(ec, HDF_SUCCESS); - ASSERT_EQ(params.key, KEY_CODEC_TYPE); - ASSERT_EQ(params.size, 20); - ASSERT_EQ(paramCnt, 3); - - HdiCodecRelease(codecObj); -} - -HWTEST_F(CodecObjCTest, CodecObjCTest_009, TestSize.Level0) -{ - struct ICodec *codecObj = HdiCodecGet(TEST_SERVICE_NAME); - ASSERT_TRUE(codecObj != nullptr); - - uint32_t handle = 5; - int paramCnt = 3; - Param *params; - params = (Param *)OsalMemAlloc(sizeof(Param)*paramCnt); - ASSERT_TRUE(params != nullptr); - params->key = KEY_CODEC_TYPE; - params->val = 0; - params->size = 20; - - int32_t ec = codecObj->CodecGetParameter(codecObj, (CODEC_HANDLETYPE *)&handle, params, paramCnt); - - ASSERT_EQ(ec, HDF_SUCCESS); - OsalMemFree(params); - HdiCodecRelease(codecObj); -} - -HWTEST_F(CodecObjCTest, CodecObjCTest_010, TestSize.Level0) -{ - struct ICodec *codecObj = HdiCodecGet(TEST_SERVICE_NAME); - ASSERT_TRUE(codecObj != nullptr); - - uint32_t handle = 5; - - int32_t ec = codecObj->CodecStart(codecObj, (CODEC_HANDLETYPE *)&handle); - - ASSERT_EQ(ec, HDF_SUCCESS); - - HdiCodecRelease(codecObj); -} - -HWTEST_F(CodecObjCTest, CodecObjCTest_011, TestSize.Level0) -{ - struct ICodec *codecObj = HdiCodecGet(TEST_SERVICE_NAME); - ASSERT_TRUE(codecObj != nullptr); - - uint32_t handle = 5; - - int32_t ec = codecObj->CodecStop(codecObj, (CODEC_HANDLETYPE *)&handle); - - ASSERT_EQ(ec, HDF_SUCCESS); - - HdiCodecRelease(codecObj); -} - -HWTEST_F(CodecObjCTest, CodecObjCTest_012, TestSize.Level0) -{ - struct ICodec *codecObj = HdiCodecGet(TEST_SERVICE_NAME); - ASSERT_TRUE(codecObj != nullptr); - - uint32_t handle = 5; - DirectionType directType = OUTPUT_TYPE; - - int32_t ec = codecObj->CodecFlush(codecObj, (CODEC_HANDLETYPE *)&handle, directType); - - ASSERT_EQ(ec, HDF_SUCCESS); - ASSERT_EQ(directType, OUTPUT_TYPE); - - HdiCodecRelease(codecObj); -} - -HWTEST_F(CodecObjCTest, CodecObjCTest_013, TestSize.Level0) -{ - struct ICodec *codecObj = HdiCodecGet(TEST_SERVICE_NAME); - ASSERT_TRUE(codecObj != nullptr); - - uint32_t handle = 5; - InputInfo inputData = {0}; - inputData.bufferCnt = 1; - inputData.buffers = (CodecBufferInfo *)OsalMemAlloc(sizeof(CodecBufferInfo) * inputData.bufferCnt); - inputData.buffers->type = BUFFER_TYPE_FD; - inputData.buffers->fd = 2; - inputData.buffers->offset = 3; - inputData.buffers->length = 4; - inputData.buffers->size = 5; - inputData.pts = 0; - inputData.flag = STREAM_FLAG_CODEC_SPECIFIC_INF; - uint32_t timeoutMs = 10; - - int32_t ec = codecObj->CodecQueueInput(codecObj, (CODEC_HANDLETYPE *)&handle, &inputData, timeoutMs); - ASSERT_EQ(ec, HDF_SUCCESS); - ASSERT_EQ(inputData.pts, 0); - ASSERT_EQ(inputData.flag, STREAM_FLAG_CODEC_SPECIFIC_INF); - ASSERT_EQ(ec, HDF_SUCCESS); - OsalMemFree(inputData.buffers); - HdiCodecRelease(codecObj); -} - -HWTEST_F(CodecObjCTest, CodecObjCTest_014, TestSize.Level0) -{ - struct ICodec *codecObj = HdiCodecGet(TEST_SERVICE_NAME); - ASSERT_TRUE(codecObj != nullptr); - - uint32_t handle = 5; - uint32_t timeoutMs = 10; - InputInfo inputData = {0}; - inputData.bufferCnt = 1; - inputData.buffers = (CodecBufferInfo *)OsalMemAlloc(sizeof(CodecBufferInfo) * (inputData.bufferCnt)); - ASSERT_TRUE(inputData.buffers != nullptr); - int32_t ec = codecObj->CodecDequeInput(codecObj, (CODEC_HANDLETYPE *)&handle, timeoutMs, &inputData); - - ASSERT_EQ(ec, HDF_SUCCESS); - ASSERT_EQ((int)timeoutMs, 10); - OsalMemFree(inputData.buffers); - HdiCodecRelease(codecObj); -} - -HWTEST_F(CodecObjCTest, CodecObjCTest_015, TestSize.Level0) -{ - struct ICodec *codecObj = HdiCodecGet(TEST_SERVICE_NAME); - ASSERT_TRUE(codecObj != nullptr); - - uint32_t handle = 5; - OutputInfo outInfo = {0}; - outInfo.bufferCnt = 1; - outInfo.buffers = (CodecBufferInfo *)OsalMemAlloc(sizeof(CodecBufferInfo) * (outInfo.bufferCnt)); - outInfo.buffers->type = BUFFER_TYPE_FD; - outInfo.buffers->fd = 1; - outInfo.buffers->offset = 2; - outInfo.buffers->length = 3; - outInfo.buffers->size = 4; - outInfo.timeStamp = 0; - outInfo.sequence = 1; - outInfo.flag = STREAM_FLAG_CODEC_SPECIFIC_INF; - outInfo.type = AUDIO_DECODER; - outInfo.vendorPrivate = 0; - uint32_t timeoutMs = 10; - int releaseFenceFd = 3; - - int32_t ec = codecObj->CodecQueueOutput(codecObj, (CODEC_HANDLETYPE *)&handle, &outInfo, timeoutMs, releaseFenceFd); - - ASSERT_EQ(ec, HDF_SUCCESS); - ASSERT_EQ((int)timeoutMs, 10); - ASSERT_EQ(releaseFenceFd, 3); - OsalMemFree(outInfo.buffers); - HdiCodecRelease(codecObj); -} - -HWTEST_F(CodecObjCTest, CodecObjCTest_016, TestSize.Level0) -{ - struct ICodec *codecObj = HdiCodecGet(TEST_SERVICE_NAME); - ASSERT_TRUE(codecObj != nullptr); - - uint32_t handle = 5; - uint32_t timeoutMs = 10; - int acquireFd; - OutputInfo outInfo = {0}; - outInfo.bufferCnt = 1; - outInfo.buffers = (CodecBufferInfo *)OsalMemAlloc(sizeof(CodecBufferInfo) * (outInfo.bufferCnt)); - ASSERT_TRUE(outInfo.buffers != nullptr); - int32_t ec = codecObj->CodecDequeueOutput(codecObj, (CODEC_HANDLETYPE *)&handle, timeoutMs, &acquireFd, &outInfo); - - ASSERT_EQ(ec, HDF_SUCCESS); - ASSERT_EQ((int)timeoutMs, 10); - OsalMemFree(outInfo.buffers); - HdiCodecRelease(codecObj); -} - -HWTEST_F(CodecObjCTest, CodecObjCTest_017, TestSize.Level0) -{ - struct ICodec *codecObj = HdiCodecGet(TEST_SERVICE_NAME); - ASSERT_TRUE(codecObj != nullptr); - - uint32_t handle = 5; - UINTPTR instance = 0; - g_callback = CodecCallbackStubObtain(); - ASSERT_TRUE(g_callback != nullptr); - - int32_t ec = codecObj->CodecSetCallback(codecObj, (CODEC_HANDLETYPE *)&handle, g_callback, instance); - - ASSERT_EQ(ec, HDF_SUCCESS); - HdiCodecRelease(codecObj); -} -} \ No newline at end of file diff --git a/codec/test/BUILD.gn b/codec/test/BUILD.gn index 8b91aa3ef8..8688b6092d 100644 --- a/codec/test/BUILD.gn +++ b/codec/test/BUILD.gn @@ -13,9 +13,11 @@ group("hdf_test_media_codec") { testonly = true - deps = [ - "demo/v2.0:codec_hdi_omx_demo", - "unittest:hdf_unittest_codec", - "//drivers/peripheral/codec/test/fuzztest:hdf_fuzztest_media_codec", - ] + deps = [ "//drivers/peripheral/codec/test/fuzztest:hdf_fuzztest_media_codec" ] + if (product_name == "rk3568") { + deps += [ + "demo/v1.0:codec_hdi_demo", + "unittest:hdf_unittest_codec", + ] + } } diff --git a/codec/test/demo/v1.0/BUILD.gn b/codec/test/demo/v1.0/BUILD.gn new file mode 100644 index 0000000000..6e4a4ec082 --- /dev/null +++ b/codec/test/demo/v1.0/BUILD.gn @@ -0,0 +1,131 @@ +# Copyright (c) 2022 Shenzhen Kaihong DID Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//drivers/adapter/uhdf2/uhdf.gni") + +ohos_executable("codec_decode_test_ipc") { + sources = [ + "//drivers/peripheral/codec/hal/v1.0/share_mem/src/ashmem_wrapper.cpp", + "//drivers/peripheral/codec/hal/v1.0/share_mem/src/share_mem.c", + "//drivers/peripheral/codec/hdi_service/codec_service_stub/codec_callback_stub.c", + "codec_decode_test_ipc.c", + "codec_utils.c", + ] + + include_dirs = [ + "//device/soc/rockchip/hardware/codec/include", + "//device/soc/rockchip/hardware/mpp/include", + "//drivers/peripheral/codec/interfaces/include", + "//drivers/peripheral/codec/hal/v1.0/share_mem/include", + "//drivers/peripheral/codec/hdi_service/codec_proxy/", + "//drivers/peripheral/codec/hdi_service/codec_service_stub/", + ] + + cflags_c = [ + "-Wall", + "-Wextra", + "-Werror", + "-Wno-predefined-identifier-outside-function", + "-Wno-macro-redefined", + "-Wno-format", + "-Wno-unused-parameter", + "-Wno-unused-variable", + "-fsigned-char", + "-fno-common", + "-fno-strict-aliasing", + ] + + deps = [ + "//device/soc/rockchip/hardware/codec:codec_oem_interface", + "//device/soc/rockchip/hardware/mpp:mpp", + "//drivers/peripheral/codec/hdi_service:codec_client", + ] + + if (is_standard_system) { + external_deps = [ + "device_driver_framework:libhdf_host", + "device_driver_framework:libhdf_ipc_adapter", + "device_driver_framework:libhdf_utils", + "device_driver_framework:libhdi", + "hiviewdfx_hilog_native:libhilog", + "utils_base:utils", + ] + } else { + external_deps = [ "hilog:libhilog" ] + } + + subsystem_name = "hdf" + part_name = "codec_device_driver" +} + +ohos_executable("codec_encode_test_ipc") { + sources = [ + "//drivers/peripheral/codec/hal/v1.0/share_mem/src/ashmem_wrapper.cpp", + "//drivers/peripheral/codec/hal/v1.0/share_mem/src/share_mem.c", + "//drivers/peripheral/codec/hdi_service/codec_service_stub/codec_callback_stub.c", + "codec_encode_test_ipc.c", + "codec_utils.c", + ] + + include_dirs = [ + "//device/soc/rockchip/hardware/codec/include", + "//device/soc/rockchip/hardware/mpp/include", + "//drivers/peripheral/codec/interfaces/include", + "//drivers/peripheral/codec/hal/v1.0/share_mem/include", + "//drivers/peripheral/codec/hdi_service/codec_proxy/", + "//drivers/peripheral/codec/hdi_service/codec_service_stub/", + ] + + cflags_c = [ + "-Wall", + "-Wextra", + "-Werror", + "-Wno-predefined-identifier-outside-function", + "-Wno-macro-redefined", + "-Wno-format", + "-Wno-unused-parameter", + "-Wno-unused-variable", + "-fsigned-char", + "-fno-common", + "-fno-strict-aliasing", + ] + + deps = [ + "//device/soc/rockchip/hardware/codec:codec_oem_interface", + "//device/soc/rockchip/hardware/mpp:mpp", + "//drivers/peripheral/codec/hdi_service:codec_client", + ] + if (is_standard_system) { + external_deps = [ + "device_driver_framework:libhdf_host", + "device_driver_framework:libhdf_ipc_adapter", + "device_driver_framework:libhdf_utils", + "device_driver_framework:libhdi", + "hiviewdfx_hilog_native:libhilog", + "utils_base:utils", + ] + } else { + external_deps = [ "hilog:libhilog" ] + } + + subsystem_name = "hdf" + part_name = "codec_device_driver" +} + +group("codec_hdi_demo") { + deps = [ + ":codec_decode_test_ipc", + ":codec_encode_test_ipc", + ] +} diff --git a/codec/test/demo/v1.0/codec_decode_test_ipc.c b/codec/test/demo/v1.0/codec_decode_test_ipc.c new file mode 100644 index 0000000000..0c3a0430a1 --- /dev/null +++ b/codec/test/demo/v1.0/codec_decode_test_ipc.c @@ -0,0 +1,575 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong DID Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "codec_callback_stub.h" +#include "codec_utils.h" +#include "hdf_log.h" +#include "hdi_mpp.h" +#include "icodec.h" +#include "osal_mem.h" +#include "share_mem.h" + +#define HDF_LOG_TAG codec_hdi_demo_decode +#define TEST_SERVICE_NAME "codec_hdi_service" +#define STREAM_PACKET_BUFFER_NUM 4 +#define MEDIA_FRAME_BUFFER_NUM 10 +#define STREAM_PACKET_BUFFER_SIZE (4 * 1024) +#define QUEUE_TIME_OUT 10 +#define HEIGHT_OPERATOR 2 +#define PACKET_BUFFER_NUM 4 +#define FRAME_BUFFER_NUM 10 +#define FRAME_SIZE_OPERATOR 2 + +typedef struct { + char *codecName; + /* end of stream flag when set quit the loop */ + unsigned int loop_end; + /* input and output */ + FILE *fpInput; + FILE *fp_output; + int32_t frameCount; + int32_t frameNum; + CodecCallback cb; +} MpiDecLoopData; + +static struct ICodec *g_codecProxy = NULL; +static CODEC_HANDLETYPE g_handle = NULL; +ShareMemory *g_inputBuffers = NULL; +ShareMemory *g_outputBuffers = NULL; +InputInfo *g_inputInfosData = NULL; +OutputInfo *g_outputInfosData = NULL; +struct ICodecCallback *g_callback = NULL; + +CodecCmd g_cmd = {0}; +MpiDecLoopData g_data = {0}; + +bool g_pktEos = false; +int32_t g_totalSrcSize = 0; +int32_t g_totalFrames = 0; + +void DumpOutputToFile(FILE *fp, uint8_t *addr) +{ + uint32_t width = g_cmd.width; + uint32_t height = g_cmd.height; + uint32_t horStride = g_cmd.width; + uint32_t verStride = g_cmd.height; + uint8_t *base = addr; + size_t ret = 0; + + // MPP_FMT_YUV420SP + uint32_t i; + uint8_t *baseY = base; + uint8_t *baseC = base + horStride * verStride; + + for (i = 0; i < height; i++, baseY += horStride) { + ret = fwrite(baseY, 1, width, fp); + if (ret != width) { + HDF_LOGE("%{public}s: DumpOutputToFile failed", __func__); + continue; + } + } + for (i = 0; i < height / HEIGHT_OPERATOR; i++, baseC += horStride) { + ret = fwrite(baseC, 1, width, fp); + if (ret != width) { + HDF_LOGE("%{public}s: DumpOutputToFile failed", __func__); + continue; + } + } +} + +int32_t ReadInputFromFile(FILE *fp, uint8_t *addr) +{ + return fread(addr, 1, STREAM_PACKET_BUFFER_SIZE, fp); +} + +static ShareMemory* GetShareMemoryById(int32_t id) +{ + int32_t i; + for (i = 0; i < STREAM_PACKET_BUFFER_NUM; i++) { + if (g_inputBuffers[i].id == id) { + return &g_inputBuffers[i]; + } + } + for (i = 0; i < MEDIA_FRAME_BUFFER_NUM; i++) { + if (g_outputBuffers[i].id == id) { + return &g_outputBuffers[i]; + } + } + return NULL; +} + +static void ReleaseShm(void) +{ + int32_t i; + if (g_inputBuffers != NULL) { + for (i = 0; i < STREAM_PACKET_BUFFER_NUM; i++) { + ReleaseShareMemory(&g_inputBuffers[i]); + } + } + if (g_outputBuffers != NULL) { + for (i = 0; i < MEDIA_FRAME_BUFFER_NUM; i++) { + ReleaseShareMemory(&g_outputBuffers[i]); + } + } +} + +static void ReleaseInfoBuffer(void) +{ + int32_t i; + if (g_inputInfosData != NULL) { + for (i = 0; i < STREAM_PACKET_BUFFER_NUM; i++) { + if (g_inputInfosData[i].buffers != NULL) { + OsalMemFree(g_inputInfosData[i].buffers); + } + } + } + if (g_outputInfosData != NULL) { + for (i = 0; i < MEDIA_FRAME_BUFFER_NUM; i++) { + if (g_outputInfosData[i].buffers != NULL) { + OsalMemFree(g_outputInfosData[i].buffers); + } + } + } +} + +static bool InitBuffer(int32_t packetBufferNum, int32_t packetBufferSize, + int32_t frameBufferNum, int32_t frameBufferSize) +{ + int32_t queueRet = 0; + g_inputBuffers = (ShareMemory *)OsalMemCalloc(sizeof(ShareMemory) * STREAM_PACKET_BUFFER_NUM); + g_outputBuffers = (ShareMemory *)OsalMemCalloc(sizeof(ShareMemory) * MEDIA_FRAME_BUFFER_NUM); + g_inputInfosData = (InputInfo *)OsalMemCalloc(sizeof(InputInfo) * STREAM_PACKET_BUFFER_NUM); + g_outputInfosData = (OutputInfo *)OsalMemCalloc(sizeof(OutputInfo) * MEDIA_FRAME_BUFFER_NUM); + if (g_inputBuffers == NULL || g_outputBuffers == NULL || g_inputInfosData == NULL || g_outputInfosData == NULL) { + HDF_LOGE("%{public}s: buffer and info mem alloc failed!", __func__); + return false; + } + + for (int32_t i = 0; i < packetBufferNum; i++) { + g_inputBuffers[i].id = i; + g_inputBuffers[i].size = packetBufferSize; + CreateShareMemory(&g_inputBuffers[i]); + g_inputInfosData[i].bufferCnt = 1; + g_inputInfosData[i].flag = STREAM_FLAG_CODEC_SPECIFIC_INF; + g_inputInfosData[i].buffers = (CodecBufferInfo *)OsalMemCalloc(sizeof(CodecBufferInfo)); + if (g_inputInfosData[i].buffers != NULL) { + g_inputInfosData[i].buffers->type = BUFFER_TYPE_FD; + g_inputInfosData[i].buffers->fd = g_inputBuffers[i].fd; + g_inputInfosData[i].buffers->offset = g_inputBuffers[i].id; + g_inputInfosData[i].buffers->size = packetBufferSize; + } + queueRet = g_codecProxy->CodecQueueInput(g_codecProxy, (CODEC_HANDLETYPE)g_handle, + &g_inputInfosData[i], (uint32_t)0); + if (queueRet != HDF_SUCCESS) { + HDF_LOGE("%{public}s: input buffer initial failed!", __func__); + return false; + } + } + + for (int32_t j = 0; j < frameBufferNum; j++) { + g_outputBuffers[j].id = STREAM_PACKET_BUFFER_NUM + j; + g_outputBuffers[j].size = frameBufferSize; + CreateShareMemory(&g_outputBuffers[j]); + g_outputInfosData[j].bufferCnt = 1; + g_outputInfosData[j].flag = STREAM_FLAG_CODEC_SPECIFIC_INF; + g_outputInfosData[j].buffers = (CodecBufferInfo *)OsalMemCalloc(sizeof(CodecBufferInfo)); + if (g_outputInfosData[j].buffers != NULL) { + g_outputInfosData[j].buffers->type = BUFFER_TYPE_FD; + g_outputInfosData[j].buffers->fd = g_outputBuffers[j].fd; + g_outputInfosData[j].buffers->offset = g_outputBuffers[j].id; + g_outputInfosData[j].buffers->size = frameBufferSize; + } + queueRet = g_codecProxy->CodecQueueOutput(g_codecProxy, (CODEC_HANDLETYPE)g_handle, + &g_outputInfosData[j], (uint32_t)0, 1); + if (queueRet != HDF_SUCCESS) { + HDF_LOGE("%{public}s: output buffer initial failed!", __func__); + return false; + } + } + return true; +} + +int32_t TestOnEvent(UINTPTR comp, UINTPTR appData, EventType event, + uint32_t data1, uint32_t data2, UINTPTR eventData) +{ + HDF_LOGI("%{public}s: TestOnEvent : event = %{public}d", __func__, event); + return HDF_SUCCESS; +} + +int32_t TestInputBufferAvailable(UINTPTR comp, UINTPTR appData, InputInfo *inBuf) +{ + HDF_LOGI("%{public}s: TestInputBufferAvailable enter", __func__); + return HDF_SUCCESS; +} + +int32_t TestOutputBufferAvailable(UINTPTR comp, UINTPTR appData, OutputInfo *outBuf) +{ + HDF_LOGI("%{public}s: TestOutputBufferAvailable write %{public}d", __func__, outBuf->buffers->size); + return HDF_SUCCESS; +} + +int32_t SetExtDecParameter(void) +{ + Param param; + int32_t paramCnt; + int32_t ret; + + // set split_parse enable mpp internal frame spliter when the input + paramCnt = 1; + memset_s(¶m, sizeof(Param), 0, sizeof(Param)); + param.key = (ParamKey)KEY_SPLIT_PARSE_RK; + int32_t needSplit = 1; + param.val = &needSplit; + param.size = sizeof(int32_t); + ret = g_codecProxy->CodecSetParameter(g_codecProxy, (CODEC_HANDLETYPE)g_handle, ¶m, paramCnt); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: CodecSetParameter failed", __func__); + return HDF_FAILURE; + } + + // set decode frame number + memset_s(¶m, sizeof(Param), 0, sizeof(Param)); + paramCnt = 1; + int32_t num = g_data.frameNum; + param.key = (ParamKey)KEY_DEC_FRAME_NUM_RK; + param.val = # + param.size = sizeof(int32_t); + ret = g_codecProxy->CodecSetParameter(g_codecProxy, (CODEC_HANDLETYPE)g_handle, ¶m, paramCnt); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: CodecSetParameter failed", __func__); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} + +int32_t SetDecParameter(void) +{ + Param param; + int32_t paramCnt = 1; + int32_t ret; + + // set CodecType + memset_s(¶m, sizeof(Param), 0, sizeof(Param)); + CodecType ct = VIDEO_DECODER; + param.key = KEY_CODEC_TYPE; + param.val = &ct; + param.size = sizeof(ct); + ret = g_codecProxy->CodecSetParameter(g_codecProxy, (CODEC_HANDLETYPE)g_handle, ¶m, paramCnt); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: CodecSetParameter KEY_CODEC_TYPE failed", __func__); + return HDF_FAILURE; + } + + // get default config + memset_s(¶m, sizeof(Param), 0, sizeof(Param)); + paramCnt = 1; + param.key = (ParamKey)KEY_DEFAULT_CFG_RK; + int32_t needDefault = 1; + param.val = &needDefault; + param.size = sizeof(int32_t); + ret = g_codecProxy->CodecGetParameter(g_codecProxy, (CODEC_HANDLETYPE)g_handle, ¶m, paramCnt); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: CodecSetParameter failed", __func__); + return HDF_FAILURE; + } + + // get format + memset_s(¶m, sizeof(Param), 0, sizeof(Param)); + paramCnt = 1; + param.key = KEY_PIXEL_FORMAT; + CodecPixelFormat fmt = PIX_FORMAT_INVALID; + param.val = &fmt; + param.size = sizeof(CodecPixelFormat); + ret = g_codecProxy->CodecGetParameter(g_codecProxy, (CODEC_HANDLETYPE)g_handle, ¶m, paramCnt); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: CodecSetParameter failed", __func__); + return HDF_FAILURE; + } + + if (SetExtDecParameter() != HDF_SUCCESS) { + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} + +void DecodeLoopHandleInput(MpiDecLoopData *g_data) +{ + int32_t ret = 0; + uint8_t readData[STREAM_PACKET_BUFFER_SIZE]; + int32_t readSize = 0; + CodecBufferInfo inputBuffer; + + memset_s(&inputBuffer, sizeof(CodecBufferInfo), 0, sizeof(CodecBufferInfo)); + inputBuffer.type = BUFFER_TYPE_FD; + InputInfo inputData; + memset_s(&inputData, sizeof(InputInfo), 0, sizeof(InputInfo)); + inputData.bufferCnt = 1; + inputData.buffers = &inputBuffer; + inputData.flag = STREAM_FLAG_CODEC_SPECIFIC_INF; + + ret = g_codecProxy->CodecDequeInput(g_codecProxy, (CODEC_HANDLETYPE)g_handle, QUEUE_TIME_OUT, &inputData); + if (ret == HDF_SUCCESS) { + // when packet size is valid read the input binary file + readSize = ReadInputFromFile(g_data->fpInput, readData); + g_pktEos = (readSize <= 0); + if (g_pktEos) { + HDF_LOGD("%{public}s: client inputData reach STREAM_FLAG_EOS", __func__); + inputData.flag = STREAM_FLAG_EOS; + } + + g_totalSrcSize += readSize; + ShareMemory *sm = GetShareMemoryById(inputBuffer.offset); + memcpy_s(sm->virAddr, readSize, (uint8_t*)readData, readSize); + inputBuffer.size = readSize; + g_codecProxy->CodecQueueInput(g_codecProxy, (CODEC_HANDLETYPE)g_handle, &inputData, QUEUE_TIME_OUT); + } +} + +static int32_t DecodeLoop(MpiDecLoopData *g_data) +{ + int32_t ret = 0; + + if (!g_pktEos) { + DecodeLoopHandleInput(g_data); + } + + CodecBufferInfo outputBuffer; + memset_s(&outputBuffer, sizeof(CodecBufferInfo), 0, sizeof(CodecBufferInfo)); + outputBuffer.type = BUFFER_TYPE_FD; + OutputInfo outputData; + memset_s(&outputData, sizeof(OutputInfo), 0, sizeof(OutputInfo)); + outputData.bufferCnt = 1; + outputData.buffers = &outputBuffer; + outputData.flag = STREAM_FLAG_CODEC_SPECIFIC_INF; + + int32_t acquireFd = 0; + ret = g_codecProxy->CodecDequeueOutput(g_codecProxy, (CODEC_HANDLETYPE)g_handle, QUEUE_TIME_OUT, + &acquireFd, &outputData); + if (ret == HDF_SUCCESS) { + g_totalFrames++; + ShareMemory *sm = GetShareMemoryById(outputBuffer.offset); + DumpOutputToFile(g_data->fp_output, sm->virAddr); + CodecBufferInfo queOutputBuffer; + memset_s(&queOutputBuffer, sizeof(CodecBufferInfo), 0, sizeof(CodecBufferInfo)); + queOutputBuffer.type = BUFFER_TYPE_FD; + queOutputBuffer.fd = outputData.buffers->fd; + queOutputBuffer.offset = outputData.buffers->offset; + OutputInfo queOutputData; + memset_s(&queOutputData, sizeof(OutputInfo), 0, sizeof(OutputInfo)); + queOutputData.bufferCnt = 1; + queOutputData.buffers = &queOutputBuffer; + queOutputData.flag = STREAM_FLAG_CODEC_SPECIFIC_INF; + g_codecProxy->CodecQueueOutput(g_codecProxy, (CODEC_HANDLETYPE)g_handle, &queOutputData, QUEUE_TIME_OUT, 1); + if (outputData.flag & STREAM_FLAG_EOS) { + HDF_LOGD("%{public}s: reach STREAM_FLAG_EOS, loop_end, g_totalFrames:%{public}d", __func__, g_totalFrames); + g_data->loop_end = 1; + } + } + + return ret; +} + +void *DecodeThread(void *arg) +{ + MpiDecLoopData *g_data = (MpiDecLoopData *)arg; + + while (!g_data->loop_end) { + DecodeLoop(g_data); + } + + HDF_LOGD("%{public}s: client loop_end", __func__); + return NULL; +} + +void RevertDecodeStep1(void) +{ + if (g_data.fpInput) { + fclose(g_data.fpInput); + g_data.fpInput = NULL; + } + if (g_data.fp_output) { + fclose(g_data.fp_output); + g_data.fp_output = NULL; + } +} + +void RevertDecodeStep2(void) +{ + int32_t ret = g_codecProxy->CodecDeinit(g_codecProxy); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: CodecDeinit failed, ret:%{public}d", __func__, ret); + } + RevertDecodeStep1(); +} + +void RevertDecodeStep3(void) +{ + ReleaseShm(); + ReleaseInfoBuffer(); + + if (g_inputBuffers != NULL) { + OsalMemFree(g_inputBuffers); + } + if (g_outputBuffers != NULL) { + OsalMemFree(g_outputBuffers); + } + if (g_inputInfosData != NULL) { + OsalMemFree(g_inputInfosData); + } + if (g_outputInfosData != NULL) { + OsalMemFree(g_outputInfosData); + } + int32_t ret = g_codecProxy->CodecDestroy(g_codecProxy, (CODEC_HANDLETYPE)g_handle); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: CodecDestroy failed, ret:%{public}d", __func__, ret); + } + RevertDecodeStep2(); +} + +int32_t OpenFile(void) +{ + g_data.fpInput = fopen(g_cmd.file_input, "rb"); + if (g_data.fpInput == NULL) { + HDF_LOGE("%{public}s: failed to open input file %{public}s", __func__, g_cmd.file_input); + RevertDecodeStep1(); + return HDF_FAILURE; + } + g_data.fp_output = fopen(g_cmd.file_output, "w+b"); + if (g_data.fp_output == NULL) { + HDF_LOGE("%{public}s: failed to open output file %{public}s", __func__, g_cmd.file_output); + RevertDecodeStep1(); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +void DecodeEnd(void) +{ + DirectionType directType = ALL_TYPE; + int32_t ret = g_codecProxy->CodecFlush(g_codecProxy, (CODEC_HANDLETYPE)g_handle, directType); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: CodecFlush failed, ret:%{public}d", __func__, ret); + } + + ret = g_codecProxy->CodecStop(g_codecProxy, (CODEC_HANDLETYPE)g_handle); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: CodecStop failed, ret:%{public}d", __func__, ret); + } + + RevertDecodeStep3(); + if (g_callback != NULL) { + CodecCallbackStubRelease(g_callback); + } +} + +int32_t Decode(void) +{ + pthread_t thd; + pthread_attr_t attr; + int32_t ret = 0; + + if (OpenFile() != HDF_SUCCESS) { + HDF_LOGE("%{public}s: Failed to open file!", __func__); + return HDF_FAILURE; + } + + ret = g_codecProxy->CodecInit(g_codecProxy); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: CodecInit failed, ret:%{public}d", __func__, ret); + RevertDecodeStep1(); + return HDF_FAILURE; + } + + Param params; + memset_s(¶ms, sizeof(Param), 0, sizeof(Param)); + int32_t val = VIDEO_DECODER; + params.key = KEY_CODEC_TYPE; + params.val = &val; + params.size = sizeof(val); + ret = g_codecProxy->CodecCreate(g_codecProxy, g_data.codecName, ¶ms, 1, &g_handle); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: CodecCreate failed, ret:%{public}d", __func__, ret); + RevertDecodeStep2(); + return HDF_FAILURE; + } + if (SetDecParameter() != HDF_SUCCESS) { + HDF_LOGE("%{public}s: SetDecParameter failed", __func__); + RevertDecodeStep3(); + return HDF_FAILURE; + } + + if (!InitBuffer(PACKET_BUFFER_NUM, STREAM_PACKET_BUFFER_SIZE, FRAME_BUFFER_NUM, + g_cmd.width * g_cmd.height * FRAME_SIZE_OPERATOR)) { + HDF_LOGE("%{public}s: InitBuffer failed", __func__); + RevertDecodeStep3(); + return HDF_FAILURE; + } + + g_codecProxy->CodecStart(g_codecProxy, (CODEC_HANDLETYPE)g_handle); + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + ret = pthread_create(&thd, &attr, DecodeThread, &g_data); + if (ret != 0) { + HDF_LOGE("%{public}s: failed to create thread for input ret %{public}d", __func__, ret); + DecodeEnd(); + pthread_attr_destroy(&attr); + return HDF_SUCCESS; + } + + pthread_join(thd, NULL); + DecodeEnd(); + pthread_attr_destroy(&attr); + + return HDF_SUCCESS; +} + +int32_t main(int32_t argc, char **argv) +{ + g_cmd.type = VIDEO_DECODER; + int32_t ret = ParseArguments(&g_cmd, argc, argv); + HDF_LOGI("%{public}s: ParseArguments width:%{public}d", __func__, g_cmd.width); + HDF_LOGI("%{public}s: ParseArguments height:%{public}d", __func__, g_cmd.height); + HDF_LOGI("%{public}s: ParseArguments codecName:%{public}s", __func__, g_cmd.codecName); + HDF_LOGI("%{public}s: ParseArguments input:%{public}s", __func__, g_cmd.file_input); + HDF_LOGI("%{public}s: ParseArguments output:%{public}s", __func__, g_cmd.file_output); + if (ret != HDF_SUCCESS) { + HDF_LOGE("ParseArguments failed!"); + return ret; + } + + memset_s(&g_data, sizeof(g_data), 0, sizeof(g_data)); + g_codecProxy = HdiCodecGet(TEST_SERVICE_NAME); + g_data.codecName = g_cmd.codecName; + + ret = Decode(); + if (ret == HDF_SUCCESS) { + HDF_LOGI("%{public}s: test success", __func__); + } else { + HDF_LOGE("%{public}s: test failed ret %{public}d", __func__, ret); + } + + // Release + HdiCodecRelease(g_codecProxy); + HDF_LOGI("%{public}s: test exit", __func__); + return ret; +} + diff --git a/codec/test/demo/v1.0/codec_encode_test_ipc.c b/codec/test/demo/v1.0/codec_encode_test_ipc.c new file mode 100644 index 0000000000..08c398bb43 --- /dev/null +++ b/codec/test/demo/v1.0/codec_encode_test_ipc.c @@ -0,0 +1,725 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong DID Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "codec_callback_stub.h" +#include "codec_type.h" +#include "codec_utils.h" +#include "hdf_log.h" +#include "hdi_mpp.h" +#include "hdi_mpp_config.h" +#include "icodec.h" +#include "osal_mem.h" +#include "share_mem.h" + +#define HDF_LOG_TAG codec_hdi_demo_encode +#define TEST_SERVICE_NAME "codec_hdi_service" +#define STREAM_PACKET_BUFFER_SIZE (4 * 1024) +#define QUEUE_TIME_OUT 10 +#define READ_SEGMENT_SIZE 8192 +#define FRAME_SIZE_MULTI 3 +#define FRAME_SIZE_OPERATOR 2 +#define BPS_BASE 16 +#define BPS_MAX 17 +#define BPS_MEDIUM 15 +#define BPS_MIN 1 +#define BPS_TARGET 2 +#define FIXQP_INIT_VALUE 20 +#define FIXQP_MAX_VALUE 20 +#define FIXQP_MIN_VALUE 20 +#define FIXQP_MAX_I_VALUE 20 +#define FIXQP_MIN_I_VALUE 20 +#define FIXQP_IP_VALUE 2 +#define OTHER_QP_INIT_VALUE 26 +#define OTHER_QP_MAX_VALUE 51 +#define OTHER_QP_MIN_VALUE 10 +#define OTHER_QP_MAX_I_VALUE 51 +#define OTHER_QP_MIN_I_VALUE 10 +#define OTHER_QP_IP_VALUE 2 +#define AVC_SETUP_LEVEL_DEFAULT 40 +#define AVC_SETUP_CABAC_EN_DEFAULT 1 +#define AVC_SETUP_CABAC_IDC_DEFAULT 0 +#define AVC_SETUP_TRANS_DEFAULT 1 +#define AVC_SETUP_PROFILE_DEFAULT 100 +#define FPS_OUT_NUM_OPERATOR 2 +#define INPUT_BUFFER_NUM 4 +#define INPUT_BUFFER_SIZE_OPERATOR 2 +#define OUTPUT_BUFFER_NUM 4 +#define ENC_SETUP_DROP_THD 20 +#define ENC_SETUP_FPS_IN_NUM 24 +#define ENC_SETUP_FPS_OUT_NUM 24 +#define PARAM_ARRAY_LEN 20 + +typedef struct { + char *codecName; + /* end of stream flag when set quit the loop */ + unsigned int loop_end; + /* input and output */ + FILE *fpInput; + FILE *fpOutput; + int32_t g_frameCount; + int32_t frameNum; + CodecCallback cb; +} CodecEnvData; + +static struct ICodec *g_codecProxy = NULL; +static CODEC_HANDLETYPE g_handle = NULL; +ShareMemory *g_inputBuffers = NULL; +ShareMemory *g_outputBuffers = NULL; +InputInfo *g_inputInfosData = NULL; +OutputInfo *g_outputInfosData = NULL; +struct ICodecCallback *g_callback = NULL; + +CodecCmd g_cmd = {0}; +CodecEnvData g_data = {0}; +CodecBufferInfo g_outputBuffer = {0}; +RKHdiEncodeSetup g_encodeSetup = {0}; + +bool g_pktEos = false; +int32_t g_totalSrcSize = 0; +int32_t g_totalDstSize = 0; +int32_t g_frameCount = 0; + +void DumpOutputToFile(FILE *fp, uint8_t *addr, uint32_t len) +{ + size_t ret = fwrite(addr, 1, len, fp); + if (ret != len) { + HDF_LOGE("%{public}s: DumpOutputToFile failed", __func__); + } +} + +int32_t ReadInputFromFile(FILE *fp, uint8_t *addr) +{ + int32_t readSize = 0; + int32_t frameSize = g_cmd.width * g_cmd.height * FRAME_SIZE_MULTI / FRAME_SIZE_OPERATOR; + int32_t loop = frameSize / READ_SEGMENT_SIZE; + for (int32_t i = 0; i < loop; i++) { + readSize += fread(addr + readSize, 1, READ_SEGMENT_SIZE, fp); + } + if (frameSize % READ_SEGMENT_SIZE > 0) { + readSize += fread(addr + readSize, 1, frameSize % READ_SEGMENT_SIZE, fp); + } + return readSize; +} + +static ShareMemory* GetShareMemoryById(int32_t id) +{ + int32_t i; + for (i = 0; i < INPUT_BUFFER_NUM; i++) { + if (g_inputBuffers[i].id == id) { + return &g_inputBuffers[i]; + } + } + for (i = 0; i < OUTPUT_BUFFER_NUM; i++) { + if (g_outputBuffers[i].id == id) { + return &g_outputBuffers[i]; + } + } + return NULL; +} + +static void ReleaseShm(void) +{ + int32_t i; + if (g_inputBuffers != NULL) { + for (i = 0; i < INPUT_BUFFER_NUM; i++) { + ReleaseShareMemory(&g_inputBuffers[i]); + } + } + if (g_outputBuffers != NULL) { + for (i = 0; i < OUTPUT_BUFFER_NUM; i++) { + ReleaseShareMemory(&g_outputBuffers[i]); + } + } +} + +static void ReleaseInfoBuffer(void) +{ + int32_t i; + if (g_inputInfosData != NULL) { + for (i = 0; i < INPUT_BUFFER_NUM; i++) { + if (g_inputInfosData[i].buffers != NULL) { + OsalMemFree(g_inputInfosData[i].buffers); + } + } + } + if (g_outputInfosData != NULL) { + for (i = 0; i < OUTPUT_BUFFER_NUM; i++) { + if (g_outputInfosData[i].buffers != NULL) { + OsalMemFree(g_outputInfosData[i].buffers); + } + } + } +} + +static bool InitBuffer(int32_t inputBufferNum, int32_t inputBufferSize, + int32_t outputBufferNum, int32_t outputBufferSize) +{ + int32_t queueRet = 0; + g_inputBuffers = (ShareMemory *)OsalMemCalloc(sizeof(ShareMemory) * inputBufferNum); + g_outputBuffers = (ShareMemory *)OsalMemCalloc(sizeof(ShareMemory) * outputBufferNum); + g_inputInfosData = (InputInfo *)OsalMemCalloc(sizeof(InputInfo) * inputBufferNum); + g_outputInfosData = (OutputInfo *)OsalMemCalloc(sizeof(OutputInfo) * outputBufferNum); + if (g_inputBuffers == NULL || g_outputBuffers == NULL || g_inputInfosData == NULL || g_outputInfosData == NULL) { + HDF_LOGE("%{public}s: buffer and info mem alloc failed!", __func__); + return false; + } + for (int32_t i = 0; i < inputBufferNum; i++) { + g_inputBuffers[i].id = i; + g_inputBuffers[i].size = inputBufferSize; + CreateShareMemory(&g_inputBuffers[i]); + g_inputInfosData[i].bufferCnt = 1; + g_inputInfosData[i].flag = STREAM_FLAG_CODEC_SPECIFIC_INF; + g_inputInfosData[i].buffers = (CodecBufferInfo *)OsalMemCalloc(sizeof(CodecBufferInfo)); + if (g_inputInfosData[i].buffers != NULL) { + g_inputInfosData[i].buffers->type = BUFFER_TYPE_FD; + g_inputInfosData[i].buffers->fd = g_inputBuffers[i].fd; + g_inputInfosData[i].buffers->offset = g_inputBuffers[i].id; + g_inputInfosData[i].buffers->size = inputBufferSize; + } + + queueRet = g_codecProxy->CodecQueueInput(g_codecProxy, (CODEC_HANDLETYPE)g_handle, + &g_inputInfosData[i], (uint32_t)0); + if (queueRet != HDF_SUCCESS) { + HDF_LOGE("%{public}s: input buffer initial failed!", __func__); + return false; + } + } + for (int32_t j = 0; j < outputBufferNum; j++) { + g_outputBuffers[j].id = INPUT_BUFFER_NUM + j; + g_outputBuffers[j].size = outputBufferSize; + CreateShareMemory(&g_outputBuffers[j]); + g_outputInfosData[j].bufferCnt = 1; + g_outputInfosData[j].flag = STREAM_FLAG_CODEC_SPECIFIC_INF; + g_outputInfosData[j].buffers = (CodecBufferInfo *)OsalMemCalloc(sizeof(CodecBufferInfo)); + if (g_outputInfosData[j].buffers != NULL) { + g_outputInfosData[j].buffers->type = BUFFER_TYPE_FD; + g_outputInfosData[j].buffers->fd = g_outputBuffers[j].fd; + g_outputInfosData[j].buffers->offset = g_outputBuffers[j].id; + g_outputInfosData[j].buffers->size = outputBufferSize; + } + queueRet = g_codecProxy->CodecQueueOutput(g_codecProxy, (CODEC_HANDLETYPE)g_handle, + &g_outputInfosData[j], (uint32_t)0, 1); + if (queueRet != HDF_SUCCESS) { + HDF_LOGE("%{public}s: output buffer initial failed!", __func__); + return false; + } + } + return true; +} + +int32_t TestOnEvent(UINTPTR comp, UINTPTR appData, EventType event, + uint32_t data1, uint32_t data2, UINTPTR eventData) +{ + HDF_LOGI("%{public}s: TestOnEvent: event = %{public}d", __func__, event); + return HDF_SUCCESS; +} + +int32_t TestInputBufferAvailable(UINTPTR comp, UINTPTR appData, InputInfo *inBuf) +{ + HDF_LOGI("%{public}s: TestInputBufferAvailable enter", __func__); + return HDF_SUCCESS; +} + +int32_t TestOutputBufferAvailable(UINTPTR comp, UINTPTR appData, OutputInfo *outBuf) +{ + HDF_LOGI("%{public}s: TestOutputBufferAvailable datasize: %{public}d", __func__, outBuf->buffers->size); + return HDF_SUCCESS; +} + +void SetQpValue(RKHdiEncodeSetup *encSetup) +{ + switch (encSetup->rc.rcMode) { + case MPP_ENC_RC_MODE_FIXQP: { + encSetup->rc.qpInit = FIXQP_INIT_VALUE; + encSetup->rc.qpMax = FIXQP_MAX_VALUE; + encSetup->rc.qpMin = FIXQP_MIN_VALUE; + encSetup->rc.qpMaxI = FIXQP_MAX_I_VALUE; + encSetup->rc.qpMinI = FIXQP_MIN_I_VALUE; + encSetup->rc.qpIp = FIXQP_IP_VALUE; + break; + } + case MPP_ENC_RC_MODE_CBR: + case MPP_ENC_RC_MODE_VBR: + case MPP_ENC_RC_MODE_AVBR: { + encSetup->rc.qpInit = OTHER_QP_INIT_VALUE; + encSetup->rc.qpMax = OTHER_QP_MAX_VALUE; + encSetup->rc.qpMin = OTHER_QP_MIN_VALUE; + encSetup->rc.qpMaxI = OTHER_QP_MAX_I_VALUE; + encSetup->rc.qpMinI = OTHER_QP_MIN_I_VALUE; + encSetup->rc.qpIp = OTHER_QP_IP_VALUE; + break; + } + default: { + HDF_LOGE("%{public}s: unsupport encoder rc mode %{public}d", __func__, encSetup->rc.rcMode); + break; + } + } +} + +void CalcBpsRange(RKHdiEncodeSetup *encSetup) +{ + switch (encSetup->rc.rcMode) { + case MPP_ENC_RC_MODE_FIXQP: { + /* do not setup bitrate on FIXQP mode */ + break; + } + case MPP_ENC_RC_MODE_CBR: { + /* CBR mode has narrow bound */ + encSetup->rc.bpsMax = encSetup->rc.bpsTarget * BPS_MAX / BPS_BASE; + encSetup->rc.bpsMin = encSetup->rc.bpsTarget * BPS_MEDIUM / BPS_BASE; + break; + } + case MPP_ENC_RC_MODE_VBR: + case MPP_ENC_RC_MODE_AVBR: { + /* VBR mode has wide bound */ + encSetup->rc.bpsMax = encSetup->rc.bpsTarget * BPS_MAX / BPS_BASE; + encSetup->rc.bpsMin = encSetup->rc.bpsTarget * BPS_MIN / BPS_BASE; + break; + } + default: { + /* default use CBR mode */ + encSetup->rc.bpsMax = encSetup->rc.bpsTarget * BPS_MAX / BPS_BASE; + encSetup->rc.bpsMin = encSetup->rc.bpsTarget * BPS_MEDIUM / BPS_BASE; + break; + } + } + /* setup qp for different codec and rc_mode */ + switch (encSetup->codecType.mimeCodecType) { + case MPP_VIDEO_CodingAVC: + case MPP_VIDEO_CodingHEVC: { + SetQpValue(encSetup); + break; + } + default: { + break; + } + } +} + +void SetCodecTypeData(RKHdiCodecTypeSetup *codecTypeSet) +{ + switch (codecTypeSet->mimeCodecType) { + case MEDIA_MIMETYPE_VIDEO_AVC: { + /* + * H.264 profile_idc parameter + * 66 - Baseline profile + * 77 - Main profile + * 100 - High profile + */ + codecTypeSet->avcSetup.profile = AVC_SETUP_PROFILE_DEFAULT; + /* + * H.264 level_idc parameter + * 10 / 11 / 12 / 13 - qcif@15fps / cif@7.5fps / cif@15fps / cif@30fps + * 20 / 21 / 22 - cif@30fps / half-D1@@25fps / D1@12.5fps + * 30 / 31 / 32 - D1@25fps / 720p@30fps / 720p@60fps + * 40 / 41 / 42 - 1080p@30fps / 1080p@30fps / 1080p@60fps + * 50 / 51 / 52 - 4K@30fps + */ + codecTypeSet->avcSetup.level = AVC_SETUP_LEVEL_DEFAULT; + codecTypeSet->avcSetup.cabacEn = AVC_SETUP_CABAC_EN_DEFAULT; + codecTypeSet->avcSetup.cabacIdc = AVC_SETUP_CABAC_IDC_DEFAULT; + codecTypeSet->avcSetup.trans8x8 = AVC_SETUP_TRANS_DEFAULT; + break; + } + case MEDIA_MIMETYPE_VIDEO_HEVC: + case MEDIA_MIMETYPE_VIDEO_MJPEG: { + break; + } + default: { + HDF_LOGE("%{public}s: unsupport encoder coding type %{public}d", __func__, codecTypeSet->mimeCodecType); + break; + } + } +} + +int32_t SetupExtEncParams(Param *params, RKHdiEncodeSetup *encSetup, int32_t count) +{ + Param *param = NULL; + int32_t paramCount = count; + + param = ¶ms[paramCount++]; + param->key = (ParamKey)KEY_EXT_SETUP_DROP_MODE_RK; + encSetup->drop.dropMode = MPP_ENC_RC_DROP_FRM_DISABLED; + encSetup->drop.dropThd = ENC_SETUP_DROP_THD; + encSetup->drop.dropGap = 1; + param->val = &(encSetup->drop); + param->size = sizeof(encSetup->drop); + + param = ¶ms[paramCount++]; + param->key = KEY_MIMETYPE; + encSetup->codecType.mimeCodecType = MEDIA_MIMETYPE_VIDEO_AVC; + SetCodecTypeData(&encSetup->codecType); + param->val = &(encSetup->codecType); + param->size = sizeof(encSetup->codecType); + + param = ¶ms[paramCount++]; + param->key = KEY_CODEC_TYPE; + CodecType codecType = VIDEO_ENCODER; + param->val = &codecType; + param->size = sizeof(codecType); + + param = ¶ms[paramCount++]; + param->key = KEY_VIDEO_RC_MODE; + encSetup->rc.rcMode = VENCOD_RC_VBR; + encSetup->rc.bpsTarget = g_cmd.width * g_cmd.height * BPS_TARGET / BPS_BASE * + (encSetup->fps.fpsOutNum / encSetup->fps.fpsOutDen); + CalcBpsRange(encSetup); + param->val = &(encSetup->rc); + param->size = sizeof(encSetup->rc); + + param = ¶ms[paramCount++]; + param->key = KEY_VIDEO_GOP_MODE; + encSetup->gop.gopMode = VENCOD_GOPMODE_NORMALP; + encSetup->gop.gopLen = 0; + encSetup->gop.viLen = 0; + encSetup->gop.gop = encSetup->gop.gopLen ? encSetup->gop.gopLen: encSetup->fps.fpsOutNum * + FPS_OUT_NUM_OPERATOR; + param->val = &(encSetup->gop); + param->size = sizeof(encSetup->gop); + + param = ¶ms[paramCount++]; + param->key = (ParamKey)KEY_EXT_ENC_VALIDATE_SETUP_RK; + + return paramCount; +} + +int32_t SetupEncParams(RKHdiEncodeSetup *encSetup) +{ + Param params[PARAM_ARRAY_LEN] = {0}; + Param *param = NULL; + int32_t paramCount = 0; + + param = ¶ms[paramCount++]; + param->key = KEY_WIDTH; + encSetup->width = g_cmd.width; + param->val = &(encSetup->width); + param->size = sizeof(encSetup->width); + + param = ¶ms[paramCount++]; + param->key = KEY_HEIGHT; + encSetup->height = g_cmd.height; + param->val = &(encSetup->height); + param->size = sizeof(encSetup->height); + + param = ¶ms[paramCount++]; + param->key = KEY_PIXEL_FORMAT; + encSetup->fmt = YVU_SEMIPLANAR_420; + param->val = &(encSetup->fmt); + param->size = sizeof(encSetup->fmt); + + param = ¶ms[paramCount++]; + param->key = KEY_STRIDE; + encSetup->stride.horStride = GetDefaultHorStride(g_cmd.width, encSetup->fmt); + encSetup->stride.verStride = g_cmd.height; + param->val = &(encSetup->stride); + param->size = sizeof(encSetup->stride); + + param = ¶ms[paramCount++]; + param->key = KEY_VIDEO_FRAME_RATE; + encSetup->fps.fpsInFlex = 0; + encSetup->fps.fpsInNum = ENC_SETUP_FPS_IN_NUM; + encSetup->fps.fpsOutNum = ENC_SETUP_FPS_OUT_NUM; + encSetup->fps.fpsInDen = 1; + encSetup->fps.fpsOutDen = 1; + encSetup->fps.fpsOutFlex = 0; + param->val = &(encSetup->fps); + param->size = sizeof(encSetup->fps); + + paramCount = SetupExtEncParams(params, encSetup, paramCount); + int32_t ret = g_codecProxy->CodecSetParameter(g_codecProxy, (CODEC_HANDLETYPE)g_handle, params, paramCount); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: CodecSetParameter KEY_ENC_SETUP_RK failed", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +void EncodeLoopHandleInput(CodecEnvData *p_data, uint8_t *readData) +{ + int32_t ret = 0; + int32_t readSize = 0; + + CodecBufferInfo inputBuffer; + memset_s(&inputBuffer, sizeof(CodecBufferInfo), 0, sizeof(CodecBufferInfo)); + inputBuffer.type = BUFFER_TYPE_FD; + InputInfo inputData; + memset_s(&inputData, sizeof(InputInfo), 0, sizeof(InputInfo)); + inputData.bufferCnt = 1; + inputData.buffers = &inputBuffer; + inputData.flag = STREAM_FLAG_CODEC_SPECIFIC_INF; + + ret = g_codecProxy->CodecDequeInput(g_codecProxy, (CODEC_HANDLETYPE)g_handle, QUEUE_TIME_OUT, &inputData); + if (ret == HDF_SUCCESS) { + // when packet size is valid read the input binary file + g_frameCount++; + readSize = ReadInputFromFile(p_data->fpInput, readData); + + g_pktEos = (readSize <= 0); + if (g_pktEos) { + HDF_LOGD("%{public}s: client inputData reach STREAM_FLAG_EOS, g_frameCount:%{public}d", + __func__, g_frameCount); + inputData.flag = STREAM_FLAG_EOS; + } + + g_totalSrcSize += readSize; + ShareMemory *sm = GetShareMemoryById(inputBuffer.offset); + memcpy_s(sm->virAddr, readSize, (uint8_t*)readData, readSize); + inputBuffer.size = readSize; + g_codecProxy->CodecQueueInput(g_codecProxy, (CODEC_HANDLETYPE)g_handle, &inputData, QUEUE_TIME_OUT); + } +} + +static int32_t EncodeLoop(CodecEnvData *p_data, uint8_t *readData) +{ + int32_t ret = 0; + + if (!g_pktEos) { + EncodeLoopHandleInput(p_data, readData); + } + + CodecBufferInfo g_outputBuffer; + memset_s(&g_outputBuffer, sizeof(CodecBufferInfo), 0, sizeof(CodecBufferInfo)); + g_outputBuffer.type = BUFFER_TYPE_FD; + OutputInfo outputData; + memset_s(&outputData, sizeof(OutputInfo), 0, sizeof(OutputInfo)); + outputData.bufferCnt = 1; + outputData.buffers = &g_outputBuffer; + outputData.flag = STREAM_FLAG_CODEC_SPECIFIC_INF; + + int32_t acquireFd = 0; + ret = g_codecProxy->CodecDequeueOutput(g_codecProxy, (CODEC_HANDLETYPE)g_handle, QUEUE_TIME_OUT, + &acquireFd, &outputData); + if (ret == HDF_SUCCESS) { + g_totalDstSize += outputData.buffers->length; + ShareMemory *sm = GetShareMemoryById(g_outputBuffer.offset); + DumpOutputToFile(p_data->fpOutput, sm->virAddr, outputData.buffers->length); + CodecBufferInfo queOutputBuffer; + memset_s(&queOutputBuffer, sizeof(CodecBufferInfo), 0, sizeof(CodecBufferInfo)); + queOutputBuffer.type = BUFFER_TYPE_FD; + queOutputBuffer.fd = outputData.buffers->fd; + queOutputBuffer.offset = outputData.buffers->offset; + OutputInfo queOutputData; + memset_s(&queOutputData, sizeof(OutputInfo), 0, sizeof(OutputInfo)); + queOutputData.bufferCnt = 1; + queOutputData.buffers = &queOutputBuffer; + queOutputData.flag = STREAM_FLAG_CODEC_SPECIFIC_INF; + g_codecProxy->CodecQueueOutput(g_codecProxy, (CODEC_HANDLETYPE)g_handle, &queOutputData, QUEUE_TIME_OUT, 1); + if (outputData.flag & STREAM_FLAG_EOS) { + HDF_LOGD("%{public}s: client reach STREAM_FLAG_EOS, CodecEncode loop_end", __func__); + p_data->loop_end = 1; + } + } + + return ret; +} + +void *EncodeThread(void *arg) +{ + CodecEnvData *p_data = (CodecEnvData *)arg; + uint8_t *readData = (uint8_t*)OsalMemCalloc(g_cmd.width * g_cmd.height * 2); + if (readData == NULL) { + HDF_LOGE("%{public}s: input readData buffer mem alloc failed", __func__); + return NULL; + } + + HDF_LOGI("%{public}s: client EncodeThread start", __func__); + while (p_data->loop_end != 1) { + EncodeLoop(p_data, readData); + } + OsalMemFree(readData); + HDF_LOGI("%{public}s: client loop_end, g_totalSrcSize:%{public}d, g_totalDstSize: %{public}d", + __func__, g_totalSrcSize, g_totalDstSize); + return NULL; +} + +void RevertEncodeStep1(void) +{ + if (g_data.fpInput) { + fclose(g_data.fpInput); + g_data.fpInput = NULL; + } + if (g_data.fpOutput) { + fclose(g_data.fpOutput); + g_data.fpOutput = NULL; + } +} + +void RevertEncodeStep2(void) +{ + int32_t ret = g_codecProxy->CodecDeinit(g_codecProxy); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: failed to CodecDeinit %{public}d", __func__, ret); + } + RevertEncodeStep1(); +} + +void RevertEncodeStep3(void) +{ + ReleaseShm(); + ReleaseInfoBuffer(); + + if (g_inputBuffers != NULL) { + OsalMemFree(g_inputBuffers); + } + if (g_outputBuffers != NULL) { + OsalMemFree(g_outputBuffers); + } + if (g_inputInfosData != NULL) { + OsalMemFree(g_inputInfosData); + } + if (g_outputInfosData != NULL) { + OsalMemFree(g_outputInfosData); + } + int32_t ret = g_codecProxy->CodecDestroy(g_codecProxy, (CODEC_HANDLETYPE)g_handle); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: failed to CodecDestroy %{public}d", __func__, ret); + } + RevertEncodeStep2(); +} + +int32_t OpenFile(void) +{ + g_data.fpInput = fopen(g_cmd.file_input, "rb"); + if (g_data.fpInput == NULL) { + HDF_LOGE("%{public}s: failed to open input file %{public}s", __func__, g_cmd.file_input); + RevertEncodeStep1(); + return HDF_FAILURE; + } + + g_data.fpOutput = fopen(g_cmd.file_output, "w+b"); + if (g_data.fpOutput == NULL) { + HDF_LOGE("%{public}s: failed to open output file %{public}s", __func__, g_cmd.file_output); + RevertEncodeStep1(); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} + +void EncodeEnd(void) +{ + DirectionType directType = ALL_TYPE; + int32_t ret = g_codecProxy->CodecFlush(g_codecProxy, (CODEC_HANDLETYPE)g_handle, directType); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: CodecFlush failed", __func__); + } + + ret = g_codecProxy->CodecStop(g_codecProxy, (CODEC_HANDLETYPE)g_handle); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: failed to CodecStop %{public}d", __func__, ret); + } + + RevertEncodeStep3(); + + if (g_callback != NULL) { + CodecCallbackStubRelease(g_callback); + } +} + +int32_t Encode(void) +{ + pthread_t thd; + pthread_attr_t attr; + int32_t ret = 0; + + if (OpenFile() != HDF_SUCCESS) { + return HDF_FAILURE; + } + + ret = g_codecProxy->CodecInit(g_codecProxy); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: CodecInit failed", __func__); + RevertEncodeStep1(); + return HDF_FAILURE; + } + + Param param; + memset_s(¶m, sizeof(Param), 0, sizeof(Param)); + int32_t val = VIDEO_ENCODER; + param.key = KEY_CODEC_TYPE; + param.val = &val; + param.size = sizeof(val); + ret = g_codecProxy->CodecCreate(g_codecProxy, g_data.codecName, ¶m, 1, &g_handle); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: CodecCreate failed, ret:%{public}d", __func__, ret); + RevertEncodeStep2(); + return HDF_FAILURE; + } + + if (SetupEncParams(&g_encodeSetup) != HDF_SUCCESS) { + RevertEncodeStep3(); + return HDF_FAILURE; + } + if (!InitBuffer(INPUT_BUFFER_NUM, g_cmd.width * g_cmd.height * INPUT_BUFFER_SIZE_OPERATOR, + OUTPUT_BUFFER_NUM, STREAM_PACKET_BUFFER_SIZE)) { + HDF_LOGE("%{public}s: InitBuffer failed", __func__); + RevertEncodeStep3(); + return HDF_FAILURE; + } + + g_codecProxy->CodecStart(g_codecProxy, (CODEC_HANDLETYPE)g_handle); + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + ret = pthread_create(&thd, &attr, EncodeThread, &g_data); + if (ret != 0) { + HDF_LOGE("%{public}s: failed to create thread for input ret %{public}d", __func__, ret); + EncodeEnd(); + pthread_attr_destroy(&attr); + return HDF_FAILURE; + } + + pthread_join(thd, NULL); + EncodeEnd(); + pthread_attr_destroy(&attr); + + return HDF_SUCCESS; +} + +int32_t main(int32_t argc, char **argv) +{ + g_cmd.type = VIDEO_ENCODER; + int32_t ret = ParseArguments(&g_cmd, argc, argv); + HDF_LOGI("%{public}s: ParseArguments width:%{public}d", __func__, g_cmd.width); + HDF_LOGI("%{public}s: ParseArguments height:%{public}d", __func__, g_cmd.height); + HDF_LOGI("%{public}s: ParseArguments codecName:%{public}s", __func__, g_cmd.codecName); + HDF_LOGI("%{public}s: ParseArguments input:%{public}s", __func__, g_cmd.file_input); + HDF_LOGI("%{public}s: ParseArguments output:%{public}s", __func__, g_cmd.file_output); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: ParseArguments failed"); + return ret; + } + + memset_s(&g_data, sizeof(g_data), 0, sizeof(g_data)); + g_codecProxy = HdiCodecGet(TEST_SERVICE_NAME); + + g_data.codecName = g_cmd.codecName; + + ret = Encode(); + if (ret == HDF_SUCCESS) { + HDF_LOGI("%{public}s: test success", __func__); + } else { + HDF_LOGE("%{public}s: test failed ret %{public}d", __func__, ret); + } + + HdiCodecRelease(g_codecProxy); + HDF_LOGI("%{public}s: test exit", __func__); + return ret; +} + diff --git a/codec/test/demo/v1.0/codec_utils.c b/codec/test/demo/v1.0/codec_utils.c new file mode 100644 index 0000000000..b95fef4fce --- /dev/null +++ b/codec/test/demo/v1.0/codec_utils.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong DID Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "codec_utils.h" +#include +#include "hdf_base.h" +#include "hdf_log.h" + +#define HDF_LOG_TAG codec_hdi_demo_utils +#define CMD_OPTION_MARK_OFFSET 0 +#define CMD_OPTION_NAME_OFFSET 1 + +int32_t GetCodecName(CodecCmd* cmd) +{ + int32_t ret = HDF_SUCCESS; + if (strstr(cmd->codecName, "avc") || strstr(cmd->codecName, "AVC")) { + if (cmd->type == VIDEO_ENCODER) { + strcpy_s(cmd->codecName, TYPE_NAME_LENGTH, "codec.avc.hardware.encoder"); + } else { + strcpy_s(cmd->codecName, TYPE_NAME_LENGTH, "codec.avc.hardware.decoder"); + } + } else if (strstr(cmd->codecName, "hevc") || strstr(cmd->codecName, "HEVC")) { + if (cmd->type == VIDEO_ENCODER) { + strcpy_s(cmd->codecName, TYPE_NAME_LENGTH, "codec.hevc.hardware.encoder"); + } else { + strcpy_s(cmd->codecName, TYPE_NAME_LENGTH, "codec.hevc.hardware.decoder"); + } + } else { + memset_s(cmd->codecName, TYPE_NAME_LENGTH, 0, TYPE_NAME_LENGTH); + HDF_LOGE("%{public}s: not support coding codecName", __func__); + ret = HDF_FAILURE; + } + return ret; +} + +int32_t ParseCmdOption(CodecCmd* cmd, const char *opt, const char *next) +{ + int32_t ret = HDF_SUCCESS; + if (cmd == NULL || opt == NULL || next == NULL) { + return HDF_FAILURE; + } + switch (*opt) { + case 'i': { + int32_t len = strnlen(next, MAX_FILE_NAME_LENGTH); + if (len) { + strcpy_s(cmd->file_input, MAX_FILE_NAME_LENGTH, next); + } else { + ret = HDF_FAILURE; + } + } break; + case 'o': { + int32_t len = strnlen(next, MAX_FILE_NAME_LENGTH); + if (len) { + strcpy_s(cmd->file_output, MAX_FILE_NAME_LENGTH, next); + } else { + ret = HDF_FAILURE; + } + } break; + case 'w': { + cmd->width = atoi(next); + } break; + case 'h': { + cmd->height = atoi(next); + } break; + case 't': { + int32_t len = strnlen(next, TYPE_NAME_LENGTH); + if (len) { + strcpy_s(cmd->codecName, TYPE_NAME_LENGTH, next); + ret = GetCodecName(cmd); + } else { + ret = HDF_FAILURE; + } + } break; + default: + break; + } + return ret; +} + +int32_t ParseArguments(CodecCmd* cmd, int argc, char **argv) +{ + const char *opt; + const char *next; + int32_t optindex = 1; + int32_t handleoptions = 1; + int32_t ret = HDF_SUCCESS; + int32_t optMark = 0; + int32_t optName = 1; + + if ((argc <= 1) || (cmd == NULL)) + return ret; + + /* parse options */ + while (optindex < argc) { + opt = (const char*)argv[optindex++]; + next = (const char*)argv[optindex]; + optMark = CMD_OPTION_MARK_OFFSET; + optName = CMD_OPTION_NAME_OFFSET; + + if (handleoptions && opt[optMark] == '-' && opt[optName] != '\0') { + optMark++; + optName++; + if (opt[optMark] == '-' && opt[optName] != '\0') { + opt++; + } + if (opt[optMark] == '-' && opt[optName] == '\0') { + handleoptions = 0; + ret = HDF_FAILURE; + break; + } + + opt++; + if (ParseCmdOption(cmd, opt, next) == HDF_FAILURE) { + ret = HDF_FAILURE; + break; + } + optindex++; + } + } + return ret; +} \ No newline at end of file diff --git a/codec/test/demo/v1.0/codec_utils.h b/codec/test/demo/v1.0/codec_utils.h new file mode 100644 index 0000000000..35be4cd33d --- /dev/null +++ b/codec/test/demo/v1.0/codec_utils.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong DID Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CODEC_UTILS_H +#define __CODEC_UTILS_H + +#include "hdf_types.h" +#include "codec_type.h" + +#define MAX_FILE_NAME_LENGTH 256 +#define TYPE_NAME_LENGTH 256 + +/* For overall configure setup */ +typedef struct { + CodecType type; + char file_input[MAX_FILE_NAME_LENGTH]; + char file_output[MAX_FILE_NAME_LENGTH]; + char codecName[TYPE_NAME_LENGTH]; + int32_t width; + int32_t height; +} CodecCmd; + +int32_t ParseArguments(CodecCmd* cmd, int argc, char **argv); + +#endif // __CODEC_UTILS_H diff --git a/codec/test/unittest/BUILD.gn b/codec/test/unittest/BUILD.gn index d5bf08202d..529bce4933 100644 --- a/codec/test/unittest/BUILD.gn +++ b/codec/test/unittest/BUILD.gn @@ -13,8 +13,5 @@ group("hdf_unittest_codec") { testonly = true - deps = [ - "config:codec_config_test", - "hdi_omx:codec_hdi_omx_test", - ] + deps = [ "hdi_v1.0:codec_client_test" ] } diff --git a/codec/hdi_service/codec_test/BUILD.gn b/codec/test/unittest/hdi_v1.0/BUILD.gn similarity index 61% rename from codec/hdi_service/codec_test/BUILD.gn rename to codec/test/unittest/hdi_v1.0/BUILD.gn index ce51248d1a..36c9cbeed3 100644 --- a/codec/hdi_service/codec_test/BUILD.gn +++ b/codec/test/unittest/hdi_v1.0/BUILD.gn @@ -15,14 +15,21 @@ import("//drivers/adapter/uhdf2/uhdf.gni") module_output_path = "hdf/codec" -ohos_unittest("codec_test") { +ohos_unittest("codec_hdi_1.0_test") { module_out_path = module_output_path include_dirs = [ "//drivers/peripheral/codec/interfaces/include/", "//drivers/peripheral/codec/hdi_service/codec_proxy/", "//drivers/peripheral/codec/hdi_service/codec_service_stub/", + "//drivers/peripheral/codec/hal/config/capability_config/include", + "//drivers/peripheral/codec/hal/config/common/include", + "//drivers/peripheral/codec/hal/v1.0/share_mem/include", + ] + sources = [ + "//drivers/peripheral/codec/hal/config/capability_config/src/codec_config_reader.c", + "//drivers/peripheral/codec/hal/config/common/src/codec_utils.c", + "codec_proxy_test.cpp", ] - sources = [ "unittest/codec_proxy_test.cpp" ] cflags = [ "-Wall", @@ -38,13 +45,21 @@ ohos_unittest("codec_test") { "//drivers/peripheral/codec/hdi_service:codec_service", "//third_party/googletest:gtest_main", ] - external_deps = [ - "device_driver_framework:libhdf_utils", - "hiviewdfx_hilog_native:libhilog", - ] + + if (is_standard_system) { + external_deps = [ + "device_driver_framework:libhdf_host", + "device_driver_framework:libhdf_ipc_adapter", + "device_driver_framework:libhdf_utils", + "device_driver_framework:libhdi", + "hiviewdfx_hilog_native:libhilog", + ] + } else { + external_deps = [ "hilog:libhilog" ] + } } group("codec_client_test") { testonly = true - deps = [ ":codec_test" ] + deps = [ ":codec_hdi_1.0_test" ] } diff --git a/codec/test/unittest/hdi_v1.0/codec_proxy_test.cpp b/codec/test/unittest/hdi_v1.0/codec_proxy_test.cpp new file mode 100644 index 0000000000..15bca8caec --- /dev/null +++ b/codec/test/unittest/hdi_v1.0/codec_proxy_test.cpp @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "codec_callback_stub.h" +#include "codec_config_reader.h" +#include "codec_utils.h" +#include "icodec.h" +#include "share_mem.h" + +using namespace std; +using namespace testing::ext; + +namespace { +enum class ParamExtKeys { + KEY_START = 0xF000, + KEY_DEFAULT_CFG_RK, /**< Default config. Used for RK codec. */ + KEY_SPLIT_PARSE_RK, /**< Split parse. Used for RK codec. */ + KEY_DEC_FRAME_NUM_RK, /**< Decode frame number. Used for RK codec. */ + KEY_EXT_SETUP_DROP_MODE_RK, /**< Drop mode setup. Used for RK codec. */ + KEY_EXT_ENC_VALIDATE_SETUP_RK, /**< Validate config setup. Used for RK codec. */ + KEY_ENC_SETUP_AVC_RK, /**< AVC config setup. Used for RK codec. */ + KEY_ENC_FRAME_NUM_RK, /**< Frame num setup. Used for RK codec. */ + KEY_END = 0xFFFF, +}; + +constexpr const char *TEST_SERVICE_NAME = "codec_hdi_service"; +constexpr const int TEST_PACKET_BUFFER_SIZE = 4096; +constexpr const int TEST_FRAME_BUFFER_SIZE = 640 * 480 * 3 / 2; +constexpr const int QUEUE_TIME_OUT = 10; +struct ICodec *codecObj = nullptr; +ShareMemory inputBuffer; +ShareMemory outputBuffer; +InputInfo inputInfoData = {0}; +CodecBufferInfo inputCodecBufferInfo = {BUFFER_TYPE_FD}; +OutputInfo outputInfoData = {0}; +CodecBufferInfo outputCodecBufferInfo = {BUFFER_TYPE_FD}; +CODEC_HANDLETYPE handle = NULL; + +class CodecProxyTest : public testing::Test { +public: + ICodecCallback *g_callback = nullptr; + static void SetUpTestCase() {} + static void TearDownTestCase() {} + void SetUp() {} + void TearDown() {} +}; + +HWTEST_F(CodecProxyTest, CodecHdiGetCodecObj, TestSize.Level1) +{ + codecObj = HdiCodecGet(TEST_SERVICE_NAME); + ASSERT_TRUE(codecObj != nullptr); +} + +HWTEST_F(CodecProxyTest, CodecHdiEnumerateCapbility, TestSize.Level1) +{ + struct HdfRemoteService *remote = GetConfigService(); + ASSERT_TRUE(remote != nullptr); + + int32_t ret = HDF_SUCCESS; + for (int32_t index = 0; index < 8; index++) { + CodecCapbility cap; + ret = EnumrateCapability(remote, index, &cap); + ASSERT_EQ(ret, HDF_SUCCESS); + PrintCapability("codec_config_utest", &cap); + } +} + +HWTEST_F(CodecProxyTest, CodecHdiGetCapbility, TestSize.Level1) +{ + struct HdfRemoteService *remote = GetConfigService(); + ASSERT_TRUE(remote != nullptr); + + CodecCapbility cap; + int32_t ret = GetCapability(remote, MEDIA_MIMETYPE_VIDEO_HEVC, VIDEO_ENCODER, 0, &cap); + ASSERT_EQ(ret, HDF_SUCCESS); + PrintCapability("codec_config_utest", &cap); +} + +HWTEST_F(CodecProxyTest, CodecHdiInitCodec, TestSize.Level1) +{ + ASSERT_TRUE(codecObj != nullptr); + int32_t errorCode = codecObj->CodecInit(codecObj); + ASSERT_EQ(errorCode, HDF_SUCCESS); +} + +HWTEST_F(CodecProxyTest, CodecHdiCreateCodec, TestSize.Level1) +{ + const char* name = "codec.avc.hardware.decoder"; + Param params; + params.key = KEY_CODEC_TYPE; + CodecType ct = VIDEO_DECODER; + params.val = (void *)&ct; + params.size = sizeof(ct); + int len = 1; + + int32_t errorCode = codecObj->CodecCreate(codecObj, name, ¶ms, len, &handle); + + ASSERT_EQ(errorCode, HDF_SUCCESS); + ASSERT_TRUE(handle != nullptr); +} + +HWTEST_F(CodecProxyTest, CodecHdiSetPortMode, TestSize.Level1) +{ + DirectionType type = OUTPUT_TYPE; + BufferMode mode = EXTERNAL; + + int32_t errorCode = codecObj->CodecSetPortMode(codecObj, handle, type, mode); + ASSERT_EQ(errorCode, HDF_SUCCESS); +} + +HWTEST_F(CodecProxyTest, CodecHdiSetCodecType, TestSize.Level1) +{ + Param *params; + int paramCnt = 1; + params = (Param *)OsalMemAlloc(sizeof(Param)*paramCnt); + ASSERT_TRUE(params != nullptr); + params->key = KEY_CODEC_TYPE; + CodecType ct = VIDEO_DECODER; + params->val = (void *)&ct; + params->size = sizeof(ct); + + int32_t errorCode = codecObj->CodecSetParameter(codecObj, handle, params, paramCnt); + OsalMemFree(params); + ASSERT_EQ(errorCode, HDF_SUCCESS); +} + +HWTEST_F(CodecProxyTest, CodecHdiGetDefaultCfg, TestSize.Level1) +{ + Param *params; + int paramCnt = 1; + params = (Param *)OsalMemAlloc(sizeof(Param)*paramCnt); + ASSERT_TRUE(params != nullptr); + params->key = (ParamKey)ParamExtKeys::KEY_DEFAULT_CFG_RK; + params->val = nullptr; + params->size = 0; + + int32_t errorCode = codecObj->CodecGetParameter(codecObj, handle, params, paramCnt); + OsalMemFree(params); + ASSERT_EQ(errorCode, HDF_SUCCESS); +} + +HWTEST_F(CodecProxyTest, CodecHdiSetSplitMode, TestSize.Level1) +{ + Param *params; + int paramCnt = 1; + params = (Param *)OsalMemAlloc(sizeof(Param)*paramCnt); + ASSERT_TRUE(params != nullptr); + params->key = (ParamKey)ParamExtKeys::KEY_SPLIT_PARSE_RK; + int32_t needSplit = 1; + params->val = (void *)&needSplit; + params->size = sizeof(needSplit); + + int32_t errorCode = codecObj->CodecSetParameter(codecObj, handle, params, paramCnt); + OsalMemFree(params); + ASSERT_EQ(errorCode, HDF_SUCCESS); +} + +HWTEST_F(CodecProxyTest, CodecHdiQueueInput, TestSize.Level1) +{ + inputBuffer.id = 0; + inputBuffer.size = TEST_PACKET_BUFFER_SIZE; + int32_t ret = CreateShareMemory(&inputBuffer); + ASSERT_EQ(ret, HDF_SUCCESS); + inputInfoData.bufferCnt = 1; + inputInfoData.flag = STREAM_FLAG_CODEC_SPECIFIC_INF; + inputInfoData.buffers = &inputCodecBufferInfo; + if (inputInfoData.buffers != NULL) { + inputInfoData.buffers->type = BUFFER_TYPE_FD; + inputInfoData.buffers->fd = inputBuffer.fd; + inputInfoData.buffers->offset = inputBuffer.id; + inputInfoData.buffers->size = TEST_PACKET_BUFFER_SIZE; + } + int32_t errorCode = codecObj->CodecQueueInput(codecObj, handle, &inputInfoData, (uint32_t)0); + ASSERT_EQ(errorCode, HDF_SUCCESS); +} + +HWTEST_F(CodecProxyTest, CodecHdiDequeInput, TestSize.Level1) +{ + InputInfo inputInfo = {0}; + CodecBufferInfo codecBufferInfo = {BUFFER_TYPE_FD}; + + inputInfo.bufferCnt = 1; + inputInfo.buffers = &codecBufferInfo; + int32_t errorCode = codecObj->CodecDequeInput(codecObj, handle, QUEUE_TIME_OUT, &inputInfo); + ASSERT_EQ(errorCode, HDF_SUCCESS); + ASSERT_EQ(inputInfo.buffers->type, inputInfoData.buffers->type); + ASSERT_EQ(inputInfo.buffers->size, inputInfoData.buffers->size); + ASSERT_EQ(inputInfo.buffers->offset, inputInfoData.buffers->offset); +} + +HWTEST_F(CodecProxyTest, CodecHdiStartCodec, TestSize.Level1) +{ + int32_t errorCode = codecObj->CodecStart(codecObj, handle); + ASSERT_EQ(errorCode, HDF_SUCCESS); +} + +HWTEST_F(CodecProxyTest, CodecHdiStopCodec, TestSize.Level1) +{ + int32_t errorCode = codecObj->CodecStop(codecObj, handle); + ASSERT_EQ(errorCode, HDF_SUCCESS); +} + +HWTEST_F(CodecProxyTest, CodecHdiQueueOutput, TestSize.Level1) +{ + outputBuffer.id = 1; + outputBuffer.size = TEST_FRAME_BUFFER_SIZE; + CreateShareMemory(&outputBuffer); + outputInfoData.bufferCnt = 1; + outputInfoData.flag = STREAM_FLAG_CODEC_SPECIFIC_INF; + outputInfoData.buffers = &outputCodecBufferInfo; + if (outputInfoData.buffers != NULL) { + outputInfoData.buffers->type = BUFFER_TYPE_FD; + outputInfoData.buffers->fd = outputBuffer.fd; + outputInfoData.buffers->offset = outputBuffer.id; + outputInfoData.buffers->size = TEST_FRAME_BUFFER_SIZE; + } + int32_t errorCode = codecObj->CodecQueueOutput(codecObj, handle, &outputInfoData, (uint32_t)0, 1); + ASSERT_EQ(errorCode, HDF_SUCCESS); +} + +HWTEST_F(CodecProxyTest, CodecHdiDequeueOutput, TestSize.Level1) +{ + int32_t errorCode = 0; + int32_t acquireFd; + OutputInfo outInfo = {0}; + CodecBufferInfo codecBufferInfo = {BUFFER_TYPE_FD}; + outInfo.bufferCnt = 1; + outInfo.buffers = &codecBufferInfo; + errorCode = codecObj->CodecDequeueOutput(codecObj, handle, QUEUE_TIME_OUT, &acquireFd, &outInfo); + ASSERT_EQ(errorCode, HDF_SUCCESS); + ASSERT_EQ(outInfo.buffers->type, outputInfoData.buffers->type); + ASSERT_EQ(outInfo.buffers->size, outputInfoData.buffers->size); + ASSERT_EQ(outInfo.buffers->offset, outputInfoData.buffers->offset); +} + +HWTEST_F(CodecProxyTest, CodecHdiFlush, TestSize.Level1) +{ + DirectionType directType = OUTPUT_TYPE; + + int32_t errorCode = codecObj->CodecFlush(codecObj, handle, directType); + ASSERT_EQ(errorCode, HDF_SUCCESS); + ASSERT_EQ(directType, OUTPUT_TYPE); +} + +HWTEST_F(CodecProxyTest, CodecHdiSetCallback, TestSize.Level1) +{ + UINTPTR instance = 0; + g_callback = CodecCallbackStubObtain(); + ASSERT_TRUE(g_callback != nullptr); + + int32_t errorCode = codecObj->CodecSetCallback(codecObj, handle, g_callback, instance); + ASSERT_EQ(errorCode, HDF_SUCCESS); +} + +HWTEST_F(CodecProxyTest, CodecHdiDestroyCodec, TestSize.Level1) +{ + int32_t errorCode = codecObj->CodecDestroy(codecObj, handle); + ASSERT_EQ(errorCode, HDF_SUCCESS); +} + +HWTEST_F(CodecProxyTest, CodecHdiDeinit, TestSize.Level1) +{ + int32_t errorCode = codecObj->CodecDeinit(codecObj); + ASSERT_EQ(errorCode, HDF_SUCCESS); + HdiCodecRelease(codecObj); +} +} -- Gitee