You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

762 lines
25 KiB

#include <stdio.h>
#include <string.h>
#include "mpp_encoder.h"
#include "rockchip/mpp_buffer.h"
#define MPP_ALIGN(x, a) (((x)+(a)-1)&~((a)-1))
#define SZ_4K 4096
#define LOGD printf
// #define LOGD
#define LOGE printf
int MppEncoder::InitParams(MppEncoderParams& params)
{
memcpy(&enc_params, &params, sizeof(MppEncoderParams));
// get paramter from cmd
if (enc_params.hor_stride == 0) {
enc_params.hor_stride = MPP_ALIGN(enc_params.width, 16);
}
if (enc_params.ver_stride == 0) {
enc_params.ver_stride = (MPP_ALIGN(enc_params.height, 16));
}
if (enc_params.fps_in_den == 0)
enc_params.fps_in_den = 1;
if (enc_params.fps_in_num == 0)
enc_params.fps_in_num = 30;
if (enc_params.fps_out_den == 0)
enc_params.fps_out_den = 1;
if (enc_params.fps_out_num == 0)
enc_params.fps_out_num = 30;
if (!enc_params.bps)
enc_params.bps = enc_params.width * enc_params.height / 8 * (enc_params.fps_out_num / enc_params.fps_out_den);
this->mdinfo_size = (MPP_VIDEO_CodingHEVC == enc_params.type) ?
(MPP_ALIGN(enc_params.hor_stride, 32) >> 5) *
(MPP_ALIGN(enc_params.ver_stride, 32) >> 5) * 16 :
(MPP_ALIGN(enc_params.hor_stride, 64) >> 6) *
(MPP_ALIGN(enc_params.ver_stride, 16) >> 4) * 16;
// update resource parameter
switch (enc_params.fmt & MPP_FRAME_FMT_MASK) {
case MPP_FMT_YUV420SP:
case MPP_FMT_YUV420P: {
this->frame_size = MPP_ALIGN(enc_params.hor_stride, 64) * MPP_ALIGN(enc_params.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 : {
this->frame_size = MPP_ALIGN(enc_params.hor_stride, 64) * MPP_ALIGN(enc_params.ver_stride, 64) * 2;
} break;
case MPP_FMT_RGB444 :
case MPP_FMT_BGR444 :
case MPP_FMT_RGB555 :
case MPP_FMT_BGR555 :
case MPP_FMT_RGB565 :
case MPP_FMT_BGR565 :
case MPP_FMT_RGB888 :
case MPP_FMT_BGR888 :
case MPP_FMT_RGB101010 :
case MPP_FMT_BGR101010 :
case MPP_FMT_ARGB8888 :
case MPP_FMT_ABGR8888 :
case MPP_FMT_BGRA8888 :
case MPP_FMT_RGBA8888 : {
this->frame_size = MPP_ALIGN(enc_params.hor_stride, 64) * MPP_ALIGN(enc_params.ver_stride, 64);
} break;
default: {
this->frame_size = MPP_ALIGN(enc_params.hor_stride, 64) * MPP_ALIGN(enc_params.ver_stride, 64) * 4;
} break;
}
if (MPP_FRAME_FMT_IS_FBC(enc_params.fmt)) {
if ((enc_params.fmt & MPP_FRAME_FBC_MASK) == MPP_FRAME_FBC_AFBC_V1)
this->header_size = MPP_ALIGN(MPP_ALIGN(enc_params.width, 16) * MPP_ALIGN(enc_params.height, 16) / 16, SZ_4K);
else
this->header_size = MPP_ALIGN(enc_params.width, 16) * MPP_ALIGN(enc_params.height, 16) / 16;
} else {
this->header_size = 0;
}
return 0;
}
int MppEncoder::SetupEncCfg()
{
MPP_RET ret;
ret = mpp_enc_cfg_init(&cfg);
if (ret) {
LOGE("mpp_enc_cfg_init failed ret %d\n", ret);
return -1;
}
/* setup default parameter */
if (enc_params.fps_in_den == 0)
enc_params.fps_in_den = 1;
if (enc_params.fps_in_num == 0)
enc_params.fps_in_num = 30;
if (enc_params.fps_out_den == 0)
enc_params.fps_out_den = 1;
if (enc_params.fps_out_num == 0)
enc_params.fps_out_num = 30;
if (!enc_params.bps)
enc_params.bps = enc_params.width * enc_params.height / 8 * (enc_params.fps_out_num / enc_params.fps_out_den);
mpp_enc_cfg_set_s32(cfg, "prep:width", enc_params.width);
mpp_enc_cfg_set_s32(cfg, "prep:height", enc_params.height);
mpp_enc_cfg_set_s32(cfg, "prep:hor_stride", enc_params.hor_stride);
mpp_enc_cfg_set_s32(cfg, "prep:ver_stride", enc_params.ver_stride);
mpp_enc_cfg_set_s32(cfg, "prep:format", enc_params.fmt);
mpp_enc_cfg_set_s32(cfg, "rc:mode", enc_params.rc_mode);
/* fix input / output frame rate */
mpp_enc_cfg_set_s32(cfg, "rc:fps_in_flex", enc_params.fps_in_flex);
mpp_enc_cfg_set_s32(cfg, "rc:fps_in_num", enc_params.fps_in_num);
mpp_enc_cfg_set_s32(cfg, "rc:fps_in_denorm", enc_params.fps_in_den);
mpp_enc_cfg_set_s32(cfg, "rc:fps_out_flex", enc_params.fps_out_flex);
mpp_enc_cfg_set_s32(cfg, "rc:fps_out_num", enc_params.fps_out_num);
mpp_enc_cfg_set_s32(cfg, "rc:fps_out_denorm", enc_params.fps_out_den);
mpp_enc_cfg_set_s32(cfg, "rc:gop", enc_params.gop_len ? enc_params.gop_len : enc_params.fps_out_num * 2);
/* drop frame or not when bitrate overflow */
mpp_enc_cfg_set_u32(cfg, "rc:drop_mode", MPP_ENC_RC_DROP_FRM_DISABLED);
mpp_enc_cfg_set_u32(cfg, "rc:drop_thd", 20); /* 20% of max bps */
mpp_enc_cfg_set_u32(cfg, "rc:drop_gap", 1); /* Do not continuous drop frame */
/* setup bitrate for different rc_mode */
mpp_enc_cfg_set_s32(cfg, "rc:bps_target", enc_params.bps);
switch (enc_params.rc_mode) {
case MPP_ENC_RC_MODE_FIXQP : {
/* do not setup bitrate on FIXQP mode */
} break;
case MPP_ENC_RC_MODE_CBR : {
/* CBR mode has narrow bound */
mpp_enc_cfg_set_s32(cfg, "rc:bps_max", enc_params.bps_max ? enc_params.bps_max : enc_params.bps * 17 / 16);
mpp_enc_cfg_set_s32(cfg, "rc:bps_min", enc_params.bps_min ? enc_params.bps_min : enc_params.bps * 15 / 16);
} break;
case MPP_ENC_RC_MODE_VBR :
case MPP_ENC_RC_MODE_AVBR : {
/* VBR mode has wide bound */
mpp_enc_cfg_set_s32(cfg, "rc:bps_max", enc_params.bps_max ? enc_params.bps_max : enc_params.bps * 17 / 16);
mpp_enc_cfg_set_s32(cfg, "rc:bps_min", enc_params.bps_min ? enc_params.bps_min : enc_params.bps * 1 / 16);
} break;
default : {
/* default use CBR mode */
mpp_enc_cfg_set_s32(cfg, "rc:bps_max", enc_params.bps_max ? enc_params.bps_max : enc_params.bps * 17 / 16);
mpp_enc_cfg_set_s32(cfg, "rc:bps_min", enc_params.bps_min ? enc_params.bps_min : enc_params.bps * 15 / 16);
} break;
}
/* setup qp for different codec and rc_mode */
switch (enc_params.type) {
case MPP_VIDEO_CodingAVC :
case MPP_VIDEO_CodingHEVC : {
switch (enc_params.rc_mode) {
case MPP_ENC_RC_MODE_FIXQP : {
RK_S32 fix_qp = enc_params.qp_init;
mpp_enc_cfg_set_s32(cfg, "rc:qp_init", fix_qp);
mpp_enc_cfg_set_s32(cfg, "rc:qp_max", fix_qp);
mpp_enc_cfg_set_s32(cfg, "rc:qp_min", fix_qp);
mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", fix_qp);
mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", fix_qp);
mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 0);
} break;
case MPP_ENC_RC_MODE_CBR :
case MPP_ENC_RC_MODE_VBR :
case MPP_ENC_RC_MODE_AVBR : {
mpp_enc_cfg_set_s32(cfg, "rc:qp_init", -1);
mpp_enc_cfg_set_s32(cfg, "rc:qp_max", 51);
mpp_enc_cfg_set_s32(cfg, "rc:qp_min", 10);
mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", 51);
mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", 10);
mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 2);
} break;
default : {
LOGE("unsupport encoder rc mode %d\n", enc_params.rc_mode);
} break;
}
} break;
case MPP_VIDEO_CodingVP8 : {
/* vp8 only setup base qp range */
mpp_enc_cfg_set_s32(cfg, "rc:qp_init", 40);
mpp_enc_cfg_set_s32(cfg, "rc:qp_max", 127);
mpp_enc_cfg_set_s32(cfg, "rc:qp_min", 0);
mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", 127);
mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", 0);
mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 6);
} break;
case MPP_VIDEO_CodingMJPEG : {
/* jpeg use special codec config to control qtable */
mpp_enc_cfg_set_s32(cfg, "jpeg:q_factor", 80);
mpp_enc_cfg_set_s32(cfg, "jpeg:qf_max", 99);
mpp_enc_cfg_set_s32(cfg, "jpeg:qf_min", 1);
} break;
default : {
} break;
}
/* setup codec */
mpp_enc_cfg_set_s32(cfg, "codec:type", enc_params.type);
switch (enc_params.type) {
case MPP_VIDEO_CodingAVC : {
RK_U32 constraint_set = enc_params.constraint_set;
/*
* H.264 profile_idc parameter
* 66 - Baseline profile
* 77 - Main profile
* 100 - High profile
*/
mpp_enc_cfg_set_s32(cfg, "h264:profile", 100);
/*
* H.264 level_idc parameter
* 10 / 11 / 12 / 13 - qcif@15fps / cif@7.5fps / cif@15fps / cif@30fps
* 20 / 21 / 22 - cif@30fps / half-D1@@25fps / D1@12.5fps
* 30 / 31 / 32 - D1@25fps / 720p@30fps / 720p@60fps
* 40 / 41 / 42 - 1080p@30fps / 1080p@30fps / 1080p@60fps
* 50 / 51 / 52 - 4K@30fps
*/
mpp_enc_cfg_set_s32(cfg, "h264:level", 40);
mpp_enc_cfg_set_s32(cfg, "h264:cabac_en", 1);
mpp_enc_cfg_set_s32(cfg, "h264:cabac_idc", 0);
mpp_enc_cfg_set_s32(cfg, "h264:trans8x8", 1);
if (constraint_set & 0x3f0000)
mpp_enc_cfg_set_s32(cfg, "h264:constraint_set", constraint_set);
} break;
case MPP_VIDEO_CodingHEVC :
case MPP_VIDEO_CodingMJPEG :
case MPP_VIDEO_CodingVP8 : {
} break;
default : {
LOGE("unsupport encoder coding type %d\n", enc_params.type);
} break;
}
if (enc_params.split_mode) {
LOGD("%p split mode %d arg %d out %d\n", mpp_ctx,
enc_params.split_mode, enc_params.split_arg, enc_params.split_out);
mpp_enc_cfg_set_s32(cfg, "split:mode", enc_params.split_mode);
mpp_enc_cfg_set_s32(cfg, "split:arg", enc_params.split_arg);
mpp_enc_cfg_set_s32(cfg, "split:out", enc_params.split_out);
}
mpp_enc_cfg_set_s32(cfg, "prep:mirroring", enc_params.mirroring);
mpp_enc_cfg_set_s32(cfg, "prep:rotation", enc_params.rotation);
mpp_enc_cfg_set_s32(cfg, "prep:flip", enc_params.flip);
ret = mpp_mpi->control(mpp_ctx, MPP_ENC_SET_CFG, cfg);
if (ret) {
LOGE("mpi control enc set cfg failed ret %d\n", ret);
goto RET;
}
#if 0
/* optional */
{
ret = mpp_mpi->control(mpp_ctx, MPP_ENC_SET_SEI_CFG, &enc_params.sei_mode);
if (ret) {
LOGE("mpi control enc set sei cfg failed ret %d\n", ret);
goto RET;
}
}
#endif
if (enc_params.type == MPP_VIDEO_CodingAVC || enc_params.type == MPP_VIDEO_CodingHEVC) {
enc_params.header_mode = MPP_ENC_HEADER_MODE_EACH_IDR;
ret = mpp_mpi->control(mpp_ctx, MPP_ENC_SET_HEADER_MODE, &enc_params.header_mode);
if (ret) {
LOGE("mpi control enc set header mode failed ret %d\n", ret);
goto RET;
}
}
#if 0
RK_U32 gop_mode = enc_params.gop_mode;
if (gop_mode) {
MppEncRefCfg ref;
mpp_enc_ref_cfg_init(&ref);
if (enc_params.gop_mode < 4)
mpi_enc_gen_ref_cfg(ref, gop_mode);
else
mpi_enc_gen_smart_gop_ref_cfg(ref, enc_params.gop_len, enc_params.vi_len);
ret = mpp_mpi->control(mpp_ctx, MPP_ENC_SET_REF_CFG, ref);
if (ret) {
LOGE("mpi control enc set ref cfg failed ret %d\n", ret);
goto RET;
}
mpp_enc_ref_cfg_deinit(&ref);
}
if (enc_params.roi_enable) {
mpp_enc_roi_init(&enc_params.roi_mpp_ctx, enc_params.width, enc_params.height, enc_params.type, 4);
mpp_assert(enc_params.roi_mpp_ctx);
}
#endif
RET:
return ret;
}
MppEncoder::MppEncoder() {
memset(&enc_params, 0, sizeof(MppEncoderParams));
this->mpp_ctx = NULL;
this->mpp_mpi = NULL;
memset(&osd_data, 0, sizeof(MppEncOSDData));
}
MppEncoder::~MppEncoder() {
if (this->mpp_ctx) {
mpp_destroy(this->mpp_ctx);
this->mpp_ctx = NULL;
}
if (this->cfg) {
mpp_enc_cfg_deinit(this->cfg);
this->cfg = NULL;
}
if (this->frm_buf) {
mpp_buffer_put(this->frm_buf);
this->frm_buf = NULL;
}
if (this->pkt_buf) {
mpp_buffer_put(this->pkt_buf);
this->pkt_buf = NULL;
}
if (this->md_info) {
mpp_buffer_put(this->md_info);
this->md_info = NULL;
}
if (this->osd_data.buf) {
mpp_buffer_put(this->osd_data.buf);
this->osd_data.buf = NULL;
}
if (this->buf_grp) {
mpp_buffer_group_put(this->buf_grp);
this->buf_grp = NULL;
}
}
int MppEncoder::Init(MppEncoderParams& params, void* userdata) {
int ret;
MppPollType timeout = MPP_POLL_BLOCK;
this->userdata = userdata;
this->InitParams(params);
ret = mpp_buffer_group_get_internal(&this->buf_grp, MPP_BUFFER_TYPE_DRM);
if (ret) {
LOGD("failed to get mpp buffer group ret %d\n", ret);
goto MPP_TEST_OUT;
}
ret = mpp_buffer_get(this->buf_grp, &this->pkt_buf, this->frame_size);
if (ret) {
LOGD("failed to get buffer for output packet ret %d\n", ret);
goto MPP_TEST_OUT;
}
ret = mpp_buffer_get(this->buf_grp, &this->md_info, this->mdinfo_size);
if (ret) {
LOGD("failed to get buffer for motion info output packet ret %d\n", ret);
goto MPP_TEST_OUT;
}
// encoder demo
ret = mpp_create(&this->mpp_ctx, &this->mpp_mpi);
if (ret) {
LOGE("mpp_create failed ret %d\n", ret);
goto MPP_TEST_OUT;
}
LOGD("%p encoder test start w %d h %d type %d\n",
this->mpp_ctx, enc_params.width, enc_params.height, enc_params.type);
ret = mpp_mpi->control(mpp_ctx, MPP_SET_OUTPUT_TIMEOUT, &timeout);
if (MPP_OK != ret) {
LOGE("mpi control set output timeout %d ret %d\n", timeout, ret);
goto MPP_TEST_OUT;
}
ret = mpp_init(mpp_ctx, MPP_CTX_ENC, enc_params.type);
if (ret) {
LOGE("mpp_init failed ret %d\n", ret);
goto MPP_TEST_OUT;
}
this->SetupEncCfg();
MPP_TEST_OUT:
if (ret) {
if (this->mpp_ctx) {
mpp_destroy(this->mpp_ctx);
this->mpp_ctx = NULL;
}
if (this->cfg) {
mpp_enc_cfg_deinit(this->cfg);
this->cfg = NULL;
}
if (this->frm_buf) {
mpp_buffer_put(this->frm_buf);
this->frm_buf = NULL;
}
if (this->pkt_buf) {
mpp_buffer_put(this->pkt_buf);
this->pkt_buf = NULL;
}
if (this->md_info) {
mpp_buffer_put(this->md_info);
this->md_info = NULL;
}
if (this->osd_data.buf) {
mpp_buffer_put(this->osd_data.buf);
this->osd_data.buf = NULL;
}
if (this->buf_grp) {
mpp_buffer_group_put(this->buf_grp);
this->buf_grp = NULL;
}
// if (this->roi_ctx) {
// mpp_enc_roi_deinit(this->roi_ctx);
// this->roi_ctx = NULL;
// }
}
return ret;
}
int MppEncoder::SetCallback(MppEncoderFrameCallback callback) {
this->callback = callback;
return 0;
}
int MppEncoder::GetHeader(char* enc_buf, int max_size) {
int ret;
void* out_ptr = enc_buf;
size_t out_len = 0;
if (enc_params.type == MPP_VIDEO_CodingAVC || enc_params.type == MPP_VIDEO_CodingHEVC) {
MppPacket packet = NULL;
/*
* Can use packet with normal malloc buffer as input not pkt_buf.
* Please refer to vpu_api_legacy.cpp for normal buffer case.
* Using pkt_buf buffer here is just for simplifing demo.
*/
mpp_packet_init_with_buffer(&packet, this->pkt_buf);
/* NOTE: It is important to clear output packet length!! */
mpp_packet_set_length(packet, 0);
ret = mpp_mpi->control(mpp_ctx, MPP_ENC_GET_HDR_SYNC, packet);
if (ret) {
LOGD("mpi control enc get extra info failed\n");
return -1;
} else {
/* get and write sps/pps for H.264 */
void *ptr = mpp_packet_get_pos(packet);
size_t len = mpp_packet_get_length(packet);
memcpy(out_ptr, ptr, len);
out_ptr = (char*)(out_ptr) + len;
out_len += len;
}
mpp_packet_deinit(&packet);
}
return out_len;
}
int MppEncoder::Encode(void* mpp_buf, char* enc_buf, int max_size) {
MPP_RET ret;
void* out_ptr = enc_buf;
size_t out_len = 0;
MppMeta meta = NULL;
MppFrame frame = NULL;
MppPacket packet = NULL;
// void *buf = mpp_buffer_get_ptr(this->frm_buf);
// RK_S32 cam_frm_idx = -1;
// MppBuffer cam_buf = NULL;
RK_U32 eoi = 1;
RK_U32 frm_eos = 0;
ret = mpp_frame_init(&frame);
if (ret) {
LOGD("mpp_frame_init failed\n");
return -1;
}
mpp_frame_set_width(frame, enc_params.width);
mpp_frame_set_height(frame, enc_params.height);
mpp_frame_set_hor_stride(frame, enc_params.hor_stride);
mpp_frame_set_ver_stride(frame, enc_params.ver_stride);
mpp_frame_set_fmt(frame, enc_params.fmt);
mpp_frame_set_eos(frame, frm_eos);
mpp_frame_set_buffer(frame, mpp_buf);
meta = mpp_frame_get_meta(frame);
mpp_packet_init_with_buffer(&packet, pkt_buf);
/* NOTE: It is important to clear output packet length!! */
mpp_packet_set_length(packet, 0);
mpp_meta_set_packet(meta, KEY_OUTPUT_PACKET, packet);
mpp_meta_set_buffer(meta, KEY_MOTION_INFO, this->md_info);
#if 0
if (enc_params.osd_enable || enc_params.user_data_enable || enc_params.roi_enable) {
if (enc_params.user_data_enable) {
MppEncUserData user_data;
char *str = "this is user data\n";
if ((enc_params.frame_count & 10) == 0) {
user_data.pdata = str;
user_data.len = strlen(str) + 1;
mpp_meta_set_ptr(meta, KEY_USER_DATA, &user_data);
}
static RK_U8 uuid_debug_info[16] = {
0x57, 0x68, 0x97, 0x80, 0xe7, 0x0c, 0x4b, 0x65,
0xa9, 0x06, 0xae, 0x29, 0x94, 0x11, 0xcd, 0x9a
};
MppEncUserDataSet data_group;
MppEncUserDataFull datas[2];
char *str1 = "this is user data 1\n";
char *str2 = "this is user data 2\n";
data_group.count = 2;
datas[0].len = strlen(str1) + 1;
datas[0].pdata = str1;
datas[0].uuid = uuid_debug_info;
datas[1].len = strlen(str2) + 1;
datas[1].pdata = str2;
datas[1].uuid = uuid_debug_info;
data_group.datas = datas;
mpp_meta_set_ptr(meta, KEY_USER_DATAS, &data_group);
}
if (enc_params.osd_enable) {
/* gen and cfg osd plt */
mpi_enc_gen_osd_plt(&enc_params.osd_plt, enc_params.frame_count);
enc_params.osd_plt_cfg.change = MPP_ENC_OSD_PLT_CFG_CHANGE_ALL;
enc_params.osd_plt_cfg.type = MPP_ENC_OSD_PLT_TYPE_USERDEF;
enc_params.osd_plt_cfg.plt = &enc_params.osd_plt;
ret = mpp_mpi->control(mpp_ctx, MPP_ENC_SET_OSD_PLT_CFG, &enc_params.osd_plt_cfg);
if (ret) {
LOGD("mpi control enc set osd plt failed ret %d\n", ret);
goto RET;
}
/* gen and cfg osd plt */
mpi_enc_gen_osd_data(&enc_params.osd_data, enc_params.buf_grp, enc_params.width,
enc_params.height, enc_params.frame_count);
mpp_meta_set_ptr(meta, KEY_OSD_DATA, (void*)&enc_params.osd_data);
}
if (enc_params.roi_enable) {
RoiRegionCfg *region = &enc_params.roi_region;
/* calculated in pixels */
region->x = MPP_ALIGN(enc_params.width / 8, 16);
region->y = MPP_ALIGN(enc_params.height / 8, 16);
region->w = 128;
region->h = 256;
region->force_intra = 0;
region->qp_mode = 1;
region->qp_val = 24;
mpp_enc_roi_add_region(enc_params.roi_mpp_ctx, region);
region->x = MPP_ALIGN(enc_params.width / 2, 16);
region->y = MPP_ALIGN(enc_params.height / 4, 16);
region->w = 256;
region->h = 128;
region->force_intra = 1;
region->qp_mode = 1;
region->qp_val = 10;
mpp_enc_roi_add_region(enc_params.roi_mpp_ctx, region);
/* send roi info by metadata */
mpp_enc_roi_setup_meta(enc_params.roi_mpp_ctx, meta);
}
}
#endif
/*
* NOTE: in non-block mode the frame can be resent.
* The default input timeout mode is block.
*
* User should release the input frame to meet the requirements of
* resource creator must be the resource destroyer.
*/
ret = mpp_mpi->encode_put_frame(mpp_ctx, frame);
mpp_frame_deinit(&frame);
if (ret) {
LOGD("chn %d encode put frame failed\n", chn);
return -1;
}
do {
ret = mpp_mpi->encode_get_packet(mpp_ctx, &packet);
if (ret) {
LOGD("chn %d encode get packet failed\n", chn);
return -1;
}
// mpp_assert(packet);
if (packet) {
// write packet to file here
void *ptr = mpp_packet_get_pos(packet);
size_t len = mpp_packet_get_length(packet);
char log_buf[256];
RK_S32 log_size = sizeof(log_buf) - 1;
RK_S32 log_len = 0;
// if (!enc_params.first_pkt)
// enc_params.first_pkt = mpp_time();
RK_U32 pkt_eos = mpp_packet_get_eos(packet);
/* set encode result */
if (this->callback != nullptr) {
this->callback(this->userdata, (const char*)ptr, len);
}
if (enc_buf != nullptr && max_size > 0) {
if (out_len + log_len < max_size) {
memcpy(out_ptr, ptr, len);
out_len += len;
out_ptr = (char*)out_ptr + len;
} else {
LOGE("error enc_buf no enought");
}
}
// log_len += snprintf(log_buf + log_len, log_size - log_len,
// "encoded frame %-4d", enc_params.frame_count);
/* for low delay partition encoding */
if (mpp_packet_is_partition(packet)) {
eoi = mpp_packet_is_eoi(packet);
// log_len += snprintf(log_buf + log_len, log_size - log_len,
// " pkt %d", enc_params.frm_pkt_cnt);
// enc_params.frm_pkt_cnt = (eoi) ? (0) : (enc_params.frm_pkt_cnt + 1);
}
log_len += snprintf(log_buf + log_len, log_size - log_len,
" size %-7zu", len);
if (mpp_packet_has_meta(packet)) {
meta = mpp_packet_get_meta(packet);
RK_S32 temporal_id = 0;
RK_S32 lt_idx = -1;
RK_S32 avg_qp = -1;
if (MPP_OK == mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &temporal_id))
log_len += snprintf(log_buf + log_len, log_size - log_len,
" tid %d", temporal_id);
if (MPP_OK == mpp_meta_get_s32(meta, KEY_LONG_REF_IDX, &lt_idx))
log_len += snprintf(log_buf + log_len, log_size - log_len,
" lt %d", lt_idx);
if (MPP_OK == mpp_meta_get_s32(meta, KEY_ENC_AVERAGE_QP, &avg_qp))
log_len += snprintf(log_buf + log_len, log_size - log_len,
" qp %d", avg_qp);
}
LOGD("chn %d %s\n", chn, log_buf);
mpp_packet_deinit(&packet);
// enc_params.stream_size += len;
// enc_params.frame_count += eoi;
// if (enc_params.pkt_eos) {
// LOGD("chn %d found last packet\n", chn);
// mpp_assert(enc_params.frm_eos);
// }
}
} while (!eoi);
// if (enc_params.frm_eos && enc_params.pkt_eos)
// break;
return out_len;
}
int MppEncoder::Reset() {
if (mpp_mpi != NULL) {
mpp_mpi->reset(mpp_ctx);
}
return 0;
}
size_t MppEncoder::GetFrameSize() {
return this->frame_size;
}
void* MppEncoder::ImportBuffer(int index, size_t size, int fd, int type) {
MppBuffer buf;
MppBufferInfo info;
memset(&info, 0, sizeof(MppBufferInfo));
info.type = (MppBufferType)type; // MPP_BUFFER_TYPE_EXT_DMA
info.fd = fd;
info.size = size;
info.index = index;
mpp_buffer_import(&buf, &info);
return buf;
}
void* MppEncoder::GetInputFrameBuffer() {
int ret;
if (this->frm_buf == nullptr) {
ret = mpp_buffer_get(this->buf_grp, &this->frm_buf, this->frame_size);
if (ret) {
LOGD("failed to get buffer for input frame ret %d\n", ret);
return NULL;
}
}
return this->frm_buf;
}
int MppEncoder::GetInputFrameBufferFd(void* mpp_buffer) {
return mpp_buffer_get_fd(mpp_buffer);
}
void* MppEncoder::GetInputFrameBufferAddr(void* mpp_buffer) {
return mpp_buffer_get_ptr(mpp_buffer);
}