提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
经过测试,使用rtsp+mpp+rga取流1920*1080图像一帧耗时60ms左右,基本可满足要求
一、mpp解码
void decoder_routine(QImage &img,bool &bOK)
{
int ret;
RK_U32 pkt_done = 0;
// write data to packet
mpp_packet_write(packet, 0, packet_buffer, packet_wpos);
// reset pos and set valid length
mpp_packet_set_pos(packet, packet_buffer);
mpp_packet_set_length(packet, packet_wpos);
// printf("packet_wpos = :%d\n",packet_wpos);
packet_wpos = 0;
// setup eos flag
if (pkt_eos)
mpp_packet_set_eos(packet);
do {
RK_S32 times = 5;
// send the packet first if packet is not done
if (!pkt_done)
{
ret = mpi->decode_put_packet(ctx, packet);
if (MPP_OK == ret)
pkt_done = 1;
}
// then get all available frame and release
do {
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--;
msleep(MPP_H264_DECODE_TIMEOUT);
goto try_again;
}
mpp_err("decode_get_frame failed too much time\n");
}
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);
mpp_log("decode_get_frame get info changed found\n");
mpp_log("decoder require buffer w:h [%d:%d] stride [%d:%d]\n",
width, height, hor_stride, ver_stride);
ret = mpp_buffer_group_get_internal(&frm_grp,MPP_BUFFER_TYPE_DRM);
if (ret) {
mpp_err("get mpp buffer group failed ret %d\n", ret);
break;
}
mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, frm_grp);
mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
} else {
RK_U32 err_info = mpp_frame_get_errinfo(frame) | mpp_frame_get_discard(frame);
if (err_info) {
frame_err++;
mpp_log("decoder_get_frame get err info:%d discard:%d.\n",
mpp_frame_get_errinfo(frame), mpp_frame_get_discard(frame));
}
else
{
/** Got a frame */
timeval start,end;
gettimeofday(&start,NULL);
frame_out(img);
bOK = true;
gettimeofday(&end,NULL);
float use_time = 1000*(end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec)/1000;
qDebug() << "rgacvt use time ="<< use_time;
static timeval last,now;
gettimeofday(&now,NULL);
float t = 1000*(now.tv_sec - last.tv_sec) + (now.tv_usec - last.tv_usec)/1000;
printf("*******time******:%f\n",t);
last = now;
}
}
frm_eos = mpp_frame_get_eos(frame);
mpp_frame_deinit(&frame);
frame = NULL;
get_frm = 1;
}
// if last packet is send but last frame is not found continue
if (pkt_eos && pkt_done && !frm_eos) {
msleep(MPP_H264_DECODE_TIMEOUT);
qDebug() << "continue";
continue;
}
if (frm_eos) {
mpp_log("found last frame\n");
break;
}
if (!get_frm)
break;
} while (1);
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 .
*/
msleep(MPP_H264_DECODE_TIMEOUT);
} while (1);
}
void frame_out()
{
// MppFrameFormat fmt = mpp_frame_get_fmt(frame);
MppBuffer buff = mpp_frame_get_buffer(frame);
// size_t size = mpp_frame_get_buf_size(frame);
RK_U32 h = mpp_frame_get_height(frame);
RK_U32 w = mpp_frame_get_width(frame);
FrameData *framedata = convertdata((char*)mpp_buffer_get_ptr(buff),w,h);
if(framedata->data == nullptr)
{
qDebug() << "frame->data = null";
return;
}
}
二、rga转换
char *dst_buf = nullptr;
char *dst_output_buf = nullptr;
char *dst_resize_output_buf = nullptr;
// read frame
struct FrameData *convertdata(char *srcdata,int width, int height)
{
FrameData * data = new FrameData();
// rga
rga_buffer_t src;
rga_buffer_t dst;
rga_buffer_t dst_output;
rga_buffer_t dst_resize_output;
try {
// h264 16bit 1920 * 1080 == 1920 * 1088
int size = 1920 * 1088* 1.5;
printf("size = %d",size);
if (size == 3133440 || size == 4177920 )
{
src = wrapbuffer_virtualaddr(srcdata, 1920, 1088, RK_FORMAT_YCrCb_420_SP);
if (dst_buf == NULL)
{
dst_buf = (char*)malloc(1920*1088*get_bpp_from_format(DST_FORMAT));
}
dst = wrapbuffer_virtualaddr(dst_buf, 1920, 1088, DST_FORMAT);
if (dst_output_buf == NULL)
{
dst_output_buf = (char*)malloc(1920*1080*get_bpp_from_format(DST_FORMAT));
}
dst_output = wrapbuffer_virtualaddr(dst_output_buf, 1920, 1080, DST_FORMAT);
if (dst_resize_output_buf == NULL)
{
dst_resize_output_buf = (char*)malloc(width*height*get_bpp_from_format(DST_FORMAT));
}
dst_resize_output = wrapbuffer_virtualaddr(dst_resize_output_buf, width, height, DST_FORMAT);
if(src.width == 0 || dst.width == 0 || dst_output.width == 0)
{
printf("%s, %s\n", __FUNCTION__, imStrError());
// return data;
}
else
{
imcvtcolor(src, dst, src.format, dst.format);
im_rect src_rect = {0, 0, 1920, 1080};
imcrop(dst,dst_output,src_rect);
imresize(dst_output,dst_resize_output);
data->width = width;
data->height = height;
data->data = dst_resize_output_buf;
data->size = width*height*get_bpp_from_format(DST_FORMAT);
}
}
}
catch (...)
{
data->isRun = STATUS_DISCONNECT;
data->size = 0;
return data;
}
return data;
}