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

rkmpp 解码 精简mpi_dec_test.c例程

rkmpp 解码流程(除 MPP_VIDEO_CodingMJPEG 之外)

解码流程

源码

输入h264码流 输出nv12文件

/** Copyright 2015 Rockchip Electronics 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.*/#if defined(_WIN32)
#include "vld.h"
#endif#define MODULE_TAG "mpi_dec_test"#include <string.h>#include "mpi_dec_utils.h"
#include "mpp_common.h"
#include "mpp_env.h"
#include "mpp_mem.h"
#include "mpp_time.h"
#include "rk_mpi.h"typedef struct {MpiDecTestCmd *cmd;MppCtx ctx;MppApi *mpi;RK_U32 quiet;/* end of stream flag when set quit the loop */RK_U32 loop_end;/* input and output */DecBufMgr buf_mgr;MppBufferGroup frm_grp;MppPacket packet;MppFrame frame;FILE *fp_output;RK_S32 frame_count;RK_S32 frame_num;RK_S64 first_pkt;RK_S64 first_frm;size_t max_usage;float frame_rate;RK_S64 elapsed_time;RK_S64 delay;FILE *fp_verify;FrmCrc checkcrc;
} MpiDecLoopData;int main(int argc, char **argv) {char *video_path = "/home/ido/chenFan/mpp/test/video/test.h264";// RK_S32 max_dec_frame_num = 100;  //最大解码帧数RK_S32 max_dec_frame_num = 0;  //解码完整个文件char *file_output = "/home/ido/chenFan/mpp/test/video/out.yuv";size_t max_usage;  //记录解码器最大使用内存MppCtx ctx = NULL;MppApi *mpi = NULL;// 1. 创建解码器int ret = mpp_create(&ctx, &mpi);if (ret) {mpp_err("mpp_create failed\n");goto MPP_TEST_OUT;}// mpp_log("")// 2. 初始化解码器MppCodingType video_type = MPP_VIDEO_CodingAVC;ret = mpp_init(ctx, MPP_CTX_DEC, video_type);if (ret) {mpp_err("%p mpp_init failed\n", ctx);goto MPP_TEST_OUT;}MppParam cfg = NULL;mpp_dec_cfg_init(&cfg);// 2.1 获取默认配置ret = mpi->control(ctx, MPP_DEC_GET_CFG, cfg);// 2.2 设置内部分帧模式uint32_t need_split = 1;ret = mpp_dec_cfg_set_u32(cfg, "base:split_parse", need_split);if (ret) {mpp_err("%p failed to set split_parse ret %d\n", ctx, ret);goto MPP_TEST_OUT;}ret = mpi->control(ctx, MPP_DEC_SET_CFG, cfg);if (ret) {mpp_err("%p failed to set cfg %p ret %d\n", ctx, cfg, ret);goto MPP_TEST_OUT;}//解码码流保存到文件FILE *fp_output = NULL;
#if 0fp_output = fopen(file_output, "w+b");if (NULL == fp_output) {mpp_err("failed to open output file %s\n", file_output);goto MPP_TEST_OUT;}
#endif//半内部模式配置MppDecBufMode buf_mode = MPP_DEC_BUF_HALF_INT;MppBufferGroup grp = NULL;DecBufMgr buf_mgr;ret = dec_buf_mgr_init(&buf_mgr);if (ret) {mpp_err("dec_buf_mgr_init failed\n");goto MPP_TEST_OUT;}// 配置输入pktMppPacket packet = NULL;ret = mpp_packet_init(&packet, NULL, 0);if (ret) {mpp_err("mpp_packet_init failed\n");goto MPP_TEST_OUT;}// 3. 解码/* end of stream flag when set quit the loop */RK_U32 loop_end = 0;RK_S32 frame_count = 0;RK_S64 first_pkt = 0;RK_S64 first_frm = 0;// 3.1 打开输入码流FileReader reader = NULL;reader_init(&reader, video_path, video_type);if (!reader) {mpp_err("input file %s reader_init failed\n");return -1;}mpp_log("input file %s size %ld\n", video_path, reader_size(reader));RK_S64 t_s, t_e;t_s = mpp_time();// 3.2 解码循环while (!loop_end) {// 3.2.1 读取输入码流FileBufSlot *slot = NULL;ret = reader_read(reader, &slot);if (ret < 0) {mpp_err("input file %s reader_read failed\n");return -1;}RK_U32 pkt_eos = 0;pkt_eos = slot->eos;if (pkt_eos) {//如果指定最大帧数小于0即一直解码 或 码流自身帧数小于指定最大解码帧数,//则重载码流继续解码if (max_dec_frame_num < 0 || max_dec_frame_num > frame_count) {mpp_log("%p loop again\n", ctx);reader_rewind(reader);pkt_eos = 0;} else {mpp_log("%p found last packet\n", ctx);loop_end = 1;}}// 3.2.2 配置输入pktmpp_packet_set_data(packet, slot->data);mpp_packet_set_size(packet, slot->size);mpp_packet_set_pos(packet, slot->data);mpp_packet_set_length(packet, slot->size);if (pkt_eos) mpp_packet_set_eos(packet);RK_U32 pkt_done = 0;do {RK_S32 dec_frame_timeout = 30;RK_U32 frm_eos = 0;if (!pkt_done) {// 3.2.3 packet传入解码器ret = mpi->decode_put_packet(ctx, packet);if (ret == MPP_OK) {pkt_done = 1;if (!first_pkt) {first_pkt = mpp_time();  // 记录第一个成功送入解码器的时间戳}}}do {RK_S32 get_frm = 0;MppFrame frame = NULL;try_again:// 3.2.4 从解码器获取解码后的帧ret = mpi->decode_get_frame(ctx, &frame);//超时等待if (ret == MPP_ERR_TIMEOUT) {if (dec_frame_timeout > 0) {dec_frame_timeout--;msleep(1);goto try_again;}mpp_err("%p decode_get_frame failed too much time\n", ctx);}if (ret) {mpp_err("%p decode_get_frame failed ret %d\n", ret, ctx);break;}if (frame) {// 3.2.5 配置MppBufferGroup 并 通知解码器// MPP_DEC_SET_INFO_CHANGE_READY//半内部分配模式//可通过mpp_buffer_group_limit_config限制解码器的内存使用量if (mpp_frame_get_info_change(frame)) {RK_U32 width = mpp_frame_get_width(frame);RK_U32 height = mpp_frame_get_height(frame);RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);RK_U32 buf_size = mpp_frame_get_buf_size(frame);mpp_log("%p decode_get_frame get info changed found\n", ctx);mpp_log("%p decoder require buffer w:h [%d:%d] stride [%d:%d] ""buf_size %d",ctx, width, height, hor_stride, ver_stride, buf_size);grp = dec_buf_mgr_setup(buf_mgr, buf_size, 24, buf_mode);/* Set buffer to mpp decoder */ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, grp);if (ret) {mpp_err("%p set buffer group failed ret %d\n", ctx, ret);break;}ret = mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);if (ret) {mpp_err("%p info change ready failed ret %d\n", ctx, ret);break;}} else {// 3.2.6 解码所得帧char log_buf[256];RK_S32 log_size = sizeof(log_buf) - 1;RK_S32 log_len = 0;RK_U32 err_info = mpp_frame_get_errinfo(frame);RK_U32 discard = mpp_frame_get_discard(frame);if (!first_frm) first_frm = mpp_time();log_len += snprintf(log_buf + log_len, log_size - log_len,"decode get frame %d", frame_count);if (err_info || discard) {log_len += snprintf(log_buf + log_len, log_size - log_len," err %x discard %x", err_info, discard);}mpp_log("%p %s\n", ctx, log_buf);if (fp_output && !err_info)dump_mpp_frame_to_file(frame, fp_output);frame_count++;}frm_eos = mpp_frame_get_eos(frame);mpp_frame_deinit(&frame);get_frm = 1;}// try get runtime frame memory usageif (grp) {size_t usage = mpp_buffer_group_usage(grp);if (usage > max_usage) max_usage = usage;}// if last packet is send but last frame is not found continueif (pkt_eos && pkt_done && !frm_eos) {msleep(1);continue;}if (frm_eos) {mpp_log("%p found last packet\n", ctx);break;}//解码指定帧数 或 解码完一帧//注意:当前是内部分帧模式,一个 packet 不一定正好包含一个 frameif ((max_dec_frame_num > 0 && (frame_count >= max_dec_frame_num)) ||((max_dec_frame_num == 0) && frm_eos))break;//内部分帧模式if (get_frm) continue;break;} while (1);//解码指定帧数 或 解码完整个码流if ((max_dec_frame_num > 0 && (frame_count >= max_dec_frame_num)) ||((max_dec_frame_num == 0) && frm_eos)) {loop_end = 1;break;}if (pkt_done) break;//休眠等待,避免传入过快占满解码器内部队列msleep(1);} while (1);}t_e = mpp_time();RK_S64 elapsed_time = t_e - t_s;float frame_rate = (float)frame_count * 1000000 / elapsed_time;RK_S64 delay = first_frm - first_pkt;mpp_log("decode %d frames time %lld ms delay %3d ms fps %3.2f\n", frame_count,(RK_S64)(elapsed_time / 1000), (RK_S32)(delay / 1000), frame_rate);mpp_log("test success max memory %.2f MB\n", max_usage / (float)(1 << 20));// 4. 重置解码器,恢复为正常初始化后的状态, 用于循环解码,// 解码器在接收到eos之后不再接收码流,需要reset重置ret = mpi->reset(ctx);if (ret) {mpp_err("%p mpi->reset failed\n", ctx);goto MPP_TEST_OUT;}MPP_TEST_OUT:// 5. 销毁解码器if (ctx) {mpp_destroy(ctx);ctx = NULL;}if (cfg) {mpp_dec_cfg_deinit(cfg);cfg = NULL;}if (packet) {mpp_packet_deinit(&packet);packet = NULL;}grp = NULL;if (buf_mgr) {dec_buf_mgr_deinit(buf_mgr);buf_mgr = NULL;}if (fp_output) {fclose(fp_output);fp_output = NULL;}return 0;
}

相关文章:

rkmpp 解码 精简mpi_dec_test.c例程

rkmpp 解码流程&#xff08;除 MPP_VIDEO_CodingMJPEG 之外&#xff09; 源码 输入h264码流 输出nv12文件 /** Copyright 2015 Rockchip Electronics Co. LTD** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file exce…...

怎么构造思维链数据?思维链提示工程的五大原则

我来为您翻译这篇关于思维链提示工程的文章&#xff0c;采用通俗易懂的中文表达&#xff1a; 思维链(CoT)提示工程是生成式AI(GenAI)中一种强大的方法&#xff0c;它能让模型通过逐步推理来解决复杂任务。通过构建引导模型思考过程的提示&#xff0c;思维链能提高输出的准确性…...

网络安全之-信息收集

域名收集 域名注册信息 站长之家 https://whois.chinaz.com/ whois 查询的相关网站有:中国万网域名WHOIS信息查询地址: https://whois.aliyun.com/西部数码域名WHOIS信息查询地址: https://whois.west.cn/新网域名WHOIS信息查询地址: http://whois.xinnet.com/domain/whois/in…...

JdbcTemplate基本使用

JdbcTemplate概述 它是spring框架中提供的一个对象&#xff0c;是对原始繁琐的JdbcAPI对象的简单封装。spring框架为我们提供了很多的操作模板类。例如:操作关系型数据的JdbcTemplate和MbernateTemplate&#xff0c;操作nosql数据库的RedisTemplate&#xff0c;操作消息队列的…...

pnpm 中 Next.js 模块无法找到问题解决

问题概述 项目在使用 pnpm 管理依赖时,出现了 “Cannot find module ‘next/link’ or its corresponding type declarations” 的错误。这是因为 pnpm 的软链接机制在某些情况下可能导致模块路径解析问题。 问题诊断 通过命令 pnpm list next 确认项目已安装 Next.js 15.2.…...

openEuler24.03 LTS下安装Spark

目录 安装模式介绍 下载Spark 安装Local模式 前提条件 解压安装包 简单使用 安装Standalone模式 前提条件 集群规划 解压安装包 配置Spark 配置Spark-env.sh 配置workers 分发到其他机器 启动集群 简单使用 关闭集群 安装YARN模式 前提条件 解压安装包 配…...

蓝桥杯真题——接龙序列

蓝桥杯2023年第十四届省赛真题-接龙数列 题目描述 对于一个长度为 K 的整数数列&#xff1a;A1, A2, . . . , AK&#xff0c;我们称之为接龙数列当且仅当 Ai 的首位数字恰好等于 Ai−1 的末位数字 (2 ≤ i ≤ K)。 例如 12, 23, 35, 56, 61, 11 是接龙数列&#xff1b;12, 2…...

使用 DeepSeek API 实现新闻文章地理位置检测与地图可视化

使用 DeepSeek API 实现新闻文章地理位置检测与地图可视化 | Implementing News Article Location Detection and Map Visualization with DeepSeek API 作者&#xff1a;zhutoutoutousan | Author: zhutoutoutousan 发布时间&#xff1a;2025-04-08 | Published: 2025-04-08 标…...

如何精准控制大模型的推理深度

论文标题 ThinkEdit: Interpretable Weight Editing to Mitigate Overly Short Thinking in Reasoning Models 论文地址 https://arxiv.org/pdf/2503.22048 代码地址 https://github.com/Trustworthy-ML-Lab/ThinkEdit 作者背景 加州大学圣迭戈分校 动机 链式推理能显…...

【力扣hot100题】(078)跳跃游戏Ⅱ

好难啊&#xff0c;我愿称之为跳崖游戏。 依旧用了两种方法&#xff0c;一种是我一开始想到的&#xff0c;一种是看答案学会的。 我自己用的方法是动态规划&#xff0c;维护一个数组记录到该位置的最少步长&#xff0c;每遍历到一个位置就嵌套循环遍历这个位置能到达的位置&a…...

Leetcode 34.在排序数组中查找元素的第一个和最后一个位置

题目描述 给你一个按照非递减顺序排列的整数数组 nums&#xff0c;和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。 如果数组中不存在目标值 target&#xff0c;返回 [-1, -1]。 你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。 考察二…...

LangChain入门指南:调用DeepSeek api

文章目录 1. 什么是LangChain&#xff1f;2. 核心组件3. 为什么选择LangChain&#xff1f;4. 实战案例安装简单chat案例流式交互Prompt模板 5. 简单总结 1. 什么是LangChain&#xff1f; 定义&#xff1a;LangChain是一个用于构建大语言模型&#xff08;LLM&#xff09;应用的…...

WES与WGS数据线粒体DNA数据分析及检测工具

1. 线粒体DNA的异质性 传统的全外显子组测序&#xff08;WES&#xff09;和全基因组测序&#xff08;WGS&#xff09;的二代测序&#xff08;SGS&#xff09; 数据分析流程&#xff0c;能够识别多种类型的基因改变。但大多数用于基因变异分析和注释的工具&#xff0c;在输出文…...

word表格间隔设置

1.怎么解决word表格间隔达不到我们想要的要求 其实很简单, 我们直接在word表格里面, 全选表格中里面的内容。接着,我们选择自动调整---->根据内容自动调整表格,即可达到我们想要的要求...

SpringBoot 接口限流Lua脚本接合Redis 服务熔断 自定义注解 接口保护

介绍 Spring Boot 接口限流是防止接口被频繁请求而导致服务器负载过重或服务崩溃的一种策略。通过限流&#xff0c;我们可以控制单位时间内允许的请求次数&#xff0c;确保系统的稳定性。限流可以帮助防止恶意请求、保护系统资源&#xff0c;并优化 API 的可用性&#xff0c;避…...

设计模式 --- 观察者模式

设计模式 --- 观察者模式 什么是观察者模式观察者模式典型应用 --- C#中的事件使用观察者模式实现事件处理机制 什么是观察者模式 观察者模式&#xff08;Observer Pattern&#xff09;是一种行为型设计模式&#xff0c;用于在对象之间建立一对多的依赖关系。当一个对象&#x…...

电商核心指标解析与行业趋势:数据驱动的增长策略【大模型总结】

电商核心指标解析与行业趋势&#xff1a;数据驱动的增长策略 在电商领域&#xff0c;数据是决策的核心。从流量监测到用户行为分析&#xff0c;从价格策略到技术赋能&#xff0c;每一个环节的优化都离不开对核心指标的深度理解。本文结合行业最新趋势与头部平台实践&#xff0…...

I/O进程4

day4 九、信号灯集 1.概念 信号灯(semaphore)&#xff0c;也叫信号量。它是不同进程间或一个给定进程内部不同线程间同步的机制&#xff1b;System V的信号灯是一个或者多个信号灯的一个集合。其中的每一个都是单独的计数信号灯。 通过信号灯集实现共享内存的同步操作。 2.编程…...

【语法】C++的list

目录 为什么会有list&#xff1f; 迭代器失效&#xff1a; list和vector的迭代器不同的地方&#xff1a; list的大部分用法和vector都很像&#xff0c;例如push_back&#xff0c;构造&#xff0c;析构&#xff0c;赋值重载这些就不再废话了&#xff0c;本篇主要讲的是和vecto…...

【算法笔记】并查集详解

&#x1f680; 并查集&#xff08;Union-Find&#xff09;详解&#xff1a;原理、实现与优化 并查集&#xff08;Union-Find&#xff09;是一种非常高效的数据结构&#xff0c;用于处理动态连通性问题&#xff0c;即判断若干个元素是否属于同一个集合&#xff0c;并支持集合合…...

【Ai/Agent】Windows11中安装CrewAI过程中的错误解决记录

CrewAi是什么&#xff0c;可以看之下之前写的 《初识CrewAI多智能代理团队协框架》 (注&#xff1a;这篇是基于linux系统下安装实践的) 基于以下记录解决问题后&#xff0c;可以再回到之前的文章继续进行CrewAI的安装 遇到问题 在windows系统中安装 CrewAi 不管是使用 pip 或者…...

OSPF的数据报文格式【复习篇】

OSPF协议是跨层封装的协议&#xff08;跨四层封装&#xff09;&#xff0c;直接将应用层的数据封装在网络层协议之后&#xff0c;IP协议包中协议号字段对应的数值为89 OSPF的头部信息&#xff1a; 所有的数据共有的信息字段 字段名描述版本当前OSPF进程使用的版本&#xff08;…...

[leetcode]查询区间内的所有素数

一.暴力求解 #include<iostream> #include<vector> using namespace std; vector<int> result; bool isPrime(int i) { if (i < 2) return false; for (int j 2;j * j < i;j) { if (i % j 0) { …...

【力扣刷题实战】Z字形变换

大家好&#xff0c;我是小卡皮巴拉 文章目录 目录 力扣题目&#xff1a;Z字形变换 题目描述 解题思路 问题理解 算法选择 具体思路 解题要点 完整代码&#xff08;C&#xff09; 兄弟们共勉 &#xff01;&#xff01;&#xff01; 每篇前言 博客主页&#xff1a;小卡…...

【RK3588 嵌入式图形编程】-SDL2-扫雷游戏-添加地雷到网格

添加地雷到网格 文章目录 添加地雷到网格1、概述2、更新Globals.h3、在随机单元格中放置地雷4、更新单元格以接收地雷5、渲染地雷图像6、开发助手7、完整代码8、总结在本文中,我们将更新游戏以在网格中随机放置地雷,并在单元格被清除时渲染它们。 1、概述 在我们扫雷游戏教程…...

Fortran 中读取 MATLAB 生成的数据文件

在 Fortran 中读取 MATLAB 生成的数据文件&#xff0c;可以通过以下几种方法实现&#xff0c;包括使用开源工具和手动解析&#xff1a; 1. 使用开源工具&#xff1a;MATFOR MATFOR 是一个商业/开源混合工具&#xff08;部分功能免费&#xff09;&#xff0c;提供 Fortran 与 M…...

Kubernetes 入门篇之网络插件 calico 部署与安装

在运行kubeadm init 和 join 命令部署好master和node节点后&#xff0c;kubectl get nodes 看到节点都是NotReady状态&#xff0c;这是因为没有安装CNI网络插件。 kubectl get nodes NAME STATUS ROLES AGE VERSION k8s-master Not…...

力扣题解:142. 环形链表 II

在链表学习中&#xff0c;我们已经了解了单链表和双链表&#xff0c;两者的最后一个结点都会指向NULL&#xff1b;今天我们介绍的循环列表则不同&#xff0c;其末尾结点指向的这是链表中的一个结点。 循环链表是一种特殊类型的链表&#xff0c;其尾节点的指针指向头节点&#…...

latex模板文件

LaTeX 是一款广泛应用于学术领域的​​文档排版系统​​&#xff0c;尤其以其在数学公式、科学符号和复杂技术文档排版中的强大能力著称。虽然它本身并非专门的“数学软件”&#xff0c;但在处理数学相关内容时表现尤为出色。 1. LaTeX 的核心特点​ 数学公式支持​​&#xff…...

BLE 协议栈事件驱动机制详解

在 BlueNRG-LP 等 BLE 系统中,事件驱动是控制状态转移、数据交互和外设协作的基础。本文将深入讲解 BLE 协议栈中事件的来源、分发流程、处理结构与实际工程实践策略,帮助你构建稳定、可维护的 BLE 系统。 📦 一、BLE 事件的来源分类 BLE 协议栈中的事件严格来自协议栈本身…...