当前位置: 首页 > news >正文

RockChip MPP编码

  1. 概述

瑞芯微提供的媒体处理软件平台(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)

  1. MPP源码下载

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

  1. 编码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播放器播放:

  1. 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); 

  1. RK官方编码demo mpi_enc_test.c简化

#if defined(_WIN32)
#include "vld.h"
#endif#define MODULE_TAG "mpi_enc_test"#include <string.h>
#include "rk_mpi.h"
#include "mpp_mem.h"
#include "mpp_common.h"
#include "utils.h"
#include "mpi_enc_utils.h"#include <stdio.h>typedef struct {// base flow contextMppCtx ctx;MppApi *mpi;// global flow control flagRK_U32 frm_eos;RK_U32 pkt_eos;RK_S32 frame_count;// src and dstFILE *fp_output;/* encoder config set */MppEncCfg       cfg;// input / outputMppBufferGroup buf_grp;MppBuffer frm_buf;MppBuffer pkt_buf;MppBuffer md_info;MppEncSeiMode sei_mode;MppEncHeaderMode header_mode;// paramter for resource mallocRK_U32 width;RK_U32 height;RK_U32 hor_stride;RK_U32 ver_stride;MppFrameFormat fmt;MppCodingType type;// resourcessize_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 infoconst char          *name;pthread_t           thd;        // thread for for each instanceMpiEncTestData      ctx;        // context of encoderMpiEncMultiCtxRet   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); //创建 MPPp->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); //输入frameif (ret) {mpp_frame_deinit(&frame);}mpp_frame_deinit(&frame);ret = mpi->encode_get_packet(ctx, &packet); //输出packetmpp_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); // 初始化MPPret = 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 optionret = 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;
}
http://www.lryc.cn/news/2767.html

相关文章:

  • 【学习笔记】NOIP暴零赛2
  • linux基本功系列之hostname实战
  • Easy-Es框架实践测试整理 基于ElasticSearch的ORM框架
  • 【数据结构】双向链表的模拟实现(无头)
  • vue自定义指令---处理加载图片失败时出现的碎图,onerror事件
  • 加盟管理系统挑选法则,看完不怕被坑!
  • alertmanager笔记
  • Android Jetpack组件之WorkManager后台任务管理的介绍与使用(二)
  • 【MySQL】第十七部分 约束
  • java ssm集装箱码头TOS系统调度模块的设计与实现
  • MS14-064(OLE远程代码执行漏洞复现)
  • 【C++深陷】之shared_ptr
  • SpringMVC中遇到的错误
  • 姿态估计端到端新方案 | DirectMHP:用于全范围角度2D多人头部姿势估计
  • jvm学习的核心(五)---垃圾回收算法和常见垃圾回收器
  • 亿级高并发电商项目-- 实战篇 --万达商城项目 二(Zookeeper、Docker、Dubbo-Admin等搭建工作
  • 【C#基础】 C# 数据类型总结
  • 格子玻尔兹曼法介绍
  • 活动星投票在时间的河流上造园分组怎么设置如何进行分组报名
  • c#小笔记本-基础
  • DamiCMS SQL注入分析
  • 图傅里叶变换的推导和理解
  • Java八股文(Java面试题)
  • java ssm idea高校图书借阅管理系统设计2z87z
  • 电脑重装系统注册表恢复方法
  • 信道建模(大尺度、小尺度、莱斯衰落、瑞利衰落、莱斯信道、瑞利信道)
  • 2022年12月电子学会Python等级考试试卷(四级)答案解析
  • 通过实例告诉你lua中ipairs到底是怎么遍历的!
  • Axios异步请求 json格式
  • Postgresql源码(100)Portal与事务的关系(顶层事务与子事务)