From: Jeongmo Yang Date: Tue, 11 Mar 2025 10:59:00 +0000 (+0900) Subject: Support HAL backend service X-Git-Tag: accepted/tizen/unified/20250313.164544^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c4af14809d6b6d583fbc13c6a348567336e1636e;p=platform%2Fhal%2Fapi%2Fcodec.git Support HAL backend service [Version] 1.1.0 [Issue Type] New feature Change-Id: I315f224b589702c6688424f9bbda359a9df7973b Signed-off-by: Jeongmo Yang --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 38e87ea..111fc1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,14 +5,18 @@ SET(PREFIX ${CMAKE_INSTALL_PREFIX}) SET(EXEC_PREFIX "${CMAKE_INSTALL_PREFIX}/bin") SET(INCLUDEDIR "${CMAKE_INSTALL_PREFIX}/include") SET(LIBDIR ${CMAKE_LIBDIR_PREFIX}) -SET(VERSION_MAJOR 1) -SET(VERSION "${VERSION_MAJOR}.0.0") -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/generated) SET(PKG_MODULES dlog glib-2.0 + rpc-port + bundle + capi-appfw-app-common + capi-appfw-app-manager + capi-appfw-package-manager hal-api-common ) @@ -25,15 +29,24 @@ ENDFOREACH(flag) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -fno-omit-frame-pointer -finstrument-functions") SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fPIC -Wall -Wextra -Wno-array-bounds -Wno-empty-body -Wno-ignored-qualifiers -Wno-unused-parameter -Wshadow -Wwrite-strings -Wswitch-default -Wno-unused-but-set-parameter -Wno-unused-but-set-variable") -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -lrt") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -lrt -Wno-discarded-qualifiers") -SET(SRCS src/hal-api-codec.c) +SET(SRCS + src/generated/hal_codec_proxy_1.c + src/hal-api-codec.c + src/hal-api-codec-passthrough.c + src/hal-api-codec-ipc.c +) ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS}) TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} -Wl,--as-needed -Wl,--rpath=${LIBDIR}/hal) -SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${VERSION_MAJOR}) -SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${VERSION}) + +SET_TARGET_PROPERTIES(${PROJECT_NAME} + PROPERTIES + VERSION ${FULLVER} + SOVERSION ${MAJORVER} +) CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY) @@ -45,6 +58,8 @@ INSTALL(DIRECTORY include/ DESTINATION include/hal INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc DESTINATION ${LIBDIR}/pkgconfig) +ADD_SUBDIRECTORY(src/service_plugin) + IF(ENABLE_TESTS) ADD_SUBDIRECTORY(tests) ENDIF(ENABLE_TESTS) diff --git a/include/hal-codec-ipc.h b/include/hal-codec-ipc.h new file mode 100644 index 0000000..749d0f1 --- /dev/null +++ b/include/hal-codec-ipc.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2025 Samsung Electronics 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 __HAL_CODEC_IPC__ +#define __HAL_CODEC_IPC__ + +#include "hal-codec-interface.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#define HAL_BACKEND_SERVICE_APPID "d::HalBackendService" + +#define HAL_CODEC_IPC_PARAM_KEY_BUFFER "HAL_CODEC_BUFFER_S" +#define HAL_CODEC_IPC_PARAM_KEY_PLANE0_DATA "HAL_CODEC_PLANE0" +#define HAL_CODEC_IPC_PARAM_KEY_PLANE1_DATA "HAL_CODEC_PLANE1" +#define HAL_CODEC_IPC_PARAM_KEY_PLANE2_DATA "HAL_CODEC_PLANE2" +#define HAL_CODEC_IPC_PARAM_KEY_PLANE3_DATA "HAL_CODEC_PLANE3" +#define HAL_CODEC_IPC_PARAM_KEY_MESSAGE "HAL_CODEC_MESSAGE_S" + +#define HAL_CODEC_BUFFER_MAX 32 + + +int hal_codec_ipc_init(hal_codec_type_e type, void **codec_handle); +int hal_codec_ipc_deinit(void *codec_handle); +int hal_codec_ipc_configure(void *codec_handle, int width, int height, hal_codec_format_e in_format, hal_codec_format_e out_format, bool is_secure); +int hal_codec_ipc_release(void *codec_handle); +int hal_codec_ipc_start(void *codec_handle, hal_codec_message_cb callback, void *user_data); +int hal_codec_ipc_stop(void *codec_handle); +int hal_codec_ipc_flush(void *codec_handle); +int hal_codec_ipc_decode(void *codec_handle, hal_codec_buffer_s *buffer); +int hal_codec_ipc_encode(void *codec_handle, hal_codec_buffer_s *buffer); +int hal_codec_ipc_release_output_buffer(void *codec_handle, int buffer_index); +int hal_codec_ipc_get_state(void *codec_handle, hal_codec_state_e *state); +int hal_codec_ipc_set_command(void *codec_handle, hal_codec_command_e command, void *value); +int hal_codec_ipc_get_command(void *codec_handle, hal_codec_command_e command, void **value); +int hal_codec_ipc_set_batch_command(void *codec_handle, hal_codec_batch_command_control_s *batch_command, hal_codec_command_e *error_command); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __HAL_CODEC_IPC__ */ diff --git a/include/hal-codec-passthrough.h b/include/hal-codec-passthrough.h new file mode 100644 index 0000000..4bce2af --- /dev/null +++ b/include/hal-codec-passthrough.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Samsung Electronics 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 __HAL_CODEC_PASSTHROUGH__ +#define __HAL_CODEC_PASSTHROUGH__ + +#include "hal-codec-interface.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +int hal_codec_passthrough_init(hal_codec_type_e type, void **codec_handle); +int hal_codec_passthrough_deinit(void *codec_handle); +int hal_codec_passthrough_configure(void *codec_handle, int width, int height, hal_codec_format_e in_format, hal_codec_format_e out_format, bool is_secure); +int hal_codec_passthrough_release(void *codec_handle); +int hal_codec_passthrough_start(void *codec_handle, hal_codec_message_cb callback, void *user_data); +int hal_codec_passthrough_stop(void *codec_handle); +int hal_codec_passthrough_flush(void *codec_handle); +int hal_codec_passthrough_decode(void *codec_handle, hal_codec_buffer_s *buffer); +int hal_codec_passthrough_encode(void *codec_handle, hal_codec_buffer_s *buffer); +int hal_codec_passthrough_release_output_buffer(void *codec_handle, int buffer_index); +int hal_codec_passthrough_get_state(void *codec_handle, hal_codec_state_e *state); +int hal_codec_passthrough_set_command(void *codec_handle, hal_codec_command_e command, void *value); +int hal_codec_passthrough_get_command(void *codec_handle, hal_codec_command_e command, void **value); +int hal_codec_passthrough_set_batch_command(void *codec_handle, hal_codec_batch_command_control_s *batch_command, hal_codec_command_e *error_command); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __HAL_CODEC_PASSTHROUGH__ */ diff --git a/include/hal_codec_ipc_1.tidl b/include/hal_codec_ipc_1.tidl new file mode 100644 index 0000000..7e44634 --- /dev/null +++ b/include/hal_codec_ipc_1.tidl @@ -0,0 +1,26 @@ +protocol 2 + +interface codec { + void message(bundle msg, array fd) delegate; + + int init(int type); + int deinit(); + + int configure(int width, int height, int in_format, int out_format, bool is_secure); + int release(); + + int start(message callback); + int stop(); + int flush(); + + int decode(bundle buffer); + int encode(bundle buffer, array fd); + int release_output_buffer(int buffer_index); + + int get_state(out int state); + + int set_command(long command, bundle value); + int get_command(long command, out bundle value); + int set_batch_command(bundle command, out long error_command); +} + diff --git a/packaging/hal-api-codec-manifest.xml b/packaging/hal-api-codec-manifest.xml index ef7b3ef..f8e8ea0 100644 --- a/packaging/hal-api-codec-manifest.xml +++ b/packaging/hal-api-codec-manifest.xml @@ -2,7 +2,7 @@ HAL_MODULE_CODEC - 1.0 + 1.0 diff --git a/packaging/hal-api-codec.spec b/packaging/hal-api-codec.spec index 5d05100..67e820a 100644 --- a/packaging/hal-api-codec.spec +++ b/packaging/hal-api-codec.spec @@ -6,7 +6,7 @@ ### main package ######### Name: %{name} Summary: %{name} interface -Version: 1.0.0 +Version: 1.1.0 Release: 0 Group: Development/Libraries License: Apache-2.0 @@ -18,6 +18,12 @@ BuildRequires: cmake BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(hal-api-common) +BuildRequires: tidl +BuildRequires: pkgconfig(rpc-port) +BuildRequires: pkgconfig(bundle) +BuildRequires: pkgconfig(capi-appfw-app-common) +BuildRequires: pkgconfig(capi-appfw-app-manager) +BuildRequires: pkgconfig(capi-appfw-package-manager) %if "%{enable_test}" == "1" BuildRequires: pkgconfig(gmock) %endif @@ -49,15 +55,29 @@ Haltests for %{name} ### build and install ######### %prep %setup -q + +mkdir -p ./src/generated +pushd src/generated +tidlc -p -l C -i ../../include/hal_codec_ipc_1.tidl -o hal_codec_proxy_1 +popd + +mkdir -p ./src/service_plugin/generated +pushd src/service_plugin/generated +tidlc -s -l C -i ../../../include/hal_codec_ipc_1.tidl -o hal_codec_stub_1 +popd + %if "%{enable_test}" == "1" export CXXFLAGS+=" -D_LARGEFILE64_SOURCE -DSYSCONFDIR=\\\"%{_hal_sysconfdir}\\\" -DTEST_FILES_PATH=\\\"%{_datadir}%{res_path}\\\"" %endif +MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` %cmake . \ %if "%{enable_test}" == "1" -DENABLE_TESTS=YES\ -DTESTCASE_RES_DIR=%{_datadir}%{res_path}\ %endif + -DFULLVER=%{version}\ + -DMAJORVER=${MAJORVER}\ -DCMAKE_INSTALL_PREFIX=%{_prefix}\ -DCMAKE_LIBDIR_PREFIX=%{_libdir} @@ -91,13 +111,14 @@ rm -rf %{buildroot} %license LICENSE %defattr(-,root,root,-) %{_libdir}/hal/*.so.* +%{_libdir}/hal/libhal-backend-service-codec.so %{_sysconfdir}/hal/%{name}-manifest.xml %files devel %defattr(-,root,root,-) %{_includedir}/hal/*.h -%{_libdir}/hal/*.so +%{_libdir}/hal/libhal-api-*.so %{_libdir}/pkgconfig/*.pc %if "%{enable_test}" == "1" diff --git a/src/hal-api-codec-ipc.c b/src/hal-api-codec-ipc.c new file mode 100644 index 0000000..c39b01e --- /dev/null +++ b/src/hal-api-codec-ipc.c @@ -0,0 +1,695 @@ +/* + * Copyright (c) 2025 Samsung Electronics 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 +#include +#include + +#include +#include + +#include "hal-codec-ipc.h" +#include "hal_codec_proxy_1.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "HALAPI_CODEC_IPC" + +#define HAL_CODEC_IPC_CONNECT_COUNT_MAX 10 + + +#define HAL_CODEC_RETURN_IF_FAILED(arg) \ + do {\ + if (!(arg)) {\ + SLOGE("[%s]failed", #arg);\ + return;\ + }\ + } while (0) + +#define HAL_CODEC_RETURN_VAL_IF_FAILED(arg, ret) \ + do {\ + if (!(arg)) {\ + SLOGE("[%s]failed, return[%s]", #arg, #ret);\ + return (ret);\ + }\ + } while (0) + +typedef struct _hal_codec_ipc_s { + rpc_port_proxy_codec_h rpc_handle; + rpc_port_proxy_codec_message_h rpc_msg_handle; + + hal_codec_message_cb msg_cb; + void *msg_cb_data; + + GMutex buffer_lock; + GMutex msg_lock; + + hal_codec_buffer_s *input_buffers[HAL_CODEC_BUFFER_MAX]; + hal_codec_buffer_s *output_buffers[HAL_CODEC_BUFFER_MAX]; +} hal_codec_ipc_s; + + +static void __hal_codec_ipc_connected(rpc_port_proxy_codec_h h, void *user_data) +{ + SLOGI("connected: handle[%p]", h); +} + + +static void __hal_codec_ipc_disconnected(rpc_port_proxy_codec_h h, void *user_data) +{ + SLOGI("disonnected: handle[%p]", h); +} + + +static void __hal_codec_ipc_rejected(rpc_port_proxy_codec_h h, void *user_data) +{ + SLOGE("connection rejected: handle[%p]", h); +} + + +static void __hal_codec_ipc_hal_buffer_release(hal_codec_buffer_s *hal_buffer) +{ + uint32_t i = 0; + size_t unmap_size = 0; + + if (!hal_buffer) { + SLOGD("NULL buffer"); + return; + } + + SLOGD("release hal buffer[%d] %p", hal_buffer->index, hal_buffer); + + for (i = 0 ; i < hal_buffer->memory.num_fd ; i++) { + if (hal_buffer->memory.fd[i] > 0) { + SLOGD(" close fd[%u] %d", i, hal_buffer->memory.fd[i]); + close(hal_buffer->memory.fd[i]); + hal_buffer->memory.fd[i] = 0; + } else { + SLOGW(" invalid fd[%u] %d", i, hal_buffer->memory.fd[i]); + } + + if (hal_buffer->memory.num_fd == 1) + unmap_size = hal_buffer->size; + else + unmap_size = hal_buffer->planes.plane[i].size; + + if (hal_buffer->planes.plane[i].data) { + SLOGD(" munmap data[%u] %p, size[%zu]", i, hal_buffer->planes.plane[i].data, unmap_size); + if (munmap(hal_buffer->planes.plane[i].data, unmap_size) != 0) + SLOGE(" munmap failed for data[%u] %p, size[%zu]", i, hal_buffer->planes.plane[i].data, unmap_size); + } + } + + g_free(hal_buffer); +} + + +static void __hal_codec_ipc_message_cb(void *user_data, bundle *b_msg, rpc_port_proxy_array_file_desc_h fd_handle) +{ + int i = 0; + int ipc_ret = 0; + int *fd = NULL; + int fd_size = 0; + void *b_data = NULL; + size_t mmap_length = 0; + size_t hal_message_size = 0; + size_t hal_buffer_size = 0; + hal_codec_message_s *hal_message = NULL; + hal_codec_buffer_s *hal_buffer = NULL; + hal_codec_ipc_s *handle = (hal_codec_ipc_s *)user_data; + + HAL_CODEC_RETURN_IF_FAILED(handle); + HAL_CODEC_RETURN_IF_FAILED(b_msg); + HAL_CODEC_RETURN_IF_FAILED(fd_handle); + + /* message */ + ipc_ret = bundle_get_byte(b_msg, HAL_CODEC_IPC_PARAM_KEY_MESSAGE, (void **)&hal_message, &hal_message_size); + if (ipc_ret != BUNDLE_ERROR_NONE || + hal_message_size != sizeof(hal_codec_message_s)) { + SLOGE("get message from bundle failed[0x%x], size[%zu:%zu]", + ipc_ret, hal_message_size, sizeof(hal_codec_message_s)); + return; + } + + SLOGD("message: type[%d]", hal_message->type); + + switch (hal_message->type) { + case HAL_CODEC_MESSAGE_TYPE_INPUT_BUFFER_USED: + ipc_ret = bundle_get_byte(b_msg, HAL_CODEC_IPC_PARAM_KEY_BUFFER, (void **)&hal_buffer, &hal_buffer_size); + if (ipc_ret != BUNDLE_ERROR_NONE || + hal_buffer_size != sizeof(hal_codec_buffer_s)) { + SLOGE("get message from bundle failed[0x%x], size[%zu:%zu]", + ipc_ret, hal_message_size, sizeof(hal_codec_message_s)); + goto _CODEC_IPC_MESSAGE_CB_DONE; + } + + if (hal_buffer->index >= HAL_CODEC_BUFFER_MAX) { + SLOGE("[INPUT_USED] invalid buffer index[%d]", hal_buffer->index); + goto _CODEC_IPC_MESSAGE_CB_DONE; + } + + g_mutex_lock(&handle->buffer_lock); + + if (!handle->input_buffers[hal_buffer->index]) { + SLOGE("[INPUT_USED] NULL buffer for index[%d]", hal_buffer->index); + g_mutex_unlock(&handle->buffer_lock); + goto _CODEC_IPC_MESSAGE_CB_DONE; + } + + hal_message->buffer = handle->input_buffers[hal_buffer->index]; + handle->input_buffers[hal_buffer->index] = NULL; + + SLOGD("check index [%d] vs [%d]", hal_message->buffer->index, hal_buffer->index); + + g_mutex_unlock(&handle->buffer_lock); + + break; + + case HAL_CODEC_MESSAGE_TYPE_OUTPUT_BUFFER: + ipc_ret = bundle_get_byte(b_msg, HAL_CODEC_IPC_PARAM_KEY_BUFFER, (void **)&b_data, &hal_buffer_size); + if (ipc_ret != BUNDLE_ERROR_NONE || + hal_buffer_size != sizeof(hal_codec_buffer_s)) { + SLOGE("get message from bundle failed[0x%x], size[%zu:%zu]", + ipc_ret, hal_message_size, sizeof(hal_codec_message_s)); + goto _CODEC_IPC_MESSAGE_CB_DONE; + } + + hal_buffer = g_memdup2(b_data, hal_buffer_size); + + ipc_ret = rpc_port_proxy_array_file_desc_get(fd_handle, &fd, &fd_size); + if (ipc_ret != RPC_PORT_ERROR_NONE || + hal_buffer->memory.num_fd != (uint32_t)fd_size) { + SLOGE("get fd failed[0x%x], num_fd[%u] vs fd_size[%d]", + ipc_ret, hal_buffer->memory.num_fd, fd_size); + goto _CODEC_IPC_MESSAGE_CB_DONE; + } + + for (i = 0 ; i < fd_size ; i++) { + SLOGD("[OUTPUT] fd[%d] %d", i, fd[i]); + hal_buffer->memory.fd[i] = fd[i]; + + if (fd_size == 1) + mmap_length = hal_buffer->size; + else + mmap_length = hal_buffer->planes.plane[i].size; + + hal_buffer->planes.plane[i].data = mmap(NULL, + mmap_length, PROT_READ | PROT_WRITE, + MAP_SHARED, fd[i], 0); + if (hal_buffer->planes.plane[i].data == MAP_FAILED) { + hal_buffer->planes.plane[i].data = NULL; + SLOGE(" mmap failed for fd[%d] %d", i, fd[i]); + } else { + SLOGD("plane[%d] data %p", i, hal_buffer->planes.plane[i].data); + } + } + + if (fd_size != (int)hal_buffer->planes.num_planes) { + for (i = 1 ; i < (int)hal_buffer->planes.num_planes ; i++) { + hal_buffer->planes.plane[i].data = hal_buffer->planes.plane[i-1].data + hal_buffer->planes.plane[i-1].size; + SLOGD("plane[%d] data %p", i, hal_buffer->planes.plane[i].data); + } + } + + g_mutex_lock(&handle->buffer_lock); + + if (handle->output_buffers[hal_buffer->index]) { + SLOGE("duplicated buffer index[%d]", hal_buffer->index); + g_free(hal_buffer); + g_mutex_unlock(&handle->buffer_lock); + goto _CODEC_IPC_MESSAGE_CB_DONE; + } + + hal_message->buffer = hal_buffer; + handle->output_buffers[hal_buffer->index] = hal_buffer; + + g_mutex_unlock(&handle->buffer_lock); + + /* The fd will be closed in release_output_buffer via hal_buffer. */ + fd = NULL; + fd_size = 0; + break; + + case HAL_CODEC_MESSAGE_TYPE_RESOLUTION_CHANGED: + break; + + default: + break; + } + + g_mutex_lock(&handle->msg_lock); + + if (handle->msg_cb) { + SLOGD(">>>>> msg cb: type[%d]", hal_message->type); + ((hal_codec_message_cb)handle->msg_cb)(hal_message, handle->msg_cb_data); + SLOGD("<<<<< msg cb: type[%d]", hal_message->type); + } else { + SLOGW("no msg cb for handle[%p]", handle); + + if (hal_message->type == HAL_CODEC_MESSAGE_TYPE_OUTPUT_BUFFER) { + SLOGW("release output buffer[%d]", hal_message->buffer->index); + hal_codec_ipc_release_output_buffer(handle, hal_message->buffer->index); + } + } + + g_mutex_unlock(&handle->msg_lock); + +_CODEC_IPC_MESSAGE_CB_DONE: + for (i = 0 ; i < fd_size && fd ; i++) { + /* error case */ + SLOGW("message type[%d]: close fd[%d] %d", hal_message->type, i, fd[i]); + close(fd[i]); + } +} + + +int hal_codec_ipc_init(hal_codec_type_e type, void **codec_handle) +{ + int ret = 0; + int connect_count = 0; + hal_codec_ipc_s *new_handle = NULL; + rpc_port_proxy_codec_callback_s rpc_callbacks = { + .connected = __hal_codec_ipc_connected, + .disconnected = __hal_codec_ipc_disconnected, + .rejected = __hal_codec_ipc_rejected + }; + + HAL_CODEC_RETURN_VAL_IF_FAILED(codec_handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + + SLOGI("start"); + + new_handle = g_new0(hal_codec_ipc_s, 1); + + ret = rpc_port_proxy_codec_create(HAL_BACKEND_SERVICE_APPID, + &rpc_callbacks, NULL, &new_handle->rpc_handle); + if (ret != RPC_PORT_ERROR_NONE) { + SLOGE("RPC handle failed[0x%x]", ret); + g_free(new_handle); + return HAL_CODEC_ERROR_INTERNAL; + } + + while (connect_count++ < HAL_CODEC_IPC_CONNECT_COUNT_MAX) { + ret = rpc_port_proxy_codec_connect_sync(new_handle->rpc_handle); + if (ret == RPC_PORT_ERROR_NONE) + break; + + SLOGW("RPC connect failed: ret[0x%x], retry(%d)...", ret, connect_count); + + g_usleep(100000); + } + + if (ret != RPC_PORT_ERROR_NONE) { + rpc_port_proxy_codec_destroy(new_handle->rpc_handle); + g_free(new_handle); + return HAL_CODEC_ERROR_INTERNAL; + } + + ret = rpc_port_proxy_codec_invoke_init(new_handle->rpc_handle, type); + if (ret != RPC_PORT_ERROR_NONE) { + SLOGE("invoke init failed[0x%x]", ret); + rpc_port_proxy_codec_destroy(new_handle->rpc_handle); + g_free(new_handle); + return HAL_CODEC_ERROR_INTERNAL; + } + + g_mutex_init(&new_handle->buffer_lock); + g_mutex_init(&new_handle->msg_lock); + + *codec_handle = (void *)new_handle; + + SLOGI("new handle[%p:,rpc:%p]", new_handle, new_handle->rpc_handle); + + return HAL_CODEC_ERROR_NONE; +} + + +int hal_codec_ipc_deinit(void *codec_handle) +{ + int ret = 0; + hal_codec_ipc_s *handle = (hal_codec_ipc_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->rpc_handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + + SLOGI("start"); + + ret = rpc_port_proxy_codec_invoke_deinit(handle->rpc_handle); + if (ret != RPC_PORT_ERROR_NONE) { + SLOGE("invoke deinit failed[0x%x]", ret); + return HAL_CODEC_ERROR_INTERNAL; + } + + if (handle->rpc_msg_handle) { + ret = rpc_port_proxy_codec_message_dispose(handle->rpc_handle, handle->rpc_msg_handle); + if (ret != RPC_PORT_ERROR_NONE) + rpc_port_proxy_codec_message_destroy(handle->rpc_msg_handle); + handle->rpc_msg_handle = NULL; + } + + ret = rpc_port_proxy_codec_disconnect(handle->rpc_handle); + if (ret != RPC_PORT_ERROR_NONE) { + SLOGE("disconnect failed: handle[%p], ret[%d]", handle->rpc_handle, ret); + return HAL_CODEC_ERROR_INTERNAL; + } + + ret = rpc_port_proxy_codec_destroy(handle->rpc_handle); + if (ret != RPC_PORT_ERROR_NONE) { + SLOGE("destroy failed: handle[%p], ret[%d]", handle->rpc_handle, ret); + return HAL_CODEC_ERROR_INTERNAL; + } + + g_mutex_clear(&handle->buffer_lock); + g_mutex_clear(&handle->msg_lock); + + SLOGI("release handle[%p]", handle); + + g_free(handle); + + return HAL_CODEC_ERROR_NONE; +} + + +int hal_codec_ipc_configure(void *codec_handle, int width, int height, hal_codec_format_e in_format, hal_codec_format_e out_format, bool is_secure) +{ + hal_codec_ipc_s *handle = (hal_codec_ipc_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->rpc_handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + + return rpc_port_proxy_codec_invoke_configure(handle->rpc_handle, width, height, in_format, out_format, is_secure); +} + + +int hal_codec_ipc_release(void *codec_handle) +{ + hal_codec_ipc_s *handle = (hal_codec_ipc_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->rpc_handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + + return rpc_port_proxy_codec_invoke_release(handle->rpc_handle); +} + + +int hal_codec_ipc_start(void *codec_handle, hal_codec_message_cb callback, void *user_data) +{ + int ret = HAL_CODEC_ERROR_NONE; + int ipc_ret = 0; + hal_codec_ipc_s *handle = (hal_codec_ipc_s *)codec_handle; + rpc_port_proxy_codec_message_h msg_handle = NULL; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->rpc_handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + + ipc_ret = rpc_port_proxy_codec_message_create(&msg_handle); + if (ipc_ret != RPC_PORT_ERROR_NONE) { + SLOGE("msg handle create failed[0x%x]", ipc_ret); + return HAL_CODEC_ERROR_OUT_OF_MEMORY; + } + + ipc_ret = rpc_port_proxy_codec_message_set_callback(msg_handle, + __hal_codec_ipc_message_cb, handle); + if (ipc_ret != RPC_PORT_ERROR_NONE) { + SLOGE("set callback failed[0x%x]", ipc_ret); + rpc_port_proxy_codec_message_destroy(msg_handle); + return HAL_CODEC_ERROR_INTERNAL; + } + + rpc_port_proxy_codec_message_set_once(msg_handle, false); + + g_mutex_lock(&handle->msg_lock); + + ret = rpc_port_proxy_codec_invoke_start(handle->rpc_handle, msg_handle); + if (ret == HAL_CODEC_ERROR_NONE) { + handle->msg_cb = callback; + handle->msg_cb_data = user_data; + handle->rpc_msg_handle = msg_handle; + } else { + SLOGE("start failed[0x%x]", ret); + rpc_port_proxy_codec_message_destroy(msg_handle); + } + + g_mutex_unlock(&handle->msg_lock); + + return ret; +} + + +int hal_codec_ipc_stop(void *codec_handle) +{ + int ret = HAL_CODEC_ERROR_NONE; + int ipc_ret = 0; + hal_codec_ipc_s *handle = (hal_codec_ipc_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->rpc_handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + + ret = rpc_port_proxy_codec_invoke_stop(handle->rpc_handle); + + g_mutex_lock(&handle->msg_lock); + + if (ret == HAL_CODEC_ERROR_NONE) { + handle->msg_cb = NULL; + handle->msg_cb_data = NULL; + + SLOGI("dispose msg handle[%p]", handle->rpc_msg_handle); + + if (handle->rpc_msg_handle) { + ipc_ret = rpc_port_proxy_codec_message_dispose(handle->rpc_handle, handle->rpc_msg_handle); + if (ipc_ret != RPC_PORT_ERROR_NONE) { + SLOGW("msg handle dispose failed[0x%x]", ipc_ret); + rpc_port_proxy_codec_message_destroy(handle->rpc_msg_handle); + } + + handle->rpc_msg_handle = NULL; + } + } + + g_mutex_unlock(&handle->msg_lock); + + return ret; +} + + +int hal_codec_ipc_flush(void *codec_handle) +{ + hal_codec_ipc_s *handle = (hal_codec_ipc_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->rpc_handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + + return rpc_port_proxy_codec_invoke_flush(handle->rpc_handle); +} + + +int hal_codec_ipc_decode(void *codec_handle, hal_codec_buffer_s *buffer) +{ + int ret = HAL_CODEC_ERROR_NONE; + int ipc_ret = 0; + hal_codec_ipc_s *handle = (hal_codec_ipc_s *)codec_handle; + bundle *b_buffer = NULL; + g_autoptr(GMutexLocker) locker = NULL; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->rpc_handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(buffer, HAL_CODEC_ERROR_INVALID_PARAMETER); + + if (buffer->index >= HAL_CODEC_BUFFER_MAX) { + SLOGE("invalid buffer index[%d]", buffer->index); + return HAL_CODEC_ERROR_INVALID_PARAMETER; + } + + locker = g_mutex_locker_new(&handle->buffer_lock); + + if (handle->input_buffers[buffer->index]) { + SLOGE("already existed input buffer[%d] %p", + buffer->index, handle->input_buffers[buffer->index]); + return HAL_CODEC_ERROR_INVALID_PARAMETER; + } + + b_buffer = bundle_create(); + if (!b_buffer) { + SLOGE("bundle failed"); + return HAL_CODEC_ERROR_OUT_OF_MEMORY; + } + + ipc_ret = bundle_add_byte(b_buffer, HAL_CODEC_IPC_PARAM_KEY_BUFFER, + (const char *)buffer, sizeof(hal_codec_buffer_s)); + if (ipc_ret != BUNDLE_ERROR_NONE) { + SLOGE("add byte failed for buffer"); + ret = HAL_CODEC_ERROR_OUT_OF_MEMORY; + goto _IPC_DECODE_DONE; + } + + ipc_ret = bundle_add_byte(b_buffer, HAL_CODEC_IPC_PARAM_KEY_PLANE0_DATA, + (const char *)buffer->planes.plane[0].data, buffer->planes.plane[0].size); + if (ipc_ret != BUNDLE_ERROR_NONE) { + SLOGE("add byte failed for buffer[%d] size[%u]", buffer->index, buffer->planes.plane[0].size); + ret = HAL_CODEC_ERROR_OUT_OF_MEMORY; + goto _IPC_DECODE_DONE; + } + + SLOGD("buffer[%d] size[%u]", buffer->index, buffer->size); + + ret = rpc_port_proxy_codec_invoke_decode(handle->rpc_handle, b_buffer); + + if (ret == HAL_CODEC_ERROR_NONE) { + SLOGD("set input buffer[%d] %p", buffer->index, buffer); + handle->input_buffers[buffer->index] = buffer; + } + +_IPC_DECODE_DONE: + bundle_free(b_buffer); + + return ret; +} + + +int hal_codec_ipc_encode(void *codec_handle, hal_codec_buffer_s *buffer) +{ + int ret = HAL_CODEC_ERROR_NONE; + int ipc_ret = 0; + hal_codec_ipc_s *handle = (hal_codec_ipc_s *)codec_handle; + bundle *b_buffer = NULL; + rpc_port_proxy_array_file_desc_h fd_handle = NULL; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->rpc_handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + + b_buffer = bundle_create(); + if (!b_buffer) { + SLOGE("bundle failed"); + return HAL_CODEC_ERROR_OUT_OF_MEMORY; + } + + ipc_ret = bundle_add_byte(b_buffer, HAL_CODEC_IPC_PARAM_KEY_BUFFER, + (const char *)buffer, sizeof(hal_codec_buffer_s)); + if (ipc_ret != BUNDLE_ERROR_NONE) { + SLOGE("add byte failed for buffer"); + ret = HAL_CODEC_ERROR_OUT_OF_MEMORY; + goto _IPC_ENCODE_DONE; + } + + ipc_ret = rpc_port_proxy_array_file_desc_create(&fd_handle); + if (ipc_ret != RPC_PORT_ERROR_NONE) { + SLOGE("fd handle create failed[0x%x]", ipc_ret); + ret = HAL_CODEC_ERROR_OUT_OF_MEMORY; + goto _IPC_ENCODE_DONE; + } + + ipc_ret = rpc_port_proxy_array_file_desc_set(fd_handle, buffer->memory.fd, buffer->memory.num_fd); + if (ipc_ret != RPC_PORT_ERROR_NONE) { + SLOGE("fd set failed[0x%x]", ipc_ret); + ret = HAL_CODEC_ERROR_INTERNAL; + goto _IPC_ENCODE_DONE; + } + + ipc_ret = rpc_port_proxy_codec_invoke_encode(handle->rpc_handle, b_buffer, fd_handle); + +_IPC_ENCODE_DONE: + if (fd_handle) + rpc_port_proxy_array_file_desc_destroy(fd_handle); + + bundle_free(b_buffer); + + return ret; +} + + +int hal_codec_ipc_release_output_buffer(void *codec_handle, int buffer_index) +{ + int ret = HAL_CODEC_ERROR_NONE; + hal_codec_ipc_s *handle = (hal_codec_ipc_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->rpc_handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + + ret = rpc_port_proxy_codec_invoke_release_output_buffer(handle->rpc_handle, buffer_index); + + g_mutex_lock(&handle->buffer_lock); + + if (ret == HAL_CODEC_ERROR_NONE) { + if (handle->output_buffers[buffer_index]) { + __hal_codec_ipc_hal_buffer_release(handle->output_buffers[buffer_index]); + handle->output_buffers[buffer_index] = NULL; + } else { + SLOGW("[OUTPUT] no buffer for index[%d]", buffer_index); + } + } + + g_mutex_unlock(&handle->buffer_lock); + + return ret; +} + + +int hal_codec_ipc_get_state(void *codec_handle, hal_codec_state_e *state) +{ + hal_codec_ipc_s *handle = (hal_codec_ipc_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(state, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->rpc_handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + + return rpc_port_proxy_codec_invoke_get_state(handle->rpc_handle, (int *)state); +} + + +int hal_codec_ipc_set_command(void *codec_handle, hal_codec_command_e command, void *value) +{ + hal_codec_ipc_s *handle = (hal_codec_ipc_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(value, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->rpc_handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + + /* TODO: It's not used yet, but it will be updated later. */ + + return HAL_CODEC_ERROR_NOT_IMPLEMENTED; +} + + +int hal_codec_ipc_get_command(void *codec_handle, hal_codec_command_e command, void **value) +{ + hal_codec_ipc_s *handle = (hal_codec_ipc_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(value, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->rpc_handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + + /* TODO: It's not used yet, but it will be updated later. */ + + return HAL_CODEC_ERROR_NOT_IMPLEMENTED; +} + + +int hal_codec_ipc_set_batch_command(void *codec_handle, hal_codec_batch_command_control_s *batch_command, hal_codec_command_e *error_command) +{ + hal_codec_ipc_s *handle = (hal_codec_ipc_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(batch_command, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->rpc_handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + + /* TODO: It's not used yet, but it will be updated later. */ + + return HAL_CODEC_ERROR_NOT_IMPLEMENTED; +} diff --git a/src/hal-api-codec-passthrough.c b/src/hal-api-codec-passthrough.c new file mode 100644 index 0000000..869d218 --- /dev/null +++ b/src/hal-api-codec-passthrough.c @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2025 Samsung Electronics 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 + +#include + +#include "hal-codec-passthrough.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "HALAPI_CODEC_PT" + +#define HAL_CODEC_RETURN_VAL_IF_FAILED(arg, ret) \ + do {\ + if (!(arg)) {\ + SLOGE("[%s]failed, return[%s]", #arg, #ret);\ + return (ret);\ + }\ + } while (0) + + +typedef struct _hal_codec_s { + void *backend; + hal_backend_codec_funcs *funcs; +} hal_codec_s; + + +static int __hal_codec_passthrough_init_backend(void **data, void *user_data) +{ + if (!data) { + SLOGE("NULL data"); + return -EINVAL; + } + + *data = g_new0(hal_backend_codec_funcs, 1); + + SLOGI("new - codec HAL funcs[%p], size[%zu]", + *data, sizeof(hal_backend_codec_funcs)); + + return 0; +} + + +static int __hal_codec_passthrough_exit_backend(void *data, void *user_data) +{ + if (!data) { + SLOGE("NULL data"); + return -EINVAL; + } + + SLOGI("release - codec HAL funcs[%p], size[%zu]", + data, sizeof(hal_backend_codec_funcs)); + + g_free(data); + + return 0; +} + + +int hal_codec_passthrough_init(hal_codec_type_e type, void **codec_handle) +{ + int ret = 0; + hal_codec_s *new_handle = NULL; + + HAL_CODEC_RETURN_VAL_IF_FAILED(codec_handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + + SLOGI("start"); + + new_handle = g_new0(hal_codec_s, 1); + + ret = hal_common_get_backend_v2(HAL_MODULE_CODEC, + (void **)&new_handle->funcs, + NULL, + __hal_codec_passthrough_init_backend); + if (ret != 0) { + SLOGE("Failed to get backend"); + goto __HAL_INIT_FAILED; + } + + if (!new_handle->funcs || !new_handle->funcs->init) { + SLOGE("invalid ptr[%p]", new_handle->funcs); + goto __HAL_INIT_FAILED; + } + + ret = new_handle->funcs->init(type, &new_handle->backend); + if (ret != HAL_CODEC_ERROR_NONE) { + SLOGE("backend init failed[0x%x]", ret); + goto __HAL_INIT_FAILED; + } + + *codec_handle = (void *)new_handle; + + SLOGI("done"); + + return HAL_CODEC_ERROR_NONE; + +__HAL_INIT_FAILED: + if (new_handle->funcs) { + hal_common_put_backend_v2(HAL_MODULE_CODEC, + (void *)new_handle->funcs, + NULL, + __hal_codec_passthrough_exit_backend); + } + + g_free(new_handle); + + return HAL_CODEC_ERROR_INTERNAL; +} + + +int hal_codec_passthrough_deinit(void *codec_handle) +{ + int ret = 0; + hal_codec_s *handle = (hal_codec_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs->deinit, HAL_CODEC_ERROR_NOT_IMPLEMENTED); + + SLOGI("start"); + + ret = handle->funcs->deinit(handle->backend); + if (ret != HAL_CODEC_ERROR_NONE) { + SLOGE("deinit failed[0x%x]", ret); + return ret; + } + + hal_common_put_backend_v2(HAL_MODULE_CODEC, + (void *)handle->funcs, + NULL, + __hal_codec_passthrough_exit_backend); + + g_free(handle); + + SLOGI("done"); + + return HAL_CODEC_ERROR_NONE; +} + + +int hal_codec_passthrough_configure(void *codec_handle, int width, int height, hal_codec_format_e in_format, hal_codec_format_e out_format, bool is_secure) +{ + hal_codec_s *handle = (hal_codec_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs->configure, HAL_CODEC_ERROR_NOT_IMPLEMENTED); + + return handle->funcs->configure(handle->backend, width, height, in_format, out_format, is_secure); +} + + +int hal_codec_passthrough_release(void *codec_handle) +{ + hal_codec_s *handle = (hal_codec_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs->release, HAL_CODEC_ERROR_NOT_IMPLEMENTED); + + return handle->funcs->release(handle->backend); +} + + +int hal_codec_passthrough_start(void *codec_handle, hal_codec_message_cb callback, void *user_data) +{ + hal_codec_s *handle = (hal_codec_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs->start, HAL_CODEC_ERROR_NOT_IMPLEMENTED); + + return handle->funcs->start(handle->backend, callback, user_data); +} + + +int hal_codec_passthrough_stop(void *codec_handle) +{ + hal_codec_s *handle = (hal_codec_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs->stop, HAL_CODEC_ERROR_NOT_IMPLEMENTED); + + return handle->funcs->stop(handle->backend); +} + + +int hal_codec_passthrough_flush(void *codec_handle) +{ + hal_codec_s *handle = (hal_codec_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs->flush, HAL_CODEC_ERROR_NOT_IMPLEMENTED); + + return handle->funcs->flush(handle->backend); +} + + +int hal_codec_passthrough_decode(void *codec_handle, hal_codec_buffer_s *buffer) +{ + hal_codec_s *handle = (hal_codec_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs->decode, HAL_CODEC_ERROR_NOT_IMPLEMENTED); + + return handle->funcs->decode(handle->backend, buffer); +} + + +int hal_codec_passthrough_encode(void *codec_handle, hal_codec_buffer_s *buffer) +{ + hal_codec_s *handle = (hal_codec_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs->encode, HAL_CODEC_ERROR_NOT_IMPLEMENTED); + + return handle->funcs->encode(handle->backend, buffer); +} + + +int hal_codec_passthrough_release_output_buffer(void *codec_handle, int buffer_index) +{ + hal_codec_s *handle = (hal_codec_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs->release_output_buffer, HAL_CODEC_ERROR_NOT_IMPLEMENTED); + + return handle->funcs->release_output_buffer(handle->backend, buffer_index); +} + + +int hal_codec_passthrough_get_state(void *codec_handle, hal_codec_state_e *state) +{ + hal_codec_s *handle = (hal_codec_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs->get_state, HAL_CODEC_ERROR_NOT_IMPLEMENTED); + + return handle->funcs->get_state(handle->backend, state); +} + + +int hal_codec_passthrough_set_command(void *codec_handle, hal_codec_command_e command, void *value) +{ + hal_codec_s *handle = (hal_codec_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs->set_command, HAL_CODEC_ERROR_NOT_IMPLEMENTED); + + return handle->funcs->set_command(handle->backend, command, value); +} + + +int hal_codec_passthrough_get_command(void *codec_handle, hal_codec_command_e command, void **value) +{ + hal_codec_s *handle = (hal_codec_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs->get_command, HAL_CODEC_ERROR_NOT_IMPLEMENTED); + + return handle->funcs->get_command(handle->backend, command, value); +} + + +int hal_codec_passthrough_set_batch_command(void *codec_handle, hal_codec_batch_command_control_s *batch_command, hal_codec_command_e *error_command) +{ + hal_codec_s *handle = (hal_codec_s *)codec_handle; + + HAL_CODEC_RETURN_VAL_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_RETURN_VAL_IF_FAILED(handle->funcs->set_batch_command, HAL_CODEC_ERROR_NOT_IMPLEMENTED); + + return handle->funcs->set_batch_command(handle->backend, batch_command, error_command); +} diff --git a/src/hal-api-codec.c b/src/hal-api-codec.c index 15664c6..b8739e6 100644 --- a/src/hal-api-codec.c +++ b/src/hal-api-codec.c @@ -25,288 +25,156 @@ #include #include "hal-codec.h" +#include "hal-codec-passthrough.h" +#include "hal-codec-ipc.h" #ifdef LOG_TAG #undef LOG_TAG #endif #define LOG_TAG "HALAPI_CODEC" -#define HAL_CODEC_RETURN_IF_FAILED(arg, ret) \ - do {\ - if (!(arg)) {\ - SLOGE("[%s]failed, return[%s]", #arg, #ret);\ - return (ret);\ - }\ - } while (0) +#define HAL_CODEC_IS_TRANSPORT_IPC (g_hal_codec_transport == HAL_COMMON_TRANSPORT_IPC) -#define HAL_CODEC_DO_RETURN_IF_FAILED(arg, do_something, ret) \ - do {\ - if (!(arg)) {\ - SLOGE("[%s]failed, return[%s]", #arg, #ret);\ - do_something;\ - return (ret);\ - }\ - } while (0); +static enum hal_common_transport g_hal_codec_transport; +static void __hal_codec_constructor(void) __attribute__((constructor)); -typedef struct _hal_codec_s { - void *backend; - hal_backend_codec_funcs *funcs; -} hal_codec_s; - -static int hal_codec_init_backend(void **data, void *user_data) +static void __hal_codec_constructor(void) { - if (!data) { - SLOGE("NULL data"); - return -EINVAL; - } - - *data = g_new0(hal_backend_codec_funcs, 1); - - SLOGI("new - codec HAL funcs[%p], size[%zu]", - *data, sizeof(hal_backend_codec_funcs)); - - return 0; -} - + int ret = 0; -static int hal_codec_exit_backend(void *data, void *user_data) -{ - if (!data) { - SLOGE("NULL data"); - return -EINVAL; + ret = hal_common_get_transport(HAL_MODULE_CODEC, &g_hal_codec_transport); + if (ret < 0) { + SLOGW("failed to get transport for Codec HAL, set default(PASSTHROUGH)"); + g_hal_codec_transport = HAL_COMMON_TRANSPORT_PASSTHROUGH; } - SLOGI("release - codec HAL funcs[%p], size[%zu]", - data, sizeof(hal_backend_codec_funcs)); - - g_free(data); - - return 0; + SLOGI("transport[%d]", g_hal_codec_transport); } int hal_codec_init(hal_codec_type_e type, void **codec_handle) { - int ret = 0; - hal_codec_s *new_handle = NULL; - - HAL_CODEC_RETURN_IF_FAILED(codec_handle, HAL_CODEC_ERROR_INVALID_PARAMETER); - - SLOGI("start"); - - new_handle = g_new0(hal_codec_s, 1); - - ret = hal_common_get_backend_v2(HAL_MODULE_CODEC, - (void **)&new_handle->funcs, - NULL, - hal_codec_init_backend); - if (ret != 0) { - SLOGE("Failed to get backend"); - goto __HAL_INIT_FAILED; - } - - if (!new_handle->funcs || !new_handle->funcs->init) { - SLOGE("invalid ptr[%p]", new_handle->funcs); - goto __HAL_INIT_FAILED; - } - - ret = new_handle->funcs->init(type, &new_handle->backend); - if (ret != HAL_CODEC_ERROR_NONE) { - SLOGE("backend init failed[0x%x]", ret); - goto __HAL_INIT_FAILED; - } - - *codec_handle = (void *)new_handle; - - SLOGI("done"); - - return HAL_CODEC_ERROR_NONE; + if (HAL_CODEC_IS_TRANSPORT_IPC) + return hal_codec_ipc_init(type, codec_handle); -__HAL_INIT_FAILED: - if (new_handle->funcs) { - hal_common_put_backend_v2(HAL_MODULE_CODEC, - (void *)new_handle->funcs, - NULL, - hal_codec_exit_backend); - } - - g_free(new_handle); - - return HAL_CODEC_ERROR_INTERNAL; + return hal_codec_passthrough_init(type, codec_handle); } int hal_codec_deinit(void *codec_handle) { - int ret = 0; - hal_codec_s *handle = (hal_codec_s *)codec_handle; - - HAL_CODEC_RETURN_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs->deinit, HAL_CODEC_ERROR_NOT_IMPLEMENTED); - - SLOGI("start"); + if (HAL_CODEC_IS_TRANSPORT_IPC) + return hal_codec_ipc_deinit(codec_handle); - ret = handle->funcs->deinit(handle->backend); - if (ret != HAL_CODEC_ERROR_NONE) { - SLOGE("deinit failed[0x%x]", ret); - return ret; - } - - hal_common_put_backend_v2(HAL_MODULE_CODEC, - (void *)handle->funcs, - NULL, - hal_codec_exit_backend); - - g_free(handle); - - SLOGI("done"); - - return HAL_CODEC_ERROR_NONE; + return hal_codec_passthrough_deinit(codec_handle); } int hal_codec_configure(void *codec_handle, int width, int height, hal_codec_format_e in_format, hal_codec_format_e out_format, bool is_secure) { - hal_codec_s *handle = (hal_codec_s *)codec_handle; - - HAL_CODEC_RETURN_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs->configure, HAL_CODEC_ERROR_NOT_IMPLEMENTED); + if (HAL_CODEC_IS_TRANSPORT_IPC) + return hal_codec_ipc_configure(codec_handle, width, height, in_format, out_format, is_secure); - return handle->funcs->configure(handle->backend, width, height, in_format, out_format, is_secure); + return hal_codec_passthrough_configure(codec_handle, width, height, in_format, out_format, is_secure); } int hal_codec_release(void *codec_handle) { - hal_codec_s *handle = (hal_codec_s *)codec_handle; + if (HAL_CODEC_IS_TRANSPORT_IPC) + return hal_codec_ipc_release(codec_handle); - HAL_CODEC_RETURN_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs->release, HAL_CODEC_ERROR_NOT_IMPLEMENTED); - - return handle->funcs->release(handle->backend); + return hal_codec_passthrough_release(codec_handle); } int hal_codec_start(void *codec_handle, hal_codec_message_cb callback, void *user_data) { - hal_codec_s *handle = (hal_codec_s *)codec_handle; - - HAL_CODEC_RETURN_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs->start, HAL_CODEC_ERROR_NOT_IMPLEMENTED); + if (HAL_CODEC_IS_TRANSPORT_IPC) + return hal_codec_ipc_start(codec_handle, callback, user_data); - return handle->funcs->start(handle->backend, callback, user_data); + return hal_codec_passthrough_start(codec_handle, callback, user_data); } int hal_codec_stop(void *codec_handle) { - hal_codec_s *handle = (hal_codec_s *)codec_handle; - - HAL_CODEC_RETURN_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs->stop, HAL_CODEC_ERROR_NOT_IMPLEMENTED); + if (HAL_CODEC_IS_TRANSPORT_IPC) + return hal_codec_ipc_stop(codec_handle); - return handle->funcs->stop(handle->backend); + return hal_codec_passthrough_stop(codec_handle); } int hal_codec_flush(void *codec_handle) { - hal_codec_s *handle = (hal_codec_s *)codec_handle; + if (HAL_CODEC_IS_TRANSPORT_IPC) + return hal_codec_ipc_flush(codec_handle); - HAL_CODEC_RETURN_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs->flush, HAL_CODEC_ERROR_NOT_IMPLEMENTED); - - return handle->funcs->flush(handle->backend); + return hal_codec_passthrough_flush(codec_handle); } int hal_codec_decode(void *codec_handle, hal_codec_buffer_s *buffer) { - hal_codec_s *handle = (hal_codec_s *)codec_handle; - - HAL_CODEC_RETURN_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs->decode, HAL_CODEC_ERROR_NOT_IMPLEMENTED); + if (HAL_CODEC_IS_TRANSPORT_IPC) + return hal_codec_ipc_decode(codec_handle, buffer); - return handle->funcs->decode(handle->backend, buffer); + return hal_codec_passthrough_decode(codec_handle, buffer); } int hal_codec_encode(void *codec_handle, hal_codec_buffer_s *buffer) { - hal_codec_s *handle = (hal_codec_s *)codec_handle; - - HAL_CODEC_RETURN_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs->encode, HAL_CODEC_ERROR_NOT_IMPLEMENTED); + if (HAL_CODEC_IS_TRANSPORT_IPC) + return hal_codec_ipc_encode(codec_handle, buffer); - return handle->funcs->encode(handle->backend, buffer); + return hal_codec_passthrough_encode(codec_handle, buffer); } int hal_codec_release_output_buffer(void *codec_handle, int buffer_index) { - hal_codec_s *handle = (hal_codec_s *)codec_handle; + if (HAL_CODEC_IS_TRANSPORT_IPC) + return hal_codec_ipc_release_output_buffer(codec_handle, buffer_index); - HAL_CODEC_RETURN_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs->release_output_buffer, HAL_CODEC_ERROR_NOT_IMPLEMENTED); - - return handle->funcs->release_output_buffer(handle->backend, buffer_index); + return hal_codec_passthrough_release_output_buffer(codec_handle, buffer_index); } int hal_codec_get_state(void *codec_handle, hal_codec_state_e *state) { - hal_codec_s *handle = (hal_codec_s *)codec_handle; - - HAL_CODEC_RETURN_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs->get_state, HAL_CODEC_ERROR_NOT_IMPLEMENTED); + if (HAL_CODEC_IS_TRANSPORT_IPC) + return hal_codec_ipc_get_state(codec_handle, state); - return handle->funcs->get_state(handle->backend, state); + return hal_codec_passthrough_get_state(codec_handle, state); } int hal_codec_set_command(void *codec_handle, hal_codec_command_e command, void *value) { - hal_codec_s *handle = (hal_codec_s *)codec_handle; - - HAL_CODEC_RETURN_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs->set_command, HAL_CODEC_ERROR_NOT_IMPLEMENTED); + if (HAL_CODEC_IS_TRANSPORT_IPC) + return hal_codec_ipc_set_command(codec_handle, command, value); - return handle->funcs->set_command(handle->backend, command, value); + return hal_codec_passthrough_set_command(codec_handle, command, value); } int hal_codec_get_command(void *codec_handle, hal_codec_command_e command, void **value) { - hal_codec_s *handle = (hal_codec_s *)codec_handle; + if (HAL_CODEC_IS_TRANSPORT_IPC) + return hal_codec_ipc_get_command(codec_handle, command, value); - HAL_CODEC_RETURN_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs->get_command, HAL_CODEC_ERROR_NOT_IMPLEMENTED); - - return handle->funcs->get_command(handle->backend, command, value); + return hal_codec_passthrough_get_command(codec_handle, command, value); } int hal_codec_set_batch_command(void *codec_handle, hal_codec_batch_command_control_s *batch_command, hal_codec_command_e *error_command) { - hal_codec_s *handle = (hal_codec_s *)codec_handle; - - HAL_CODEC_RETURN_IF_FAILED(handle, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs, HAL_CODEC_ERROR_INVALID_PARAMETER); - HAL_CODEC_RETURN_IF_FAILED(handle->funcs->set_batch_command, HAL_CODEC_ERROR_NOT_IMPLEMENTED); + if (HAL_CODEC_IS_TRANSPORT_IPC) + return hal_codec_ipc_set_batch_command(codec_handle, batch_command, error_command); - return handle->funcs->set_batch_command(handle->backend, batch_command, error_command); + return hal_codec_passthrough_set_batch_command(codec_handle, batch_command, error_command); } diff --git a/src/service_plugin/CMakeLists.txt b/src/service_plugin/CMakeLists.txt new file mode 100644 index 0000000..8406600 --- /dev/null +++ b/src/service_plugin/CMakeLists.txt @@ -0,0 +1,41 @@ +PROJECT(hal-backend-service-codec) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(INCLUDEDIR "${CMAKE_INSTALL_PREFIX}/include") +SET(LIBDIR ${CMAKE_LIBDIR_PREFIX}) +SET(VERSION_MAJOR 1) +SET(VERSION "${VERSION_MAJOR}.0.0") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/generated) + +SET(PKG_MODULES + dlog + glib-2.0 + rpc-port + bundle + capi-appfw-app-common + capi-appfw-app-manager + capi-appfw-package-manager + hal-api-common +) + +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED ${PKG_MODULES}) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(SRCS + ${CMAKE_SOURCE_DIR}/src/hal-api-codec-passthrough.c + generated/hal_codec_stub_1.c + hal-backend-service-codec.c +) + +ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS}) + +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} -ldl) + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIBDIR}/hal) + diff --git a/src/service_plugin/hal-backend-service-codec.c b/src/service_plugin/hal-backend-service-codec.c new file mode 100644 index 0000000..fef0208 --- /dev/null +++ b/src/service_plugin/hal-backend-service-codec.c @@ -0,0 +1,493 @@ +/* + * Copyright (c) 2025 Samsung Electronics 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 "hal_codec_stub_1.h" +#include "hal-codec.h" +#include "hal-codec-ipc.h" +#include "hal-codec-passthrough.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "HAL_BACKEND_SERVICE_CODEC" + +#define HAL_CODEC_SERVICE_MSG_LOGE(format, ...) SLOGE(format, ##__VA_ARGS__) +#define HAL_CODEC_SERVICE_MSG_LOGW(format, ...) SLOGW(format, ##__VA_ARGS__) +#define HAL_CODEC_SERVICE_MSG_LOGI(format, ...) SLOGI(format, ##__VA_ARGS__) +#define HAL_CODEC_SERVICE_MSG_LOGD(format, ...) SLOGD(format, ##__VA_ARGS__) + +#define HAL_CODEC_MSG_RETURN_VAL_IF_FAILED(arg, ret) \ + do {\ + if (!(arg)) {\ + HAL_CODEC_SERVICE_MSG_LOGE("[%s]failed, return[%s]", #arg, #ret);\ + return (ret);\ + }\ + } while (0) + +#define HAL_CODEC_SERVICE_LOGE(format, ...) SLOGE("context[%p] "format, context, ##__VA_ARGS__) +#define HAL_CODEC_SERVICE_LOGW(format, ...) SLOGW("context[%p] "format, context, ##__VA_ARGS__) +#define HAL_CODEC_SERVICE_LOGI(format, ...) SLOGI("context[%p] "format, context, ##__VA_ARGS__) +#define HAL_CODEC_SERVICE_LOGD(format, ...) SLOGD("context[%p] "format, context, ##__VA_ARGS__) + +#define HAL_CODEC_RETURN_IF_FAILED(arg) \ + do {\ + if (!(arg)) {\ + HAL_CODEC_SERVICE_LOGE("[%s]failed", #arg);\ + return;\ + }\ + } while (0) + +#define HAL_CODEC_RETURN_VAL_IF_FAILED(arg, ret) \ + do {\ + if (!(arg)) {\ + HAL_CODEC_SERVICE_LOGE("[%s]failed, return[%s]", #arg, #ret);\ + return (ret);\ + }\ + } while (0) + + +typedef struct _hal_codec_service_s { + void *codec_handle; + rpc_port_stub_codec_message_h cb_handle; + GMutex cb_lock; +} hal_codec_service_s; + + + +static hal_codec_service_s *__hal_codec_service_get_handle(rpc_port_stub_codec_context_h context) +{ + int ipc_ret = 0; + hal_codec_service_s *service_handle = NULL; + + HAL_CODEC_RETURN_VAL_IF_FAILED(context, NULL); + + ipc_ret = rpc_port_stub_codec_context_get_tag(context, (void **)&service_handle); + if (ipc_ret != RPC_PORT_ERROR_NONE || service_handle == NULL) { + HAL_CODEC_SERVICE_LOGE("get handle[%p] from context[%p] failed[0x%x]", + service_handle, context, ipc_ret); + return NULL; + } + + HAL_CODEC_SERVICE_LOGI("handle[%p, %p]", service_handle, service_handle->codec_handle); + + return service_handle; +} + + +static int __hal_codec_service_message_cb(hal_codec_message_s *message, void *user_data) +{ + int ipc_ret = 0; + hal_codec_buffer_s *buffer = NULL; + bundle *b_msg = NULL; + rpc_port_stub_array_file_desc_h fd_handle = NULL; + hal_codec_service_s *service_handle = (hal_codec_service_s *)user_data; + + HAL_CODEC_MSG_RETURN_VAL_IF_FAILED(message, HAL_CODEC_ERROR_INVALID_PARAMETER); + HAL_CODEC_MSG_RETURN_VAL_IF_FAILED(service_handle, HAL_CODEC_ERROR_INVALID_PARAMETER); + + HAL_CODEC_SERVICE_MSG_LOGD("message[%p] type[%d] handle[service:%p,cb_handle:%p]", + message, message->type, service_handle, service_handle->cb_handle); + + b_msg = bundle_create(); + ipc_ret = bundle_add_byte(b_msg, HAL_CODEC_IPC_PARAM_KEY_MESSAGE, (const void *)message, sizeof(hal_codec_message_s)); + if (ipc_ret != BUNDLE_ERROR_NONE) { + HAL_CODEC_SERVICE_MSG_LOGE("add byte for message[type:%d] failed[0x%x]", message->type, ipc_ret); + return HAL_CODEC_ERROR_INTERNAL; + } + + switch (message->type) { + case HAL_CODEC_MESSAGE_TYPE_INPUT_BUFFER_USED: + buffer = message->buffer; + if (!buffer) { + HAL_CODEC_SERVICE_MSG_LOGE("NULL buffer for INPUT_BUFFER_USED, message[%p]", message); + goto _SERVICE_MESSAGE_CB_DONE; + } + + bundle_add_byte(b_msg, HAL_CODEC_IPC_PARAM_KEY_BUFFER, (const void *)buffer, sizeof(hal_codec_buffer_s)); + + HAL_CODEC_SERVICE_MSG_LOGD("[INPUT_BUFFER_USED] buffer[%p, index:%d, num_fd:%d] fd[%d:%d:%d:%d]", + buffer, buffer->index, buffer->memory.num_fd, + buffer->memory.fd[0], + buffer->memory.fd[1], + buffer->memory.fd[2], + buffer->memory.fd[3]); + + rpc_port_stub_array_file_desc_create(&fd_handle); + rpc_port_stub_array_file_desc_set(fd_handle, (int *)buffer->memory.fd, buffer->memory.num_fd); + + for (uint32_t i = 0; i < buffer->planes.num_planes; i++) { + HAL_CODEC_SERVICE_MSG_LOGD("free INPUT_BUFFER[%d] %p", i, buffer->planes.plane[i].data); + g_free(buffer->planes.plane[i].data); + } + + g_free(buffer); + break; + + case HAL_CODEC_MESSAGE_TYPE_OUTPUT_BUFFER: + buffer = message->buffer; + if (!buffer) { + HAL_CODEC_SERVICE_MSG_LOGE("NULL buffer for OUTPUT_BUFFER, message[%p]", message); + goto _SERVICE_MESSAGE_CB_DONE; + } + + HAL_CODEC_SERVICE_MSG_LOGD("[OUTPUT_BUFFER] buffer[%p, index:%d, num_planes:%d] fd[%d:%d:%d:%d]", + buffer, buffer->index, buffer->planes.num_planes, + buffer->memory.fd[0], + buffer->memory.fd[1], + buffer->memory.fd[2], + buffer->memory.fd[3]); + + bundle_add_byte(b_msg, HAL_CODEC_IPC_PARAM_KEY_BUFFER, (const void *)buffer, sizeof(hal_codec_buffer_s)); + + rpc_port_stub_array_file_desc_create(&fd_handle); + rpc_port_stub_array_file_desc_set(fd_handle, (int *)buffer->memory.fd, buffer->memory.num_fd); + break; + + default: + break; + } + + g_mutex_lock(&service_handle->cb_lock); + + if (service_handle->cb_handle == NULL) { + HAL_CODEC_SERVICE_MSG_LOGW("NULL cb_handle"); + g_mutex_unlock(&service_handle->cb_lock); + goto _SERVICE_MESSAGE_CB_DONE; + } + + ipc_ret = rpc_port_stub_codec_message_invoke(service_handle->cb_handle, b_msg, fd_handle); + if (ipc_ret != RPC_PORT_ERROR_NONE) { + HAL_CODEC_SERVICE_MSG_LOGE("Failed to invoke message_cb"); + g_mutex_unlock(&service_handle->cb_lock); + goto _SERVICE_MESSAGE_CB_DONE; + } + + g_mutex_unlock(&service_handle->cb_lock); + + HAL_CODEC_SERVICE_MSG_LOGD("invoke message: type[%d]", message->type); + +_SERVICE_MESSAGE_CB_DONE: + bundle_free(b_msg); + rpc_port_stub_array_file_desc_destroy(fd_handle); + + return HAL_CODEC_ERROR_NONE; +} + + +static void _hal_codec_service_rpc_create(rpc_port_stub_codec_context_h context, void *user_data) +{ + HAL_CODEC_SERVICE_LOGI("create"); +} + + +static void _hal_codec_service_rpc_terminate(rpc_port_stub_codec_context_h context, void *user_data) +{ + HAL_CODEC_SERVICE_LOGI("terminate"); +} + + +static int _hal_codec_service_backend_init(rpc_port_stub_codec_context_h context, int type, void *user_data) +{ + int ret = HAL_CODEC_ERROR_NONE; + int rpc_ret = RPC_PORT_ERROR_NONE; + hal_codec_service_s *service_handle = NULL; + + HAL_CODEC_RETURN_VAL_IF_FAILED(context, HAL_CODEC_ERROR_INTERNAL); + + HAL_CODEC_SERVICE_LOGI("type[%d]", type); + + service_handle = g_new0(hal_codec_service_s, 1); + + ret = hal_codec_passthrough_init(type, &service_handle->codec_handle); + if (ret != HAL_CODEC_ERROR_NONE) { + HAL_CODEC_SERVICE_LOGE("backend init failed[0x%x]", ret); + g_free(service_handle); + return ret; + } + + rpc_ret = rpc_port_stub_codec_context_set_tag(context, (char *)service_handle); + if (rpc_ret != RPC_PORT_ERROR_NONE) { + HAL_CODEC_SERVICE_LOGE("set handle to context failed[0x%x]", rpc_ret); + hal_codec_passthrough_deinit(service_handle->codec_handle); + g_free(service_handle); + return HAL_CODEC_ERROR_INTERNAL; + } + + g_mutex_init(&service_handle->cb_lock); + + HAL_CODEC_SERVICE_LOGI("new handle: service[%p], codec[%p]", + service_handle, service_handle->codec_handle); + + return HAL_CODEC_ERROR_NONE; +} + + +static int _hal_codec_service_backend_deinit(rpc_port_stub_codec_context_h context, void *user_data) +{ + int ret = HAL_CODEC_ERROR_NONE; + hal_codec_service_s *service_handle = __hal_codec_service_get_handle(context); + + HAL_CODEC_RETURN_VAL_IF_FAILED(service_handle, HAL_CODEC_ERROR_INTERNAL); + + ret = hal_codec_passthrough_deinit(service_handle->codec_handle); + if (ret != HAL_CODEC_ERROR_NONE) { + HAL_CODEC_SERVICE_LOGE("deinit failed[0x%x]", ret); + return ret; + } + + service_handle->codec_handle = NULL; + + if (service_handle->cb_handle) { + HAL_CODEC_SERVICE_LOGW("remove remained cb_handle[%p]", service_handle->cb_handle); + rpc_port_stub_codec_message_destroy(service_handle->cb_handle); + service_handle->cb_handle = NULL; + } + + HAL_CODEC_SERVICE_LOGI("reset tag[service_handle:%p] in context", service_handle); + + rpc_port_stub_codec_context_set_tag(context, NULL); + + g_mutex_clear(&service_handle->cb_lock); + + g_free(service_handle); + + return HAL_CODEC_ERROR_NONE; +} + + +static int _hal_codec_service_backend_configure(rpc_port_stub_codec_context_h context, + int width, int height, int in_format, int out_format, bool is_secure, void *user_data) +{ + int ret = HAL_CODEC_ERROR_NONE; + hal_codec_service_s *service_handle = __hal_codec_service_get_handle(context); + + HAL_CODEC_RETURN_VAL_IF_FAILED(service_handle, HAL_CODEC_ERROR_INTERNAL); + + HAL_CODEC_SERVICE_LOGI("[%dx%d], format[in:%d,out:%d], secure[%d]", + width, height, in_format, out_format, is_secure); + + ret = hal_codec_passthrough_configure(service_handle->codec_handle, + width, height, in_format, out_format, is_secure); + + if (ret != HAL_CODEC_ERROR_NONE) + HAL_CODEC_SERVICE_LOGE("configure failed[0x%x]", ret); + + return ret; +} + + +static int _hal_codec_service_backend_release(rpc_port_stub_codec_context_h context, void *user_data) +{ + int ret = HAL_CODEC_ERROR_NONE; + hal_codec_service_s *service_handle = __hal_codec_service_get_handle(context); + + HAL_CODEC_RETURN_VAL_IF_FAILED(service_handle, HAL_CODEC_ERROR_INTERNAL); + + ret = hal_codec_passthrough_release(service_handle->codec_handle); + + if (ret != HAL_CODEC_ERROR_NONE) + HAL_CODEC_SERVICE_LOGE("release failed[0x%x]", ret); + + return ret; +} + + +static int _hal_codec_service_backend_start(rpc_port_stub_codec_context_h context, rpc_port_stub_codec_message_h cb_handle, void *user_data) +{ + int ret = HAL_CODEC_ERROR_NONE; + int ipc_ret = 0; + hal_codec_service_s *service_handle = __hal_codec_service_get_handle(context); + rpc_port_stub_codec_message_h cb_handle_new = NULL; + + HAL_CODEC_RETURN_VAL_IF_FAILED(service_handle, HAL_CODEC_ERROR_INTERNAL); + + ipc_ret = rpc_port_stub_codec_message_clone(cb_handle, &cb_handle_new); + if (ipc_ret != RPC_PORT_ERROR_NONE) { + HAL_CODEC_SERVICE_LOGE("msg cb handle clone failed[0x%x]", ipc_ret); + return HAL_CODEC_ERROR_INTERNAL; + } + + g_mutex_lock(&service_handle->cb_lock); + service_handle->cb_handle = cb_handle_new; + g_mutex_unlock(&service_handle->cb_lock); + + ret = hal_codec_passthrough_start(service_handle->codec_handle, + __hal_codec_service_message_cb, service_handle); + if (ret != HAL_CODEC_ERROR_NONE) { + HAL_CODEC_SERVICE_LOGE("start failed[0x%x]", ret); + rpc_port_stub_codec_message_destroy(cb_handle_new); + service_handle->cb_handle = NULL; + } + + return ret; +} + + +static int _hal_codec_service_backend_stop(rpc_port_stub_codec_context_h context, void *user_data) +{ + int ret = HAL_CODEC_ERROR_NONE; + hal_codec_service_s *service_handle = __hal_codec_service_get_handle(context); + + HAL_CODEC_RETURN_VAL_IF_FAILED(service_handle, HAL_CODEC_ERROR_INTERNAL); + + ret = hal_codec_passthrough_stop(service_handle->codec_handle); + if (ret != HAL_CODEC_ERROR_NONE) { + HAL_CODEC_SERVICE_LOGE("stop failed[0x%x]", ret); + return ret; + } + + HAL_CODEC_SERVICE_LOGD("release cb_handle[%p]", service_handle->cb_handle); + rpc_port_stub_codec_message_destroy(service_handle->cb_handle); + + g_mutex_lock(&service_handle->cb_lock); + service_handle->cb_handle = NULL; + g_mutex_unlock(&service_handle->cb_lock); + + return HAL_CODEC_ERROR_NONE; +} + + +static int _hal_codec_service_backend_flush(rpc_port_stub_codec_context_h context, void *user_data) +{ + int ret = HAL_CODEC_ERROR_NONE; + hal_codec_service_s *service_handle = __hal_codec_service_get_handle(context); + + HAL_CODEC_RETURN_VAL_IF_FAILED(service_handle, HAL_CODEC_ERROR_INTERNAL); + + ret = hal_codec_passthrough_flush(service_handle->codec_handle); + + if (ret != HAL_CODEC_ERROR_NONE) + HAL_CODEC_SERVICE_LOGE("flush failed[0x%x]", ret); + + return ret; +} + + +static int _hal_codec_service_backend_decode(rpc_port_stub_codec_context_h context, bundle *b_buffer, void *user_data) +{ + int ret = HAL_CODEC_ERROR_NONE; + int ipc_ret = 0; + void *b_data = NULL; + size_t b_size = 0; + hal_codec_buffer_s *buffer = NULL; + hal_codec_service_s *service_handle = __hal_codec_service_get_handle(context); + + HAL_CODEC_RETURN_VAL_IF_FAILED(service_handle, HAL_CODEC_ERROR_INTERNAL); + + ipc_ret = bundle_get_byte(b_buffer, HAL_CODEC_IPC_PARAM_KEY_BUFFER, &b_data, &b_size); + if (ipc_ret != BUNDLE_ERROR_NONE || b_data == NULL || b_size != sizeof(hal_codec_buffer_s)) { + HAL_CODEC_SERVICE_LOGE("get data to decode failed[0x%x,%p,%zu/%zu", + ipc_ret, b_data, b_size, sizeof(hal_codec_buffer_s)); + return HAL_CODEC_ERROR_INTERNAL; + } + + buffer = (hal_codec_buffer_s *)g_memdup2(b_data, b_size); + + b_data = NULL; + b_size = 0; + + ipc_ret = bundle_get_byte(b_buffer, HAL_CODEC_IPC_PARAM_KEY_PLANE0_DATA, &b_data, &b_size); + if (ipc_ret != BUNDLE_ERROR_NONE || b_data == NULL || b_size != buffer->planes.plane[0].size) { + HAL_CODEC_SERVICE_LOGE("get data to decode failed[0x%x,%p,%zu/%u]", + ipc_ret, b_data, b_size, buffer->planes.plane[0].size); + ret = HAL_CODEC_ERROR_INTERNAL; + goto _SERVICE_DECODE_DONE; + } + + buffer->planes.plane[0].data = (unsigned char *)g_memdup2(b_data, b_size); + + HAL_CODEC_SERVICE_LOGD("buffer[%d] size[%zu]", buffer->index, b_size); + + ret = hal_codec_passthrough_decode(service_handle->codec_handle, buffer); + +_SERVICE_DECODE_DONE: + if (ret != HAL_CODEC_ERROR_NONE) { + HAL_CODEC_SERVICE_LOGE("decode failed[0x%x]", ret); + + if (buffer->planes.plane[0].data) + g_free(buffer->planes.plane[0].data); + + g_free(buffer); + } + + return ret; +} + + +static int _hal_codec_service_backend_release_output_buffer(rpc_port_stub_codec_context_h context, int buffer_index, void *user_data) +{ + int ret = HAL_CODEC_ERROR_NONE; + hal_codec_service_s *service_handle = __hal_codec_service_get_handle(context); + + HAL_CODEC_RETURN_VAL_IF_FAILED(service_handle, HAL_CODEC_ERROR_INTERNAL); + + HAL_CODEC_SERVICE_LOGD("buffer index[%d]", buffer_index); + + ret = hal_codec_passthrough_release_output_buffer(service_handle->codec_handle, buffer_index); + + if (ret != HAL_CODEC_ERROR_NONE) + HAL_CODEC_SERVICE_LOGE("release_output_buffer failed[0x%x]", ret); + + return ret; +} + + +static int hal_codec_service_init(void *data) +{ + int rpc_ret = 0; + + rpc_port_stub_codec_callback_s callbacks = { + .create = _hal_codec_service_rpc_create, + .terminate = _hal_codec_service_rpc_terminate, + .init = _hal_codec_service_backend_init, + .deinit = _hal_codec_service_backend_deinit, + .configure = _hal_codec_service_backend_configure, + .release = _hal_codec_service_backend_release, + .start = _hal_codec_service_backend_start, + .stop = _hal_codec_service_backend_stop, + .flush = _hal_codec_service_backend_flush, + .decode = _hal_codec_service_backend_decode, + .release_output_buffer = _hal_codec_service_backend_release_output_buffer + }; + + rpc_ret = rpc_port_stub_codec_register(&callbacks, NULL); + + SLOGW("register HAL codec service[0x%x]", rpc_ret); + + return 0; +} + + +static int hal_codec_service_exit(void *data) +{ + SLOGI("exit"); + return 0; +} + + +hal_backend_service hal_backend_service_codec_data = { + .module = HAL_MODULE_CODEC, + .name = "hal-backend-service-codec", + .early_init = NULL, + .init = hal_codec_service_init, + .exit = hal_codec_service_exit, + .late_exit = NULL, +}; diff --git a/tests/codec_hal_test.cpp b/tests/codec_hal_test.cpp index 93dc09e..76c6b3c 100644 --- a/tests/codec_hal_test.cpp +++ b/tests/codec_hal_test.cpp @@ -27,7 +27,6 @@ using namespace std; - #define CONTENTS_H264_PATH RES_DIR"/decode_test.h264" #define CONTENTS_H264_FRAME_NUM 10 @@ -40,7 +39,7 @@ using namespace std; }\ } while (0) -#define DUMP_OUTPUT_BUFFER +static bool g_codec_hal_test_dump_decoder_output; static int decode_test_frame_size[CONTENTS_H264_FRAME_NUM] = {151919, 84650, 8389, 20692, 18090, 18737, 17585, 18476, 11879, 10796}; @@ -86,7 +85,6 @@ class CodecHalTest : public testing::Test return; } -#ifdef DUMP_OUTPUT_BUFFER static void DumpBuffer(hal_codec_buffer_s *buffer, const char *dumpPath) { static int dumpCount = 0; @@ -109,35 +107,34 @@ class CodecHalTest : public testing::Test fout.close(); } -#endif static int MessageCb(hal_codec_message_s *message, void *user_data) { - int *decoded_count = (int *)user_data; + int *decodedCount = (int *)user_data; if (!message) { cout << "Codec HAL : NULL message" << endl; return 0; } - cout << "Codec HAL : message type[" << message->type << "]" << endl; - switch (message->type) { case HAL_CODEC_MESSAGE_TYPE_INPUT_BUFFER_USED: - cout << "Codec HAL : INPUT BUFFER USED p:" << message->buffer << endl; + cout << "[INPUT_BUFFER_USED] buffer[" << message->buffer->index << "] "<< message->buffer; + cout << " size[" << message->buffer->planes.plane[0].bytesused << "]" << endl; break; case HAL_CODEC_MESSAGE_TYPE_OUTPUT_BUFFER: - if (decoded_count) - (*decoded_count)++; + if (decodedCount) + (*decodedCount)++; + + cout << "[OUTPUT_BUFFER] index: " << message->buffer->index << endl; + + if (g_codec_hal_test_dump_decoder_output) + DumpBuffer(message->buffer, "/home/owner/media/dump.yuv"); - cout << "Codec HAL : OUTPUT BUFFER index: " << message->buffer->index << endl; -#ifdef DUMP_OUTPUT_BUFFER - DumpBuffer(message->buffer, "/home/owner/media/dump.yuv"); -#endif hal_codec_release_output_buffer(gHalHandle, message->buffer->index); - cout << "Codec HAL : OUTPUT BUFFER Released" << endl; break; default: + cout << "[UNHANDLED MSG] type: " << message->type << endl; break; } @@ -177,10 +174,42 @@ class CodecHalTest : public testing::Test mappedFileContents_ = nullptr; } + int FeedData(void) + { + memset(&buffer_[feedCount_], 0x0, sizeof(hal_codec_buffer_s)); + + buffer_[feedCount_].index = (int)feedCount_; + buffer_[feedCount_].size = decode_test_frame_size[feedCount_]; + buffer_[feedCount_].planes.num_planes = 1; + buffer_[feedCount_].planes.plane[0].data = (unsigned char *)(mappedFileContents_ + mappedFileOffset_); + buffer_[feedCount_].planes.plane[0].size = buffer_[feedCount_].size; + buffer_[feedCount_].planes.plane[0].bytesused = buffer_[feedCount_].size; + buffer_[feedCount_].meta.timestamp = feedCount_ * 1000000000; /* ns */ + + cout << "[FeedData] buffer[" << feedCount_ << "] " << &buffer_[feedCount_]; + cout << " size[" << buffer_[feedCount_].planes.plane[0].bytesused << "]" << endl; + + ret = hal_codec_decode(gHalHandle, &buffer_[feedCount_]); + if (ret != HAL_CODEC_ERROR_NONE) + cout << "[FeedData] failed " << ret << endl; + + mappedFileOffset_ += decode_test_frame_size[feedCount_]; + feedCount_++; + + if (feedCount_ >= 10) + return G_SOURCE_REMOVE; + else + return G_SOURCE_CONTINUE; + } + GMappedFile *mappedFile_ {}; gsize mappedFileLength_ {}; gchar *mappedFileContents_ {}; gsize mappedFileOffset_ {}; + hal_codec_buffer_s buffer_[CONTENTS_H264_FRAME_NUM] {}; + guint feedCount_ {}; + guint decodedCount_ {}; + GMainLoop *mainLoop_ {}; }; /** @@ -309,9 +338,6 @@ TEST_F(CodecHalTest, StartStopP) */ TEST_F(CodecHalTest, DecodeP) { - int offset = 0; - int decoded_count = 0; - hal_codec_buffer_s buffer[CONTENTS_H264_FRAME_NUM]; CODEC_SUPPORT_CHECK; ASSERT_NE(gHalHandle, nullptr); @@ -320,32 +346,33 @@ TEST_F(CodecHalTest, DecodeP) ret = hal_codec_configure(gHalHandle, 1920, 1080, HAL_CODEC_FORMAT_H264, HAL_CODEC_FORMAT_NV12, false); ASSERT_EQ(ret, HAL_CODEC_ERROR_NONE); - ret = hal_codec_start(gHalHandle, CodecHalTest::MessageCb, (void *)&decoded_count); + ret = hal_codec_start(gHalHandle, CodecHalTest::MessageCb, &decodedCount_); ASSERT_EQ(ret, HAL_CODEC_ERROR_NONE); ret = GetContents(CONTENTS_H264_PATH); ASSERT_EQ(ret, 0); - for (uint64_t i = 0 ; i < CONTENTS_H264_FRAME_NUM ; i++) { - memset(&buffer[i], 0x0, sizeof(hal_codec_buffer_s)); + mainLoop_ = g_main_loop_new(NULL, TRUE); - buffer[i].size = decode_test_frame_size[i]; - buffer[i].planes.plane[0].data = (unsigned char *)(mappedFileContents_ + offset); - buffer[i].planes.plane[0].size = buffer[i].size; - buffer[i].planes.plane[0].bytesused = buffer[i].size; - buffer[i].meta.timestamp = i * 1000000000; /* ns */ + feedCount_ = 0; + decodedCount_ = 0; - cout << " Codec HAL : [" << i << "] decode buffer: size[" << buffer[i].planes.plane[0].bytesused << "]" << endl; + g_timeout_add(50, [](gpointer user_data) -> gboolean { + CodecHalTest *self = (CodecHalTest *)user_data; + return self->FeedData(); + }, this); - ret = hal_codec_decode(gHalHandle, &buffer[i]); - ASSERT_EQ(ret, HAL_CODEC_ERROR_NONE); + g_timeout_add(1000, [](gpointer user_data) -> gboolean { + CodecHalTest *self = (CodecHalTest *)user_data; + cout << "decoded count: " << self->decodedCount_ << endl; + g_main_loop_quit(self->mainLoop_); + return G_SOURCE_REMOVE; + }, this); - offset += decode_test_frame_size[i]; - } + g_main_loop_run(mainLoop_); + g_main_loop_unref(mainLoop_); - usleep(1000000); - - ASSERT_NE(decoded_count, 0); + ASSERT_NE(decodedCount_, 0); ReleaseContents(); @@ -361,5 +388,8 @@ int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); + if (argc > 1 && g_strcmp0(argv[1], "dump_output") == 0) + g_codec_hal_test_dump_decoder_output = true; + return RUN_ALL_TESTS(); }