RockChip MPP编码

您所在的位置:网站首页 gop怎么计算 RockChip MPP编码

RockChip MPP编码

2023-03-13 10:45| 来源: 网络整理| 查看: 265

概述

瑞芯微提供的媒体处理软件平台(Media Process Platform,简称 MPP)是适用于瑞芯微芯片系列的

通用媒体处理软件平台。该平台对应用软件屏蔽了芯片相关的复杂底层处理,其目的是为了屏蔽不

同芯片的差异,为使用者提供统一的视频媒体处理接口(Media Process Interface,缩写 MPI)。MPP

提供的功能包括:

视频解码:

H.265 / H.264 / H.263 / VP9 / VP8 / MPEG-4 / MPEG-2 / MPEG-1 / VC1 / MJPEG

视频编码:

H.264 / VP8 / MJPEG

视频处理:

视频拷贝,缩放,色彩空间转换,场视频解交织(Deinterlace)

MPP源码下载

git clone https://github.com/rockchip-linux/mpp.git

编码demo测试

mpi_enc_test -w 720 -h 480 -t 7 -i /sdcard/soccer_720x480_30fps.yuv -o /sdcard/out.h264 -n 1000

mpi_enc_test 的命令参数中,图像宽度(w)图像高度(h),码流类型(t)为强制要求参数,其他参

数如输入文件(i),输出文件(o),编码帧数(n)等为可选参数。

执行完测试程序在/sdcard目录下会生成out.h264文件。

将out.h264在VLC media player播放器播放:

MPI接口使用流程

创建 MPP context 和 MPP api 接口

ret = mpp_create(&p->ctx, &p->mpi);

初始化 MPP

ret = mpp_init(p->ctx, MPP_CTX_ENC, p->type); // 初始化MPP

设置一些MPP的模式

ret = mpi->control(ctx, MPP_ENC_SET_SEI_CFG, &p->sei_mode);

编码就是喂MppFrame,输出MppPacket;

输入frame

ret = mpi->encode_put_frame(ctx, frame);

输出packet

ret = mpi->encode_get_packet(ctx, &packet);

RK官方编码demo mpi_enc_test.c简化

#if defined(_WIN32) #include "vld.h" #endif #define MODULE_TAG "mpi_enc_test" #include #include "rk_mpi.h" #include "mpp_mem.h" #include "mpp_common.h" #include "utils.h" #include "mpi_enc_utils.h" #include typedef struct { // base flow context MppCtx ctx; MppApi *mpi; // global flow control flag RK_U32 frm_eos; RK_U32 pkt_eos; RK_S32 frame_count; // src and dst FILE *fp_output; /* encoder config set */ MppEncCfg cfg; // input / output MppBufferGroup buf_grp; MppBuffer frm_buf; MppBuffer pkt_buf; MppBuffer md_info; MppEncSeiMode sei_mode; MppEncHeaderMode header_mode; // paramter for resource malloc RK_U32 width; RK_U32 height; RK_U32 hor_stride; RK_U32 ver_stride; MppFrameFormat fmt; MppCodingType type; // resources size_t header_size; size_t frame_size; size_t mdinfo_size; } MpiEncTestData; /* For each instance thread return value */ typedef struct { RK_S32 frame_count; } MpiEncMultiCtxRet; typedef struct { MpiEncTestArgs *cmd; // pointer to global command line info const char *name; pthread_t thd; // thread for for each instance MpiEncTestData ctx; // context of encoder MpiEncMultiCtxRet ret; // return of encoder } MpiEncMultiCtxInfo; MPP_RET test_ctx_init(MpiEncMultiCtxInfo *info) { MpiEncTestArgs *cmd = info->cmd; MpiEncTestData *p = &info->ctx; MPP_RET ret = MPP_OK; // 设置编码宽高、对齐后宽高参数 p->width = cmd->width; p->height = cmd->height; p->hor_stride = (cmd->hor_stride) ? (cmd->hor_stride) : (MPP_ALIGN(cmd->width, 16)); p->ver_stride = (cmd->ver_stride) ? (cmd->ver_stride) : (MPP_ALIGN(cmd->height, 16)); p->fmt = cmd->format; p->type = cmd->type; p->mdinfo_size = (MPP_VIDEO_CodingHEVC == cmd->type) ? (MPP_ALIGN(p->hor_stride, 64) >> 6) * (MPP_ALIGN(p->ver_stride, 64) >> 6) * 32 : (MPP_ALIGN(p->hor_stride, 64) >> 6) * (MPP_ALIGN(p->ver_stride, 16) >> 4) * 8; p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64) * 4; return ret; } MPP_RET test_ctx_deinit(MpiEncTestData *p) { if (p) { if (p->fp_output) { fclose(p->fp_output); p->fp_output = NULL; } } return MPP_OK; } MPP_RET test_mpp_enc_cfg_setup(MpiEncMultiCtxInfo *info) { MpiEncTestData *p = &info->ctx; MppApi *mpi = p->mpi; MppCtx ctx = p->ctx; MppEncCfg cfg = p->cfg; MPP_RET ret; mpp_enc_cfg_set_s32(cfg, "prep:width", p->width); mpp_enc_cfg_set_s32(cfg, "prep:height", p->height); mpp_enc_cfg_set_s32(cfg, "prep:hor_stride", p->hor_stride); mpp_enc_cfg_set_s32(cfg, "prep:ver_stride", p->ver_stride); mpp_enc_cfg_set_s32(cfg, "prep:format", p->fmt); ret = mpi->control(ctx, MPP_ENC_SET_CFG, cfg); //创建 MPP p->sei_mode = MPP_ENC_SEI_MODE_ONE_FRAME; ret = mpi->control(ctx, MPP_ENC_SET_SEI_CFG, &p->sei_mode); //设置一些MPP的模式 if (p->type == MPP_VIDEO_CodingAVC || p->type == MPP_VIDEO_CodingHEVC) { p->header_mode = MPP_ENC_HEADER_MODE_EACH_IDR; ret = mpi->control(ctx, MPP_ENC_SET_HEADER_MODE, &p->header_mode); } return ret; } MPP_RET test_mpp_run(MpiEncMultiCtxInfo *info) //图像编码函数 { MpiEncTestData *p = &info->ctx; MppApi *mpi = p->mpi; MppCtx ctx = p->ctx; MPP_RET ret = MPP_OK; MppMeta meta = NULL; MppFrame frame = NULL; MppPacket packet = NULL; // 存放编码数据 void *buf = mpp_buffer_get_ptr(p->frm_buf); ret = fill_image(buf, p->width, p->height, p->hor_stride, p->ver_stride, p->fmt, p->frame_count); ret = mpp_frame_init(&frame); mpp_frame_set_width(frame, p->width); mpp_frame_set_height(frame, p->height); mpp_frame_set_hor_stride(frame, p->hor_stride); mpp_frame_set_ver_stride(frame, p->ver_stride); mpp_frame_set_fmt(frame, p->fmt); mpp_frame_set_eos(frame, p->frm_eos); mpp_frame_set_buffer(frame, p->frm_buf); meta = mpp_frame_get_meta(frame); mpp_packet_init_with_buffer(&packet, p->pkt_buf); mpp_packet_set_length(packet, 0); mpp_meta_set_packet(meta, KEY_OUTPUT_PACKET, packet); mpp_meta_set_buffer(meta, KEY_MOTION_INFO, p->md_info); ret = mpi->encode_put_frame(ctx, frame); //输入frame if (ret) { mpp_frame_deinit(&frame); } mpp_frame_deinit(&frame); ret = mpi->encode_get_packet(ctx, &packet); //输出packet mpp_assert(packet); void *ptr = mpp_packet_get_pos(packet); size_t len = mpp_packet_get_length(packet); p->pkt_eos = mpp_packet_get_eos(packet); fwrite(ptr, 1, len, p->fp_output); mpp_packet_deinit(&packet); return ret; } void *enc_test(void *arg) //编码器初始化函数 { MpiEncMultiCtxInfo *info = (MpiEncMultiCtxInfo *)arg; MpiEncTestData *p = &info->ctx; MppPollType timeout = MPP_POLL_BLOCK; MPP_RET ret = MPP_OK; ret = test_ctx_init(info); ret = mpp_buffer_group_get_internal(&p->buf_grp, MPP_BUFFER_TYPE_DRM); ret = mpp_buffer_get(p->buf_grp, &p->frm_buf, p->frame_size + p->header_size); ret = mpp_buffer_get(p->buf_grp, &p->pkt_buf, p->frame_size); ret = mpp_buffer_get(p->buf_grp, &p->md_info, p->mdinfo_size); ret = mpp_create(&p->ctx, &p->mpi); //创建 MPP context 和 MPP api 接口 ret = p->mpi->control(p->ctx, MPP_SET_OUTPUT_TIMEOUT, &timeout); ret = mpp_init(p->ctx, MPP_CTX_ENC, p->type); // 初始化MPP ret = mpp_enc_cfg_init(&p->cfg); ret = test_mpp_enc_cfg_setup(info); ret = test_mpp_run(info); ret = p->mpi->reset(p->ctx); test_ctx_deinit(p); return NULL; } int enc_test_multi(MpiEncTestArgs* cmd, const char *name) { MpiEncMultiCtxInfo *ctxs = NULL; RK_S32 ret = MPP_NOK; RK_S32 i = 0; ctxs = mpp_calloc(MpiEncMultiCtxInfo, cmd->nthreads); ctxs[i].cmd = cmd; ctxs[i].name = name; ret = pthread_create(&ctxs[i].thd, NULL, enc_test, &ctxs[i]); pthread_join(ctxs[i].thd, NULL); MPP_FREE(ctxs); return ret; } int main(int argc,char **argv) { argc = 13; char* argvv[] = {"mpi_enc_test","-w","720","-h","480","-t","7","-i","/sdcard/soccer_720x480_30fps.yuv","-o","/sdcard/out.h264","-n","10"}; RK_S32 ret = MPP_NOK; MpiEncTestArgs* cmd = mpi_enc_test_cmd_get(); // parse the cmd option ret = mpi_enc_test_cmd_update_by_args(cmd, argc, argvv); mpi_enc_test_cmd_show_opt(cmd); ret = enc_test_multi(cmd, argvv[0]); return ret; }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3