diff --git a/CMakeLists.txt b/CMakeLists.txt index d810491e..808a2b7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,6 +71,10 @@ endif() # System architecture detection # ---------------------------------------------------------------------------- string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" SYSPROC) +if (ARMLINUX) + set(SYSPROC "armv7-a") + message(STATUS "CMAKE_SYSTEM_PROCESSOR=${SYSPROC}") +endif() set(X86_ALIASES x86 i386 i686 x86_64 amd64) list(FIND X86_ALIASES "${SYSPROC}" X86MATCH) if("${SYSPROC}" STREQUAL "" OR X86MATCH GREATER "-1") @@ -172,8 +176,8 @@ if(GCC) if(ARM) if(ARMEABI_V6) add_definitions(-march=armv6 -mfloat-abi=hard -mfpu=vfp) - elseif(ARMEABI_V7A) - add_definitions(-march=armv7-a -mfloat-abi=softfp -mfpu=neon) +# elseif(ARMEABI_V7A) +# add_definitions(-march=armv7-a -mfloat-abi=softfp -mfpu=neon) endif() endif() # disable multichar warning diff --git a/inc/rk_mpi.h b/inc/rk_mpi.h index 8d160eb2..0a2167b6 100644 --- a/inc/rk_mpi.h +++ b/inc/rk_mpi.h @@ -82,6 +82,8 @@ typedef enum { MPP_DEC_GET_STREAM_COUNT, MPP_ENC_CMD_BASE = 0x50000, + MPP_ENC_SET_EXTRA_INFO, + MPP_ENC_GET_EXTRA_INFO, MPP_ENC_SETCFG, MPP_ENC_GETCFG, MPP_ENC_SETFORMAT, @@ -201,7 +203,7 @@ typedef struct MppApi_t { // control interface MPP_RET (*reset)(MppCtx ctx); MPP_RET (*control)(MppCtx ctx, MpiCmd cmd, MppParam param); - MPP_RET (*config)(MppCtx ctx, MppEncConfig cfg); + MPP_RET (*config)(MppCtx ctx, MpiCmd cmd, MppEncConfig cfg); RK_U32 reserv[16]; } MppApi; @@ -227,6 +229,8 @@ MPP_RET mpp_destroy(MppCtx ctx); // coding type format function MPP_RET mpp_check_support_format(MppCtxType type, MppCodingType coding); void mpp_show_support_format(); +RK_U8 *mpp_enc_get_extra_data(MppCtx ctx); +RK_U32 mpp_enc_get_extra_data_size(MppCtx ctx); #ifdef __cplusplus } diff --git a/inc/vpu.h b/inc/vpu.h index 75b7a121..8c29fe2f 100644 --- a/inc/vpu.h +++ b/inc/vpu.h @@ -48,6 +48,7 @@ typedef enum { VPU_DEC_PP = 0x3, VPU_DEC_HEVC = 0x4, VPU_DEC_RKV = 0x5, + VPU_ENC_RKV = 0x6, VPU_TYPE_BUTT , } VPU_CLIENT_TYPE; diff --git a/mpp/codec/CMakeLists.txt b/mpp/codec/CMakeLists.txt index 036ca703..178866c9 100644 --- a/mpp/codec/CMakeLists.txt +++ b/mpp/codec/CMakeLists.txt @@ -5,6 +5,7 @@ # ---------------------------------------------------------------------------- add_library(mpp_codec STATIC mpp_enc.cpp + mpp_controller.cpp mpp_dec.cpp mpp_parser.cpp ) @@ -23,6 +24,7 @@ target_link_libraries(mpp_codec codec_mpg4d codec_vp8d codec_vp9d + codec_h264e codec_dummy_enc codec_dummy_dec mpp_base) diff --git a/mpp/codec/enc/CMakeLists.txt b/mpp/codec/enc/CMakeLists.txt index 3471de4d..fb450a84 100644 --- a/mpp/codec/enc/CMakeLists.txt +++ b/mpp/codec/enc/CMakeLists.txt @@ -2,4 +2,4 @@ add_subdirectory(dummy) -#add_subdirectory(h264) \ No newline at end of file +add_subdirectory(h264) \ No newline at end of file diff --git a/mpp/codec/enc/h264/CMakeLists.txt b/mpp/codec/enc/h264/CMakeLists.txt index ed8bb06a..ee593257 100644 --- a/mpp/codec/enc/h264/CMakeLists.txt +++ b/mpp/codec/enc/h264/CMakeLists.txt @@ -15,8 +15,6 @@ set(H264E_COMMON set(H264E_HDR include/basetype.h include/EncGetOption.h - include/H264Cabac.h - include/H264CabacContext.h include/H264CodeFrame.h include/H264Init.h include/H264Instance.h @@ -42,7 +40,6 @@ set(H264E_HDR # h264 encoder sourse set(H264E_SRC src/EncGetOption.c - src/H264Cabac.c src/H264CodeFrame.c src/H264EncApi.c src/H264Init.c diff --git a/mpp/codec/enc/h264/include/encasiccontroller.h b/mpp/codec/enc/h264/include/encasiccontroller.h index 9991214d..51404fe1 100644 --- a/mpp/codec/enc/h264/include/encasiccontroller.h +++ b/mpp/codec/enc/h264/include/encasiccontroller.h @@ -169,7 +169,6 @@ typedef struct { u32 riceEnable; u32 riceReadBase; u32 riceWriteBase; - u32 cabacCtxBase; u32 colorConversionCoeffA; u32 colorConversionCoeffB; u32 colorConversionCoeffC; @@ -210,7 +209,6 @@ typedef struct { MppBufferGroup asicDataBufferGroup; MppBuffer internalImageLuma[2]; MppBuffer internalImageChroma[2]; - MppBuffer cabacCtx; MppBuffer riceRead; MppBuffer riceWrite; u32 sizeTblSize; diff --git a/mpp/codec/enc/h264/src/H264EncApi.c b/mpp/codec/enc/h264/src/H264EncApi.c index d40b1ffa..5fd6dd0e 100644 --- a/mpp/codec/enc/h264/src/H264EncApi.c +++ b/mpp/codec/enc/h264/src/H264EncApi.c @@ -41,7 +41,6 @@ #include "H264CodeFrame.h" #include "H264Sei.h" #include "H264RateControl.h" -#include "H264Cabac.h" #define LOG_TAG "H264_ENC" //#include // mask by lance 2016.05.05 #ifdef INTERNAL_TEST @@ -1010,16 +1009,6 @@ H264EncRet H264EncStrmStart(H264EncInst inst, const H264EncIn * pEncIn, rc->virtualBuffer.bufferSize); } - /* Initialize cabac context tables for HW */ - if (pEncInst->picParameterSet.entropyCodingMode == ENCHW_YES) { - // mask and add by lance 2016.05.05 - /*VPUMemInvalidate(&pEncInst->asic.cabacCtx); - H264CabacInit(pEncInst->asic.cabacCtx.vir_addr, - pEncInst->slice.cabacInitIdc); - VPUMemClean(&pEncInst->asic.cabacCtx);*/ - H264CabacInit((u32*)(mpp_buffer_get_ptr(pEncInst->asic.cabacCtx)), - pEncInst->slice.cabacInitIdc); - } /* Use the first frame QP in the PPS */ pEncInst->picParameterSet.picInitQpMinus26 = (i32) (rc->qpHdr) - 26; diff --git a/mpp/codec/enc/h264/src/encasiccontroller.c b/mpp/codec/enc/h264/src/encasiccontroller.c index dac3b98c..de53603b 100644 --- a/mpp/codec/enc/h264/src/encasiccontroller.c +++ b/mpp/codec/enc/h264/src/encasiccontroller.c @@ -150,7 +150,6 @@ i32 EncAsicControllerInit(asicData_s * asic) asic->internalImageChroma[0] = NULL; // modify by lance 2016.05.05 asic->internalImageLuma[1] = NULL; // modify by lance 2016.05.05 asic->internalImageChroma[1] = NULL; - asic->cabacCtx = NULL; asic->riceRead = NULL; asic->riceWrite = NULL; @@ -437,7 +436,6 @@ void EncAsicFrameStart(void * inst, /*const void *ewl, */regValues_s * val, h264 val->regMirror[80] = val->riceWriteBase; - val->regMirror[81] = val->cabacCtxBase; //roi1 area val->regMirror[82] = (val->roi1Top & 0xff) << 24; val->regMirror[82] |= (val->roi1Bottom & 0xff) << 16; @@ -609,7 +607,6 @@ void EncAsicFrameStart(void * inst, /*const void *ewl, */regValues_s * val, h264 fprintf(valCompareFile, "val->constrainedIntraPrediction 0x%08X\n", val->constrainedIntraPrediction); fprintf(valCompareFile, "val->vsNextLumaBase 0x%08X\n", val->vsNextLumaBase); fprintf(valCompareFile, "val->riceWriteBase 0x%08X\n", val->riceWriteBase); - fprintf(valCompareFile, "val->cabacCtxBase 0x%08X\n", val->cabacCtxBase); fprintf(valCompareFile, "val->roi1Top 0x%08X\n", val->roi1Top); fprintf(valCompareFile, "val->roi1Bottom 0x%08X\n", val->roi1Bottom); fprintf(valCompareFile, "val->roi1Left 0x%08X\n", val->roi1Left); @@ -682,7 +679,6 @@ void EncAsicFrameStart(void * inst, /*const void *ewl, */regValues_s * val, h264 } syntax_data->output_strm_limit_size = val->outputStrmSize; syntax_data->output_strm_addr = val->outputStrmBase; - syntax_data->cabac_table_addr = val->cabacCtxBase; syntax_data->pic_luma_width = instH264Encoder->preProcess.lumWidth; syntax_data->pic_luma_height = instH264Encoder->preProcess.lumHeight; syntax_data->ref_luma_addr = val->internalImageLumBaseR; // need to talk with kesheng by lance 2016.05.07 diff --git a/mpp/codec/enc/h264/src/encasiccontroller_v2.c b/mpp/codec/enc/h264/src/encasiccontroller_v2.c index 11eac696..d57c4b72 100644 --- a/mpp/codec/enc/h264/src/encasiccontroller_v2.c +++ b/mpp/codec/enc/h264/src/encasiccontroller_v2.c @@ -177,21 +177,6 @@ i32 EncAsicMemAlloc_V2(asicData_s * asic, u32 width, u32 height, return ENCHW_NOK; } - /* CABAC context tables: all qps, intra+inter, 464 bytes/table */ - // mask and add by lance 2016.05.05 - /*if (VPUMallocLinear(&asic->cabacCtx, 52 * 2 * 464) != EWL_OK) { - EncAsicMemFree_V2(asic); - return ENCHW_NOK; - } - regs->cabacCtxBase = asic->cabacCtx.phy_addr;*/ - if (asic->cabacCtx == NULL) { - if (mpp_buffer_get(asic->asicDataBufferGroup, &(asic->cabacCtx), (52 * 2 * 464)) != MPP_OK) { - mpp_err("asic->cabacCtx alloc failed!\n"); - return ENCHW_NOK; - } - } - regs->cabacCtxBase = mpp_buffer_get_fd(asic->cabacCtx); - // mask and add by lance 2016.05.05 /*if (regs->riceEnable) { u32 bytes = ((width + 11) / 12 * (height * 2 - 1)) * 8; @@ -295,11 +280,6 @@ void EncAsicMemFree_V2(asicData_s * asic) asic->sizeTbl.nal = NULL; } - if (asic->cabacCtx != NULL) { - mpp_buffer_put(asic->cabacCtx); - asic->cabacCtx = NULL; - } - if (asic->riceRead != NULL) { mpp_buffer_put(asic->riceRead); asic->riceRead = NULL; diff --git a/mpp/codec/inc/encoder_codec_api.h b/mpp/codec/inc/encoder_codec_api.h new file mode 100644 index 00000000..3208e528 --- /dev/null +++ b/mpp/codec/inc/encoder_codec_api.h @@ -0,0 +1,79 @@ +/* + * Copyright 2010 Rockchip Electronics S.LSI 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 __CONTROL_API_H__ +#define __CONTROL_API_H__ + +#include "rk_mpi.h" +#include "mpp_buf_slot.h" +#include "hal_task.h" + +// TODO +#include "../enc/h264/include/h264encapi.h" + +// config cmd +typedef enum EncCfgCmd_t { + GET_OUTPUT_STREAM_SIZE, +} EncCfgCmd; + +/* + * the reset wait for extension + */ +typedef struct EncControllerInitCfg_t { + H264EncConfig encCfg; + + // input + MppCodingType coding; + + // output + RK_S32 task_count; + IOInterruptCB notify_cb; +} ControllerCfg; + +/* + * ControlApi is the data structure provided from different encoders + * + * They will be static register to mpp_enc for scaning + * name - encoder name + * coding - encoder coding type + * ctx_size - encoder context size, mpp_dec will use this to malloc memory + * flag - reserve + * + * init - encoder initialization function + * deinit - encoder de-initialization function + * encoder - encoder main working function, mpp_dec will input packet and get output syntax + * reset - encoder reset function + * flush - encoder output all frames + * control - encoder configure function + */ +typedef struct ControlApi_t { + char *name; + MppCodingType coding; + RK_U32 ctx_size; + RK_U32 flag; + + MPP_RET (*init)(void *ctx, ControllerCfg *ctrlCfg); + MPP_RET (*deinit)(void *ctx); + + MPP_RET (*encode)(void *ctx, /*HalEncTask **/void *task); // TODO + + MPP_RET (*reset)(void *ctx); + MPP_RET (*flush)(void *ctx); + MPP_RET (*config)(void *ctx, RK_S32 cmd, void *param); + MPP_RET (*callback)(void *ctx, void *feedback); +} ControlApi; + +#endif /*__CONTROL_API_H__*/ diff --git a/mpp/codec/inc/h264e_api.h b/mpp/codec/inc/h264e_api.h index 86caee47..d8cb717f 100644 --- a/mpp/codec/inc/h264e_api.h +++ b/mpp/codec/inc/h264e_api.h @@ -17,6 +17,24 @@ #ifndef __H264E_API_H__ #define __H264E_API_H__ +#include "encoder_codec_api.h" +#ifdef __cplusplus +extern "C" { +#endif -#endif /*__H264E_API_H__*/ \ No newline at end of file +extern const ControlApi api_h264e_controller; + +MPP_RET h264e_init(void *ctx, ControllerCfg *ctrlCfg); +MPP_RET h264e_deinit(void *ctx); +MPP_RET h264e_encode(void *ctx, /*HalEncTask **/void *task); +MPP_RET h264e_reset(void *ctx); +MPP_RET h264e_flush(void *ctx); +MPP_RET h264e_config(void *ctx, RK_S32 cmd, void *param); +MPP_RET h264e_callback(void *ctx, void *feedback); + +#ifdef __cplusplus +} +#endif + +#endif /*__H264E_API_H__*/ diff --git a/mpp/codec/inc/mpp_controller.h b/mpp/codec/inc/mpp_controller.h new file mode 100644 index 00000000..1828d211 --- /dev/null +++ b/mpp/codec/inc/mpp_controller.h @@ -0,0 +1,85 @@ +/* + * Copyright 2010 Rockchip Electronics S.LSI 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 __ENCODER_CONTROLLER_API_H__ +#define __ENCODER_CONTROLLER_API_H__ + +#include "encoder_codec_api.h" + +typedef void* Controller; + +typedef union ControllerTaskWait_u { + RK_U32 val; + struct { + RK_U32 task_hnd : 1; + RK_U32 mpp_pkt_in : 1; + RK_U32 enc_pkt_idx : 1; + RK_U32 enc_pkt_buf : 1; + RK_U32 prev_task : 1; + RK_U32 info_change : 1; + RK_U32 enc_pic_buf : 1; + }; +} ControllerTaskWait; + +typedef union EncTaskStatus_u { + RK_U32 val; + struct { + RK_U32 task_hnd_rdy : 1; + RK_U32 mpp_pkt_in_rdy : 1; + RK_U32 enc_pkt_idx_rdy : 1; + RK_U32 enc_pkt_buf_rdy : 1; + RK_U32 task_valid_rdy : 1; + RK_U32 enc_pkt_copy_rdy : 1; + RK_U32 prev_task_rdy : 1; + RK_U32 info_task_gen_rdy : 1; + RK_U32 curr_task_rdy : 1; + RK_U32 task_controled_rdy : 1; + }; +} EncTaskStatus; + + +typedef struct EncTask_t { + HalTaskHnd hnd; + + EncTaskStatus status; + ControllerTaskWait wait; + + RK_S32 hal_frm_idx_in; + RK_S32 hal_pkt_idx_out; + + MppBuffer ctrl_frm_buf_in; + MppBuffer ctrl_pkt_buf_out; + + h264e_syntax syntax_data; + + HalTaskInfo info; +} EncTask; + + +#ifdef __cplusplus +extern "C" { +#endif +MPP_RET controller_init(Controller *ctrller, ControllerCfg *cfg); +MPP_RET controller_deinit(Controller ctrller); +MPP_RET controller_encode(Controller ctrller, /*HalEncTask **/EncTask *task); +MPP_RET controller_config(Controller ctrller, RK_S32 cmd, void *para); +MPP_RET hal_enc_callback(void* ctrller, void *err_info); + +#ifdef __cplusplus +} +#endif + +#endif /*__ENCODER_CONTROLLER_API_H__*/ diff --git a/mpp/codec/inc/mpp_enc.h b/mpp/codec/inc/mpp_enc.h index a97af8cd..9f9dc865 100644 --- a/mpp/codec/inc/mpp_enc.h +++ b/mpp/codec/inc/mpp_enc.h @@ -17,19 +17,28 @@ #ifndef __MPP_ENC_H__ #define __MPP_ENC_H__ +#include "rk_mpi.h" +#include "mpp_controller.h" #include "mpp_hal.h" typedef struct MppEnc_t MppEnc; struct MppEnc_t { MppCodingType coding; - + Controller controller; MppHal hal; // common resource MppBufSlots frame_slots; MppBufSlots packet_slots; HalTaskGroup tasks; + + RK_U32 reset_flag; + void *mpp; + + H264EncConfig encCfg; + h264e_control_extra_info_cfg extra_info_cfg; + h264e_control_extra_info extra_info; }; #ifdef __cplusplus @@ -42,10 +51,10 @@ extern "C" { void *mpp_enc_control_thread(void *data); void *mpp_enc_hal_thread(void *data); - -MPP_RET mpp_enc_init(MppEnc **enc, MppCodingType coding); +MPP_RET mpp_enc_init(MppEnc *enc, MppCodingType coding); MPP_RET mpp_enc_deinit(MppEnc *enc); - +MPP_RET mpp_enc_config(MppEnc *enc, MpiCmd cmd, void *param); +MPP_RET mpp_enc_notify(void *ctx, void *info); MPP_RET mpp_enc_reset(MppEnc *enc); #ifdef __cplusplus diff --git a/mpp/codec/mpp_controller.cpp b/mpp/codec/mpp_controller.cpp new file mode 100644 index 00000000..e4a52904 --- /dev/null +++ b/mpp/codec/mpp_controller.cpp @@ -0,0 +1,133 @@ +/* + * Copyright 2010 Rockchip Electronics S.LSI 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. + */ + +#define MODULE_TAG "mpp_enc" + +#include "mpp_mem.h" +#include "mpp_log.h" +#include "mpp_common.h" +#include "h264e_api.h" +#include "mpp_controller.h" + +/* + * all decoder static register here + */ +static const ControlApi *controllers[] = { + &api_h264e_controller, +}; + +typedef struct ControllerImpl_t { + ControllerCfg cfg; + const ControlApi *api; + void *ctx; +} ControllerImpl; + +MPP_RET controller_encode(Controller ctrller, /*HalEncTask **/EncTask *task) +{ + if (NULL == ctrller || NULL == task) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + ControllerImpl *p = (ControllerImpl *)ctrller; + if (!p->api->encode) + return MPP_OK; + + return p->api->encode(p->ctx, (void*)task); +} + +MPP_RET controller_init(Controller *ctrl, ControllerCfg *cfg) +{ + if (NULL == ctrl || NULL == cfg) { + mpp_err_f("found NULL input controller %p config %p\n", ctrl, cfg); + return MPP_ERR_NULL_PTR; + } + + *ctrl = NULL; + + RK_U32 i; + for (i = 0; i < MPP_ARRAY_ELEMS(controllers); i++) { + const ControlApi *api = controllers[i]; + if (cfg->coding == api->coding) { + ControllerImpl *p = mpp_calloc(ControllerImpl, 1); + void *ctx = mpp_calloc_size(void, api->ctx_size); + if (NULL == ctx || NULL == p) { + mpp_err_f("failed to alloc parser context\n"); + mpp_free(p); + mpp_free(ctx); + return MPP_ERR_MALLOC; + } + + MPP_RET ret = api->init(ctx, cfg); // FIXME need to be thinked by lance 2016.05.18 + if (MPP_OK != ret) { + mpp_err_f("failed to init controller\n"); + mpp_free(p); + mpp_free(ctx); + return ret; + } + + p->cfg = *cfg; + p->api = api; + p->ctx = ctx; + *ctrl = p; + return MPP_OK; + } + } + + return MPP_NOK; +} + +MPP_RET controller_deinit(Controller ctrl) +{ + if (NULL == ctrl) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + ControllerImpl *p = (ControllerImpl *)ctrl; + if (p->api->deinit) + p->api->deinit(p->ctx); + + mpp_free(p->ctx); + mpp_free(p); + return MPP_OK; +} + +MPP_RET hal_enc_callback(void *ctrller, void *err_info) +{ + if (NULL == ctrller) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + ControllerImpl *p = (ControllerImpl *)ctrller; + if (!p->api->callback) + return MPP_OK; + return p->api->callback(p->ctx, err_info); +} + +MPP_RET controller_config(Controller ctrller, RK_S32 cmd, void *para) +{ + if (NULL == ctrller) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + ControllerImpl *p = (ControllerImpl *)ctrller; + if (!p->api->config) + return MPP_OK; + + return p->api->config(p->ctx, cmd, para); +} diff --git a/mpp/codec/mpp_enc.cpp b/mpp/codec/mpp_enc.cpp index c9300132..6e369231 100644 --- a/mpp/codec/mpp_enc.cpp +++ b/mpp/codec/mpp_enc.cpp @@ -16,6 +16,8 @@ #define MODULE_TAG "mpp_enc" +#include "string.h" + #include "mpp_log.h" #include "mpp_mem.h" @@ -24,45 +26,63 @@ #include "mpp_frame_impl.h" #include "mpp_packet.h" #include "mpp_packet_impl.h" +#include "hal_h264e_api.h" void *mpp_enc_control_thread(void *data) { Mpp *mpp = (Mpp*)data; - MppThread *thd_enc = mpp->mThreadCodec; + MppThread *thd_enc = mpp->mThreadCodec; + EncTask task; // TODO + HalTaskInfo task_info; MppPort input = mpp_task_queue_get_port(mpp->mInputTaskQueue, MPP_PORT_OUTPUT); MppPort output = mpp_task_queue_get_port(mpp->mOutputTaskQueue, MPP_PORT_INPUT); - MppTask task = NULL; + MppTask mpp_task = NULL; MPP_RET ret = MPP_OK; + memset(&task_info, 0, sizeof(HalTaskInfo)); + while (MPP_THREAD_RUNNING == thd_enc->get_status()) { thd_enc->lock(); - ret = mpp_port_dequeue(input, &task); - if (ret || NULL == task) + ret = mpp_port_dequeue(input, &mpp_task); + if (ret || NULL == mpp_task) { thd_enc->wait(); + } thd_enc->unlock(); - - if (task) { - MppFrame frame = NULL; - MppPacket packet = NULL; + if (mpp_task != NULL) { + MppFrame mpp_frame = NULL; + MppPacket mpp_packet = NULL; // task process here // enqueue task back to input input - mpp_task_meta_get_frame (task, MPP_META_KEY_INPUT_FRM, &frame); - mpp_task_meta_get_packet(task, MPP_META_KEY_OUTPUT_PKT, &packet); + mpp_task_meta_get_frame (mpp_task, MPP_META_KEY_INPUT_FRM, &mpp_frame); + mpp_task_meta_get_packet(mpp_task, MPP_META_KEY_OUTPUT_PKT, &mpp_packet); - mpp_port_enqueue(input, task); - task = NULL; + mpp_port_enqueue(input, mpp_task); + mpp_task = NULL; + memset(&task, 0, sizeof(EncTask)); + task.ctrl_frm_buf_in = mpp_frame_get_buffer(mpp_frame); + task.ctrl_pkt_buf_out = mpp_packet_get_buffer(mpp_packet); + controller_encode(mpp->mEnc->controller, &task); + + task_info.enc.syntax.data = (void *)(&(task.syntax_data)); + mpp_hal_reg_gen((mpp->mEnc->hal), &task_info); + mpp_hal_hw_start((mpp->mEnc->hal), &task_info); + /*vpuWaitResult = */mpp_hal_hw_wait((mpp->mEnc->hal), &task_info); // TODO need to check the return value + + + RK_U32 outputStreamSize = 0; + controller_config(mpp->mEnc->controller, GET_OUTPUT_STREAM_SIZE, (void*)&outputStreamSize); + + mpp_packet_set_length(mpp_packet, outputStreamSize); // send finished task to output port - mpp_port_dequeue(output, &task); - - mpp_task_meta_set_frame(task, MPP_META_KEY_INPUT_FRM, frame); - mpp_task_meta_set_packet(task, MPP_META_KEY_OUTPUT_PKT, packet); - + mpp_port_dequeue(output, &mpp_task); + mpp_task_meta_set_frame(mpp_task, MPP_META_KEY_INPUT_FRM, mpp_frame); + mpp_task_meta_set_packet(mpp_task, MPP_META_KEY_OUTPUT_PKT, mpp_packet); // setup output task here - mpp_port_enqueue(output, task); - task = NULL; + mpp_port_enqueue(output, mpp_task); + mpp_task = NULL; } } return NULL; @@ -131,40 +151,107 @@ void *mpp_enc_hal_thread(void *data) return NULL; } -MPP_RET mpp_enc_init(MppEnc **enc, MppCodingType coding) +static MPP_RET mpp_extra_info_generate(h264e_control_extra_info_cfg *info, const H264EncConfig *encCfg) { - MppEnc *p = mpp_calloc(MppEnc, 1); + info->chroma_qp_index_offset = encCfg->chroma_qp_index_offset; + info->enable_cabac = encCfg->enable_cabac; + info->pic_init_qp = encCfg->pic_init_qp; + info->pic_luma_height = encCfg->height; + info->pic_luma_width = encCfg->width; + info->transform8x8_mode = encCfg->transform8x8_mode; + + info->input_image_format = encCfg->input_image_format; + info->profile_idc = encCfg->profile; + info->level_idc = encCfg->level; + info->keyframe_max_interval = encCfg->keyframe_max_interval; + info->second_chroma_qp_index_offset = encCfg->second_chroma_qp_index_offset; + info->pps_id = encCfg->pps_id; + return MPP_OK; +} + +MPP_RET mpp_enc_init(MppEnc *enc, MppCodingType coding) +{ + MPP_RET ret; + MppBufSlots frame_slots = NULL; + MppBufSlots packet_slots = NULL; + Controller controller = NULL; + MppHal hal = NULL; + MppEnc *p = enc; + RK_S32 task_count = 2; + IOInterruptCB cb = {NULL, NULL}; + if (NULL == p) { mpp_err_f("failed to malloc context\n"); return MPP_ERR_NULL_PTR; } - MPP_RET ret = MPP_NOK; - MppHal hal = NULL; + do { + ret = mpp_buf_slot_init(&frame_slots); + if (ret) { + mpp_err_f("could not init frame buffer slot\n"); + break; + } - MppHalCfg hal_cfg = { - MPP_CTX_ENC, - coding, - HAL_MODE_LIBVPU, - HAL_RKVDEC, - NULL, - NULL, - NULL, - 2, - 0, - NULL, - }; + ret = mpp_buf_slot_init(&packet_slots); + if (ret) { + mpp_err_f("could not init packet buffer slot\n"); + break; + } - ret = mpp_hal_init(&hal, &hal_cfg); - if (ret) { - mpp_err_f("could not init hal\n"); - } + mpp_buf_slot_setup(packet_slots, task_count); + cb.callBack = mpp_enc_notify; + cb.opaque = enc; - p->coding = coding; + ControllerCfg controller_cfg = { + enc->encCfg, + coding, + task_count, + cb, + }; - *enc = p; + ret = controller_init(&controller, &controller_cfg); + if (ret) { + mpp_err_f("could not init parser\n"); + break; + } + cb.callBack = hal_enc_callback; + cb.opaque = controller; + // then init hal with task count from parser + MppHalCfg hal_cfg = { + MPP_CTX_ENC, + coding, + HAL_MODE_LIBVPU, + HAL_VEPU, + frame_slots, + packet_slots, + NULL, + 1/*controller_cfg.task_count*/, // TODO + 0, + cb, + }; + + ret = mpp_hal_init(&hal, &hal_cfg); + if (ret) { + mpp_err_f("could not init hal\n"); + break; + } + + mpp_extra_info_generate(&(enc->extra_info_cfg), &(enc->encCfg)); + mpp_hal_control(hal, MPP_ENC_SET_EXTRA_INFO, (void*)(&(enc->extra_info_cfg))); + mpp_hal_control(hal, MPP_ENC_GET_EXTRA_INFO, (void*)(&(enc->extra_info))); + + p->coding = coding; + p->controller = controller; + p->hal = hal; + p->tasks = hal_cfg.tasks; + p->frame_slots = frame_slots; + p->packet_slots = packet_slots; + return MPP_OK; + } while (0); + + mpp_enc_deinit(p); + return MPP_NOK; - return MPP_OK; } MPP_RET mpp_enc_deinit(MppEnc *enc) @@ -174,10 +261,26 @@ MPP_RET mpp_enc_deinit(MppEnc *enc) return MPP_ERR_NULL_PTR; } - MPP_RET ret = mpp_hal_deinit(enc->hal); - if (ret) { - mpp_err_f("mpp enc hal deinit failed\n"); + if (enc->controller) { + controller_deinit(enc->controller); + enc->controller = NULL; } + + if (enc->hal) { + mpp_hal_deinit(enc->hal); + enc->hal = NULL; + } + + if (enc->frame_slots) { + mpp_buf_slot_deinit(enc->frame_slots); + enc->frame_slots = NULL; + } + + if (enc->packet_slots) { + mpp_buf_slot_deinit(enc->packet_slots); + enc->packet_slots = NULL; + } + mpp_free(enc); return MPP_OK; } @@ -188,4 +291,69 @@ MPP_RET mpp_enc_reset(MppEnc *enc) return MPP_OK; } +MPP_RET mpp_enc_notify(void *ctx, void *info) +{ + // TODO + (void)ctx; + (void)info; + return MPP_OK; +} +MPP_RET mpp_enc_config(MppEnc *enc, MpiCmd cmd, void *param) +{ + if (NULL == enc) { + mpp_err_f("found NULL input enc %p\n", enc); + return MPP_ERR_NULL_PTR; + } + + // TODO + MppEncConfig *mppCfg = (MppEncConfig*)param; + H264EncConfig *encCfg = &(enc->encCfg); + + switch (cmd) { + case MPP_ENC_SETCFG: + encCfg->streamType = H264ENC_BYTE_STREAM;//H264ENC_NAL_UNIT_STREAM; // decide whether stream start with start code,e.g."00 00 00 01" + encCfg->frameRateDenom = 1; + if (0 != mppCfg->profile) + encCfg->profile = (h264e_profile)mppCfg->profile; + else + encCfg->profile = H264_PROFILE_BASELINE; + if (0 != mppCfg->level) + encCfg->level = (H264EncLevel)mppCfg->level; + else + encCfg->level = H264ENC_LEVEL_4_0; + if (0 != mppCfg->width && 0 != mppCfg->height) { + encCfg->width = mppCfg->width; + encCfg->height = mppCfg->height; + mpp_log("widthxheight %dx%d", encCfg->width, encCfg->height); + } else + mpp_err("Width or height is not set, width %d height %d", mppCfg->width, mppCfg->height); + if (0 != mppCfg->fps_in) + encCfg->frameRateNum = mppCfg->fps_in; + else + encCfg->frameRateNum = 30; + if (mppCfg->gop > 0) + encCfg->intraPicRate = mppCfg->gop; + else + encCfg->intraPicRate = 30; + if (0 != mppCfg->cabac_en) + encCfg->enable_cabac = mppCfg->cabac_en; // TODO + else + encCfg->enable_cabac = 0; + if (0 != mppCfg->trans8x8_en) + encCfg->transform8x8_mode = mppCfg->trans8x8_en; // TODO + else + encCfg->transform8x8_mode = 0; + encCfg->chroma_qp_index_offset = 2; // TODO + encCfg->pic_init_qp = 26; // TODO + encCfg->keyframe_max_interval = 150; // TODO + encCfg->second_chroma_qp_index_offset = 2; // TODO + encCfg->pps_id = 0; // TODO + encCfg->input_image_format = H264ENC_YUV420_SEMIPLANAR; // TODO + break; + default: + break; + } + + return MPP_OK; +} diff --git a/mpp/common/h264e_syntax.h b/mpp/common/h264e_syntax.h new file mode 100644 index 00000000..4dae47f9 --- /dev/null +++ b/mpp/common/h264e_syntax.h @@ -0,0 +1,124 @@ +#ifndef __H264E_SYNTAX_H__ +#define __H264E_SYNTAX_H__ +#include "rk_type.h" + +#define H264_BIT_DEPTH 8 +#define H264_QP_BD_OFFSET (6*(H264_BIT_DEPTH-8)) + +typedef enum h264e_profile_t { + H264_PROFILE_BASELINE = 66, + H264_PROFILE_MAIN = 77, + H264_PROFILE_HIGH = 100, + H264_PROFILE_HIGH10 = 110, + H264_PROFILE_HIGH422 = 122, + H264_PROFILE_HIGH444_PREDICTIVE = 244, +} h264e_profile; + +typedef struct h264e_osd_pos_t { + RK_U32 lt_pos_x : 8; + RK_U32 lt_pos_y : 8; + RK_U32 rd_pos_x : 8; + RK_U32 rd_pos_y : 8; +} h264e_osd_pos; //OSD_POS0-7 + +typedef struct h264e_syntax_t { + RK_U32 frame_coding_type; //(VEPU)0: inter, 1: intra (RKVENC)RKVENC_FRAME_TYPE_* + RK_U32 slice_type; + RK_S32 pic_init_qp; //COMB, TODO: merge with swreg59.pic_init_qp + RK_S32 slice_alpha_offset; //COMB TODO: merge with swreg62.sli_beta_ofst + RK_S32 slice_beta_offset; //COMB TODO: merge with swreg62.sli_alph_ofst + RK_S32 chroma_qp_index_offset; //COMB + RK_S32 second_chroma_qp_index_offset; //TODO: may be removed later, get from sps/pps instead + RK_S32 deblocking_filter_control; //COMB + RK_S32 disable_deblocking_filter_idc; + RK_S32 filter_disable; //TODO: merge width disable_deblocking_filter_idc above + RK_U16 idr_pic_id; //COMB + RK_S32 pps_id; //COMB TODO: merge with swreg60.pps_id //TODO: may be removed later, get from sps/pps instead + RK_S32 frame_num; //COMB TODO: swreg60.frm_num + RK_S32 slice_size_mb_rows; + RK_S32 h264_inter4x4_disabled; //COMB + RK_S32 enable_cabac; //COMB + RK_S32 transform8x8_mode; //COMB + RK_S32 cabac_init_idc; //COMB TODO: merge with swreg60.cbc_init_idc + RK_S32 pic_order_cnt_lsb; + + /* rate control relevant */ + RK_S32 qp; + RK_S32 mad_qp_delta; + RK_S32 mad_threshold; + RK_S32 qp_min; //COMB, TODO: merge width swreg54.rc_min_qp + RK_S32 qp_max; //COMB, TODO: merge width swreg54.rc_max_qp + RK_S32 cp_distance_mbs; + RK_S32 cp_target[10]; + RK_S32 target_error[7]; + RK_S32 delta_qp[7]; + + + RK_U32 output_strm_limit_size; // outputStrmSize + RK_U32 output_strm_addr; // outputStrmBase + RK_U32 pic_luma_width; // preProcess->lumWidth + RK_U32 pic_luma_height; // preProcess->lumHeight + RK_U32 input_luma_addr; // inputLumBase + RK_U32 input_cb_addr; // inputCbBase + RK_U32 input_cr_addr; // inputCrBase + RK_U32 input_image_format; // inputImageFormat + RK_U32 color_conversion_coeff_a; //colorConversionCoeffA + RK_U32 color_conversion_coeff_b; //colorConversionCoeffB + RK_U32 color_conversion_coeff_c; //colorConversionCoeffC + RK_U32 color_conversion_coeff_e; //colorConversionCoeffE + RK_U32 color_conversion_coeff_f; //colorConversionCoeffF + RK_U32 color_conversion_r_mask_msb; //rMaskMsb + RK_U32 color_conversion_g_mask_msb; //gMaskMsb + RK_U32 color_conversion_b_mask_msb; //bMaskMsb + + /* RKVENC extra syntax below */ + RK_S32 profile_idc; //TODO: may be removed later, get from sps/pps instead + RK_S32 level_idc; //TODO: may be removed later, get from sps/pps instead + RK_S32 link_table_en; + RK_S32 keyframe_max_interval; + + /* remove later */ + RK_U32 ref_luma_addr; // internalImageLumBaseR + RK_U32 ref_chroma_addr; // internalImageChrBaseR + RK_U32 recon_luma_addr; // internalImageLumBaseW + RK_U32 recon_chroma_addr; // internalImageChrBaseW + RK_U32 nal_size_table_addr; // +} h264e_syntax; + +typedef struct h264e_feedback_t { + /* rc */ + RK_U32 hw_status; + RK_S32 qp_sum; + RK_S32 cp[10]; + RK_S32 mad_count; + RK_S32 rlc_count; + RK_U32 out_strm_size; +} h264e_feedback; + + +typedef struct h264e_control_extra_info_cfg_t { + /* common cfg */ + RK_U32 pic_luma_width; + RK_U32 pic_luma_height; + RK_S32 enable_cabac; + RK_S32 transform8x8_mode; + RK_S32 chroma_qp_index_offset; + RK_S32 pic_init_qp; + //RK_S32 rotation_enable; //0: 0/180 degrees, 1: 90/270 degrees //TODO: add rotation + + /* additional cfg only for rkv */ + RK_U32 input_image_format; + RK_S32 profile_idc; + RK_S32 level_idc; //TODO: may be removed later, get from sps/pps instead + RK_S32 keyframe_max_interval; + RK_S32 second_chroma_qp_index_offset; + RK_S32 pps_id; //TODO: may be removed later, get from sps/pps instead +} h264e_control_extra_info_cfg; + + +typedef struct h264e_control_extra_info_t { + RK_U32 size; // preProcess->lumWidth + RK_U8 buf[256]; // preProcess-> +} h264e_control_extra_info; + +#endif diff --git a/mpp/hal/CMakeLists.txt b/mpp/hal/CMakeLists.txt index 209c3c81..b08ae48c 100644 --- a/mpp/hal/CMakeLists.txt +++ b/mpp/hal/CMakeLists.txt @@ -30,6 +30,8 @@ add_subdirectory(vpu/mpg4d) add_subdirectory(vpu/vp8d) +add_subdirectory(rkenc/h264e) + # ---------------------------------------------------------------------------- # add hardware worker implement # ---------------------------------------------------------------------------- @@ -50,6 +52,7 @@ target_link_libraries(mpp_hal hal_mpg4d hal_vp8d hal_vp9d + hal_h264e hal_dummy ${RKPLAT_VPU} ) diff --git a/mpp/hal/inc/hal_h264e_api.h b/mpp/hal/inc/hal_h264e_api.h new file mode 100644 index 00000000..c6015bbd --- /dev/null +++ b/mpp/hal/inc/hal_h264e_api.h @@ -0,0 +1,25 @@ +#ifndef __HAL_H264E_API_H__ +#define __HAL_H264E_API_H__ + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_api_h264e; + +MPP_RET hal_h264e_init (void *hal, MppHalCfg *cfg); +MPP_RET hal_h264e_deinit (void *hal); +MPP_RET hal_h264e_gen_regs(void *hal, HalTaskInfo *task); +MPP_RET hal_h264e_start (void *hal, HalTaskInfo *task); +MPP_RET hal_h264e_wait (void *hal, HalTaskInfo *task); +MPP_RET hal_h264e_reset (void *hal); +MPP_RET hal_h264e_flush (void *hal); +MPP_RET hal_h264e_control (void *hal, RK_S32 cmd_type, void *param); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/mpp/hal/inc/mpp_hal.h b/mpp/hal/inc/mpp_hal.h index 54f1adf4..ac9dd610 100644 --- a/mpp/hal/inc/mpp_hal.h +++ b/mpp/hal/inc/mpp_hal.h @@ -31,6 +31,7 @@ typedef enum MppHalHardType_e { HAL_VDPU, //!< vpu combined decoder HAL_VEPU, //!< vpu combined encoder HAL_RKVDEC, //!< rock-chip h264 h265 vp9 combined decoder + HAL_RKVENC, //!< rock-chip h264 h265 combined encoder HAL_DEVICE_BUTT, } HalDeviceId; diff --git a/mpp/hal/mpp_hal.cpp b/mpp/hal/mpp_hal.cpp index 38fe7a38..b0a546e0 100644 --- a/mpp/hal/mpp_hal.cpp +++ b/mpp/hal/mpp_hal.cpp @@ -33,6 +33,7 @@ #include "hal_m2vd_api.h" #include "hal_mpg4d_api.h" #include "hal_vp8d_api.h" +#include "hal_h264e_api.h" // for test and demo #include "hal_dummy_dec_api.h" @@ -50,6 +51,7 @@ static const MppHalApi *hw_apis[] = { &hal_api_mpg4d, &hal_api_vp8d, &hal_api_vp9d, + &hal_api_h264e, &hal_api_dummy_dec, &hal_api_dummy_enc, }; diff --git a/mpp/hal/rkenc/h264e/CMakeLists.txt b/mpp/hal/rkenc/h264e/CMakeLists.txt index 86c546d2..bbd89d02 100644 --- a/mpp/hal/rkenc/h264e/CMakeLists.txt +++ b/mpp/hal/rkenc/h264e/CMakeLists.txt @@ -28,13 +28,11 @@ add_library(hal_h264e STATIC ${HAL_H264E_SRC} ) if(ANDROID) - target_link_libraries(hal_h264e vpu mpp_base) + target_link_libraries(hal_h264e worker_vpu mpp_base) else() target_link_libraries(hal_h264e mpp_base) endif() -target_link_libraries(hal_h264e - mpp - ) + set_target_properties(hal_h264e PROPERTIES FOLDER "mpp/hal") add_subdirectory(test) diff --git a/mpp/legacy/vpu_api.cpp b/mpp/legacy/vpu_api.cpp index d87e33a0..652ec025 100644 --- a/mpp/legacy/vpu_api.cpp +++ b/mpp/legacy/vpu_api.cpp @@ -348,7 +348,11 @@ RK_S32 vpu_close_context(VpuCodecContext **ctx) delete api; s->vpuApiObj = NULL; } - mpp_free(s->extradata); + //mpp_free(s->extradata); // TODO + if (s->extradata_size > 0) { // TODO + s->extradata_size = 0; + s->extradata = NULL; + } mpp_free(s->private_data); mpp_free(s); *ctx = s = NULL; diff --git a/mpp/legacy/vpu_api_legacy.cpp b/mpp/legacy/vpu_api_legacy.cpp index a091d4c7..57f7565e 100644 --- a/mpp/legacy/vpu_api_legacy.cpp +++ b/mpp/legacy/vpu_api_legacy.cpp @@ -30,7 +30,9 @@ #define MAX_WRITE_HEIGHT (480) #define MAX_WRITE_WIDTH (960) -VpuApiLegacy::VpuApiLegacy() +VpuApiLegacy::VpuApiLegacy() : + use_fd_flag(0), + task(NULL) { mpp_log_f("in\n"); mpp_ctx = NULL; @@ -42,6 +44,7 @@ VpuApiLegacy::VpuApiLegacy() vpu_api_debug = 0; fp = NULL; fp_buf = NULL; + outData = NULL; mpp_env_get_u32("vpu_api_debug", &vpu_api_debug, 0); if (vpu_api_debug & VPU_API_DBG_DUMP_YUV) { fp = fopen("/sdcard/rk_mpp_dump.yuv", "wb"); @@ -62,6 +65,14 @@ VpuApiLegacy::~VpuApiLegacy() mpp_free(fp_buf); fp_buf = NULL; } + if (memGroup != NULL) { + mpp_err("memGroup deInit"); + mpp_buffer_group_put(memGroup); + } + if (outData != NULL) { + free(outData); + outData = NULL; + } mpp_destroy(mpp_ctx); mpp_log_f("ok\n"); } @@ -76,6 +87,27 @@ RK_S32 VpuApiLegacy::init(VpuCodecContext *ctx, RK_U8 *extraData, RK_U32 extra_s if (CODEC_DECODER == ctx->codecType) { type = MPP_CTX_DEC; } else if (CODEC_ENCODER == ctx->codecType) { + memGroup = NULL; + pictureMem = NULL; + outbufMem = NULL; + inputFrame = NULL; + outputPakcet = NULL; + if (memGroup == NULL) { + ret = mpp_buffer_group_get_internal(&memGroup, MPP_BUFFER_TYPE_ION); + if (MPP_OK != ret) { + mpp_err("memGroup mpp_buffer_group_get failed\n"); + return ret; + } + } + // TODO set control cmd + MppParam param = NULL; + RK_U32 output_block = 1; + param = &output_block; + ret = mpi->control(mpp_ctx, MPP_SET_OUTPUT_BLOCK, param); + if (MPP_OK != ret) { + mpp_err("mpi->control MPP_SET_OUTPUT_BLOCK failed\n"); + } + type = MPP_CTX_ENC; } else { return MPP_ERR_VPU_CODEC_INIT; @@ -85,17 +117,48 @@ RK_S32 VpuApiLegacy::init(VpuCodecContext *ctx, RK_U8 *extraData, RK_U32 extra_s mpp_err("found invalid context input"); return MPP_ERR_NULL_PTR; } - + if (MPP_CTX_ENC == type) { + EncParameter_t *encParam = (EncParameter_t*)ctx->private_data; + MppEncConfig encCfg; + memset(&encCfg, 0, sizeof(MppEncConfig)); + // TODO + if (0 != encParam->width && 0 != encParam->height) { + encCfg.width = encParam->width; + encCfg.height = encParam->height; + } else + mpp_err("Width and height is not set."); + outData = (RK_U8*)malloc(encParam->width * encParam->height); + if (0 != encParam->levelIdc) + encCfg.level = encParam->levelIdc; + if (0 != encParam->framerate) + encCfg.fps_in = encParam->framerate; + if (0 != encParam->framerateout) + encCfg.fps_out = encParam->framerateout; + else + encCfg.fps_out = encParam->framerate; + if (0 != encParam->intraPicRate) + encCfg.gop = encParam->intraPicRate; + mpi->config(mpp_ctx, MPP_ENC_SETCFG, encCfg); // input parameter config + } ret = mpp_init(mpp_ctx, type, (MppCodingType)ctx->videoCoding); if (ret) { mpp_err_f(" init error. \n"); return ret; } + // TODO + if (mpp_enc_get_extra_data_size(mpp_ctx) > 0) { + ctx->extradata_size = mpp_enc_get_extra_data_size(mpp_ctx); + ctx->extradata = mpp_enc_get_extra_data(mpp_ctx); + mpp_log("Mpp generate extra data!"); + } else + mpp_err("No extra data generate!"); + VPU_GENERIC vpug; vpug.CodecType = ctx->codecType; vpug.ImgWidth = ctx->width; vpug.ImgHeight = ctx->height; - control(ctx, VPU_API_SET_DEFAULT_WIDTH_HEIGH, &vpug); + if (MPP_CTX_ENC != type) + control(ctx, VPU_API_SET_DEFAULT_WIDTH_HEIGH, &vpug); if (extraData != NULL) { mpp_packet_init(&pkt, extraData, extra_size); mpp_packet_set_extra_data(pkt); @@ -309,8 +372,8 @@ RK_S32 VpuApiLegacy:: decode_getoutframe(DecoderOut_t *aDecOut) RK_S32 VpuApiLegacy::encode(VpuCodecContext *ctx, EncInputStream_t *aEncInStrm, EncoderOut_t *aEncOut) { + MPP_RET ret = MPP_OK; mpp_log_f("in\n"); - RK_S32 ret = MPP_OK; if (!init_ok) { return VPU_API_ERR_VPU_CODEC_INIT; @@ -319,8 +382,160 @@ RK_S32 VpuApiLegacy::encode(VpuCodecContext *ctx, EncInputStream_t *aEncInStrm, (void)ctx; (void)aEncInStrm; (void)aEncOut; + // TODO + if (1) { + ret = mpp_frame_init(&inputFrame); + if (MPP_OK != ret) { + mpp_err("mpp_frame_init failed\n"); + goto ENCODE_FAIL; + } + RK_U32 width = ctx->width; + RK_U32 height = ctx->height; + RK_U32 horStride = MPP_ALIGN(width, 16); + RK_U32 verStride = MPP_ALIGN(height, 16); + mpp_frame_set_width(inputFrame, width); + mpp_frame_set_height(inputFrame, height); + mpp_frame_set_hor_stride(inputFrame, horStride); + mpp_frame_set_ver_stride(inputFrame, verStride); + + if (!use_fd_flag) { + RK_U32 outputBufferSize = horStride * verStride; + ret = mpp_buffer_get(memGroup, &pictureMem, aEncInStrm->size); + if (ret != MPP_OK) { + mpp_err( "Failed to allocate pictureMem buffer!\n"); + pictureMem = NULL; + return ret; + } + memcpy((RK_U8*) mpp_buffer_get_ptr(pictureMem), aEncInStrm->buf, aEncInStrm->size); + ret = mpp_buffer_get(memGroup, &outbufMem, outputBufferSize); + if (ret != MPP_OK) { + mpp_err( "Failed to allocate output buffer!\n"); + outbufMem = NULL; + return 1; + } + } else { + MppBufferInfo inputCommit; + MppBufferInfo outputCommit; + memset(&inputCommit, 0, sizeof(inputCommit)); + memset(&outputCommit, 0, sizeof(outputCommit)); + inputCommit.type = MPP_BUFFER_TYPE_ION; + inputCommit.size = aEncInStrm->size; + inputCommit.fd = aEncInStrm->bufPhyAddr; + outputCommit.type = MPP_BUFFER_TYPE_ION; + outputCommit.size = horStride * verStride; // TODO + outputCommit.fd = aEncOut->keyFrame/*bufferFd*/; + outputCommit.ptr = (void*)aEncOut->data; + mpp_log_f(" new ffmpeg provide fd input fd %d output fd %d", aEncInStrm->bufPhyAddr, aEncOut->keyFrame/*bufferFd*/); + ret = mpp_buffer_import(&pictureMem, &inputCommit); + if (MPP_OK != ret) { + mpp_err("mpp_buffer_test mpp_buffer_commit failed\n"); + //goto ??; // TODO + } + + ret = mpp_buffer_import(&outbufMem, &outputCommit); + if (MPP_OK != ret) { + mpp_err("mpp_buffer_test mpp_buffer_commit failed\n"); + } + mpp_log_f("mpp import input fd %d output fd %d", + mpp_buffer_get_fd(pictureMem), mpp_buffer_get_fd(outbufMem)/*(((MppBufferImpl*)pictureMem)->info.fd), (((MppBufferImpl*)outbufMem)->info.fd)*/); + } + + //mpp_packet_init(&outputPakcet, outbufMem, aEncOut->size); + mpp_frame_set_buffer(inputFrame, pictureMem); + mpp_packet_init_with_buffer(&outputPakcet, outbufMem); + + do { + ret = mpi->dequeue(mpp_ctx, MPP_PORT_INPUT, &task); + if (ret) { + mpp_err("mpp task input dequeue failed\n"); + goto ENCODE_FAIL; + } + if (task == NULL) { + mpp_log("mpi dequeue from MPP_PORT_INPUT fail, task equal with NULL!"); + usleep(3000); + } else + break; + } while (1); + + mpp_task_meta_set_frame (task, MPP_META_KEY_INPUT_FRM, inputFrame); + mpp_task_meta_set_packet(task, MPP_META_KEY_OUTPUT_PKT, outputPakcet); + + if (mpi != NULL) { + ret = mpi->enqueue(mpp_ctx, MPP_PORT_INPUT, task); + if (ret) { + mpp_err("mpp task input enqueue failed\n"); + goto ENCODE_FAIL; + } + task = NULL; + + do { + ret = mpi->dequeue(mpp_ctx, MPP_PORT_OUTPUT, &task); + if (ret) { + mpp_err("ret %d mpp task output dequeue failed\n", ret); + goto ENCODE_FAIL; + } + + if (task) { + MppFrame frame_out = NULL; + MppFrame packet_out = NULL; + + mpp_task_meta_get_frame (task, MPP_META_KEY_INPUT_FRM, &frame_out); + mpp_task_meta_get_packet(task, MPP_META_KEY_OUTPUT_PKT, &packet_out); + + mpp_assert(packet_out == outputPakcet); + mpp_assert(frame_out == inputFrame); + mpp_log_f("encoded frame %d\n", frame_count); + frame_count++; + + ret = mpi->enqueue(mpp_ctx, MPP_PORT_OUTPUT, task); + if (ret) { + mpp_err("mpp task output enqueue failed\n"); + goto ENCODE_FAIL; + } + task = NULL; + break; + } + usleep(3000); + } while (1); + } else { + mpp_err("mpi pointer is NULL, failed!"); + } + + // copy encoded stream into output buffer, and set outpub stream size + if (outputPakcet != NULL) { + aEncOut->size = mpp_packet_get_length(outputPakcet); + if (!use_fd_flag) + memcpy(aEncOut->data, (RK_U8*) mpp_buffer_get_ptr(outbufMem), aEncOut->size); + mpp_buffer_put(outbufMem); + mpp_packet_deinit(&outputPakcet); + } else { + mpp_log("outputPacket is NULL!"); + } + + if (inputFrame) { + mpp_frame_deinit(&inputFrame); + inputFrame = NULL; + } + } else { + aEncOut->data[0] = 0x00; + aEncOut->data[1] = 0x00; + aEncOut->data[2] = 0x00; + aEncOut->data[3] = 0x01; + memset(aEncOut->data + 4, 0xFF, 500 - 4); + aEncOut->size = 500; + } mpp_log_f("ok\n"); return ret; + +ENCODE_FAIL: + + if (inputFrame != NULL) + mpp_frame_deinit(&inputFrame); + + if (outputPakcet != NULL) + mpp_packet_deinit(&outputPakcet); + + return ret; } RK_S32 VpuApiLegacy::encoder_sendframe(VpuCodecContext *ctx, EncInputStream_t *aEncInStrm) diff --git a/mpp/legacy/vpu_api_legacy.h b/mpp/legacy/vpu_api_legacy.h index 35f0b355..3cd6a764 100644 --- a/mpp/legacy/vpu_api_legacy.h +++ b/mpp/legacy/vpu_api_legacy.h @@ -52,6 +52,14 @@ private: RK_U32 vpu_api_debug; FILE *fp; RK_U8 *fp_buf; + MppBufferGroup memGroup; + MppBuffer pictureMem; + MppBuffer outbufMem; + MppFrame inputFrame; + MppPacket outputPakcet; + RK_U8* outData; + RK_U32 use_fd_flag; + MppTask task; }; #endif /*_VPU_API_H_*/ diff --git a/mpp/mpi.cpp b/mpp/mpi.cpp index 4d9f7758..acdeb075 100644 --- a/mpp/mpi.cpp +++ b/mpp/mpi.cpp @@ -43,7 +43,7 @@ static MppCodingTypeInfo support_list[] = { { MPP_CTX_DEC, MPP_VIDEO_CodingVP8, "dec", "vp8", }, { MPP_CTX_DEC, MPP_VIDEO_CodingVP9, "dec", "VP9", }, { MPP_CTX_DEC, MPP_VIDEO_CodingAVS, "dec", "avs+", }, -// { MPP_CTX_ENC, MPP_VIDEO_CodingAVC, "enc", "h.264/AVC", }, + { MPP_CTX_ENC, MPP_VIDEO_CodingAVC, "enc", "h.264/AVC", }, }; #define check_mpp_ctx(ctx) _check_mpp_ctx(ctx, __FUNCTION__) @@ -57,7 +57,7 @@ static MPP_RET _check_mpp_ctx(MpiImpl *p, const char *caller) return MPP_OK; } -static MPP_RET mpi_config(MppCtx ctx, MppEncConfig cfg) +static MPP_RET mpi_config(MppCtx ctx, MpiCmd cmd, MppEncConfig cfg) { MPP_RET ret = MPP_NOK; MpiImpl *p = (MpiImpl *)ctx; @@ -68,7 +68,7 @@ static MPP_RET mpi_config(MppCtx ctx, MppEncConfig cfg) if (ret) break; - // TODO: do config here + ret = p->ctx->config(cmd, cfg); // configure parameter set } while (0); mpi_dbg_func("leave ret %d\n", ret); @@ -478,3 +478,21 @@ void mpp_show_support_format() } } +RK_U32 mpp_enc_get_extra_data_size(MppCtx ctx) +{ + mpi_dbg_func("enter ctx %p\n", ctx); + MpiImpl *p = (MpiImpl*)ctx; + RK_U32 ret = p->ctx->mEnc->extra_info.size; + mpi_dbg_func("leave\n"); + return ret; +} + +RK_U8 *mpp_enc_get_extra_data(MppCtx ctx) +{ + mpi_dbg_func("enter ctx %p\n", ctx); + MpiImpl *p = (MpiImpl*)ctx; + RK_U8 *extra_data = p->ctx->mEnc->extra_info.buf; + mpp_log("Mpp get extra data now!"); + mpi_dbg_func("leave\n"); + return extra_data; +} diff --git a/mpp/mpp.cpp b/mpp/mpp.cpp index 7830cd31..f2832b96 100644 --- a/mpp/mpp.cpp +++ b/mpp/mpp.cpp @@ -101,9 +101,9 @@ MPP_RET Mpp::init(MppCtxType type, MppCodingType coding) mPackets = new mpp_list((node_destructor)mpp_packet_deinit); mTasks = new mpp_list((node_destructor)NULL); - mpp_enc_init(&mEnc, coding); + mpp_enc_init(mEnc, coding); mThreadCodec = new MppThread(mpp_enc_control_thread, this, "mpp_enc_ctrl"); - mThreadHal = new MppThread(mpp_enc_hal_thread, this, "mpp_enc_hal"); + //mThreadHal = new MppThread(mpp_enc_hal_thread, this, "mpp_enc_hal"); mpp_buffer_group_get_internal(&mPacketGroup, MPP_BUFFER_TYPE_NORMAL); mpp_buffer_group_get_external(&mFrameGroup, MPP_BUFFER_TYPE_ION); @@ -122,12 +122,19 @@ MPP_RET Mpp::init(MppCtxType type, MppCodingType coding) mOutputPort = mpp_task_queue_get_port(mOutputTaskQueue, MPP_PORT_OUTPUT); if (mFrames && mPackets && - (mDec || mEnc) && + (mDec) && mThreadCodec && mThreadHal && mPacketGroup) { mThreadCodec->start(); mThreadHal->start(); mInitDone = 1; + } else if (mFrames && mPackets && + (mEnc) && + mThreadCodec/* && mThreadHal */ && + mPacketGroup) { + mThreadCodec->start(); + //mThreadHal->start(); // TODO + mInitDone = 1; } else { mpp_err("error found on mpp initialization\n"); clear(); @@ -420,6 +427,27 @@ MPP_RET Mpp::control(MpiCmd cmd, MppParam param) return MPP_OK; } +MPP_RET Mpp::config(MpiCmd cmd, MppEncConfig cfg) +{ + switch (cmd) { + case MPP_ENC_SETCFG: + mEnc = mpp_calloc(MppEnc, 1); + if (NULL == mEnc) { + mpp_err_f("failed to malloc context\n"); + return MPP_ERR_NULL_PTR; + } + mEnc->mpp = this; // TODO put these code into config function + + mpp_enc_config(mEnc, cmd, &cfg); + break; + default: + mpp_log("MpiCmd is not found in mpi_config."); + break; + } + + return MPP_OK; +} + MPP_RET Mpp::reset() { if (!mInitDone) diff --git a/mpp/mpp.h b/mpp/mpp.h index 069929e2..6c6dbea9 100644 --- a/mpp/mpp.h +++ b/mpp/mpp.h @@ -76,6 +76,7 @@ public: MPP_RET reset(); MPP_RET control(MpiCmd cmd, MppParam param); + MPP_RET config(MpiCmd cmd, MppEncConfig cfg); mpp_list *mPackets; mpp_list *mFrames; diff --git a/osal/inc/mpp_thread.h b/osal/inc/mpp_thread.h index d2be98c0..03c67ccf 100644 --- a/osal/inc/mpp_thread.h +++ b/osal/inc/mpp_thread.h @@ -45,7 +45,8 @@ int pthread_setname_np(pthread_t thread, const char *name); #include #include -#if defined(ANDROID) +#ifdef ARMLINUX +#elif defined(ANDROID) #define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER #endif diff --git a/osal/mpp_thread.cpp b/osal/mpp_thread.cpp index ff93334a..49322872 100644 --- a/osal/mpp_thread.cpp +++ b/osal/mpp_thread.cpp @@ -58,9 +58,11 @@ void MppThread::start() // NOTE: set status here first to avoid unexpected loop quit racing condition mStatus = MPP_THREAD_RUNNING; if (0 == pthread_create(&mThread, &attr, mFunction, mContext)) { +#ifndef ARMLINUX RK_S32 ret = pthread_setname_np(mThread, mName); if (ret) mpp_err("thread %p setname %s failed\n", mFunction, mName); +#endif thread_dbg(MPP_THREAD_DBG_FUNCTION, "thread %s %p context %p create success\n", mName, mFunction, mContext); @@ -120,6 +122,7 @@ void SetThreadName(DWORD dwThreadID, const char* threadName) } +#ifndef ARMLINUX /* * add pthread_setname_np for windows */ @@ -129,6 +132,7 @@ int pthread_setname_np(pthread_t thread, const char *name) SetThreadName(dwThreadID, name); return 0; } +#endif #endif diff --git a/test/mpi_test.c b/test/mpi_test.c index 19de8d38..b111ae69 100644 --- a/test/mpi_test.c +++ b/test/mpi_test.c @@ -192,7 +192,7 @@ int mpi_test() memset(&cfg, 0, sizeof(cfg)); - ret = mpi->config(ctx, cfg); + ret = mpi->config(ctx, MPP_ENC_SETCFG, cfg); if (MPP_OK != ret) { mpp_err("mpi->config failed\n"); goto MPP_TEST_FAILED; diff --git a/test/vpu_api_test.c b/test/vpu_api_test.c index 1cd6b504..9d3ecae9 100644 --- a/test/vpu_api_test.c +++ b/test/vpu_api_test.c @@ -26,6 +26,8 @@ #include "vpu_api.h" #include "utils.h" +#define FOR_TEST_ENCODE 1 + static RK_U32 VPU_API_DEMO_DEBUG_DISABLE = 0; #define BSWAP32(x) \ @@ -241,6 +243,7 @@ static RK_S32 vpu_encode_demo(VpuApiDemoCmdContext_t *cmd) struct VpuCodecContext *ctx = NULL; RK_S32 nal = 0x00000001; RK_S32 fileSize, ret, size; + RK_U32 readOneFrameSize = 0; EncoderOut_t enc_out_yuv; EncoderOut_t *enc_out = NULL; VpuApiEncInput enc_in_strm; @@ -251,7 +254,16 @@ static RK_S32 vpu_encode_demo(VpuApiDemoCmdContext_t *cmd) RK_U32 w_align = 0; RK_U32 h_align = 0; - int Format = VPU_H264ENC_YUV420_SEMIPLANAR; +#ifdef FOR_TEST_ENCODE + ctx = (struct VpuCodecContext*)malloc(sizeof(struct VpuCodecContext)); + if (!ctx) { + mpp_err("Input context has not been properly allocated"); + return -1; + } + memset(ctx, 0, sizeof(struct VpuCodecContext)); +#endif + + int Format = VPU_H264ENC_YUV420_PLANAR;//VPU_H264ENC_YUV420_SEMIPLANAR; if (cmd == NULL) { return -1; @@ -288,6 +300,12 @@ static RK_S32 vpu_encode_demo(VpuApiDemoCmdContext_t *cmd) } } +#ifdef FOR_TEST_ENCODE + ctx->videoCoding = OMX_RK_VIDEO_CodingAVC; + ctx->codecType = CODEC_ENCODER; + ctx->width = cmd->width; + ctx->height = cmd->height; +#endif fseek(pInFile, 0L, SEEK_END); fileSize = ftell(pInFile); fseek(pInFile, 0L, SEEK_SET); @@ -362,6 +380,8 @@ static RK_S32 vpu_encode_demo(VpuApiDemoCmdContext_t *cmd) w_align = ((ctx->width + 15) & (~15)); h_align = ((ctx->height + 15) & (~15)); size = w_align * h_align * 3 / 2; + readOneFrameSize = ctx->width * ctx->height * 3 / 2; + mpp_log("%d %d %d %d %d", ctx->width, ctx->height, w_align, h_align, size); nal = BSWAP32(nal); do { @@ -387,7 +407,7 @@ static RK_S32 vpu_encode_demo(VpuApiDemoCmdContext_t *cmd) api_enc_in->capability = size; } - if (readBytesFromFile(enc_in->buf, size, pInFile)) { + if (readBytesFromFile(enc_in->buf, readOneFrameSize, pInFile)) { break; } else { enc_in->size = size; @@ -402,6 +422,7 @@ static RK_S32 vpu_encode_demo(VpuApiDemoCmdContext_t *cmd) if ((ret = ctx->encode(ctx, enc_in, enc_out)) < 0) { ENCODE_ERR_RET(ERROR_VPU_DECODE); } else { + enc_in->size = 0; // TODO encode completely, and set enc_in->size to 0 mpp_log("vpu encode one frame, out len: %d, left size: %d\n", enc_out->size, enc_in->size); @@ -413,7 +434,7 @@ static RK_S32 vpu_encode_demo(VpuApiDemoCmdContext_t *cmd) if (pOutFile) { mpp_log("dump %d bytes enc output stream to file\n", enc_out->size); - fwrite((RK_U8*)&nal, 1, 4, pOutFile); + //fwrite((RK_U8*)&nal, 1, 4, pOutFile); // because output stream have start code, so here mask this code fwrite(enc_out->data, 1, enc_out->size, pOutFile); fflush(pOutFile); }