From e8c1db2556ebe78adee6055fd25c41977b141e65 Mon Sep 17 00:00:00 2001 From: Herman Chen Date: Thu, 10 May 2018 11:14:13 +0800 Subject: [PATCH] [mpp_dec_vproc]: Add post process module Add mpp dec post-process thread and functions. Change-Id: I2a03e6ddfd6c746d272dd58b629e81f98b530c4a Signed-off-by: Herman Chen --- mpp/CMakeLists.txt | 3 +- mpp/vproc/CMakeLists.txt | 2 +- mpp/vproc/inc/mpp_dec_vproc.h | 49 +++++++ mpp/vproc/mpp_dec_vproc.cpp | 265 ++++++++++++++++++++++++++++++++++ 4 files changed, 317 insertions(+), 2 deletions(-) create mode 100644 mpp/vproc/inc/mpp_dec_vproc.h create mode 100644 mpp/vproc/mpp_dec_vproc.cpp diff --git a/mpp/CMakeLists.txt b/mpp/CMakeLists.txt index a3a406d4..7262bc46 100644 --- a/mpp/CMakeLists.txt +++ b/mpp/CMakeLists.txt @@ -14,6 +14,7 @@ include_directories(base/inc) include_directories(codec/inc) include_directories(hal/inc) include_directories(hal/common) +include_directories(vproc/inc) # ---------------------------------------------------------------------------- # add mpp base component @@ -51,7 +52,7 @@ set(MPP_ABI_VERSION "1") add_library(${MPP_STATIC} STATIC ${MPP_SRC}) set_target_properties(${MPP_STATIC} PROPERTIES FOLDER "mpp") set_target_properties(${MPP_STATIC} PROPERTIES CLEAN_DIRECT_OUTPUT 1) -target_link_libraries(${MPP_STATIC} mpp_base mpp_codec mpp_hal) +target_link_libraries(${MPP_STATIC} mpp_base mpp_codec mpp_hal mpp_vproc) add_library(${MPP_SHARED} SHARED ${MPP_SRC}) set_target_properties(${MPP_SHARED} PROPERTIES FOLDER "mpp") diff --git a/mpp/vproc/CMakeLists.txt b/mpp/vproc/CMakeLists.txt index 0ce36232..21885fec 100644 --- a/mpp/vproc/CMakeLists.txt +++ b/mpp/vproc/CMakeLists.txt @@ -3,7 +3,7 @@ # ---------------------------------------------------------------------------- # add mpp video process implement # ---------------------------------------------------------------------------- -include_directories(inc) +add_library(mpp_vproc STATIC mpp_dec_vproc.cpp) add_subdirectory(rga) add_subdirectory(iep) diff --git a/mpp/vproc/inc/mpp_dec_vproc.h b/mpp/vproc/inc/mpp_dec_vproc.h new file mode 100644 index 00000000..d30bcc70 --- /dev/null +++ b/mpp/vproc/inc/mpp_dec_vproc.h @@ -0,0 +1,49 @@ +/* + * Copyright 2018 Rockchip 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 __MPP_DEC_VPROC_H__ +#define __MPP_DEC_VPROC_H__ + +typedef void* MppDecVprocCtx; + +#ifdef __cplusplus +#include "mpp.h" + +extern "C" { +#endif + +/* + * Functions usage: + * dec_vproc_init - get context with cfg + * dec_vproc_deinit - stop thread and destory context + * dec_vproc_start - start thread processing + * dec_vproc_signal - signal thread that one frame has be pushed for process + * dec_vproc_reset - reset process thread and discard all input + */ + +MPP_RET dec_vproc_init(MppDecVprocCtx *ctx, void *mpp); +MPP_RET dec_vproc_deinit(MppDecVprocCtx ctx); + +MPP_RET dec_vproc_start(MppDecVprocCtx ctx); +MPP_RET dec_vproc_stop(MppDecVprocCtx ctx); +MPP_RET dec_vproc_signal(MppDecVprocCtx ctx); +MPP_RET dec_vproc_reset(MppDecVprocCtx ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* __MPP_DEC_VPROC_H__ */ diff --git a/mpp/vproc/mpp_dec_vproc.cpp b/mpp/vproc/mpp_dec_vproc.cpp new file mode 100644 index 00000000..3ddf193c --- /dev/null +++ b/mpp/vproc/mpp_dec_vproc.cpp @@ -0,0 +1,265 @@ +/* + * Copyright 2018 Rockchip 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 "mpp_env.h" +#include "mpp_mem.h" + +#include "mpp_dec_vproc.h" + +#define vproc_dbg(flag, fmt, ...) \ + do { \ + _mpp_dbg(vproc_debug, flag, fmt, ## __VA_ARGS__); \ + } while (0) + +#define vproc_dbg_f(flag, fmt, ...) \ + do { \ + _mpp_dbg_f(vproc_debug, flag, fmt, ## __VA_ARGS__); \ + } while (0) + +#define VPROC_DBG_FUNCTION (0x00000001) + +#define vproc_func(fmt, ...) \ + vproc_dbg_f(VPROC_DBG_FUNCTION, fmt, ## __VA_ARGS__); + +RK_U32 vproc_debug = 0; + +typedef struct MppDecVprocCtxImpl_t { + Mpp *mpp; + MppBufSlots slots; + + MppThread *thd; + RK_U32 reset; + RK_S32 count; +} MppDecVprocCtxImpl; + +static void mpp_enqueue_frames(Mpp *mpp, MppFrame frame) +{ + mpp_list *list = mpp->mFrames; + + list->lock(); + list->add_at_tail(&frame, sizeof(frame)); + + if (mpp_debug & MPP_DBG_PTS) + mpp_log("output frame pts %lld\n", mpp_frame_get_pts(frame)); + + mpp->mFramePutCount++; + list->signal(); + list->unlock(); +} + +static void *dec_vproc_thread(void *data) +{ + MppDecVprocCtxImpl *ctx = (MppDecVprocCtxImpl *)data; + MppThread *thd = ctx->thd; + Mpp *mpp = ctx->mpp; + MppDec *dec = mpp->mDec; + MppBufSlots slots = dec->frame_slots; + + mpp_dbg(MPP_DBG_INFO, "mpp_dec_post_proc_thread started\n"); + + while (1) { + RK_S32 index = -1; + + { + AutoMutex autolock(thd->mutex()); + MPP_RET ret = MPP_OK; + + if (MPP_THREAD_RUNNING != thd->get_status()) + break; + + if (ctx->reset) { + mpp_log_f("reset start\n"); + // on reset just return all index + do { + ret = mpp_buf_slot_dequeue(slots, &index, QUEUE_DEINTERLACE); + if (MPP_OK == ret && index >= 0) { + mpp_buf_slot_clr_flag(slots, index, SLOT_QUEUE_USE); + ctx->count--; + mpp_log_f("reset index %d\n", index); + } + } while (ret == MPP_OK); + mpp_log_f("reset done\n"); + + thd->lock(THREAD_CONTROL); + ctx->reset = 0; + thd->signal(THREAD_CONTROL); + thd->unlock(THREAD_CONTROL); + } else { + ret = mpp_buf_slot_dequeue(slots, &index, QUEUE_DEINTERLACE); + if (ret) + thd->wait(); + else + ctx->count--; + } + + if (ret) + continue; + } + + + // dequeue from deinterlace queue then send to mpp->mFrames + if (index >= 0) { + MppFrame frame = NULL; + mpp_buf_slot_get_prop(slots, index, SLOT_FRAME, &frame); + if (mpp_frame_get_info_change(frame)) { + mpp_enqueue_frames(mpp, frame); + goto VPROC_DONE; + } + + if (!dec->reset_flag) { + mpp_enqueue_frames(mpp, frame); + } else + mpp_frame_deinit(&frame); + + VPROC_DONE: + mpp_buf_slot_clr_flag(slots, index, SLOT_QUEUE_USE); + } + } + mpp_dbg(MPP_DBG_INFO, "mpp_dec_post_proc_thread exited\n"); + + return NULL; +} + +MPP_RET dec_vproc_init(MppDecVprocCtx *ctx, void *mpp) +{ + if (NULL == ctx || NULL == mpp) { + mpp_err_f("found NULL input ctx %p mpp %p\n", ctx, mpp); + return MPP_ERR_NULL_PTR; + } + + vproc_func("in"); + mpp_env_get_u32("vproc_debug", &vproc_debug, 0); + + *ctx = NULL; + + MppDecVprocCtxImpl *p = mpp_calloc(MppDecVprocCtxImpl, 1); + if (NULL == p) { + mpp_err_f("malloc failed\n"); + return MPP_ERR_MALLOC; + } + + p->mpp = (Mpp *)mpp; + p->slots = p->mpp->mDec->frame_slots; + p->thd = new MppThread(dec_vproc_thread, p, "mpp_dec_vproc"); + + *ctx = p; + + vproc_func("out"); + return MPP_OK; +} + +MPP_RET dec_vproc_deinit(MppDecVprocCtx ctx) +{ + if (NULL == ctx) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + vproc_func("in"); + + MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx; + if (p->thd) + p->thd->stop(); + + mpp_free(p); + + vproc_func("out"); + return MPP_OK; +} + +MPP_RET dec_vproc_start(MppDecVprocCtx ctx) +{ + if (NULL == ctx) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + vproc_func("in"); + + MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx; + + if (p->thd) + p->thd->start(); + else + mpp_err("failed to start dec vproc thread\n"); + + vproc_func("out"); + return MPP_OK; +} + +MPP_RET dec_vproc_stop(MppDecVprocCtx ctx) +{ + if (NULL == ctx) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + vproc_func("in"); + + MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx; + + if (p->thd) + p->thd->stop(); + else + mpp_err("failed to stop dec vproc thread\n"); + + vproc_func("out"); + return MPP_OK; +} + +MPP_RET dec_vproc_signal(MppDecVprocCtx ctx) +{ + if (NULL == ctx) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + vproc_func("in"); + + MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx; + if (p->thd) { + p->thd->lock(); + p->count++; + p->thd->signal(); + p->thd->unlock(); + } + + vproc_func("out"); + return MPP_OK; +} + +MPP_RET dec_vproc_reset(MppDecVprocCtx ctx) +{ + if (NULL == ctx) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + vproc_func("in"); + + MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx; + if (p->thd) { + p->thd->lock(); + p->reset = 1; + p->thd->signal(); + p->thd->unlock(); + + // wait reset finished + p->thd->lock(THREAD_CONTROL); + p->thd->wait(THREAD_CONTROL); + p->thd->unlock(THREAD_CONTROL); + + mpp_assert(p->reset == 0); + } + + vproc_func("out"); + return MPP_OK; +}