...
|
...
|
@@ -6,110 +6,206 @@ |
|
|
#include "./RTK_mmp_enc.h"
|
|
|
|
|
|
#ifdef RTK_MPP_STATUS_ON
|
|
|
#include "rockchip/mpp_packet.h"
|
|
|
#include "rockchip/rk_mpi.h"
|
|
|
#include "rockchip/mpp_env.h" //这个.h能在mpp的源码中找到
|
|
|
#include "rockchip/rk_venc_rc.h"
|
|
|
#include "rockchip/mpp_common.h" //这个.h能在mpp的源码中找到
|
|
|
|
|
|
typedef struct {
|
|
|
// 基础流上下文
|
|
|
MppCtx ctx;
|
|
|
MppApi *mpi;
|
|
|
MppCodingType type; //处理的码流类型
|
|
|
|
|
|
// 输入/输出
|
|
|
MppBufferGroup BufferGop; //数据缓冲池
|
|
|
|
|
|
MppBuffer PacketBuffer; //输出数组缓冲区
|
|
|
unsigned int Packet_data_size; //packet包的长度
|
|
|
unsigned int Packet_eos; //packet包的结束标志
|
|
|
|
|
|
MppBuffer FrameBuffer; //输入数组缓冲区
|
|
|
unsigned int Frame_data_size; //Frame包的长度
|
|
|
unsigned int Frame_eos; //Frame包的结束标志
|
|
|
|
|
|
// 资源分配参数
|
|
|
unsigned int width;
|
|
|
unsigned int height;
|
|
|
unsigned int hor_stride;
|
|
|
unsigned int ver_stride;
|
|
|
unsigned int FrameNum; //帧数
|
|
|
unsigned int IDR_gop; //i帧间隔数
|
|
|
|
|
|
// 运行时的配置
|
|
|
MppEncCfg cfg;
|
|
|
MppEncHeaderMode header_mode;
|
|
|
int header_size;
|
|
|
MppFrameFormat Input_fmt;
|
|
|
MppEncSeiMode sei_mode;
|
|
|
|
|
|
} MPP_ENC_CONFIG ;
|
|
|
|
|
|
//设置编码器参数
|
|
|
int RTK_mmp_enc_cfg(MPP_ENC_CONFIG *EncCfg)
|
|
|
|
|
|
|
|
|
T_JZsdkReturnCode RTK_mmp_enc_Init(T_rtk_mmp_enc_info *enc_info)
|
|
|
{
|
|
|
|
|
|
int ret;
|
|
|
|
|
|
enc_info->ctx = NULL;
|
|
|
enc_info->mpi = NULL;
|
|
|
|
|
|
//编解码一体的情况下用不上这里了
|
|
|
switch (enc_info->Input_fmt & MPP_FRAME_FMT_MASK)
|
|
|
{
|
|
|
case MPP_FMT_YUV420SP:
|
|
|
case MPP_FMT_YUV420P: {
|
|
|
enc_info->Frame_data_size = MPP_ALIGN(enc_info->hor_stride, 64) * MPP_ALIGN(enc_info->ver_stride, 64) * 3 / 2;
|
|
|
} break;
|
|
|
|
|
|
case MPP_FMT_YUV422_YUYV :
|
|
|
case MPP_FMT_YUV422_YVYU :
|
|
|
case MPP_FMT_YUV422_UYVY :
|
|
|
case MPP_FMT_YUV422_VYUY :
|
|
|
case MPP_FMT_YUV422P :
|
|
|
case MPP_FMT_YUV422SP :
|
|
|
case MPP_FMT_RGB444 :
|
|
|
case MPP_FMT_BGR444 :
|
|
|
case MPP_FMT_RGB555 :
|
|
|
case MPP_FMT_BGR555 :
|
|
|
case MPP_FMT_RGB565 :
|
|
|
case MPP_FMT_BGR565 : {
|
|
|
enc_info->Frame_data_size = MPP_ALIGN(enc_info->hor_stride, 64) * MPP_ALIGN(enc_info->ver_stride, 64) * 2;
|
|
|
} break;
|
|
|
|
|
|
default: {
|
|
|
enc_info->Frame_data_size = MPP_ALIGN(enc_info->hor_stride, 64) * MPP_ALIGN(enc_info->ver_stride, 64) * 4;
|
|
|
} break;
|
|
|
}
|
|
|
|
|
|
//获取h264头长度
|
|
|
if (MPP_FRAME_FMT_IS_FBC(enc_info->Input_fmt))
|
|
|
{
|
|
|
enc_info->header_size = MPP_ALIGN(MPP_ALIGN(enc_info->width, 16) * MPP_ALIGN(enc_info->height, 16) / 16, SZ_4K);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
enc_info->header_size = 0;
|
|
|
}
|
|
|
|
|
|
/***************************************************
|
|
|
*
|
|
|
* 注册输入输出数组的内存
|
|
|
*
|
|
|
* *****************************************************/
|
|
|
// 获取MPP缓冲区组,缓冲区类型为ION且可缓存
|
|
|
ret = mpp_buffer_group_get_internal(&enc_info->BufferGop, MPP_BUFFER_TYPE_ION);
|
|
|
if (ret) {
|
|
|
printf("获取MPP缓冲区组失败failed to get mpp buffer group ret %d\n", ret);
|
|
|
}
|
|
|
|
|
|
// 从缓冲区组中获取用于输入帧的缓冲区
|
|
|
ret = mpp_buffer_get(enc_info->BufferGop, &enc_info->FrameBuffer, enc_info->Frame_data_size + enc_info->header_size);
|
|
|
if (ret) {
|
|
|
printf("获取输入帧缓冲区失败failed to get buffer for input frame ret %d\n", ret);
|
|
|
}
|
|
|
|
|
|
// 从缓冲区组中获取用于输出包的缓冲区
|
|
|
ret = mpp_buffer_get(enc_info->BufferGop, &enc_info->PacketBuffer, enc_info->Frame_data_size);
|
|
|
if (ret) {
|
|
|
printf("获取输出包缓冲区失败failed to get buffer for output packet ret %d\n", ret);
|
|
|
}
|
|
|
|
|
|
// // 从缓冲区组中获取用于运动信息输出包的缓冲区
|
|
|
// ret = mpp_buffer_get(enc_info->BufferGop, &p->md_info, p->mdinfo_size);
|
|
|
// if (ret) {
|
|
|
// printf("获取运动信息输出包缓冲区失败failed to get buffer for motion info output packet ret %d\n", ret);
|
|
|
// }
|
|
|
|
|
|
//创建一个编码器
|
|
|
ret = mpp_create(&(enc_info->ctx), &enc_info->mpi);
|
|
|
if (ret != MPP_OK)
|
|
|
{
|
|
|
JZSDK_LOG_ERROR("mpp_create failed ret %d", ret);
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
printf("编码器创建完毕\n");
|
|
|
}
|
|
|
|
|
|
//设置编码超时(堵塞)
|
|
|
MppPollType timeout = MPP_POLL_BLOCK;
|
|
|
ret = enc_info->mpi->control(enc_info->ctx, MPP_SET_OUTPUT_TIMEOUT, &timeout);
|
|
|
if (ret != MPP_OK)
|
|
|
{
|
|
|
JZSDK_LOG_ERROR("编码超时设置失败 %d", ret);
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
printf("编码超时设置成功\n");
|
|
|
}
|
|
|
|
|
|
//初始化编码器
|
|
|
ret = mpp_init(enc_info->ctx, MPP_CTX_ENC, MPP_VIDEO_CodingAVC);
|
|
|
if (ret != MPP_OK)
|
|
|
{
|
|
|
JZSDK_LOG_ERROR("mpp_init failed ret %d", ret);
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
printf("编码器初始化完毕\n");
|
|
|
}
|
|
|
|
|
|
//初始化编码器配置
|
|
|
ret = mpp_enc_cfg_init(&enc_info->cfg);
|
|
|
if (ret) {
|
|
|
JZSDK_LOG_ERROR("mpp_enc_cfg_init failed ret %d", ret);
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
printf("编码器配置初始化完毕\n");
|
|
|
}
|
|
|
|
|
|
//获得基本编码器配置
|
|
|
ret = enc_info->mpi->control(enc_info->ctx, MPP_ENC_GET_CFG, enc_info->cfg);
|
|
|
if (ret) {
|
|
|
JZSDK_LOG_ERROR("get enc cfg failed ret %d", ret);
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
|
|
|
/***********************************************************************************************************************
|
|
|
*
|
|
|
*
|
|
|
* 设置编码器参数
|
|
|
*
|
|
|
*
|
|
|
************************************************************************************************************************/
|
|
|
//设置位固定码率模式
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "rc:mode", MPP_ENC_RC_MODE_CBR);
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "rc:mode", MPP_ENC_RC_MODE_CBR);
|
|
|
|
|
|
//设置码率 dji要小于8M 先填个4M 4000000
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "rc:bps_target", 4000000);
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "rc:bps_target", 4000000);
|
|
|
|
|
|
//设置输入帧率不变
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "rc:fps_in_flex", 0);
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "rc:fps_in_flex", 0);
|
|
|
|
|
|
//设置输入帧率的分子
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "rc:fps_in_num", EncCfg->FrameNum);
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "rc:fps_in_num", enc_info->FrameNum);
|
|
|
//设置输入帧率的分母
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "rc:fps_in_denorm", 1);
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "rc:fps_in_denorm", 1);
|
|
|
|
|
|
//设置输出帧率的分子
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "rc:fps_out_num", EncCfg->FrameNum);
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "rc:fps_out_num", enc_info->FrameNum);
|
|
|
//设置输出帧率的分母
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "rc:fps_out_denorm", 1);
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "rc:fps_out_denorm", 1);
|
|
|
|
|
|
//设置i帧间隔,跟随帧率 1秒1 I帧
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "rc:gop", EncCfg->IDR_gop);
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "rc:gop", enc_info->IDR_gop);
|
|
|
|
|
|
//一帧图像最大重编码次数,次数越小,重编码次数越小,越清晰
|
|
|
//这里暂不开启
|
|
|
//mpp_enc_cfg_set_s32(EncCfg->cfg, "rc:max_reenc_times", 1);
|
|
|
//mpp_enc_cfg_set_s32(enc_info->cfg, "rc:max_reenc_times", 1);
|
|
|
|
|
|
//设置输入图像的宽高
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "prep:width", EncCfg->width);
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "prep:height", EncCfg->height);
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "prep:width", enc_info->width);
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "prep:height", enc_info->height);
|
|
|
|
|
|
//垂直方向相邻两行之间的距离
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "prep:hor_stride", EncCfg->hor_stride);
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "prep:hor_stride", enc_info->hor_stride);
|
|
|
//入图像分量之间的以行数间隔数
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "prep:ver_stride", EncCfg->ver_stride);
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "prep:ver_stride", enc_info->ver_stride);
|
|
|
|
|
|
//MppFrameFormat 设置输入图像的像素格式
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "prep:format", EncCfg->Input_fmt);
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "prep:format", enc_info->Input_fmt);
|
|
|
|
|
|
//MppFrameColorSpace 设置输入图像的数据空间色彩范围, 不设置
|
|
|
//mpp_enc_cfg_set_s32(EncCfg->cfg, "prep:color", MPP_FRAME_SPC_RGB);
|
|
|
//mpp_enc_cfg_set_s32(enc_info->cfg, "prep:color", MPP_FRAME_SPC_RGB);
|
|
|
|
|
|
//MppFrameColorRange 表示输入图像是 full range 还是 limit range 不设置
|
|
|
//mpp_enc_cfg_set_s32(EncCfg->cfg, "prep:range", MPP_FRAME_RANGE_UNSPECIFIED);
|
|
|
//mpp_enc_cfg_set_s32(enc_info->cfg, "prep:range", MPP_FRAME_RANGE_UNSPECIFIED);
|
|
|
|
|
|
//MppEncRotationCfg 选择旋转方向 不旋转!
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "prep:rotation", MPP_ENC_ROT_0);
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "prep:rotation", MPP_ENC_ROT_0);
|
|
|
|
|
|
//是否镜像 0不镜像 水平镜像1 垂直镜像2
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "prep:mirroring", 0);
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "prep:mirroring", 0);
|
|
|
|
|
|
//MppCodingType 表示 MppEncCodecCfg 对应的协议类型,需要与 MppCtx初始化函数 mpp_init 的参数一致。
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "codec:type", MPP_VIDEO_CodingAVC); //h264类型
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "codec:type", MPP_VIDEO_CodingAVC); //h264类型
|
|
|
|
|
|
//h264流的码流格式类型 0 标识AnnexB 加入 00 00 00 01起始码 1 没有起始码
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "h264:stream_type", 0);
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "h264:stream_type", 0);
|
|
|
|
|
|
//h264流的表示 SPS 中的 profile_idc 参数:
|
|
|
//66 – 表示 Baseline profile。
|
|
|
//77 – 表示 Main profile。
|
|
|
//100 – 表示 High profile。
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "h264:profile", 66);
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "h264:profile", 66);
|
|
|
|
|
|
//sps档次 dji要求小于5.1 这里选4.1
|
|
|
//其中 10 表示 level 1.0:
|
...
|
...
|
@@ -118,75 +214,75 @@ int RTK_mmp_enc_cfg(MPP_ENC_CONFIG *EncCfg) |
|
|
// 30/31/32 – D1@25fps / 720p@30fps / 720p@60fps
|
|
|
// 40/41/42 – 1080p@30fps / 1080p@30fps / 1080p@60fps
|
|
|
// 50/51/52 – 4K@30fps / 4K@30fps / 4K@60fps
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "h264:level", 41);
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "h264:level", 41);
|
|
|
|
|
|
//表示编码器使用的熵编码格式: 0 CAVLC 1 CABAC cabac的精度更多,但是效率变低
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "h264:cabac_en", 1);
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "h264:cabac_en", 1);
|
|
|
|
|
|
//表示协议语法中的 cabac_init_idc,在 cabac_en 为 1 时有效,有效值为 0~2。
|
|
|
//DJI给的范围是1
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "h264:cabac_idc", 1);
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "h264:cabac_idc", 1);
|
|
|
|
|
|
//表示协议语法中的 8x8 变换使能标志。
|
|
|
//0 – 为关闭,在 Baseline/Main profile 时固定关闭。
|
|
|
//1 – 为开启,在 High profile 时可选可启。
|
|
|
mpp_enc_cfg_set_s32(EncCfg->cfg, "h264:trans8x8", 0);
|
|
|
mpp_enc_cfg_set_s32(enc_info->cfg, "h264:trans8x8", 0);
|
|
|
|
|
|
//表示协议语法中 constrained_intra_pred_mode 模式使能标志。0 – 为关闭,1 – 为开启。
|
|
|
//mpp_enc_cfg_set_s32(EncCfg->cfg, "h264:const_intra", 0);
|
|
|
//mpp_enc_cfg_set_s32(enc_info->cfg, "h264:const_intra", 0);
|
|
|
|
|
|
//表示协议语法中 scaling_list_matrix 模式 0 – 为 flat matrix,1 – 默认 matrix。
|
|
|
//mpp_enc_cfg_set_s32(EncCfg->cfg, "h264:scaling_list", 0);
|
|
|
//mpp_enc_cfg_set_s32(enc_info->cfg, "h264:scaling_list", 0);
|
|
|
|
|
|
//表示协议语法中 chroma_cb_qp_offset 值。有效范围为[-12, 12]。
|
|
|
//mpp_enc_cfg_set_s32(EncCfg->cfg, "h264:cb_qp_offset", 0);
|
|
|
//mpp_enc_cfg_set_s32(enc_info->cfg, "h264:cb_qp_offset", 0);
|
|
|
|
|
|
//表示协议语法中 chroma_cr_qp_offset 值。有效范围为[-12, 12]。
|
|
|
//mpp_enc_cfg_set_s32(EncCfg->cfg, "h264:cr_qp_offset", 0);
|
|
|
//mpp_enc_cfg_set_s32(enc_info->cfg, "h264:cr_qp_offset", 0);
|
|
|
|
|
|
//表示协议语法中 deblock_disable 标志,有效范围为[0, 2]。0 – deblocking 使能。1 – deblocking 关闭。2 – 在 slice 边界关闭 deblocking。
|
|
|
//mpp_enc_cfg_set_s32(EncCfg->cfg, "h264:dblk_disable", 0);
|
|
|
//mpp_enc_cfg_set_s32(enc_info->cfg, "h264:dblk_disable", 0);
|
|
|
|
|
|
//表示协议语法中 deblock_offset_alpha 值。有效范围为[-6, 6]。
|
|
|
//mpp_enc_cfg_set_s32(EncCfg->cfg, "h264:dblk_alpha", 0);
|
|
|
//mpp_enc_cfg_set_s32(enc_info->cfg, "h264:dblk_alpha", 0);
|
|
|
|
|
|
//表示协议语法中 deblock_dblk_beta 值。有效范围为[-6, 6]。
|
|
|
//mpp_enc_cfg_set_s32(EncCfg->cfg, "h264:dblk_beta", 0)
|
|
|
//mpp_enc_cfg_set_s32(enc_info->cfg, "h264:dblk_beta", 0)
|
|
|
|
|
|
//表示初始 QP 值,一般情况请勿配置。
|
|
|
//mpp_enc_cfg_set_s32(EncCfg->cfg, "h264:qp_init", 26);
|
|
|
//mpp_enc_cfg_set_s32(enc_info->cfg, "h264:qp_init", 26);
|
|
|
|
|
|
// 表示最大 QP 值,一般情况请勿配置。
|
|
|
// mpp_enc_cfg_set_s32(EncCfg->cfg, "h264:qp_max", 51);
|
|
|
// mpp_enc_cfg_set_s32(enc_info->cfg, "h264:qp_max", 51);
|
|
|
|
|
|
// 表示最小 QP 值,一般情况请勿配置。
|
|
|
// mpp_enc_cfg_set_s32(EncCfg->cfg, "h264:qp_min", 10);
|
|
|
// mpp_enc_cfg_set_s32(enc_info->cfg, "h264:qp_min", 10);
|
|
|
|
|
|
// 表示最大 I 帧 QP 值,一般情况请勿配置。
|
|
|
// mpp_enc_cfg_set_s32(EncCfg->cfg, "h264:qp_max_i", 51);
|
|
|
// mpp_enc_cfg_set_s32(enc_info->cfg, "h264:qp_max_i", 51);
|
|
|
|
|
|
// 表示最小 I 帧 QP 值,一般情况请勿配置。
|
|
|
// mpp_enc_cfg_set_s32(EncCfg->cfg, "h264:qp_min_i", 10);
|
|
|
// mpp_enc_cfg_set_s32(enc_info->cfg, "h264:qp_min_i", 10);
|
|
|
|
|
|
// 表示相临两帧之间的帧级 QP 变化幅度。
|
|
|
// mpp_enc_cfg_set_s32(EncCfg->cfg, "h264:qp_step", 10);
|
|
|
// mpp_enc_cfg_set_s32(enc_info->cfg, "h264:qp_step", 10);
|
|
|
|
|
|
/***** h265 的自己翻阅文档********/
|
|
|
|
|
|
//表示 JPEG 编码器使用的量化参数等级,编码器一共内置了 11 级量化系数表格,从 0 到 10,图像质量从差到好。
|
|
|
//mpp_enc_cfg_set_s32(EncCfg->cfg, "jpeg: quant", 10);
|
|
|
//mpp_enc_cfg_set_s32(enc_info->cfg, "jpeg: quant", 10);
|
|
|
|
|
|
//MppEncSplitMode 切分模式
|
|
|
//1– BY_BYTE 切分 slice 根据 slice 大小。 2– BY_CTU 切分 slice 根据宏块或 CTU 个数
|
|
|
//mpp_enc_cfg_set_s32(EncCfg->cfg, "split:mode", MPP_ENC_SPLIT_NONE);
|
|
|
//mpp_enc_cfg_set_s32(enc_info->cfg, "split:mode", MPP_ENC_SPLIT_NONE);
|
|
|
|
|
|
//切分参数 Slice 切分参数:
|
|
|
//在 BY_BYTE 模式下,参数表示每个 slice 的最大大小。
|
|
|
//在 BY_CTU 模式下,参数表示每个 slice 包含的宏块或CTU 个数。
|
|
|
//mpp_enc_cfg_set_s32(EncCfg->cfg, "split:arg", 1);
|
|
|
//mpp_enc_cfg_set_s32(enc_info->cfg, "split:arg", 1);
|
|
|
|
|
|
//将配置参数输入
|
|
|
int ret = EncCfg->mpi->control(EncCfg->ctx, MPP_ENC_SET_CFG, EncCfg->cfg);
|
|
|
ret = enc_info->mpi->control(enc_info->ctx, MPP_ENC_SET_CFG, enc_info->cfg);
|
|
|
if (ret)
|
|
|
{
|
|
|
printf("mpi control enc set cfg failed ret %d\n", ret);
|
...
|
...
|
@@ -196,8 +292,8 @@ int RTK_mmp_enc_cfg(MPP_ENC_CONFIG *EncCfg) |
|
|
//设置帧信息 (可选项)
|
|
|
RK_U32 sei_mode;
|
|
|
mpp_env_get_u32("sei_mode", &sei_mode, MPP_ENC_SEI_MODE_ONE_FRAME);
|
|
|
EncCfg->sei_mode = sei_mode;
|
|
|
ret = EncCfg->mpi->control(EncCfg->ctx, MPP_ENC_SET_SEI_CFG, &EncCfg->sei_mode);
|
|
|
enc_info->sei_mode = sei_mode;
|
|
|
ret = enc_info->mpi->control(enc_info->ctx, MPP_ENC_SET_SEI_CFG, &enc_info->sei_mode);
|
|
|
if (ret)
|
|
|
{
|
|
|
printf("mpi control enc set sei cfg failed ret %d\n", ret);
|
...
|
...
|
@@ -206,10 +302,10 @@ int RTK_mmp_enc_cfg(MPP_ENC_CONFIG *EncCfg) |
|
|
|
|
|
//设置头信息 (可选项)
|
|
|
//如果是264 或者h265 给个信息头
|
|
|
if (EncCfg->type == MPP_VIDEO_CodingAVC || EncCfg->type == MPP_VIDEO_CodingHEVC)
|
|
|
if (enc_info->encType == MPP_VIDEO_CodingAVC || enc_info->encType == MPP_VIDEO_CodingHEVC)
|
|
|
{
|
|
|
EncCfg->header_mode = MPP_ENC_HEADER_MODE_EACH_IDR;
|
|
|
ret = EncCfg->mpi->control(EncCfg->ctx, MPP_ENC_SET_HEADER_MODE, &EncCfg->header_mode);
|
|
|
enc_info->header_mode = MPP_ENC_HEADER_MODE_EACH_IDR;
|
|
|
ret = enc_info->mpi->control(enc_info->ctx, MPP_ENC_SET_HEADER_MODE, &enc_info->header_mode);
|
|
|
if (ret) {
|
|
|
printf("mpi control enc set header mode failed ret %d\n", ret);
|
|
|
return ret;
|
...
|
...
|
@@ -238,164 +334,6 @@ int RTK_mmp_enc_cfg(MPP_ENC_CONFIG *EncCfg) |
|
|
// mpp_enc_roi_init(&p->roi_ctx, p->width, p->height, p->type, 4);
|
|
|
// mpp_assert(p->roi_ctx);
|
|
|
// }
|
|
|
}
|
|
|
|
|
|
T_JZsdkReturnCode RTK_mmp_enc_Init(void **index, MppCodingType Out_video_tpye, MppFrameFormat In_format, int width, int height, int FrameNum, int IDR_gop)
|
|
|
{
|
|
|
//创建一个编码器参数
|
|
|
MPP_ENC_CONFIG *EncCfg = NULL;
|
|
|
|
|
|
//为编码器参数注册内存
|
|
|
EncCfg = (MPP_ENC_CONFIG *)malloc(sizeof(MPP_ENC_CONFIG));
|
|
|
if (EncCfg == NULL) {
|
|
|
printf("mpp编码器参数内存分配失败\n");
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
|
|
|
int ret;
|
|
|
|
|
|
EncCfg->ctx = NULL;
|
|
|
EncCfg->mpi = NULL;
|
|
|
//EncCfg->type = MPP_VIDEO_CodingAVC; //默认输出类型为h264
|
|
|
EncCfg->type = Out_video_tpye; //默认输出类型为h264
|
|
|
|
|
|
EncCfg->height = height;
|
|
|
EncCfg->width = width;
|
|
|
EncCfg->hor_stride = (MPP_ALIGN(width, 16));
|
|
|
EncCfg->ver_stride = (MPP_ALIGN(height, 16));
|
|
|
EncCfg->FrameNum = FrameNum;
|
|
|
EncCfg->IDR_gop = IDR_gop;
|
|
|
//EncCfg->Input_fmt = MPP_FMT_YUV420SP;
|
|
|
EncCfg->Input_fmt = In_format;
|
|
|
|
|
|
//编解码一体的情况下用不上这里了
|
|
|
switch (EncCfg->Input_fmt & MPP_FRAME_FMT_MASK)
|
|
|
{
|
|
|
case MPP_FMT_YUV420SP:
|
|
|
case MPP_FMT_YUV420P: {
|
|
|
EncCfg->Frame_data_size = MPP_ALIGN(EncCfg->hor_stride, 64) * MPP_ALIGN(EncCfg->ver_stride, 64) * 3 / 2;
|
|
|
} break;
|
|
|
|
|
|
case MPP_FMT_YUV422_YUYV :
|
|
|
case MPP_FMT_YUV422_YVYU :
|
|
|
case MPP_FMT_YUV422_UYVY :
|
|
|
case MPP_FMT_YUV422_VYUY :
|
|
|
case MPP_FMT_YUV422P :
|
|
|
case MPP_FMT_YUV422SP :
|
|
|
case MPP_FMT_RGB444 :
|
|
|
case MPP_FMT_BGR444 :
|
|
|
case MPP_FMT_RGB555 :
|
|
|
case MPP_FMT_BGR555 :
|
|
|
case MPP_FMT_RGB565 :
|
|
|
case MPP_FMT_BGR565 : {
|
|
|
EncCfg->Frame_data_size = MPP_ALIGN(EncCfg->hor_stride, 64) * MPP_ALIGN(EncCfg->ver_stride, 64) * 2;
|
|
|
} break;
|
|
|
|
|
|
default: {
|
|
|
EncCfg->Frame_data_size = MPP_ALIGN(EncCfg->hor_stride, 64) * MPP_ALIGN(EncCfg->ver_stride, 64) * 4;
|
|
|
} break;
|
|
|
}
|
|
|
|
|
|
//获取h264头长度
|
|
|
if (MPP_FRAME_FMT_IS_FBC(EncCfg->Input_fmt))
|
|
|
{
|
|
|
EncCfg->header_size = MPP_ALIGN(MPP_ALIGN(EncCfg->width, 16) * MPP_ALIGN(EncCfg->height, 16) / 16, SZ_4K);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
EncCfg->header_size = 0;
|
|
|
}
|
|
|
|
|
|
/***************************************************
|
|
|
*
|
|
|
* 注册输入输出数组的内存
|
|
|
*
|
|
|
* *****************************************************/
|
|
|
// 获取MPP缓冲区组,缓冲区类型为ION且可缓存
|
|
|
ret = mpp_buffer_group_get_internal(&EncCfg->BufferGop, MPP_BUFFER_TYPE_ION);
|
|
|
if (ret) {
|
|
|
printf("获取MPP缓冲区组失败failed to get mpp buffer group ret %d\n", ret);
|
|
|
}
|
|
|
|
|
|
// 从缓冲区组中获取用于输入帧的缓冲区
|
|
|
ret = mpp_buffer_get(EncCfg->BufferGop, &EncCfg->FrameBuffer, EncCfg->Frame_data_size + EncCfg->header_size);
|
|
|
if (ret) {
|
|
|
printf("获取输入帧缓冲区失败failed to get buffer for input frame ret %d\n", ret);
|
|
|
}
|
|
|
|
|
|
// 从缓冲区组中获取用于输出包的缓冲区
|
|
|
ret = mpp_buffer_get(EncCfg->BufferGop, &EncCfg->PacketBuffer, EncCfg->Frame_data_size);
|
|
|
if (ret) {
|
|
|
printf("获取输出包缓冲区失败failed to get buffer for output packet ret %d\n", ret);
|
|
|
}
|
|
|
|
|
|
// // 从缓冲区组中获取用于运动信息输出包的缓冲区
|
|
|
// ret = mpp_buffer_get(EncCfg->BufferGop, &p->md_info, p->mdinfo_size);
|
|
|
// if (ret) {
|
|
|
// printf("获取运动信息输出包缓冲区失败failed to get buffer for motion info output packet ret %d\n", ret);
|
|
|
// }
|
|
|
|
|
|
//创建一个编码器
|
|
|
ret = mpp_create(&(EncCfg->ctx), &EncCfg->mpi);
|
|
|
if (ret != MPP_OK)
|
|
|
{
|
|
|
JZSDK_LOG_ERROR("mpp_create failed ret %d", ret);
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
printf("编码器创建完毕\n");
|
|
|
}
|
|
|
|
|
|
//设置编码超时(堵塞)
|
|
|
MppPollType timeout = MPP_POLL_BLOCK;
|
|
|
ret = EncCfg->mpi->control(EncCfg->ctx, MPP_SET_OUTPUT_TIMEOUT, &timeout);
|
|
|
if (ret != MPP_OK)
|
|
|
{
|
|
|
JZSDK_LOG_ERROR("编码超时设置失败 %d", ret);
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
printf("编码超时设置成功\n");
|
|
|
}
|
|
|
|
|
|
//初始化编码器
|
|
|
ret = mpp_init(EncCfg->ctx, MPP_CTX_ENC, MPP_VIDEO_CodingAVC);
|
|
|
if (ret != MPP_OK)
|
|
|
{
|
|
|
JZSDK_LOG_ERROR("mpp_init failed ret %d", ret);
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
printf("编码器初始化完毕\n");
|
|
|
}
|
|
|
|
|
|
//初始化编码器配置
|
|
|
ret = mpp_enc_cfg_init(&EncCfg->cfg);
|
|
|
if (ret) {
|
|
|
JZSDK_LOG_ERROR("mpp_enc_cfg_init failed ret %d", ret);
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
printf("编码器配置初始化完毕\n");
|
|
|
}
|
|
|
|
|
|
//获得基本编码器配置
|
|
|
ret = EncCfg->mpi->control(EncCfg->ctx, MPP_ENC_GET_CFG, EncCfg->cfg);
|
|
|
if (ret) {
|
|
|
JZSDK_LOG_ERROR("get enc cfg failed ret %d", ret);
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
|
|
|
//设置编码器参数
|
|
|
RTK_mmp_enc_cfg(EncCfg);
|
|
|
|
|
|
|
|
|
//把编码器地址传递回去
|
|
|
*index = (void *)EncCfg;
|
|
|
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
|
|
|
}
|
...
|
...
|
@@ -420,7 +358,7 @@ T_JZsdkReturnCode RTK_mmp_enc_Init(void **index, MppCodingType Out_video_tpye, M |
|
|
// MppPacket m_packet = NULL;
|
|
|
|
|
|
// // 检查编码类型是否为AVC(H.264)或HEVC(H.265)
|
|
|
// if (EncCfg->type == MPP_VIDEO_CodingAVC || EncCfg->type == MPP_VIDEO_CodingHEVC)
|
|
|
// if (enc_info->type == MPP_VIDEO_CodingAVC || enc_info->type == MPP_VIDEO_CodingHEVC)
|
|
|
// {
|
|
|
// /*
|
|
|
// * 可以使用普通malloc分配的内存缓冲区作为输入,而不是pkt_buf。
|
...
|
...
|
@@ -428,7 +366,7 @@ T_JZsdkReturnCode RTK_mmp_enc_Init(void **index, MppCodingType Out_video_tpye, M |
|
|
// * 这里使用pkt_buf缓冲区只是为了简化演示。
|
|
|
// */
|
|
|
// // 使用pkt_buf缓冲区初始化packet
|
|
|
// mpp_packet_init_with_buffer(&m_packet, EncCfg->Packet_data);
|
|
|
// mpp_packet_init_with_buffer(&m_packet, enc_info->Packet_data);
|
|
|
// /* NOTE: It is important to clear output packet length!! */
|
|
|
// /*
|
|
|
// * 注意:清除输出数据包长度非常重要!
|
...
|
...
|
@@ -437,7 +375,7 @@ T_JZsdkReturnCode RTK_mmp_enc_Init(void **index, MppCodingType Out_video_tpye, M |
|
|
// mpp_packet_set_length(m_packet, 0);
|
|
|
|
|
|
// // 调用mpi的control函数,获取编码的头部信息(如SPS和PPS),并将其存储在packet中
|
|
|
// ret = EncCfg->mpi->control(EncCfg->ctx, MPP_ENC_GET_HDR_SYNC, m_packet);
|
|
|
// ret = enc_info->mpi->control(enc_info->ctx, MPP_ENC_GET_HDR_SYNC, m_packet);
|
|
|
// if (ret) {
|
|
|
// printf("获取h264 enc头信息失败\n");
|
|
|
// return ret;
|
...
|
...
|
@@ -464,20 +402,17 @@ T_JZsdkReturnCode RTK_mmp_enc_Init(void **index, MppCodingType Out_video_tpye, M |
|
|
// yuv420sp转h264
|
|
|
// 但是输入和输出都是mmpframe的地址
|
|
|
// 注意,输出的画面帧要记得释放内存
|
|
|
T_JZsdkReturnCode RTK_mmp_enc_yuv_to_h264_byFrame(void **index, MppFrame input_data_frame, MppPacket *out_put_frame)
|
|
|
T_JZsdkReturnCode RTK_mmp_enc_yuv_to_h264_byFrame(T_rtk_mmp_enc_info *enc_info, MppFrame input_data_frame, MppPacket *out_put_frame)
|
|
|
{
|
|
|
int ret; //返回值
|
|
|
|
|
|
//获取编码器参数
|
|
|
MPP_ENC_CONFIG *EncCfg = (MPP_ENC_CONFIG *)*index;
|
|
|
|
|
|
//获取输入的数据
|
|
|
MppFrame frame = input_data_frame;
|
|
|
|
|
|
//printf("mmp开始编码\n");
|
|
|
|
|
|
/* 将帧编码并放入编码上下文 */
|
|
|
ret = EncCfg->mpi->encode_put_frame(EncCfg->ctx, frame);
|
|
|
ret = enc_info->mpi->encode_put_frame(enc_info->ctx, frame);
|
|
|
if (ret) {
|
|
|
JZSDK_LOG_ERROR("mpp encode put frame failed");
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
...
|
...
|
@@ -486,7 +421,7 @@ T_JZsdkReturnCode RTK_mmp_enc_yuv_to_h264_byFrame(void **index, MppFrame input_d |
|
|
|
|
|
do {
|
|
|
//获取编码后的帧
|
|
|
ret = EncCfg->mpi->encode_get_packet(EncCfg->ctx, out_put_frame);
|
|
|
ret = enc_info->mpi->encode_get_packet(enc_info->ctx, out_put_frame);
|
|
|
if (ret) {
|
|
|
JZSDK_LOG_ERROR("mpp encode get packet failed");
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
...
|
...
|
@@ -496,7 +431,7 @@ T_JZsdkReturnCode RTK_mmp_enc_yuv_to_h264_byFrame(void **index, MppFrame input_d |
|
|
{
|
|
|
// write packet to file here
|
|
|
//ptr = mpp_packet_get_pos(packet);
|
|
|
//int packet_len = mpp_packet_get_length(EncCfg->Packet_data);
|
|
|
//int packet_len = mpp_packet_get_length(enc_info->Packet_data);
|
|
|
//EncConfigInput->Packet_eos = mpp_packet_get_eos(packet);
|
|
|
|
|
|
//printf("获取到编码内容 len:%d\n",packet_len);
|
...
|
...
|
@@ -509,13 +444,10 @@ T_JZsdkReturnCode RTK_mmp_enc_yuv_to_h264_byFrame(void **index, MppFrame input_d |
|
|
}
|
|
|
|
|
|
// yuv420个帧长度为 高*宽*3/2
|
|
|
T_JZsdkReturnCode RTK_mmp_enc_data_to_h264(void **index, char *in_data, int in_data_length, MppPacket *Packet)
|
|
|
T_JZsdkReturnCode RTK_mmp_enc_data_to_h264(T_rtk_mmp_enc_info *enc_info, char *in_data, int in_data_length, MppPacket *Packet)
|
|
|
{
|
|
|
int ret; //返回值
|
|
|
|
|
|
//获取编码器参数
|
|
|
MPP_ENC_CONFIG *EncCfg = (MPP_ENC_CONFIG *)*index;
|
|
|
|
|
|
MppFrame frame = NULL;
|
|
|
MppMeta meta = NULL; //元数据指针
|
|
|
|
...
|
...
|
@@ -528,27 +460,27 @@ T_JZsdkReturnCode RTK_mmp_enc_data_to_h264(void **index, char *in_data, int in_d |
|
|
|
|
|
//设置帧对象的参数
|
|
|
// 设置处理帧的宽度、高度、水平跨度、垂直跨度和格式
|
|
|
mpp_frame_set_width(frame, EncCfg->width);
|
|
|
mpp_frame_set_height(frame, EncCfg->height);
|
|
|
mpp_frame_set_hor_stride(frame, EncCfg->hor_stride);
|
|
|
mpp_frame_set_ver_stride(frame, EncCfg->ver_stride);
|
|
|
mpp_frame_set_fmt(frame, EncCfg->Input_fmt);
|
|
|
mpp_frame_set_eos(frame, EncCfg->Frame_eos); // 设置帧的结束标志
|
|
|
mpp_frame_set_width(frame, enc_info->width);
|
|
|
mpp_frame_set_height(frame, enc_info->height);
|
|
|
mpp_frame_set_hor_stride(frame, enc_info->hor_stride);
|
|
|
mpp_frame_set_ver_stride(frame, enc_info->ver_stride);
|
|
|
mpp_frame_set_fmt(frame, enc_info->Input_fmt);
|
|
|
mpp_frame_set_eos(frame, enc_info->Frame_eos); // 设置帧的结束标志
|
|
|
|
|
|
//获取帧缓冲区的指针
|
|
|
void *buf = mpp_buffer_get_ptr(EncCfg->FrameBuffer);
|
|
|
void *buf = mpp_buffer_get_ptr(enc_info->FrameBuffer);
|
|
|
|
|
|
//将yuv数据写入缓冲区
|
|
|
memcpy(buf, in_data, in_data_length);
|
|
|
|
|
|
// 使用默认的帧缓冲区
|
|
|
mpp_frame_set_buffer(frame, EncCfg->FrameBuffer);
|
|
|
mpp_frame_set_buffer(frame, enc_info->FrameBuffer);
|
|
|
|
|
|
// 获取帧的元数据对象
|
|
|
meta = mpp_frame_get_meta(frame);
|
|
|
|
|
|
// 初始化包对象,并使用指定的输出缓冲区
|
|
|
mpp_packet_init_with_buffer(Packet, EncCfg->PacketBuffer);
|
|
|
mpp_packet_init_with_buffer(Packet, enc_info->PacketBuffer);
|
|
|
|
|
|
// 注意:清除输出包的长度
|
|
|
// 设置包的长度为0
|
...
|
...
|
@@ -563,7 +495,7 @@ T_JZsdkReturnCode RTK_mmp_enc_data_to_h264(void **index, char *in_data, int in_d |
|
|
*/
|
|
|
|
|
|
/* 将frame数据放入编码器 */
|
|
|
ret = EncCfg->mpi->encode_put_frame(EncCfg->ctx, frame);
|
|
|
ret = enc_info->mpi->encode_put_frame(enc_info->ctx, frame);
|
|
|
if (ret) {
|
|
|
JZSDK_LOG_ERROR("mpp encode put frame failed");
|
|
|
mpp_frame_deinit(&frame);
|
...
|
...
|
@@ -579,7 +511,7 @@ T_JZsdkReturnCode RTK_mmp_enc_data_to_h264(void **index, char *in_data, int in_d |
|
|
|
|
|
do {
|
|
|
//获取解码后的帧
|
|
|
ret = EncCfg->mpi->encode_get_packet(EncCfg->ctx, Packet);
|
|
|
ret = enc_info->mpi->encode_get_packet(enc_info->ctx, Packet);
|
|
|
if (ret) {
|
|
|
JZSDK_LOG_ERROR("mpp encode get packet failed");
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
...
|
...
|
@@ -600,17 +532,15 @@ T_JZsdkReturnCode RTK_mmp_enc_data_to_h264(void **index, char *in_data, int in_d |
|
|
* 设置下一帧为I帧
|
|
|
*
|
|
|
* *******************/
|
|
|
T_JZsdkReturnCode RTK_mmp_enc_SetNextFrame_IDR(void **index)
|
|
|
T_JZsdkReturnCode RTK_mmp_enc_SetNextFrame_IDR(T_rtk_mmp_enc_info *enc_info)
|
|
|
{
|
|
|
//获取编码器参数
|
|
|
MPP_ENC_CONFIG *EncCfg = (MPP_ENC_CONFIG *)*index;
|
|
|
|
|
|
//将配置参数输入
|
|
|
int ret = EncCfg->mpi->control(EncCfg->ctx, MPP_ENC_SET_IDR_FRAME, EncCfg->cfg);
|
|
|
int ret = enc_info->mpi->control(enc_info->ctx, MPP_ENC_SET_IDR_FRAME, enc_info->cfg);
|
|
|
if (ret)
|
|
|
{
|
|
|
printf("设置I帧失败%d\n", ret);
|
|
|
return ret;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endif |
...
|
...
|
|