RK平台 MPP 与RGA ,解码h265绿屏,花屏解决方法
mpp 解码之后出现绿屏,花屏等现象,一般是由于h265数据对齐问题,
h264视频对齐方式为16位对齐方法。
h265视频对齐方式位256奇数对齐。
h265对齐之后的宽高可通过 MPP函数中的
reallyWidth = static_cast<int>( mpp_frame_get_hor_stride(frame));
reallyHight = static_cast<int>( mpp_frame_get_ver_stride(frame));
可将hor_stride 与 ver_stride 填入RGA 中的wrapbuffer_virtualaddr() 函数
src = wrapbuffer_virtualaddr(srcdata, reallyWidth, reallyHight, SRC_FORMAT);
dst = wrapbuffer_virtualaddr(dst_buf, srcWidth, srcHight, DST_FORMAT);
注意 上述代码中的srcWidth与srcHight是真实的宽高
此时解码出的图像有存在绿边现象。
作者用的qt,可通过Qimage 的copy函数进行拷贝,去除,也可通过rga裁剪进行去除
完整c文件如下:
mpp.c
#include "mppdecode.h"void MppDecode::slotGetSendMppSrcImg()
{srcImgSend = true;
}void MppDecode::setWidthHight(int width, int hight)
{
// initSrcHight = hight;
// initSrcWidth = width;
// while(hight%16 != 0)
// {
// hight++;
// }srcHight = hight;srcWidth = width;}size_t MppDecode::mpp_buffer_group_usage(MppBufferGroup group)
{if (nullptr == group){mpp_err_f("input invalid group %p\n", group);return MPP_BUFFER_MODE_BUTT;}MppBufferGroupImpl *p = (MppBufferGroupImpl *)group;return p->usage;
}int MppDecode::decode_simple(MppDecode::MpiDecLoopData *data, AVPacket *av_packet)
{RK_U32 pkt_done = 0;RK_U32 pkt_eos = 0;RK_U32 err_info = 0;MPP_RET ret = MPP_OK;MppCtx ctx = data->ctx;MppApi *mpi = data->mpi;MppPacket packet = nullptr;MppFrame frame = nullptr;ret = mpp_packet_init(&packet, av_packet->data, av_packet->size);if(ret < 0){return -1;}mpp_packet_set_pts(packet, av_packet->pts);//qDebug()<<"av_packet->data:"<<av_packet->data;do {RK_S32 times = 5;// send the packet first if packet is not doneif (!pkt_done) {ret = mpi->decode_put_packet(ctx, packet);if (MPP_OK == ret)pkt_done = 1;}// then get all available frame and releasedo {RK_S32 get_frm = 0;RK_U32 frm_eos = 0;try_again:ret = mpi->decode_get_frame(ctx, &frame);if (MPP_ERR_TIMEOUT == ret) {if (times > 0) {times--;mmsleep(2);goto try_again;}mpp_err("decode_get_frame failed too much time\n");}//qDebug()<< "mpp_log" <<"get MPP_OK"<<MPP_OK;if (MPP_OK != ret) {mpp_err("decode_get_frame failed ret %d\n", ret);break;}if (frame){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);qDebug()<<"mpp_log :"<<"decode_get_frame get info changed found";qDebug("mpp_log :decoder require buffer w:h [%d:%d] stride [%d:%d] buf_size %d",width, height, hor_stride, ver_stride, buf_size);ret = mpp_buffer_group_get_internal(&data->frm_grp, MPP_BUFFER_TYPE_ION);if (ret) {mpp_err("get mpp buffer group failed ret %d\n", ret);break;}mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, data->frm_grp);mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, nullptr);} else {err_info = mpp_frame_get_errinfo(frame) | mpp_frame_get_discard(frame);if (err_info) {qDebug("decoder_get_frame get err info:%d discard:%d.\n",mpp_frame_get_errinfo(frame), mpp_frame_get_discard(frame));}data->frame_count++;//qDebug("decode_get_frame get frame %d\n", data->frame_count);if (!err_info){//qDebug("no err_info");//qDebug("frame:%p",frame);MppBuffer buff = mpp_frame_get_buffer(frame);if(dst_buf == nullptr){reallyWidth = static_cast<int>( mpp_frame_get_hor_stride(frame));reallyHight = static_cast<int>( mpp_frame_get_ver_stride(frame));// //RK_U32 buf_size = mpp_frame_get_buf_size(frame);qDebug() << "srcHight"<<srcWidth<<"srcHight"<<srcHight;qDebug() << ".reallyWidth"<<reallyWidth<<".reallyHight"<<reallyHight;//dst_buf = (char*)malloc(srcWidth * srcHight * get_bpp_from_format(DST_FORMAT));dst_buf = (char*)malloc(reallyWidth * reallyHight * get_bpp_from_format(DST_FORMAT));//dstResize_buf = (char*)malloc(reallyWidth*reallyHight*get_bpp_from_format(DST_FORMAT));}convertdata((char *)mpp_buffer_get_ptr(buff),dst_buf);//convertdata((char *)mpp_buffer_get_ptr(buff),dst_buf,dstResize_buf);QImage qimg((uchar *)dst_buf,srcWidth,srcHight,QImage::Format_RGB888);if(qimg.isNull()){qDebug("空的");}
// QImage ResizeImg((uchar *)dstResize_buf,416,416,QImage::Format_RGB888);emit MySigSendMppImg(qimg.copy(0,0,2560-256,1440));//emit MySigSendMppImg(qimg.copy());// if(srcImgSend)
// {
// srcImgSend = false;
// QImage Img((uchar *)dst_buf,416,416,QImage::Format_RGB888);
// emit MySigSendMppImgSrc(Img.copy());
// }}}frm_eos = mpp_frame_get_eos(frame);mpp_frame_deinit(&frame);frame = nullptr;get_frm = 1;}// try get runtime frame memory usageif (data->frm_grp) {size_t usage = mpp_buffer_group_usage(data->frm_grp);if (usage > data->max_usage)data->max_usage = usage;}// if last packet is send but last frame is not found continueif (pkt_eos && pkt_done && !frm_eos) {mmsleep(10);continue;}if (frm_eos) {qDebug("mpp_log :found last frame\n");break;}if (data->frame_num > 0 && data->frame_count >= data->frame_num) {data->eos = 1;break;}if (get_frm)continue;break;} while (1);if (data->frame_num > 0 && data->frame_count >= data->frame_num) {data->eos = 1;qDebug("mpp_log_reach max frame number %d\n", data->frame_count);break;}if (pkt_done)break;/** why sleep here:* mpi->decode_put_packet will failed when packet in internal queue is* full,waiting the package is consumed .Usually hardware decode one* frame which resolution is 1080p needs 2 ms,so here we sleep 3ms* * is enough.*/mmsleep(3);} while (1);mpp_packet_deinit(&packet);return ret;
}int MppDecode::convertdata(char *srcdata, char *dst_buf)
{// rgaim_rect src_rect;im_rect dst_rect;rga_buffer_t src;rga_buffer_t dst;IM_STATUS STATUS;int ret = 0;memset(&src_rect, 0, sizeof(src_rect));memset(&dst_rect, 0, sizeof(dst_rect));memset(&src, 0, sizeof(src));memset(&dst, 0, sizeof(dst));//memset(dst_buf,0x00,srcWidth*srcHight*get_bpp_from_format(DST_FORMAT));src = wrapbuffer_virtualaddr(srcdata, reallyWidth, reallyHight, SRC_FORMAT);dst = wrapbuffer_virtualaddr(dst_buf, srcWidth, srcHight, DST_FORMAT);if(src.width == 0 || dst.width == 0) {printf("%s, %s\n", __FUNCTION__, imStrError());return -1;}src.format = SRC_FORMAT;dst.format = DST_FORMAT;ret = imcheck(src, dst, src_rect, dst_rect);if (IM_STATUS_NOERROR != ret) {printf("%d, check error! %s", __LINE__, imStrError((IM_STATUS)ret));return -1;}STATUS = imcvtcolor(src, dst, src.format, dst.format);//qDebug("resizing .... %s\n", imStrError(STATUS));return 0;
}int MppDecode::convertdata(char *srcdata, char *dst_buf,char *dstResize_buf)
{im_rect src_rect;im_rect dst_rect;rga_buffer_t src;rga_buffer_t dst;rga_buffer_t dstCrop;IM_STATUS STATUS;int ret = 0;memset(&src_rect, 0, sizeof(src_rect));memset(&dst_rect, 0, sizeof(dst_rect));memset(&src, 0, sizeof(src));memset(&dst, 0, sizeof(dst));memset(&dstCrop, 0, sizeof(dstCrop));//memset(dst_buf,0x00,srcWidth*srcHight*get_bpp_from_format(DST_FORMAT));src = wrapbuffer_virtualaddr(srcdata, reallyWidth, reallyHight, SRC_FORMAT);//qDebug() <<""dst = wrapbuffer_virtualaddr(dst_buf, srcWidth, srcHight, DST_FORMAT);//dstCrop = wrapbuffer_virtualaddr(dstResize_buf, srcWidth, srcHight, DST_FORMAT);if(src.width == 0 || dst.width == 0) {printf("%s, %s\n", __FUNCTION__, imStrError());return -1;}src.format = SRC_FORMAT;dst.format = DST_FORMAT;//dstCrop.format = DST_FORMAT;src_rect.x = 0;src_rect.y = 0;src_rect.width = srcWidth-256;src_rect.height = srcHight;// ret = imcheck(src, dst, src_rect, dst_rect);
// if (IM_STATUS_NOERROR != ret) {
// printf("%d, check error! %s", __LINE__, imStrError((IM_STATUS)ret));
// return -1;
// }STATUS = imcvtcolor(src, dst, src.format, dst.format);//qDebug("resizing .... %s\n", imStrError(STATUS));//STATUS = imcrop(dst,dstCrop,src_rect);//qDebug("resizing .... %s\n", imStrError(STATUS));return 0;
}
头文件如下
#ifndef MPPDECODE_H
#define MPPDECODE_H
#define MODULE_TAG "mpi_dec_test"#include <string.h>#include "utils.h"
#include "rk_mpi.h"
#include "mpp_log.h"
#include "mpp_mem.h"
#include "mpp_env.h"
#include "mpp_time.h"
#include "mpp_common.h"
#include "mpp_frame.h"
#include "mpp_buffer_impl.h"
#include "mpp_frame_impl.h"
#include <im2d.hpp>
#include <rga.h>
#include <RgaUtils.h>
#include <QPixmap>
#include <QImage>
#include <QDebug>
extern "C"
{#include <libavformat/avformat.h>
}#define SRC_FORMAT RK_FORMAT_YCbCr_420_SP#define DST_FORMAT RK_FORMAT_RGB_888
//#define SRC_WIDTH 2592
//#define SRC_HEIGHT 1944
//#define DST_WIDTH 2592
//#define DST_HEIGHT 1944
#define MPI_DEC_STREAM_SIZE (SZ_4K)
#define MPI_DEC_LOOP_COUNT 4
#define MAX_FILE_NAME_LENGTH 256
class MppDecode : public QObject
{Q_OBJECT
signals:void MySigSendMppImg(QImage img);void MySigSendMppImgSrc(QImage img);
public slots:void slotGetSendMppSrcImg();
public:void setWidthHight(int width,int hight);typedef struct{MppCtx ctx;MppApi *mpi;RK_U32 eos;char *buf;RK_U32 quiet;MppBufferGroup frm_grp;MppBufferGroup pkt_grp;MppPacket packet;size_t packet_size;MppFrame frame;FILE *fp_input;RK_S32 frame_count;RK_S32 frame_num;size_t max_usage;} MpiDecLoopData;typedef struct{char file_input[MAX_FILE_NAME_LENGTH];char file_output[MAX_FILE_NAME_LENGTH];MppCodingType type;MppFrameFormat format;RK_U32 width;RK_U32 height;RK_U32 debug;RK_U32 have_input;RK_U32 have_output;RK_U32 simple;RK_S32 timeout;RK_S32 frame_num;size_t max_usage;} MpiDecTestCmd;size_t mpp_buffer_group_usage(MppBufferGroup group);int decode_simple(MpiDecLoopData *data, AVPacket* av_packet);int convertdata(char *srcdata,char * dst_buf);int convertdata(char *srcdata,char * dstsrc_buf,char *dst_buf);char* dst_buf = nullptr;//char* dstResize_buf = nullptr;//char* dstCrop = nullptr;int cout =0;int srcWidth;int srcHight;int initSrcHight;int initSrcWidth;bool srcImgSend;int reallyWidth;int reallyHight;};#endif // MPPDECODE_H
关于h265的在mpp解码的对齐问题,作者还有许多不明白之处,欢迎评论交流
RK平台 MPP 与RGA ,解码h265绿屏,花屏解决方法相关推荐
- VM平台添加设备时提示“无效的License组件”的解决方法
VM平台添加设备时提示"无效的License组件"的解决方法 一般在添加设备时系统提示"无效的License组件"都是由于平台缺少对应的License组件导致的 ...
- ThinkBook15电脑开机出现绿屏错误代码无法使用解决方法
ThinkBook15电脑开机出现绿屏错误代码无法使用解决方法.有用户使用ThinkBook15电脑的时候,去进行了系统的升级,但是升级了系统之后,发现自己的电脑屏幕变成了绿屏的了,而且出现了一些错误 ...
- uniapp视频播放绿屏/花屏的问题
今天搞uniapp的时候发生了一个诡异的事情,有三个视频,前两个本地相册播放正常,uniapp中播放正常.第三个是本地相册播放正常,uniapp中播放有声音.进度条也正常就是绿屏,而且还花屏. 仔细检 ...
- 视频编解码 — 卡顿与花屏
目录 卡顿问题 卡顿问题出现的可能性 1.帧率不够 2.编码出码率超过实际网络带宽 3.网络本身有一定的丢包率 视频花屏 1.帧不完整 2.参考帧不完整,导致花屏 3.YUV格式问题 4.stride ...
- 如何在12315网上投诉平台把内容复制粘贴到投诉内容那里的解决方法
对于12315故意把投诉内容那里限制复制粘贴实在是很不方便.于是自己试了各种的方法,最后找到一个可行的办法,可以发出来给大家使用.免得输入半天后,登录过期或者别的问题导致提交不了,只能重新打的无耐. ...
- RK3399 Qt+RTSP+FFMPEG+MPP+RGA解码
1.首先编译FFMpeg ,源码下载地址:Download FFmpeg tar -xvf ffmpeg-4.2.2.tar.bz2 cd ffmpeg-4.2.2 ./configure \--pr ...
- 直播问题分析总结 -- 花屏绿屏
直播时有时会遇到花屏或绿屏的现象,都有那些原因会导致这种现象呢? 我梳理了部分原因: 视频直播花屏&绿屏 原因 花屏 花屏主要分为整个画面都花屏或局部花屏两种情况. 全屏花屏 正常花屏 有一种 ...
- 音视频直播开发问题分析总结 -- 花屏绿屏
直播时有时会遇到花屏或绿屏的现象,都有那些原因会导致这种现象呢? 梳理了部分原因: 视频直播花屏&绿屏 原因 花屏 花屏主要分为整个画面都花屏或局部花屏两种情况. 全屏花屏 正常花屏 本文福利 ...
- 部分华为手机解h265绿屏问题。
前言 华为荣耀某型号手机解h265绿屏,无法解码. 解 华为手机内置两个解码库,一个自己的,一个OMX.google.hevc.decoder 自己的解码绿屏 使用google的没问题,使用type方 ...
最新文章
- googleearthpro打开没有地球_人在月球上睡24小时, 相当于地球多少年? 科学家的回答出乎意料...
- mybatis调用存储过程
- 计算最小公倍数LCM
- 虚拟化平台服务器故障,Vsphere虚拟化平台故障切换
- C++基础语言知识大汇总(不断更新!!!)
- bzoj 2194: 快速傅立叶之二 FFT
- HTML&CSS:制作简易电商网站
- tftp: timeout
- 玩家浅谈MID平板电脑主流中端方案
- 1 10000以内的质数表C语言,求1万以内的质数表,有急用
- 基于龙芯CPU银河麒麟操作系统的国产半实物仿真系统ETestDEV
- linux怎么添加桌面图标,linux下添加桌面图标
- centos7系统开启ftp服务器,centos7 开启ftp服务器
- grpc原理及四种实现方式
- mysql密码认证插件_关于mysql:无法加载身份验证插件’caching_sha2_password’
- 身份证号码的严格校验(非正则)
- Android SwipeRefreshLayout GMail的下拉刷新效果
- Mac系统原生支持NTFS格式硬盘
- HR详谈求职简历筛选之道
- 文件无法上传到ftp服务器,无法上传文件到FTP服务器使用C++