【海思SS528 | VDEC】MPP媒体处理软件V5.0 | VDEC的使用总结

博客主页:https://blog.csdn.net/wkd_007
博客内容:嵌入式开发、Linux、C语言、C++、数据结构、音视频
本文内容:介绍
金句分享:你不能选择最好的,但最好的会来选择你——泰戈尔

本文未经允许,不得转发!!!

目录

  • 一、概述
  • 二、Vdec模块参数
  • 三、创建Vdec解码通道
    • ✨3.1 配置解码通道属性
    • ✨3.2 创建解码通道 hi_mpi_vdec_create_chn
    • ✨3.3 设置解码通道参数 hi_mpi_vdec_set_chn_param
    • ✨3.4 开始接收用户发送的码流 hi_mpi_vdec_start_recv_stream
  • 四、Vdec处理过程
    • ✨4.1 向视频解码通道发送码流数据 hi_mpi_vdec_send_stream
    • ✨4.2 获取视频解码通道的解码图像 hi_mpi_vdec_get_frame
  • 五、销毁解码通道
  • 六、总结


在这里插入图片描述

一、概述

上篇文章,我们学习了海思SS528的解码模块的一些基础知识,本文总结一下海思解码模块(VDEC)的使用。

使用海思的解码模块时,我们需要做下面几个步骤:

  • 1.设置Vdec模块参数;
  • 2.创建Vdec解码通道;
  • 3.通道创建成功后,可以向通道发送编码帧;
  • 4.如果解码模块没有绑定到其他模块,可以获取解码帧,手动发送到目标模块(Vpss或Vo或其他);
  • 5.使用后,可以销毁解码通道。

在这里插入图片描述

二、Vdec模块参数

Vdec模块参数的内容很少,主要有两个字段需要留意的。

  • vb_src:解码帧存VB来源
    取值范围:仅支持OT_VB_SRC_MOD、OT_VB_SRC_PRIVATE、 OT_VB_SRC_USER,默认是OT_VB_SRC_MOD
  • mini_buf_mode:码流buffer配置模式
    0:一般模式;
    1:省内存模式。

Mpp的sample:

hi_vdec_mod_param mod_param;
check_return(hi_mpi_vdec_get_mod_param(&mod_param), "vdec get mod param");
mod_param.vb_src = g_vdec_vb_src;
check_return(hi_mpi_vdec_set_mod_param(&mod_param), "vdec set mod param");

在这里插入图片描述

三、创建Vdec解码通道

本小节介绍创建Vdec通道的准备工作,以及创建过程:

  • 1.配置解码通道属性;
  • 2.创建解码通道;
  • 3.设置解码通道参数;
  • 4.开始接收用户发送的码流。

✨3.1 配置解码通道属性

typedef struct {
	ot_payload_type type;
	ot_vdec_send_mode mode;
	td_u32 pic_width;
	td_u32 pic_height;
	td_u32 stream_buf_size;
	td_u32 frame_buf_size;
	td_u32 frame_buf_cnt;
	union {
		ot_vdec_video_attr video_attr;
	};
} ot_vdec_chn_attr;

上面是解码通道的属性结构体,我们重点关注以下几个字段:

  • type:解码协议类型,主要有HI_PT_H264、HI_PT_H265、HI_PT_JPEG、HI_PT_MJPEG几个取值;
  • mode:码流发送方式,主要有
    流式发送(HI_VDEC_SEND_MODE_STREAM
    按帧发送(HI_VDEC_SEND_MODE_FRAME
    按兼容模式发送(HI_VDEC_SEND_MODE_COMPAT
  • pic_width/pic_height:通道支持的解码图像最大宽、高(以像素为单位)
  • stream_buf_size:码流缓存的大小。推荐值:一幅YUV420解码图像大小。即:宽x高x1.5

设置解码通道属性的例子:

{
    hi_pic_buf_attr buf_attr = { 0 };
    chn_attr->type = type;
    chn_attr->mode = OT_VDEC_SEND_MODE_FRAME; 	// 按帧发送
    chn_attr->pic_width = width;				// 解码图像宽高
    chn_attr->pic_height = height;
    chn_attr->stream_buf_size=width*height*1.5;	// 码流缓存的大小,推荐一幅YUV420解码图像大小。即:宽x高x1.5
    chn_attr->frame_buf_cnt = 10;				// 解码图像帧存个数,仅PrivateVB模式有效
	
    buf_attr.align = 0;
    buf_attr.height = chn_attr->pic_width;
    buf_attr.width = chn_attr->width;

    if (type == HI_PT_H264 || type == HI_PT_H265) {
        buf_attr.bit_width = HI_DATA_BIT_WIDTH_8;
        buf_attr.pixel_format = HI_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
        chn_attr->video_attr.ref_frame_num = 5;
        chn_attr->video_attr.temporal_mvp_en = 0;
        chn_attr->frame_buf_size = hi_vdec_get_pic_buf_size(chn_attr->type, &buf_attr);// 解码图像帧存buffer大小,仅PrivateVB模式有效
    } else if (type == HI_PT_JPEG || type == HI_PT_MJPEG) {
        chn_attr->mode = HI_VDEC_SEND_MODE_FRAME;
        buf_attr.bit_width = HI_DATA_BIT_WIDTH_8;
        buf_attr.pixel_format = sample_vdec->sample_vdec_picture.pixel_format;
        chn_attr->frame_buf_size = hi_vdec_get_pic_buf_size(chn_attr->type, &buf_attr);// 解码图像帧存buffer大小,仅PrivateVB模式有效
    }
    return 0;
}

✨3.2 创建解码通道 hi_mpi_vdec_create_chn

创建解码通道比较简单,只需要调用hi_mpi_vdec_create_chn函数,并指定要创建的通道号和解码通道参数即可。

hi_mpi_vdec_create_chn(chn, &chn_attr)

注意:
1.通道号不能超出最大的通道号范围;
2.属性attr不能为空,否则返回错误码OT_ERR_VDEC_NULL_PTR
3.属性attr的值不能超过解码能力集;
4.使用解码ModuleVB池方式时要在创建解码通道之前要先创建专属于VDEC的模块VB池;
5.使用解码UserVB方式时也要先创建用于解码的视频缓存VB池,且要保证VB块的大小和个数满足当前解码通道所需图像Buffer的大小和个数。
其他注意事项看文档《MPP媒体处理软件V5.0》。


✨3.3 设置解码通道参数 hi_mpi_vdec_set_chn_param

typedef struct {
	ot_payload_type type;
	td_u32 display_frame_num;
	union {
		ot_vdec_video_param video_param;
		ot_vdec_pic_param pic_param;
	};
} ot_vdec_chn_param;

首先注意区别通道属性(ot_vdec_chn_attr)和通道参数(ot_vdec_chn_param),通道参数几个需要留意的字段:

  • type:解码协议类型,主要有HI_PT_H264、HI_PT_H265、HI_PT_JPEG、HI_PT_MJPEG几个取值;
  • display_frame_num:解码缓存图像的最小帧数。取值范围: [0, 16]。默认值: 2。
  • video_param.dec_mode:解码模式。默认值:HI_VIDEO_DEC_MODE_IP;
  • video_param.compress_mode:解码图像压缩模式。
  • video_param.video_format:解码图像数据格式,SS528仅支持OT_VIDEO_FORMAT_TILE_64x16

设置通道参数例子:

{
	hi_vdec_chn_param chn_param;
	check_chn_return(hi_mpi_vdec_get_chn_param(chn, &chn_param), chn, "vdec get chn param");
	if (type == HI_PT_H264 || type == HI_PT_H265) {
		chn_param.video_param.dec_mode = HI_VIDEO_DEC_MODE_IP;		//解码模式
		chn_param.video_param.compress_mode = HI_COMPRESS_MODE_NONE;
		chn_param.video_param.video_format = HI_VIDEO_FORMAT_TILE_64x16; // SS528 只支持这个格式
	} else {
		chn_param.pic_param.pixel_format = HI_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
		chn_param.pic_param.alpha = 255;
	}
	chn_param.display_frame_num = 4; // 解码缓存图像的最小帧数
	check_chn_return(hi_mpi_vdec_set_chn_param(chn, &chn_param), chn, "vdec set chn param");
}

✨3.4 开始接收用户发送的码流 hi_mpi_vdec_start_recv_stream

创建完解码通道的最后一个步骤就是开始接收用户发送的码流,只需要在调用hi_mpi_vdec_start_recv_stream时指定解码通道就可以使该通道处于开始接收码流的状态。
看例子:

check_chn_return(hi_mpi_vdec_start_recv_stream(chn), chn, "vdec start recv stream");

注意:
1.启动接收码流之后,才能调用ss_mpi_vdec_send_stream发送码流成功;
2.启动接收码流前必须保证通道已创建,否则会返回通道未创建的错误码OT_ERR_VDEC_UNEXIST;
3.启动接收码流前必须保证已经禁止使能用户图片,否则返回该操作不允许的错误码OT_ERR_VDEC_NOT_PERM;
4.重复调用启动接收码流接口时,返回成功。


在这里插入图片描述

四、Vdec处理过程

解码通道创建完成后,用户可以向解码器发送编码帧,解码器接收正确的编码帧后,开始解码;如果绑定到其他模块如Vpss、Vo,会自动将解码帧送到目标模块处理;如果没有绑定模块,用户需要自己从解码通道取帧进行处理。下面看看常用的一些不足

✨4.1 向视频解码通道发送码流数据 hi_mpi_vdec_send_stream

向视频解码通道发送码流数据,可以需要调用函数 hi_mpi_vdec_send_stream 并指定通道和传入视频帧数据。函数原型:

hi_s32 hi_mpi_vdec_send_stream(hi_vdec_chn chn, const hi_vdec_stream *stream, hi_s32 milli_sec);

发送码流时需要按照创建解码通道时设置的发送方式进行发送。

  • 按帧发送时,调用此接口一次,必须发送完整的一帧码流,否则解码会出现错误。
  • 兼容模式发送时,一帧可以分多次接口调用,每帧码流结束时必须配置帧结束标志end_of_frame为1,否则解码会出现错误
  • 流式发送则无此限制。

按帧/兼容模式发送码流时,解码图像的时间戳等于传入参数stream结构体中的时间戳,按流发送时,解码图像的时间戳等于0

其他注意事项参考文档《MPP媒体处理软件V5.0》。


✨4.2 获取视频解码通道的解码图像 hi_mpi_vdec_get_frame

在解码器解码过程中,我们可以通过调用 hi_mpi_vdec_get_frame 函数来获取解码的数据。函数原型:

hi_s32 hi_mpi_vdec_get_frame(hi_vdec_chn chn, hi_video_frame_info *frame_info,
    hi_vdec_supplement_info *supplement,  hi_s32 milli_sec);

参数说明:

  • chn:解码通道;
  • frame_info:获取的解码图像信息。
  • supplement:获取的解码图像补充信息。如果不需要获取补充信息,可以设置为NULL
  • milli_sec:获取图像方式标志。
    -1:阻塞。
    0:非阻塞。
    正值:超时时间,没有上限值,以ms为单位

注意
1.通过ss_mpi_vdec_get_frame获取解码图像数据后,需要通过 ss_mpi_vdec_release_frame 来释放;
2.此接口支持select操作;
3.输入码流为奇数宽高分辨率的JPEG图像时,解码会对原宽高向下裁剪为2对齐。因此保存为YUV或RGB文件时,需要直接使用帧信息中的stride,不能用输出后的宽度计算stride。

其他注意事项参考文档《MPP媒体处理软件V5.0》。

在这里插入图片描述

五、销毁解码通道

解码结束后,可以销毁解码通道。销毁解码通道,需要先停止接收码流(hi_mpi_vdec_stop_recv_stream),然后再调用函数 hi_mpi_vdec_destroy_chn 进行销毁。

看例子:

hi_s32 sample_comm_vdec_stop(hi_s32 chn_num)
{
    hi_s32 i;

    for (i = 0; i < chn_num; i++) {
        check_chn_return(hi_mpi_vdec_stop_recv_stream(i), i, "vdec stop recv stream");
        check_chn_return(hi_mpi_vdec_destroy_chn(i), i, "vdec destroy chn");
    }

    return HI_SUCCESS;
}

在这里插入图片描述

六、总结

本文主要总结了使用海思Vdec模块的一些常用步骤,常用函数,供以后学习、复习。

在这里插入图片描述
如果文章有帮助的话,点赞、收藏⭐,支持一波,谢谢

你可能感兴趣的:(嵌入式开发,媒体,海思SS528,VDEC,MPP媒体处理软件V5.0,海思解码模块)