RockChip MPP编码

news2024/11/6 9:24:48
  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 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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/338204.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用java开发连连看游戏

技术&#xff1a;Java等摘要&#xff1a;社会在发展&#xff0c;人类在进步&#xff0c;生活质量保证之余&#xff0c;各种游戏蜂拥而起&#xff0c;越来越受到各界人士的追捧&#xff0c;比如老少适宜的斗地主&#xff0c;深受广大女性喜欢的节奏大师&#xff0c;受高智商人群…

Pandas——Series操作【建议收藏】

pandas——Series操作 作者&#xff1a;AOAIYI 创作不易&#xff0c;觉得文章不错或能帮助到你学习&#xff0c;可以点赞收藏评论哦 文章目录pandas——Series操作一、实验目的二、实验原理三、实验环境四、实验内容五、实验步骤1.创建Series2.从具体位置的Series中访问数据3.使…

FyListen——生命周期监听器(设计原理之理解生命周期)

FyListen——生命周期监听器&#xff08;设计原理之理解生命周期&#xff09; FyListen 的核心原理有两个&#xff1a; 通过子Fragment对Activity、Fragment进行生命周期监听Java8 接口特性 default 1. 什么是上下文Context 这是一个装饰器模式&#xff0c; ContextImpl 是 …

【ChatGPT说】我想给大家【编】一个故事,故事的主人公叫【架构师李肯】,故事的开头,还得从他那年买房说起。。。

大家好啊&#xff0c;我就是那个【天涯何处无知己&#xff0c;人穷陌路勿担忧】的架构师李肯&#xff01; 架构师李肯&#xff08;全网同名&#xff09; 在深圳白手起家&#xff0c;毕业不到4年实现一线城市核心地段的安家梦&#xff0c;从0开始谱写励志人生&#xff01;一个专…

一文手把手教你写一个 Makefile 文件

如果我们是在Linux下开发&#xff0c;那Makefile肯定要知道&#xff0c;不懂Makefile&#xff0c;面对较大的工程项目的时候就会比较麻烦&#xff0c;懂得利用开发工具将会大大提高我们的开发效率&#xff0c;也可以说Makefile是必须掌握的一项技能。 一、了解什么是 Makefile…

java集合框架内容整理

主要内容集合框架体系ArrayListLinkedListHashSetTreeSetLinkedHashSet内部比较器和外部比较器哈希表的原理List集合List集合的主要实现类有ArrayList和LinkedList&#xff0c;分别是数据结构中顺序表和链表的实现。另外还包括栈和队列的实现类&#xff1a;Deque和Queue。• Li…

steam/csgo搬砖项目真能月入过万吗?到底真的假的?

提前说明&#xff0c;这是正经、真实、官方渠道的兼职赚钱方式&#xff0c;不需要学历、不需要人脉&#xff0c;只要你认真学&#xff0c;每天花1-2个小时空闲时间动动手指&#xff0c;日赚300-1000问题不大&#xff01; 搬砖是从国外steam市场置办游戏装备回来&#xff0c;在…

javassm运列车物资进销存及领用管理系统

主要对个人中心、生产部管理、财务部管理、库房部管理、用户管理、车型分类管理、线路信息管理、列车信息管理、物资分类管理、物资信息管理、储备定额管理、物资入库管理、物资申请管理、入库记录管理的实现。 本系统设计的现状和趋势&#xff0c;从需求、结构、数据库等方面的…

五、Git本地仓库基本操作——分支管理

1. 什么是分支&#xff1f; master分支 我们在初始化git仓库的时候&#xff0c;会默认创建一个master分支&#xff0c;HEAD指针这时就会默认执行master分支。当我们在master分支提交&#xff08;commit&#xff09;了更新之后&#xff0c;master分支就会指向当前当前最新的co…

微搭中如何实现弹性布局

我们在实际开发中经常可能会有一些社交的场景&#xff0c;比如开发一个类似朋友圈九宫格图片展示的功能。因为图片的数量不确定&#xff0c;所以需要实现图片的从左到右顺序排列。 在微搭中可以以可视化的方式设置样式。但是对于我们这类特殊需求&#xff0c;只用可视化设置显…

【SSL/TLS】准备工作:HTTPS服务器部署:Nginx部署

HTTPS服务器部署&#xff1a;Nginx部署1. 准备工作2. Nginx服务器YUM部署2.1 直接安装2.2 验证3. Nginx服务器源码部署3.1 下载源码包3.2 部署过程4. Nginx基本操作4.1 nginx常用命令行4.2 nginx重要目录1. 准备工作 1. Linux版本 [rootlocalhost ~]# cat /proc/version Li…

【宝塔部署PHP项目】含域名访问部署、IP访问部署、数据库、端口号、Nginx等知识

一定要弄懂项目部署的方方面面。当服务器上部署的项目过多时&#xff0c;端口号什么时候该放行、什么时候才会发生冲突&#xff1f;多个项目使用redis怎么防止覆盖&#xff1f;Nginx的配置会不会产生站点冲突&#xff1f;二级域名如何合理配置&#xff1f;空闲的时候要自己用服…

Day886.MySQL的“饮鸩止渴”提高性能的方法 -MySQL实战

MySQL的“饮鸩止渴”提高性能的方法 HI&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于MySQL的“饮鸩止渴”提高性能的方法的内容。 不知道在实际运维过程中有没有碰到这样的情景&#xff1a; 业务高峰期&#xff0c;生产环境的 MySQL 压力太大&#xff0c;没法正常响…

力扣SQL刷题8

目录1212. 查询球队积分1270. 向公司CEO汇报工作的所有人1285. 找到连续区间的开始和结束数字1321. 餐馆营业额变化增长--重要窗口函数知识点补充1212. 查询球队积分 题型&#xff1a;读题 解答&#xff1a;先考虑做主方时&#xff0c;再考虑客方时 SELECT t.team_id, t.te…

人工智能轨道交通行业周刊-第33期(2023.2.6-2.12)

本期关键词&#xff1a;高铁激光清洗、高铁确认列车、无线通信系统、推理服务优化、量子信息技术 1 整理涉及公众号名单 1.1 行业类 RT轨道交通中关村轨道交通产业服务平台人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交通联盟V…

大数据系列之:安装pulsar详细步骤

大数据系列之&#xff1a;安装pulsar详细步骤一、Pulsar版本和jdk对应关系二、安装JDK三、设置和激活jdk环境变量四、下载和解压Pulsar五、查看Pulsar目录六、启动Pulsar standalone cluster七、创建Kafka Topic八、往Topic写入数据九、消费pulsar的Topic一、Pulsar版本和jdk对…

c#小笔记本-基础

c#基本知识一.基础操作1.打印-writeline,write2.输入-readline,readkey二.变量1.折叠代码-#region&#xff0c;#endregion2.变量类型&#xff08;在c语言变量类型上新增的&#xff09;三.常量-const四.转义字符五.显示转换1.括号强转-低精度装高精度2.parse法-作用于字符串3.co…

实践指南|如何在 Jina 中使用 OpenTelemetry 进行应用程序的监控和跟踪

随着软件和云技术的普及&#xff0c;越来越多的企业开始采用微服务架构、容器化、多云部署和持续部署模式&#xff0c;这增加了因系统失败而给运维/ SRE / DevOps 团队带来的压力&#xff0c;从而增加了开发团队和他们之间的摩擦&#xff0c;因为开发团队总是想尽快部署新功能&…

28岁才转行软件测试,目前32了,我的一些经历跟感受

我是92年的&#xff0c;算是最早的90后&#xff0c;现在跟你介绍的时候还恬不知耻的说我是90后&#xff0c;哈哈&#xff0c;计算机专业普通本科毕业。在一个二线城市&#xff0c;毕业后因为自身能力问题、认知水平问题&#xff0c;再加上运气不好&#xff0c;换过多份工作&…

关于@hide的理解

在上一篇文章《学习HandlerThread》我们提到虽然HandlerThread类里有getThreadHandler()方法得到Handler&#xff0c;但是我们不可能调用到它。因为这个方法用hide注释了 /*** return a shared {link Handler} associated with this thread* hide*/NonNullpublic Handler getT…