Initial commit.

This commit is contained in:
luocai
2024-03-12 14:46:37 +08:00
commit a66b965087
95 changed files with 39764 additions and 0 deletions

637
3rdparty/rw_mpp/include/rw_mpp_api.h vendored Normal file
View File

@ -0,0 +1,637 @@
/*
* 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__ */

BIN
3rdparty/rw_mpp/lib/librw_mpp.so vendored Normal file

Binary file not shown.