diff --git a/mpp/CMakeLists.txt b/mpp/CMakeLists.txt index fad59b13..f05d6f83 100644 --- a/mpp/CMakeLists.txt +++ b/mpp/CMakeLists.txt @@ -40,6 +40,7 @@ add_subdirectory(hal) # add mpp implement # ---------------------------------------------------------------------------- set (MPP_SRC + kmpp.c mpp_info.cpp mpp.cpp mpp_impl.cpp diff --git a/mpp/inc/kmpp.h b/mpp/inc/kmpp.h new file mode 100644 index 00000000..66335570 --- /dev/null +++ b/mpp/inc/kmpp.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef __KMPP_H__ +#define __KMPP_H__ + +#include + +#include "mpp_impl.h" +#include "mpp_dec_cfg.h" +#include "mpp_enc_cfg.h" +#include "mpp_mem_pool.h" +#include "kmpp_obj.h" + +typedef struct Kmpp_t Kmpp; +typedef struct KmppOps_t { + MPP_RET (*open_client)(Kmpp *ctx); + MPP_RET (*init)(Kmpp *ctx, MppCtxType type, MppCodingType coding); + + MPP_RET (*start)(Kmpp *ctx); + MPP_RET (*stop)(Kmpp *ctx); + + MPP_RET (*pause)(Kmpp *ctx); + MPP_RET (*resume)(Kmpp *ctx); + + MPP_RET (*put_packet)(Kmpp *ctx, MppPacket packet); + MPP_RET (*get_frame)(Kmpp *ctx, MppFrame *frame); + + MPP_RET (*put_frame)(Kmpp *ctx, MppFrame frame); + MPP_RET (*get_packet)(Kmpp *ctx, MppPacket *packet); + MPP_RET (*release_packet)(Kmpp *ctx, MppPacket *packet); + + MPP_RET (*poll)(Kmpp *ctx, MppPortType type, MppPollType timeout); + MPP_RET (*dequeue)(Kmpp *ctx, MppPortType type, MppTask *task); + MPP_RET (*enqueue)(Kmpp *ctx, MppPortType type, MppTask task); + + MPP_RET (*reset)(Kmpp *ctx); + MPP_RET (*control)(Kmpp *ctx, MpiCmd cmd, MppParam param); + + MPP_RET (*notify_flag)(Kmpp *ctx, RK_U32 flag); + MPP_RET (*notify)(Kmpp *ctx, MppBufferGroup group); + + MPP_RET (*get_fd)(Kmpp *ctx, RK_S32 *fd); + MPP_RET (*close_fd)(Kmpp *ctx, RK_S32 fd); + void (*clear)(Kmpp *ctx); +} KmppOps; + +struct Kmpp_t { + MppPollType mInputTimeout; + MppPollType mOutputTimeout; + + MppCtx mCtx; + RK_S32 mChanId; + RK_U32 mEncVersion; + + MppCtxType mType; + MppCodingType mCoding; + RK_U32 mChanDup; + + RK_U32 mInitDone; + + RK_S32 mClientFd; + struct timeval mTimeout; + + MppBufferGroup mPacketGroup; + MppPacket mPacket; + + KmppOps *mApi; + KmppObj mVencInitKcfg; + MppMemPool mVencPacketPool; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +void mpp_get_api(Kmpp *ctx); + +#ifdef __cplusplus +} +#endif +#endif /*__MPP_H__*/ diff --git a/mpp/kmpp.c b/mpp/kmpp.c new file mode 100644 index 00000000..1bd3e0c7 --- /dev/null +++ b/mpp/kmpp.c @@ -0,0 +1,625 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "kmpp" + +#include +#include +#include +#include +#include +#include + +#include "rk_mpi.h" + +#include "mpp_log.h" +#include "mpp_mem.h" +#include "mpp_env.h" +#include "mpp_time.h" +#include "mpp_impl.h" +#include "mpp_2str.h" +#include "mpp_debug.h" + +#include "kmpp.h" +#include "kmpp_obj.h" +#include "mpp_soc.h" +#include "mpp_buffer_impl.h" +#include "mpp_frame_impl.h" +#include "mpp_packet_impl.h" + +#include "mpp_vcodec_client.h" +#include "mpp_enc_cfg_impl.h" + +typedef struct KmppFrameInfos_t { + RK_U32 width; + RK_U32 height; + RK_U32 hor_stride; + RK_U32 ver_stride; + RK_U32 hor_stride_pixel; + RK_U32 offset_x; + RK_U32 offset_y; + RK_U32 fmt; + RK_U32 fd; + RK_U64 pts; + RK_S32 jpeg_chan_id; + void *osd_buf; + RK_S32 mpi_buf_id; + void *jpg_combo_osd_buf; + RK_U32 is_gray; + RK_U32 is_full; + RK_U32 phy_addr; + RK_U64 dts; + void *pp_info; + RK_U32 pskip_num; + union { + RK_U32 val; + struct { + RK_U32 eos : 1; + RK_U32 pskip : 1; + RK_U32 isr_request : 1; + }; + }; +} KmppFrameInfos; + +typedef struct KmppVencPacketInfo_t { + RK_U32 flag; + RK_U32 temporal_id; + RK_U32 packet_offset; + RK_U32 packet_len; +} KmppVencPacketInfo; + +typedef struct VencPacket_t { + RK_U64 u64priv_data; + RK_U64 u64packet_addr; + RK_U32 len; + RK_U32 buf_size; + + RK_U64 u64pts; + RK_U64 u64dts; + RK_U32 flag; + RK_U32 temporal_id; + RK_U32 offset; + RK_U32 data_num; + KmppVencPacketInfo packet[8]; +} VencPacket; + +static void kmpp_release_venc_packet(void *ctx, void *arg) +{ + Kmpp *p = (Kmpp *)ctx; + VencPacket *pkt = (VencPacket *)arg; + + if (!ctx || !pkt) { + mpp_err_f("invalid input ctx %p pkt %p\n", ctx, pkt); + return; + } + mpp_vcodec_ioctl(p->mClientFd, VCODEC_CHAN_OUT_STRM_END, 0, sizeof(VencPacket), pkt); + + mpp_mem_pool_put(p->mVencPacketPool, pkt); +} + +static MPP_RET init(Kmpp *ctx, MppCtxType type, MppCodingType coding) +{ + MPP_RET ret = MPP_NOK; + RK_U32 chan_id; + void *hnd; + RK_U32 size; + + if (!ctx) + return MPP_ERR_VALUE; + + if (mpp_check_support_format(type, coding)) { + mpp_err("unable to create %s %s for mpp unsupported\n", + strof_ctx_type(type), strof_coding_type(coding)); + return MPP_NOK; + } + + if (ctx->mClientFd < 0) { + ctx->mClientFd = mpp_vcodec_open(); + if (ctx->mClientFd < 0) { + mpp_err("mpp_vcodec dev open failed\n"); + return MPP_NOK; + } + } + + hnd = kmpp_obj_get_hnd(ctx->mVencInitKcfg); + size = kmpp_obj_get_hnd_size(ctx->mVencInitKcfg); + + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_CREATE, 0, size, hnd); + if (ret) { + mpp_err("chan %d VCODEC_CHAN_CREATE failed\n", ctx->mChanId); + return ret; + } + + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_START, 0, 0, 0); + if (ret) { + mpp_err("chan %d VCODEC_CHAN_START failed\n", ctx->mChanId); + return ret; + } + + if (ctx->mPacketGroup == NULL) + mpp_buffer_group_get_internal(&ctx->mPacketGroup, MPP_BUFFER_TYPE_ION); + + ctx->mVencPacketPool = mpp_mem_pool_init(sizeof(VencPacket)); + + kmpp_obj_get_u32(ctx->mVencInitKcfg, "chan_id", &chan_id); + mpp_log("client %d open chan_id %d ok", ctx->mClientFd, chan_id); + ctx->mInitDone = 1; + ctx->mChanId = chan_id; + ctx->mType = type; + ctx->mOutputTimeout = MPP_POLL_BLOCK; + ctx->mTimeout.tv_sec = 2; + ctx->mTimeout.tv_usec = 100000; + + return ret; +} + +static MPP_RET open_client(Kmpp *ctx) +{ + if (!ctx) + return MPP_ERR_VALUE; + + ctx->mClientFd = mpp_vcodec_open(); + if (ctx->mClientFd < 0) { + mpp_err("mpp_vcodec dev open failed\n"); + return MPP_NOK; + } + return MPP_OK; +} + +static void clear(Kmpp *ctx) +{ + if (!ctx) + return; + + if (!ctx->mChanDup) { + MPP_RET ret; + + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_DESTROY, 0, 0, 0); + if (ret) + mpp_err("chan %d VCODEC_CHAN_DESTROY failed\n", ctx->mChanId); + } + + if (ctx->mClientFd >= 0) + mpp_vcodec_close(ctx->mClientFd); + ctx->mClientFd = -1; + + if (ctx->mPacketGroup) { + mpp_buffer_group_put(ctx->mPacketGroup); + ctx->mPacketGroup = NULL; + } + + if (ctx->mVencPacketPool) { + mpp_mem_pool_deinit(ctx->mVencPacketPool); + ctx->mVencPacketPool = NULL; + } +} + +static MPP_RET start(Kmpp *ctx) +{ + MPP_RET ret = MPP_OK; + + if (!ctx) + return MPP_ERR_VALUE; + + if (ctx->mChanDup) + return MPP_OK; + + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_START, 0, 0, 0); + if (ret) + mpp_err("chan %d VCODEC_CHAN_START failed\n", ctx->mChanId); + + return ret; +} + +static MPP_RET stop(Kmpp *ctx) +{ + MPP_RET ret = MPP_OK; + + if (!ctx) + return MPP_ERR_VALUE; + + if (ctx->mChanDup) + return MPP_OK; + + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_START, 0, 0, 0); + if (ret) + mpp_err("chan %d VCODEC_CHAN_START failed\n", ctx->mChanId); + + return ret; +} + +static MPP_RET mpp_pause(Kmpp *ctx) +{ + MPP_RET ret = MPP_OK; + + if (!ctx) + return MPP_ERR_VALUE; + + if (ctx->mChanDup) + return MPP_OK; + + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_PAUSE, 0, 0, 0); + if (ret) + mpp_err("chan %d VCODEC_CHAN_PAUSE failed\n", ctx->mChanId); + + return ret; +} + +static MPP_RET resume(Kmpp *ctx) +{ + MPP_RET ret = MPP_OK; + + if (!ctx) + return MPP_ERR_VALUE; + + if (ctx->mChanDup) + return MPP_OK; + + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_RESUME, 0, 0, 0); + if (ret) + mpp_err("chan %d VCODEC_CHAN_RESUME failed\n", ctx->mChanId); + + return ret; +} + +static MPP_RET put_packet(Kmpp *ctx, MppPacket packet) +{ + (void) packet; + MPP_RET ret = MPP_OK; + + if (!ctx->mInitDone) + return MPP_ERR_INIT; + + return ret; +} + +static MPP_RET get_frame(Kmpp *ctx, MppFrame *frame) +{ + (void)frame; + if (!ctx->mInitDone) + return MPP_ERR_INIT; + + return MPP_OK; +} + +static MPP_RET put_frame(Kmpp *ctx, MppFrame frame) +{ + KmppFrameInfos frame_info; + MppBuffer buf = NULL; + MPP_RET ret = MPP_OK; + + if (!ctx) + return MPP_ERR_VALUE; + + if (!ctx->mInitDone) + return MPP_ERR_INIT; + + buf = mpp_frame_get_buffer(frame); + memset(&frame_info, 0, sizeof(frame_info)); + frame_info.width = mpp_frame_get_width(frame); + frame_info.height = mpp_frame_get_height(frame); + frame_info.hor_stride = mpp_frame_get_hor_stride(frame); + frame_info.ver_stride = mpp_frame_get_ver_stride(frame); + frame_info.hor_stride_pixel = mpp_frame_get_hor_stride_pixel(frame); + frame_info.offset_x = mpp_frame_get_offset_x(frame); + frame_info.offset_y = mpp_frame_get_offset_y(frame); + frame_info.fmt = mpp_frame_get_fmt(frame); + frame_info.fd = mpp_buffer_get_fd(buf); + // frame_info.pts = mpp_frame_get_pts(frame); + // frame_info.jpeg_chan_id = mpp_frame_get_jpege_chan_id(frame); + // frame_info.eos = mpp_frame_get_eos(frame); + // frame_info.pskip = mpp_frame_get_pskip_request(frame); + // frame_info.pskip_num = mpp_frame_get_pskip_num(frame); + if (mpp_frame_has_meta(frame)) { + MppMeta meta = mpp_frame_get_meta(frame); + MppPacket packet = NULL; + + mpp_meta_get_packet(meta, KEY_OUTPUT_PACKET, &packet); + ctx->mPacket = packet; + + /* set roi */ + { + MppEncROICfg *roi_data = NULL; + MppEncROICfgLegacy roi_data0; + + mpp_meta_get_ptr(meta, KEY_ROI_DATA, (void**)&roi_data); + if (roi_data) { + roi_data0.change = 1; + roi_data0.number = roi_data->number; + memcpy(roi_data0.regions, roi_data->regions, roi_data->number * sizeof(MppEncROIRegion)); + ctx->mApi->control(ctx, MPP_ENC_SET_ROI_CFG, &roi_data0); + } + } + } + + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_IN_FRM_RDY, 0, sizeof(frame_info), &frame_info); + if (ret) + mpp_err("chan %d VCODEC_CHAN_IN_FRM_RDY failed\n", ctx->mChanId); + + return ret; +} + +static MPP_RET get_packet(Kmpp *ctx, MppPacket *packet) +{ + RK_S32 ret; + + if (!ctx) + return MPP_ERR_VALUE; + + if (!ctx->mInitDone) + return MPP_ERR_INIT; + + struct timeval timeout; + fd_set read_fds; + + FD_ZERO(&read_fds); + FD_SET(ctx->mClientFd, &read_fds); + + memcpy(&timeout, &ctx->mTimeout, sizeof(timeout)); + ret = select(ctx->mClientFd + 1, &read_fds, NULL, NULL, &timeout); + if (ret <= 0) { + mpp_err("get venc stream error %d\n", ret); + return MPP_NOK; + } + + if (FD_ISSET(ctx->mClientFd, &read_fds)) { + VencPacket *venc_packet = mpp_mem_pool_get(ctx->mVencPacketPool); + + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_OUT_STRM_BUF_RDY, 0, sizeof(VencPacket), venc_packet); + if (ret) { + mpp_err("chan %d VCODEC_CHAN_OUT_STRM_BUF_RDY failed\n", ctx->mChanId); + return MPP_NOK; + } + + if (venc_packet->len) { + MppPacket pkt = NULL; + void *ptr = NULL; + RK_U32 len = venc_packet->len; + + ptr = (void *)(intptr_t)(venc_packet->u64priv_data); + + if (ptr) { + if (ctx->mPacket) { + void *dst; + + pkt = ctx->mPacket; + ctx->mPacket = NULL; + dst = mpp_packet_get_pos(pkt); + memcpy(dst, ptr + venc_packet->offset, len); + mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_OUT_STRM_END, 0, sizeof(VencPacket), venc_packet); + mpp_packet_set_length(pkt, len); + mpp_mem_pool_put(ctx->mVencPacketPool, venc_packet); + } else { + mpp_packet_init(&pkt, ptr + venc_packet->offset, len); + mpp_packet_set_release(pkt, kmpp_release_venc_packet, ctx, venc_packet); + } + } + *packet = pkt; + } + } + + return MPP_OK; +} + +static MPP_RET release_packet(Kmpp *ctx, MppPacket *packet) +{ + VencPacket *enc_packet = (VencPacket *) *packet; + MPP_RET ret = MPP_OK; + + if (!ctx) + return MPP_ERR_VALUE; + + if (!ctx->mInitDone) + return MPP_ERR_INIT; + + if (*packet == NULL) + return MPP_NOK; + + if (ctx->mClientFd < 0) + return MPP_NOK; + + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_OUT_STRM_END, 0, sizeof(*enc_packet), enc_packet); + if (ret) + mpp_err("chan %d VCODEC_CHAN_OUT_STRM_END failed\n", ctx->mChanId); + + return ret; +} + +static MPP_RET poll(Kmpp *ctx, MppPortType type, MppPollType timeout) +{ + MPP_RET ret = MPP_NOK; + (void)type; + (void)timeout; + + if (!ctx->mInitDone) + return MPP_ERR_INIT; + + return ret; +} + +static MPP_RET dequeue(Kmpp *ctx, MppPortType type, MppTask *task) +{ + MPP_RET ret = MPP_NOK; + (void)type; + (void)task; + + if (!ctx->mInitDone) + return MPP_ERR_INIT; + + return ret; +} + +static MPP_RET enqueue(Kmpp *ctx, MppPortType type, MppTask task) +{ + MPP_RET ret = MPP_NOK; + (void)type; + (void)task; + + if (!ctx->mInitDone) + return MPP_ERR_INIT; + + return ret; +} + +static MPP_RET control(Kmpp *ctx, MpiCmd cmd, MppParam param) +{ + MPP_RET ret = MPP_NOK; + RK_U32 size = 0; + void *arg = param; + + if (!ctx) + return MPP_ERR_VALUE; + + switch (cmd) { + case MPP_ENC_SET_CFG : + case MPP_ENC_GET_CFG : { + size = sizeof(MppEncCfgImpl); + } break; + case MPP_ENC_SET_HEADER_MODE : + case MPP_ENC_SET_SEI_CFG : { + size = sizeof(RK_U32); + } break; + case MPP_ENC_GET_REF_CFG : + case MPP_ENC_SET_REF_CFG : { + size = sizeof(MppEncRefParam); + } break; + case MPP_ENC_GET_ROI_CFG: + case MPP_ENC_SET_ROI_CFG: { + size = sizeof(MppEncROICfgLegacy); + } break; + // case MPP_ENC_SET_JPEG_ROI_CFG : { + // size = sizeof(MppJpegROICfg); + // } break; + case MPP_ENC_SET_OSD_DATA_CFG: { + size = sizeof(MppEncOSDData3); + } break; + case MPP_ENC_SET_USERDATA: { + size = sizeof(MppEncUserData); + } break; + case MPP_SET_VENC_INIT_KCFG: { + KmppObj obj = param; + + arg = kmpp_obj_get_hnd(obj); + size = kmpp_obj_get_hnd_size(obj); + } break; + case MPP_SET_SELECT_TIMEOUT: { + struct timeval *p = (struct timeval *)param; + ctx->mTimeout.tv_sec = p->tv_sec; + ctx->mTimeout.tv_usec = p->tv_usec; + return MPP_OK; + } break; + case MPP_ENC_SET_IDR_FRAME: { + size = 0; + } break; + default : { + size = 0; + return MPP_OK; + } break; + } + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_CONTROL, cmd, size, arg); + if (ret) + mpp_err("chan %d VCODEC_CHAN_CONTROL failed\n", ctx->mChanId); + + return ret; +} + +static MPP_RET reset(Kmpp *ctx) +{ + MPP_RET ret = MPP_OK; + + if (!ctx) + return MPP_ERR_VALUE; + if (ctx->mChanDup) + return MPP_OK; + if (!ctx->mInitDone) + return MPP_ERR_INIT; + + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_RESET, 0, 0, 0); + if (ret) + mpp_err("chan %d VCODEC_CHAN_RESET failed\n", ctx->mChanId); + + return ret; +} + +static MPP_RET notify_flag(Kmpp *ctx, RK_U32 flag) +{ + (void)flag; + (void)ctx; + + return MPP_NOK; +} + +static MPP_RET notify(Kmpp *ctx, MppBufferGroup group) +{ + MPP_RET ret = MPP_OK; + (void)group; + + switch (ctx->mType) { + case MPP_CTX_DEC : { + } break; + default : { + } break; + } + + return ret; +} + +static MPP_RET get_fd(Kmpp *ctx, RK_S32 *fd) +{ + MPP_RET ret = MPP_OK; + + if (!ctx) + return MPP_ERR_VALUE; + + if (ctx->mClientFd >= 0) + *fd = fcntl(ctx->mClientFd, F_DUPFD_CLOEXEC, 3); + else + *fd = -1; + + if (*fd < 0) + ret = MPP_NOK; + + return ret; +} + +static MPP_RET close_fd(Kmpp *ctx, RK_S32 fd) +{ + if (fd >= 0) + close(fd); + (void)ctx; + return MPP_OK; +} + +static KmppOps ops = { + .open_client = open_client, + .init = init, + .start = start, + .stop = stop, + .pause = mpp_pause, + .resume = resume, + .put_packet = put_packet, + .get_frame = get_frame, + .put_frame = put_frame, + .get_packet = get_packet, + .release_packet = release_packet, + .poll = poll, + .dequeue = dequeue, + .enqueue = enqueue, + .reset = reset, + .control = control, + .notify_flag = notify_flag, + .notify = notify, + .get_fd = get_fd, + .close_fd = close_fd, + .clear = clear, +}; + +void mpp_get_api(Kmpp *ctx) +{ + if (!ctx) + return; + + ctx->mApi = &ops; +} diff --git a/osal/CMakeLists.txt b/osal/CMakeLists.txt index 34cb1944..8364c975 100644 --- a/osal/CMakeLists.txt +++ b/osal/CMakeLists.txt @@ -23,6 +23,7 @@ set(MPP_DRIVER driver/mpp_device.c driver/mpp_service.c driver/vcodec_service.c + driver/mpp_vcodec_client.c ) add_library(osal STATIC diff --git a/osal/driver/inc/mpp_vcodec_client.h b/osal/driver/inc/mpp_vcodec_client.h new file mode 100644 index 00000000..6389efb6 --- /dev/null +++ b/osal/driver/inc/mpp_vcodec_client.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef __MPP_VCODEC_CLIENT_H__ +#define __MPP_VCODEC_CLIENT_H__ + +#include "rk_type.h" +#include "mpp_err.h" + +#define VCODEC_ID_BASE_COMMON (0x00000000) +#define VCODEC_ID_BASE_STATE (0x00000100) +#define VCODEC_ID_BASE_FLOW (0x00000200) + +#define VCODEC_ID_BASE_INPUT (0x00000400) +#define VCODEC_ID_BASE_INPUT_ACK (0x00000500) + +#define VCODEC_ID_BASE_OUTPUT (0x00000600) +#define VCODEC_ID_BASE_OUTPUT_ACK (0x00000700) + +enum vcodec_event_id { + /* channel comment event */ + VCODEC_CHAN_CREATE = VCODEC_ID_BASE_COMMON, + VCODEC_CHAN_DESTROY, + VCODEC_CHAN_RESET, + VCODEC_CHAN_CONTROL, + + /* channel state change event */ + VCODEC_CHAN_START = VCODEC_ID_BASE_STATE, + VCODEC_CHAN_STOP, + VCODEC_CHAN_PAUSE, + VCODEC_CHAN_RESUME, + + /* channel data flow event */ + VCODEC_CHAN_BIND = VCODEC_ID_BASE_FLOW, + VCODEC_CHAN_UNBIND, + + /* channel input side io event from external module */ + VCODEC_CHAN_IN_FRM_RDY = VCODEC_ID_BASE_INPUT, + VCODEC_CHAN_IN_FRM_START, + VCODEC_CHAN_IN_FRM_EARLY_END, + VCODEC_CHAN_IN_FRM_END, + + /* channel input side ack event from vcodec module */ + VCODEC_CHAN_IN_BLOCK = VCODEC_ID_BASE_INPUT_ACK, + + /* channel output side io event from vcodec module */ + VCODEC_CHAN_OUT_STRM_Q_FULL = VCODEC_ID_BASE_OUTPUT, + VCODEC_CHAN_OUT_STRM_BUF_RDY, + VCODEC_CHAN_OUT_STRM_END, + VCODEC_CHAN_OUT_STRM_INFO, + + /* channel input side ack event from external module */ + VCODEC_CHAN_OUT_BLOCK = VCODEC_ID_BASE_OUTPUT_ACK, + +}; + +#ifdef __cplusplus +extern "C" { +#endif + +RK_S32 mpp_vcodec_open(void); +MPP_RET mpp_vcodec_ioctl(RK_S32 fd, RK_U32 cmd, RK_U32 ctrl_cmd, RK_U32 size, void *param); +MPP_RET mpp_vcodec_close(RK_S32 fd); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/osal/driver/mpp_vcodec_client.c b/osal/driver/mpp_vcodec_client.c new file mode 100644 index 00000000..74d5a273 --- /dev/null +++ b/osal/driver/mpp_vcodec_client.c @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_vcodec" + +#include +#include +#include +#include + +#include "mpp_log.h" +#include "mpp_env.h" +#include "mpp_common.h" +#include "mpp_vcodec_client.h" + +#define VOCDEC_IOC_MAGIC 'V' +#define VOCDEC_IOC_CFG _IOW(VOCDEC_IOC_MAGIC, 1, unsigned int) + +typedef struct vcodec_req_t { + RK_U32 cmd; + RK_U32 ctrl_cmd; + RK_U32 size; + RK_U64 data; +} vcodec_req; + +#if __SIZEOF_POINTER__ == 4 +#define REQ_DATA_PTR(ptr) ((RK_U32)ptr) +#elif __SIZEOF_POINTER__ == 8 +#define REQ_DATA_PTR(ptr) ((RK_U64)ptr) +#endif + +RK_S32 mpp_vcodec_open(void) +{ + RK_S32 fd = -1; + + fd = open("/dev/vcodec", O_RDWR | O_CLOEXEC); + if (fd < 0) { + mpp_err("open /dev/vcodec failed errno %d %s\n", errno, strerror(errno)); + return -1; + } + + return fd; +} + +MPP_RET mpp_vcodec_ioctl(RK_S32 fd, RK_U32 cmd, RK_U32 ctrl_cmd, RK_U32 size, void *param) +{ + vcodec_req req; + RK_S32 ret = 0; + + memset(&req, 0, sizeof(req)); + req.cmd = cmd; + req.ctrl_cmd = ctrl_cmd; + req.size = size; + req.data = REQ_DATA_PTR(param); + + ret = (RK_S32)ioctl(fd, VOCDEC_IOC_CFG, &req); + if (ret) { + mpp_err("ioctl fd %d failed ret %d errno %d %s\n", + fd, ret, errno, strerror(errno)); + return MPP_NOK; + } + + return MPP_OK; +} + +MPP_RET mpp_vcodec_close(RK_S32 fd) +{ + if (fd) + close(fd); + + return MPP_OK; +}