Support HAL backend service 39/320939/5 accepted/tizen/unified/20250313.164544 accepted/tizen/unified/x/20250314.100501
authorJeongmo Yang <jm80.yang@samsung.com>
Tue, 11 Mar 2025 10:59:00 +0000 (19:59 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Wed, 12 Mar 2025 03:24:29 +0000 (12:24 +0900)
[Version] 1.1.0
[Issue Type] New feature

Change-Id: I315f224b589702c6688424f9bbda359a9df7973b
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
12 files changed:
CMakeLists.txt
include/hal-codec-ipc.h [new file with mode: 0644]
include/hal-codec-passthrough.h [new file with mode: 0644]
include/hal_codec_ipc_1.tidl [new file with mode: 0644]
packaging/hal-api-codec-manifest.xml
packaging/hal-api-codec.spec
src/hal-api-codec-ipc.c [new file with mode: 0644]
src/hal-api-codec-passthrough.c [new file with mode: 0644]
src/hal-api-codec.c
src/service_plugin/CMakeLists.txt [new file with mode: 0644]
src/service_plugin/hal-backend-service-codec.c [new file with mode: 0644]
tests/codec_hal_test.cpp

index 38e87ea9e410563e8b6ad155d6adad41cd9cd1a9..111fc1c26227023f65d43e53ef852470677ab5ca 100644 (file)
@@ -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 (file)
index 0000000..749d0f1
--- /dev/null
@@ -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 (file)
index 0000000..4bce2af
--- /dev/null
@@ -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 (file)
index 0000000..7e44634
--- /dev/null
@@ -0,0 +1,26 @@
+protocol 2
+
+interface codec {
+  void message(bundle msg, array<file_desc> 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<file_desc> 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);
+}
+
index ef7b3ef61fd822e8f68dae770f5918d2e92fcab4..f8e8ea0e3e85114c06cbddeb5a75c2ebec429fb6 100644 (file)
@@ -2,7 +2,7 @@
        <manifest platform-version="10.0">
                <hal-module>
                        <name>HAL_MODULE_CODEC</name>
-                       <version>1.0</version>
+                       <version transport="passthrough">1.0</version>
                </hal-module>
        </manifest>
 </hal-api>
index 5d051000dd2ed871fc2196e79a2c02cfe1425215..67e820a291b8cdb948f3b8596f4745dedd8fe021 100644 (file)
@@ -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 (file)
index 0000000..c39b01e
--- /dev/null
@@ -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 <sys/mman.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <dlfcn.h>
+#include <dlog.h>
+#include <glib.h>
+
+#include <bundle.h>
+#include <hal/hal-common.h>
+
+#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 (file)
index 0000000..869d218
--- /dev/null
@@ -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 <stdio.h>
+#include <stdint.h>
+#include <dlfcn.h>
+#include <dlog.h>
+#include <glib.h>
+
+#include <hal/hal-common.h>
+
+#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);
+}
index 15664c61a409bc9518ee80a8cec3f42e35a1d437..b8739e6a6b39404aed59cb5aa6cd19912033dff2 100644 (file)
 #include <hal/hal-common.h>
 
 #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 (file)
index 0000000..8406600
--- /dev/null
@@ -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 (file)
index 0000000..fef0208
--- /dev/null
@@ -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 <stdint.h>
+#include <dlog.h>
+#include <glib.h>
+#include <hal/hal-common.h>
+
+#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,
+};
index 93dc09e48d7c11c84db13fb762a94a0bf4fd0984..76c6b3cf02fa29c20f537133a07c8fb706c8a333 100644 (file)
@@ -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();
 }