diff --git a/mpp/codec/dec/avs/avsd_api.c b/mpp/codec/dec/avs/avsd_api.c index fe214a82..cc08e465 100644 --- a/mpp/codec/dec/avs/avsd_api.c +++ b/mpp/codec/dec/avs/avsd_api.c @@ -296,15 +296,14 @@ MPP_RET avsd_callback(void *decoder, void *info) MppFrame mframe = NULL; HalDecTask *task_dec = (HalDecTask *)ctx->task; AVSD_DBG(AVSD_DBG_CALLBACK, "reg[1]=%08x, ref=%d, dpberr=%d, harderr-%d\n", - ctx->regs[1], task_dec->flags.used_for_ref, task_dec->flags.had_error, ctx->hard_err); + ctx->regs[1], task_dec->flags.used_for_ref, task_dec->flags.had_error, ctx->hard_err); mpp_buf_slot_get_prop(p_dec->frame_slots, task_dec->output, SLOT_FRAME_PTR, &mframe); if (mframe) { if (ctx->hard_err || task_dec->flags.had_error) { if (task_dec->flags.used_for_ref) { mpp_frame_set_errinfo(mframe, MPP_FRAME_FLAG_PAIRED_FIELD); - } - else { + } else { mpp_frame_set_discard(mframe, MPP_FRAME_FLAG_PAIRED_FIELD); } } diff --git a/mpp/codec/enc/h264/include/encpreprocess.h b/mpp/codec/enc/h264/include/encpreprocess.h index 12b49c30..f80a5fa2 100644 --- a/mpp/codec/enc/h264/include/encpreprocess.h +++ b/mpp/codec/enc/h264/include/encpreprocess.h @@ -40,8 +40,10 @@ typedef struct { RK_U32 lumWidthSrc; /* Source input image width */ RK_U32 lumHeightSrc; /* Source input image height */ - RK_U32 lumWidth; /* Encoded image width */ - RK_U32 lumHeight; /* Encoded image height */ + RK_U32 lumWidth; /* Encoded image width */ + RK_U32 lumHeight; /* Encoded image height */ + RK_U32 hor_stride; /* Encoded image horizontal stride */ + RK_U32 ver_stride; /* Encoded image vertical stride */ RK_U32 horOffsetSrc; /* Encoded frame offset, reference is ... */ RK_U32 verOffsetSrc; /* ...top left corner of source image */ RK_U32 inputFormat; diff --git a/mpp/codec/enc/h264/include/h264encapi.h b/mpp/codec/enc/h264/include/h264encapi.h index a04e256e..6697c26a 100644 --- a/mpp/codec/enc/h264/include/h264encapi.h +++ b/mpp/codec/enc/h264/include/h264encapi.h @@ -210,6 +210,8 @@ typedef struct { H264Level level; RK_U32 width; /* Encoded picture width in pixels, multiple of 4 */ RK_U32 height; /* Encoded picture height in pixels, multiple of 2 */ + RK_U32 hor_stride; /* Encoded picture horizontal stride in pixels */ + RK_U32 ver_stride; /* Encoded picture vertical stride in pixels */ RK_U32 frameRateNum; /* The stream time scale, [1..65535] */ RK_U32 frameRateDenom; /* Maximum frame rate is frameRateNum/frameRateDenom * in frames/second. The actual frame rate will be diff --git a/mpp/codec/enc/h264/src/H264Init.c b/mpp/codec/enc/h264/src/H264Init.c index 3cbb665c..3e08481d 100644 --- a/mpp/codec/enc/h264/src/H264Init.c +++ b/mpp/codec/enc/h264/src/H264Init.c @@ -221,6 +221,9 @@ bool_e SetParameter(H264ECtx * inst, const H264EncConfig * pEncCfg) inst->preProcess.lumHeight = pEncCfg->height; inst->preProcess.lumHeightSrc = pEncCfg->height; + inst->preProcess.hor_stride = pEncCfg->hor_stride; + inst->preProcess.ver_stride = pEncCfg->ver_stride; + inst->preProcess.horOffsetSrc = 0; inst->preProcess.verOffsetSrc = 0; diff --git a/mpp/codec/enc/h264/src/encasiccontroller.c b/mpp/codec/enc/h264/src/encasiccontroller.c index cedaf70f..8edb9c43 100644 --- a/mpp/codec/enc/h264/src/encasiccontroller.c +++ b/mpp/codec/enc/h264/src/encasiccontroller.c @@ -109,6 +109,8 @@ void EncAsicFrameStart(void * inst, regValues_s * val, h264e_syntax *syntax_data syntax_data->output_strm_addr = val->outputStrmBase; syntax_data->pic_luma_width = ctx->preProcess.lumWidth; syntax_data->pic_luma_height = ctx->preProcess.lumHeight; + syntax_data->pic_hor_stride = ctx->preProcess.hor_stride; + syntax_data->pic_ver_stride = ctx->preProcess.ver_stride; syntax_data->input_luma_addr = val->inputLumBase; syntax_data->input_cb_addr = val->inputCbBase; syntax_data->input_cr_addr = val->inputCrBase; diff --git a/mpp/codec/enc/h264/src/h264e_api.c b/mpp/codec/enc/h264/src/h264e_api.c index 45154f12..42c9d5af 100644 --- a/mpp/codec/enc/h264/src/h264e_api.c +++ b/mpp/codec/enc/h264/src/h264e_api.c @@ -82,8 +82,8 @@ MPP_RET h264e_encode(void *ctx, HalEncTask *task) H264ECtx *p = (H264ECtx *)ctx; H264EncIn *encIn = &(p->encIn); H264EncOut *encOut = &(p->encOut); - RK_U32 srcLumaWidth = p->lumWidthSrc; - RK_U32 srcLumaHeight = p->lumHeightSrc; + RK_U32 srcHorStride = p->preProcess.hor_stride; + RK_U32 srcVerStride = p->preProcess.ver_stride; encIn->pOutBuf = (RK_U32*)mpp_buffer_get_ptr(task->output); encIn->busOutBuf = mpp_buffer_get_fd(task->output); @@ -104,14 +104,10 @@ MPP_RET h264e_encode(void *ctx, HalEncTask *task) } /* Setup encoder input */ - { - RK_U32 w = srcLumaWidth; - encIn->busLuma = mpp_buffer_get_fd(task->input); - - encIn->busChromaU = encIn->busLuma | ((w * srcLumaHeight) << 10); - encIn->busChromaV = encIn->busChromaU + - ((((w + 1) >> 1) * ((srcLumaHeight + 1) >> 1)) << 10); - } + // TODO: support more format in the future + encIn->busLuma = mpp_buffer_get_fd(task->input); + encIn->busChromaU = encIn->busLuma | ((srcHorStride * srcVerStride) << 10); + encIn->busChromaV = encIn->busLuma | ((srcHorStride * srcVerStride * 5 / 4) << 10); /* Select frame type */ if (p->intraPicRate != 0 && (p->intraPeriodCnt >= p->intraPicRate)) { @@ -287,6 +283,16 @@ MPP_RET h264e_config(void *ctx, RK_S32 cmd, void *param) } else mpp_err("width %d height %d is not available\n", mpp_cfg->width, mpp_cfg->height); + if (mpp_cfg->hor_stride && mpp_cfg->ver_stride) { + enc_cfg->hor_stride = mpp_cfg->hor_stride; + enc_cfg->ver_stride = mpp_cfg->ver_stride; + } else { + mpp_err("hor_stride %d ver_stride %d is invalid, use width and height", + mpp_cfg->hor_stride, mpp_cfg->ver_stride); + enc_cfg->hor_stride = enc_cfg->width; + enc_cfg->ver_stride = enc_cfg->height; + } + enc_cfg->input_image_format = mpp_cfg->format; enc_cfg->frameRateNum = mpp_cfg->fps_in; enc_cfg->frameRateDenom = 1; diff --git a/mpp/common/h264e_syntax.h b/mpp/common/h264e_syntax.h index 4a125b2c..b26902b2 100644 --- a/mpp/common/h264e_syntax.h +++ b/mpp/common/h264e_syntax.h @@ -51,6 +51,8 @@ typedef struct h264e_syntax_t { RK_U32 output_strm_addr; // outputStrmBase RK_U32 pic_luma_width; // preProcess->lumWidth RK_U32 pic_luma_height; // preProcess->lumHeight + RK_U32 pic_hor_stride; // preProcess->hor_stride + RK_U32 pic_ver_stride; // preProcess->ver_stride RK_U32 input_luma_addr; // inputLumBase RK_U32 input_cb_addr; // inputCbBase RK_U32 input_cr_addr; // inputCrBase diff --git a/mpp/hal/rkenc/h264e/hal_h264e_rkv.c b/mpp/hal/rkenc/h264e/hal_h264e_rkv.c index 88758b3d..4d85988f 100644 --- a/mpp/hal/rkenc/h264e/hal_h264e_rkv.c +++ b/mpp/hal/rkenc/h264e/hal_h264e_rkv.c @@ -2796,10 +2796,12 @@ MPP_RET hal_h264e_rkv_deinit(void *hal) } -MPP_RET hal_h264e_rkv_set_ioctl_extra_info(h264e_rkv_ioctl_extra_info *extra_info, h264e_syntax *syn) +MPP_RET hal_h264e_rkv_set_ioctl_extra_info(h264e_rkv_ioctl_extra_info *extra_info, h264e_syntax *syn, h264e_rkv_reg_set *regs) { h264e_rkv_ioctl_extra_info_elem *info = NULL; - RK_U32 frame_size = syn->pic_luma_width * syn->pic_luma_height; // TODO: according to yuv format + RK_U32 hor_stride = regs->swreg23.src_ystrid + 1; + RK_U32 ver_stride = syn->pic_ver_stride ? syn->pic_ver_stride : syn->pic_luma_height; + RK_U32 frame_size = hor_stride * ver_stride; // TODO: according to yuv format extra_info->magic = 0; extra_info->cnt = 2; @@ -3131,13 +3133,17 @@ MPP_RET hal_h264e_rkv_set_pp_regs(h264e_rkv_reg_set *regs, h264e_syntax *syn, Mp for (k = 0; k < 40; k++) regs->swreg22_h3d_tbl[k] = h264e_h3d_tbl[k]; - stridey = (regs->swreg19.src_rot == 1 || regs->swreg19.src_rot == 3) ? (syn->pic_luma_height - 1) : (syn->pic_luma_width - 1); - if (regs->swreg14.src_cfmt == 0 ) - stridey = (stridey + 1) * 4 - 1; - else if (regs->swreg14.src_cfmt == 1 ) - stridey = (stridey + 1) * 3 - 1; - else if ( regs->swreg14.src_cfmt == 2 || regs->swreg14.src_cfmt == 8 || regs->swreg14.src_cfmt == 9 ) - stridey = (stridey + 1) * 2 - 1; + if (syn->pic_hor_stride) { + stridey = syn->pic_hor_stride - 1; + } else { + stridey = (regs->swreg19.src_rot == 1 || regs->swreg19.src_rot == 3) ? (syn->pic_luma_height - 1) : (syn->pic_luma_width - 1); + if (regs->swreg14.src_cfmt == 0 ) + stridey = (stridey + 1) * 4 - 1; + else if (regs->swreg14.src_cfmt == 1 ) + stridey = (stridey + 1) * 3 - 1; + else if ( regs->swreg14.src_cfmt == 2 || regs->swreg14.src_cfmt == 8 || regs->swreg14.src_cfmt == 9 ) + stridey = (stridey + 1) * 2 - 1; + } stridec = (regs->swreg14.src_cfmt == 4 || regs->swreg14.src_cfmt == 6) ? stridey : ((stridey + 1) / 2 - 1); regs->swreg23.src_ystrid = stridey; //syn->swreg23.src_ystrid; regs->swreg23.src_cstrid = stridec; //syn->swreg23.src_cstrid; ////YUV420 planar; @@ -3153,6 +3159,7 @@ MPP_RET hal_h264e_rkv_gen_regs(void *hal, HalTaskInfo *task) h264e_hal_context *ctx = (h264e_hal_context *)hal; h264e_hal_param *par = &ctx->param; h264e_rkv_reg_set *regs = NULL; + h264e_rkv_ioctl_reg_info *ioctl_reg_info = NULL; h264e_hal_rkv_csp_info src_fmt; h264e_syntax *syn = (h264e_syntax *)task->enc.syntax.data; h264e_rkv_ioctl_input *ioctl_info = (h264e_rkv_ioctl_input *)ctx->ioctl_input; @@ -3216,14 +3223,14 @@ MPP_RET hal_h264e_rkv_gen_regs(void *hal, HalTaskInfo *task) } regs = ®_list[idx]; ioctl_info->reg_info[idx].reg_num = sizeof(h264e_rkv_reg_set) / 4; - hal_h264e_rkv_set_ioctl_extra_info(&ioctl_info->reg_info[idx].extra_info, syn); + ioctl_reg_info = &ioctl_info->reg_info[idx]; } else { ctx->num_frames_to_send = 1; ioctl_info->frame_num = ctx->num_frames_to_send; ioctl_info->enc_mode = ctx->enc_mode; regs = ®_list[0]; ioctl_info->reg_info[0].reg_num = sizeof(h264e_rkv_reg_set) / 4; - hal_h264e_rkv_set_ioctl_extra_info(&ioctl_info->reg_info[0].extra_info, syn); + ioctl_reg_info = &ioctl_info->reg_info[0]; } if (MPP_OK != hal_h264e_rkv_reference_frame_set(ctx, syn)) { @@ -3287,6 +3294,7 @@ MPP_RET hal_h264e_rkv_gen_regs(void *hal, HalTaskInfo *task) regs->swreg13.cime_dspw_orsd = 0x0; hal_h264e_rkv_set_pp_regs(regs, syn, bufs->hw_pp_buf[buf2_idx], bufs->hw_pp_buf[1 - buf2_idx], ctx->frame_cnt, test_cfg); + hal_h264e_rkv_set_ioctl_extra_info(&ioctl_reg_info->extra_info, syn, regs); regs->swreg24_adr_srcy = syn->input_luma_addr; //syn->addr_cfg.adr_srcy; regs->swreg25_adr_srcu = syn->input_cb_addr; //syn->addr_cfg.adr_srcu; diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vpu.c b/mpp/hal/rkenc/h264e/hal_h264e_vpu.c index 9fb830e9..fe321414 100644 --- a/mpp/hal/rkenc/h264e/hal_h264e_vpu.c +++ b/mpp/hal/rkenc/h264e/hal_h264e_vpu.c @@ -18,6 +18,7 @@ #include #include "vpu.h" #include "rk_mpi.h" +#include "mpp_common.h" #include "mpp_mem.h" #include "mpp_frame.h" #include "hal_h264e.h" @@ -1768,6 +1769,10 @@ MPP_RET hal_h264e_vpu_deinit(void *hal) static MPP_RET hal_h264e_vpu_validate_syntax(h264e_syntax *syn, h264e_hal_vpu_csp_info *src_fmt) { + MPP_RET ret = MPP_OK; + RK_U32 width_align16 = MPP_ALIGN(syn->pic_luma_width, 16); + RK_U32 height_align16 = MPP_ALIGN(syn->pic_luma_height, 16); + h264e_hal_debug_enter(); /* validate */ @@ -1781,8 +1786,24 @@ static MPP_RET hal_h264e_vpu_validate_syntax(h264e_syntax *syn, h264e_hal_vpu_cs H264E_HAL_VALIDATE_NEQ(syn->input_image_format, "input_image_format", H264E_VPU_CSP_NONE); + if (syn->pic_hor_stride != syn->pic_luma_width && + syn->pic_hor_stride != width_align16) { + mpp_err_f("syn->pic_hor_stride %d is not supported for vpu", syn->pic_hor_stride); + ret = MPP_NOK; + goto err; + } + if (syn->pic_ver_stride != syn->pic_luma_height && + syn->pic_ver_stride != height_align16) { + mpp_err_f("syn->pic_ver_stride %d is not supported for vpu", syn->pic_ver_stride); + ret = MPP_NOK; + goto err; + } + +err: + h264e_hal_debug_leave(); - return MPP_OK; + + return ret; } diff --git a/mpp/legacy/vpu_api_legacy.cpp b/mpp/legacy/vpu_api_legacy.cpp index 2c90e3ba..888e1a8f 100755 --- a/mpp/legacy/vpu_api_legacy.cpp +++ b/mpp/legacy/vpu_api_legacy.cpp @@ -627,7 +627,7 @@ RK_S32 VpuApiLegacy::decode(VpuCodecContext *ctx, VideoPacket_t *pkt, DecoderOut } vpu_api_dbg_input("input size %-6d flag %x pts %lld\n", - pkt->size, pkt->nFlags, pkt->pts); + pkt->size, pkt->nFlags, pkt->pts); ret = mpi->decode(mpp_ctx, packet, &mframe); if (MPP_OK == ret) { @@ -1313,8 +1313,8 @@ RK_S32 VpuApiLegacy::control(VpuCodecContext *ctx, VPU_API_CMD cmd, void *param) } else if (ctx->videoCoding == OMX_RK_VIDEO_CodingVP9) { p->ImgHorStride = MPP_ALIGN(ImgWidth, 128); p->ImgVerStride = MPP_ALIGN(p->ImgHeight, 64); - } else if (ctx->videoCoding == OMX_RK_VIDEO_CodingAVC - && (p->ImgWidth > 1920 || p->ImgHeight > 1088)) { + } else if (ctx->videoCoding == OMX_RK_VIDEO_CodingAVC && + (p->ImgWidth > 1920 || p->ImgHeight > 1088)) { p->ImgHorStride = hevc_hor_align_256_odd(ImgWidth); p->ImgVerStride = default_align_16(p->ImgHeight); } else { diff --git a/osal/inc/mpp_runtime.h b/osal/inc/mpp_runtime.h index 6b87f243..6b0d813d 100644 --- a/osal/inc/mpp_runtime.h +++ b/osal/inc/mpp_runtime.h @@ -23,7 +23,7 @@ * Runtime function detection is for rockchip software platform detection */ -typedef void *(*func_mmap64)(void* addr,size_t length, int prot, int flags, +typedef void *(*func_mmap64)(void* addr, size_t length, int prot, int flags, int fd, off_t offset); #ifdef __cplusplus diff --git a/test/mpi_enc_test.c b/test/mpi_enc_test.c index 13812b71..0d188c19 100644 --- a/test/mpi_enc_test.c +++ b/test/mpi_enc_test.c @@ -36,6 +36,7 @@ #define MAX_FILE_NAME_LENGTH 256 #define MPI_ENC_TEST_SET_IDR_FRAME 0 +#define MPI_ENC_TEST_SET_OSD 0 typedef struct { char file_input[MAX_FILE_NAME_LENGTH]; @@ -62,6 +63,79 @@ static OptionInfo mpi_enc_cmd[] = { {"d", "debug", "debug flag"}, }; +static MPP_RET read_yuv_image(RK_U8 *buf, MppEncConfig *mpp_cfg, FILE *fp) +{ + MPP_RET ret = MPP_OK; + RK_U32 read_size; + RK_U32 row = 0; + RK_U32 width = mpp_cfg->width; + RK_U32 height = mpp_cfg->height; + RK_U32 hor_stride = mpp_cfg->hor_stride; + RK_U32 ver_stride = mpp_cfg->ver_stride; + MppFrameFormat fmt = mpp_cfg->format; + RK_U8 *buf_y = buf; + RK_U8 *buf_u = buf_y + hor_stride * ver_stride; // NOTE: diff from gen_yuv_image + RK_U8 *buf_v = buf_u + hor_stride * ver_stride / 4; // NOTE: diff from gen_yuv_image + + switch (fmt) { + case MPP_FMT_YUV420SP : { + for (row = 0; row < height; row++) { + read_size = fread(buf_y + row * hor_stride, 1, width, fp); + if (read_size != width) { + mpp_err_f("read ori yuv file luma failed"); + ret = MPP_NOK; + goto err; + } + } + + for (row = 0; row < height / 2; row++) { + read_size = fread(buf_u + row * hor_stride, 1, width, fp); + if (read_size != width) { + mpp_err_f("read ori yuv file cb failed"); + ret = MPP_NOK; + goto err; + } + } + } break; + case MPP_FMT_YUV420P : { + for (row = 0; row < height; row++) { + read_size = fread(buf_y + row * hor_stride, 1, width, fp); + if (read_size != width) { + mpp_err_f("read ori yuv file luma failed"); + ret = MPP_NOK; + goto err; + } + } + + for (row = 0; row < height / 2; row++) { + read_size = fread(buf_u + row * hor_stride / 2, 1, width / 2, fp); + if (read_size != width / 2) { + mpp_err_f("read ori yuv file cb failed"); + ret = MPP_NOK; + goto err; + } + } + + for (row = 0; row < height / 2; row++) { + read_size = fread(buf_v + row * hor_stride / 2, 1, width / 2, fp); + if (read_size != width / 2) { + mpp_err_f("read ori yuv file cr failed"); + ret = MPP_NOK; + goto err; + } + } + } break; + default : { + mpp_err_f("read image do not support fmt %d\n", fmt); + ret = MPP_NOK; + } break; + } + +err: + + return ret; +} + static MPP_RET fill_yuv_image(RK_U8 *buf, MppEncConfig *mpp_cfg, RK_U32 frame_count) { MPP_RET ret = MPP_OK; @@ -187,7 +261,7 @@ int mpi_enc_test(MpiEncTestCmd *cmd) // paramter for resource malloc RK_U32 width = cmd->width; RK_U32 height = cmd->height; - RK_U32 hor_stride = MPP_ALIGN(width, 16); + RK_U32 hor_stride = MPP_ALIGN(width, 16); RK_U32 ver_stride = MPP_ALIGN(height, 16); MppFrameFormat fmt = cmd->format; MppCodingType type = cmd->type; @@ -201,7 +275,6 @@ int mpi_enc_test(MpiEncTestCmd *cmd) size_t mdinfo_size = (((hor_stride + 255) & (~255)) / 16) * (ver_stride / 16) * 4; //NOTE: hor_stride should be 16-MB aligned /* osd idx size range from 16x16 bytes(pixels) to hor_stride*ver_stride(bytes). for general use, 1/8 Y buffer is enough. */ size_t osd_idx_size = hor_stride * ver_stride / 8; - size_t read_size = 0; RK_U32 frame_count = 0; RK_U64 stream_size = 0; RK_U32 plt_table[8] = { @@ -349,11 +422,13 @@ int mpi_enc_test(MpiEncTestCmd *cmd) /* gen and cfg osd plt */ mpi_enc_gen_osd_plt(&osd_plt, plt_table); +#if MPI_ENC_TEST_SET_OSD ret = mpi->control(ctx, MPP_ENC_SET_OSD_PLT_CFG, &osd_plt); if (MPP_OK != ret) { mpp_err("mpi control enc set osd plt failed\n"); goto MPP_TEST_OUT; } +#endif i = 0; while (!pkt_eos) { @@ -370,9 +445,9 @@ int mpi_enc_test(MpiEncTestCmd *cmd) i = 0; if (fp_input) { - read_size = fread(buf, 1, frame_size, fp_input); - if (read_size != frame_size || feof(fp_input)) { - mpp_log("found last frame\n"); + ret = read_yuv_image(buf, &mpp_cfg, fp_input); + if (ret != MPP_OK || feof(fp_input)) { + mpp_log("found last frame. feof %d\n", feof(fp_input)); frm_eos = 1; } } else { @@ -424,11 +499,13 @@ int mpi_enc_test(MpiEncTestCmd *cmd) /* gen and cfg osd plt */ mpi_enc_gen_osd_data(&osd_data, osd_data_buf, frame_count); +#if MPI_ENC_TEST_SET_OSD ret = mpi->control(ctx, MPP_ENC_SET_OSD_DATA_CFG, &osd_data); if (MPP_OK != ret) { mpp_err("mpi control enc set osd data failed\n"); goto MPP_TEST_OUT; } +#endif ret = mpi->enqueue(ctx, MPP_PORT_INPUT, task); if (ret) {