PassengerStatistics/3rdparty/rw_mpp/include/rw_mpp_api.h
2024-03-12 14:46:37 +08:00

638 lines
19 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright(C) 2023 Reconova Information Technologies Co., Ltd.
* All rights reserved.
*
* Hi3516DV500收流封装。
*
* Created by Cyberman Wu on Sep 28th, 2023.
*
*/
#ifndef __RW_MPP_API_H__
#define __RW_MPP_API_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
///////////////////////////////////////////////////////////////////////////////
// 编码相关的一些数据结构 //
///////////////////////////////////////////////////////////////////////////////
#define NR__VENC_CHN 4
typedef
enum VENC_CODEC_type
{
CODEC_H264 = 0,
CODEC_H265 = 1,
CODEC_MJPEG = 2
} VENC_CODEC_t;
typedef
enum VENC_PROFILE
{
H264_baseline = 0,
H264_main = 1,
H264_high = 2,
H265_main = 0,
MJPEG_baseline = 0
} VENC_PROFILE_t;
typedef
enum VENC_RC
{
RC_FIXQP = 0,
RC_VBR = 1,
} VENC_RC_t;
/*
* 最早我们只需要支持H.264/H.265编码,所以数据结构都是根据这两个定的,
* 现在支持MJPEG之后我们还是用这个数据结构不过图像质量只取IQp并且
* 取决范围为[1, 99]。
*
* ***注意H.264/H.265的质量参数是值越小图像质量越好而MJPEG则是值
* 越大图像质量越好。
*/
typedef
struct venc_rc_fixQp
{
int IQp; /* RW; Range:[0, 51]; qp of the I frame (H.264/H.265) */
/* RW; Range:[1, 99]; image quality. (MJPEG) */
int PQp; /* RW; Range:[0, 51]; qp of the P frame (H.264/H.265) */
int BQp; /* RW; Range:[0, 51]; qp of the B frame (H.264/H.265) */
} S_venc_rc_fixQp;
/*
* 最早我们只需要支持H.264/H.265编码,所以数据结构都是根据这两个定的,
* 现在支持MJPEG之后我们还是用这个数据结构不过图像质量只取minIQp/maxIQp
* 并且取决范围为[1, 99]。
*
* ***注意H.264/H.265的质量参数是值越小图像质量越好而MJPEG则是值
* 越大图像质量越好。
*/
typedef
struct venc_rc_vbr
{
// max_bitrate单位是Kbps。
int max_bitrate; /* RW; Range:[2, (160 * 1024)]编码器输出最大码率单位是kbps。 */
int stats_time; /* RW; Range:[1, 60],单位是秒。 */
// 这些高级属性不再支持配置。
#if 0
// 下面的参数在海思里面是单独配置的,可以不配置而使用系统
// 缺省值或者是根据码流以及图像大小、帧率自动计算的。int src_img_spec, int dst_img_spec
// 如果全部设置为-1表示使用缺省缺省值不自己进行配置。
int minIQp; /* RW; Range:[0, 51]; the min I qp (H.264/H.265) */
/* RW; Range:[1, 99]; min image quality allowed (MJPEG)*/
int maxIQp; /* RW; Range:(MinIQp, 51]; the max I qp (H.264/H.265) */
/* RW; Range:[MinIQp, 99]; max image quailty allowed (MJPEG) */
int minQp; /* RW; Range:[0, 51]; the min P B qp (H.264/H.265) */
int maxQp; /* RW; Range:(MinQp, 51]; the max P B qp (H.264/H.265) */
#endif
} S_venc_rc_vbr;
typedef
struct venc_config
{
/*
* 编码器属性
*/
// H.264 or H.265 or MJPEG
VENC_CODEC_t codec;
VENC_PROFILE_t profile;
// 输入图像不严格要求,但限制它的最大值有助于节省存储,通常我们直接设置为进入
// 图像的分辨率。
int raw_max_width;
int raw_max_height;
// 编码输出的图像大小。
int width;
int height;
/* Group of Picture
* 严格来说H.264/H.265的GOP除了帧间隔之前还有其它一些属性至少海思的是这样的
* 不过我们不留这些配置了,只配置关键帧的间隔。
* 在海思平台上这个值实际上是在每种RC类型的配置里面而GOP则是配置了其它一些
* 属性。
*/
// 关键帧间隔。对MJPEG编码无意义。
int gop;
/*
* 码率控制属性
* rate control
* 在海思的平台上,这一块相关的控制分在两个部分,分别在不同的接口中使用,输出
* 帧率虽然每个都支持,但出现在每个类型的配置中;源帧率也可配置,但这个配置会
* 导致一些奇怪的问题所以我们自动内部使用发送给VENC的帧率。
* 这两部分,有一部分还不是所有的类型有,用起来比较麻烦,我们统一到一个接口。
*/
VENC_RC_t rc_type;
// 编码输出的帧率。
int framerate;
// 这个是指向一个S_venc_rc_fixQp或者S_venc_rc_vbr的结构根据前面的
// rc_type来确定。如果这个指针为NULL表示使用库里面的缺省配置。
void *rc_param;
} S_venc_config;
/*
* 编码帧
*/
typedef
struct mpp_venc_frame
{
uint8_t *data;
uint32_t len;
int is_key_frame;
void *priv;
} S_mpp_venc_frame;
///////////////////////////////////////////////////////////////////////////////
// 编码相关的一些数据结构 //
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// 解码相关的一些数据结构 //
///////////////////////////////////////////////////////////////////////////////
#define NR__VDEC_CHN 4
/*
* 两种发送模式。配置为FRAME模式每次发送要求是一个完整的编码帧而STREAM
* 模式则直接一直发送即可,应用中可以不去解析帧结构。
*
* 注意: FRAME模式输出的解码图像帧的PTS保留了发送时的PTS而STREAM模式固定
* 是0这个是海思的MPP导致的。不过目前我们解码基本上只用于验证算法
* 所以PTS影响不大。
*/
#define VDEC_SEND__FRAME 0
#define VDEC_SEND__STREAM 1
typedef
struct vdec_config
{
// H.264 or H.265 or MJPEG
VENC_CODEC_t codec;
// 编码图像的大小。
int raw_max_width;
int raw_max_height;
// 输出图像大小。
int width;
int height;
int send_mode;
} S_vdec_config;
typedef
struct mpp_vdec_frame
{
uint8_t *data;
uint32_t len;
// 如果输出一个非0值发送接口就使用这里输入的值如果输出0则发送接口
// 内部自动生成一个PTS对于STREAM模式PTS无效
uint64_t pts;
} S_mpp_vdec_frame;
///////////////////////////////////////////////////////////////////////////////
// 解码相关的一些数据结构 //
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// JPEG相关的一些数据结构 //
///////////////////////////////////////////////////////////////////////////////
/*
* JPEG图像
*/
typedef
struct jpeg_img
{
uint8_t *data;
int size;
} S_jpeg_img;
///////////////////////////////////////////////////////////////////////////////
// JPEG相关的一些数据结构 //
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// 收流相关的一些数据结构 //
///////////////////////////////////////////////////////////////////////////////
#define NR__VIDEO_CHN 1
#define PIX_FMT__NV21 0
#define PIX_FMT__GRAY 1
/*
* 海思平台上图像均采用NV12YVU420SP所以这里不设置图像格式参数。
*/
typedef
struct mpp_img
{
// 我们同时传物理地址,这样如果能直接使用物理地址就可以少一此处理,
// 而不能使用物理地址就忽略它。
uint64_t phy_addr;
// 数据格式有可能是NV21或GRAY具体由后面的pix_fmt来确定。对于灰度
// 也确保了指向的空间大小是NV21只是灰度数据后面是随机数据。
// 这个实际上比较理想的是直接在收流部分把它封装掉,但因为这个项目
// 追求极致性能,而有些算法能直接用灰度处理,所以这里只保留空间和
// 给出图像格式具体是否需要用memset()来处理后面VU部分由实际应用sample_vio_sys_init
// 根据算法来确定。
union
{
uint8_t *nv21;
uint8_t *gray;
};
int width;
int height;
// 图像一行的实际长度如果不等于width说明有padding。这个是图像处理中
// 常用的手段。
int linesize;
int pix_fmt;
// 这个或者增加接口通过priv来获取也可以但使用起来不太方便。严格来说
// 在图像信息中增加这个时间信息有些怪异,不过目前我们先这样用起来。
uint64_t pts;
void *priv;
} S_mpp_img;
typedef
struct video_cfg
{
// 这两个配置sensor的属性配置为-1表示使用缺省值如果有多种属性可以
// 选择的话就配置为最相近的。
// 具体内部的旋转等,我们具体的产品上做不同实现,目前在这个库中封装死。
int sns_w;
int sns_h;
// 输出图像大小。
int img_w;
int img_h;
} S_video_cfg;
///////////////////////////////////////////////////////////////////////////////
// 收流相关的一些数据结构 //
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// 缩放相关的一些数据结构 //
///////////////////////////////////////////////////////////////////////////////
#define NR__VSCALE_CHN 4
typedef
struct vscale_cfg
{
int src_max_width;
int src_max_height;
int width;
int height;
} S_vscale_cfg;
///////////////////////////////////////////////////////////////////////////////
// 缩放相关的一些数据结构 //
///////////////////////////////////////////////////////////////////////////////
/*
* 初始化平台的MPP功能分配内存。
* 或者增加一个VB配置的参数可以由外部来做一些控制不过这部分目前还没有完成
* 摸透具体什么样的buffer参数还没太想明白。也可以考虑用做一个缺省初始化
* 后面同时又实现另一个带参数的初始化?
*
* 参数说明:
* 无。
*
* 返回值:
* 成功返回0失败返回错误码。
*
*/
int rw_mpp__init(void);
/*
* 结束收流,释放相关的资源。
*
* 参数说明:
* 无。()获取到的视频图像,
*
* 返回值:
* 成功返回0失败返回错误码。
*
*/
int rw_mpp__finalize(void);
/*
* 配置调试级别。0只打印错误信息值越大测试信息越多。初始化之后
* 缺省是0。
*
* 参数说明:
* level - 调试级别。
*
* 返回值:
* 成功返回0失败返回错误码。
*
*/
int rw_mpp__set_debug(int level);
/*
* 打开一路视频。
*
* 参数说明:
* vid - 视频编号。取值范围[0, NR__VIDEO_CHN]。
* vcfg - 视频配置。
*
* 返回值:
* 成功返回0失败返回错误码。
*
*/
int rw_mpp__video_start(int vid, S_video_cfg *vcfg);
/*
* 关闭一路视频。
*
* 参数说明:
* vid - 视频编号。取值范围[0, NR__VIDEO_CHN]。
*
* 返回值:
* 成功返回0失败返回错误码。
*
*/
int rw_mpp__video_stop(int vid);
/*
* 对于创建的不用回调的一种视频主动获取一帧视频。这个获取的帧必须调用rw_mpp_free()
* 释放之后才会再次调用获取下一帧,否则获取帧会直接返回失败。
*
* 参数说明:
* vid - 视频编号。取值范围[0, NR__VIDEO_CHN]。
* ori_img - [输出]原始图像。这个是直接旋转好的图像。
* tmout_ms - 最大等待时间单位是ms。
*
* 返回值:
* 成功返回0失败返回错误码。
*
*/
int rw_mpp__video_recv(int vid, S_mpp_img *img, int tmout_ms);
/*
* 释放rw_mpp_recv获取的帧参数使用rw_mpp_recv()的输出。
*
* 参数说明:
* vid - 视频编号。取值范围[0, NR__VIDEO_CHN]。
* img - 视频图像。
*
* 返回值:
* 成功返回0失败返回错误码。
*
*/
int rw_mpp__video_free(int vid, S_mpp_img *img);
/*
* 打开一路视频图像缩放。注意目前只能缩小,不能放大。
*
* 参数说明:
* sid - 缩放通道编号,取值范围[0, NR__SCALER_CHN)。
* cfg - 缩放通道配置。
*
* 返回值:
* 0表示成功小于0表示失败。
*/
int rw_mpp__vscale_start(int sid, S_vscale_cfg *cfg);
/*
* 打开一路视频图像缩放。
*
* 参数说明:
* sid - 缩放通道编号,取值范围[0, NR__SCALER_CHN)。
*
* 返回值:
* 0表示成功小于0表示失败。
*/
int rw_mpp__vscale_stop(int sid);
/*
* 执行图像缩放,获取缩放后的图像。
*
* 参数说明:
* sid - 缩放通道编号,取值范围[0, NR__SCALER_CHN)。
* src_img - 原始图像。
* scaled_img - 缩放后的图像。会分配底层资源,需要用户及时释放。
*
* 返回值:
* 0表示成功小于0表示失败。
*/
int rw_mpp__vscale_exec(int sid, S_mpp_img *src_img, S_mpp_img *scaled_img);
/*
* 执行图像缩放,获取缩放后的图像。
*
* 参数说明:
* sid - 缩放通道编号,取值范围[0, NR__SCALER_CHN)。
* scaled_img - 缩放后的图像。
*
*
* 返回值:
* 0表示成功小于0表示失败。
*/
int rw_mpp__vscale_free(int sid, S_mpp_img *scaled_img);
/*
* 打开一路视频编码。
*
* 参数说明:
* chn - 编码通道,取值范围[0, NR__VENC_CHN)。
* cfg - 编码配置。
* vid - 是否绑定video传-1的话需要每次调用rw_mpp_vend_send()
* 发送一帧编码一帧;而传入视频通道则自动绑定获取数据,
* 用户直接接收编码帧。
*
* 返回值:
* 成功返回0失败返回错误码。
*
*/
int rw_mpp__venc_start(int chn, S_venc_config *cfg, int vid);
/*
* 关闭一路视频编码。
*
* 参数说明:
* chn - 编码通道,取值范围[0, NR__VENC_CHN)。
*
* 返回值:
* 成功返回0失败返回错误码。
*
*/
int rw_mpp__venc_stop(int chn);
/*
* 发送一帧数据做编码。如果编码通道绑定了vid发送会失败。这个没有封装为直接获取
* 编码后的数据这样更灵活一些对于绑定了vid的视频编码直接一直调用
* rw_mpp_venc_recv()收帧即可。
*
* 参数说明:
* chn - 编码通道,取值范围[0, 4)。
* img - rw_mpp__video_recv()获取到的视频图像,只能修改图像内容,
* 不能修改其它值。
*/
int rw_mpp__venc_send(int chn, S_mpp_img *img);
/*
* 接收一帧编码后的数据结果。编码没有设计是直接给原始帧编码出一帧来,分开有时候
* 更灵活一些。
* 参数说明:
* chn - 编码通道,取值范围[0, 4)。
* frame - 编码后的视频帧。对于H.264/H.265是NAL格式对于MJPEG是
* JPEG图像数据。
*/
int rw_mpp__venc_recv(int chn, S_mpp_venc_frame *frame, int tmout_ms);
/*
* 释放rw_mpp__venc_recv()获取到的编码帧。
*/
int rw_mpp__venc_free(int chn, S_mpp_venc_frame *frame);
/*
* 初始化编码器的整体配置。编码器不能使用公共VB所以需要单独初始化一下。
*/
int rw_mpp__vdec_init(void);
/*
* 反初始化编码器的整体配置。
*/
int rw_mpp__vdec_finalize(void);
/*
* 打开一路视频解码。
*
* 参数说明:
* chn - 解码通道,取值范围[0, NR__VDEC_CHN)。
* cfg - 编码配置。
*
* 返回值:
* 成功返回0失败返回错误码。
*
*/
int rw_mpp__vdec_start(int chn, S_vdec_config *cfg);
/*
* 关闭一路视频解码。
*
* 参数说明:
* chn - 解码通道,取值范围[0, NR__VDEC_CHN)。
*
* 返回值:
* 成功返回0失败返回错误码。
*
*/
int rw_mpp__vdec_stop(int chn);
/*
* 发送一帧数据做解码。
*
* 参数说明:
* chn - 解码通道,取值范围[0, NR__VDEC_CHN)。
* frame - 编码后的图像帧。
*/
int rw_mpp__vdec_send(int chn, S_mpp_vdec_frame *frame);
/*
* 发送结束。因为解码一般是用文件,有可能多个文件顺序解码,或者同一个文件循环
* 解码。为了避免前后数据混到一起用,所以发送完一个文件之后调用这个接口发送结
* 束通知解码器。
*/
int rw_mpp__vdec_send_end(int chn);
/*
* 接收一帧解码后的数据图像。
* 参数说明:
* chn - 解码通道,取值范围[0, NR__VDEC_CHN)。
* img - 编码后的视频图像。
*/
int rw_mpp__vdec_recv(int chn, S_mpp_img *img, int tmout_ms);
/*
* 释放rw_mpp__vdec_recv()获取到的解码。
*/
int rw_mpp__vdec_free(int chn, S_mpp_img *img);
/*
* 初始化JPEG编码。
*
* 参数说明:
* max_width - 图像最大宽度。
* max_height - 图像最大高度。
*
* 返回值:
* 0表示成功小于0表示失败。
*/
int rw_mpp__jpeg_init(int max_width, int max_height);
/*
* 关闭JPEG编码。
*
* 参数说明:
* 无。
*
* 返回值:
* 0表示成功小于0表示失败。
*/
int rw_mpp__jpeg_finalize(void);
/*
* 图像编码。
*
* 参数说明:
* img - 原始图像一般是Gray或NV21。这里可以是前面vscale或者video的
* 图像也可以是用户自己构造的buffer。用户自己构造的buffer这
* 一结构中priv传NULL物理地址如果是特殊申请的连续的空间并且
* 获取到了就填写如果没有就直接填0。
* jpeg - JPEG图像。成功后输入JPEG图像的信息使用完之后需要释放。
*
* 返回值:
* 0表示成功小于0表示出错。
*/
int rw_mpp__jpeg_enc(S_mpp_img *img, int quality, S_jpeg_img *jpeg);
/*
* 释放图像编码。
*
* 参数说明:
* jpeg - 要释放的JPEG图像。
*
* 返回值:
* 0表示成功小于0表示出错。
*/
int rw_mpp__jpeg_free(S_jpeg_img *jpeg);
#ifdef __cplusplus
}
#endif
#endif /* __RW_MPP_API_H__ */