//RkH264Encode.h
/*
* Copyright 2015 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __RK_H264_ENCODE_H__
#define __RK_H264_ENCODE_H__
#if defined(_WIN32)
#include "vld.h"
#endif
#define MODULE_TAG "mpi_enc_test"
#include
#include "SdkTool.h"
#include "rk_mpi.h"
#include "mpp_env.h"
#include "mpp_mem.h"
#include "mpp_time.h"
#include "mpp_debug.h"
#include "mpp_common.h"
#include "DataManager.h"
#include "../project/librga-main/inc/RgaContronl.h"
#include "utils.h"
#include "mpi_enc_utils.h"
#include "camera_source.h"
#include "mpp_enc_roi_utils.h"
#include "thread.h"
#include "CameraReader.h"
#include "hstSdkAL.h"
#define IAMGE_1080P_WIDTH 1920
#define IAMGE_1080P_HEIGHT 1080
#define IAMGE_720P_WIDTH 1280
#define IAMGE_720P_HEIGHT 720
#define H264_ENCODE_COUNT 2
enum
{
CAMERA_INPUT = 0,
IMAGER_INPUT,
FRAME_INPUT
};
typedef struct
{
// base flow context
MppCtx ctx;
MppApi *mpi;
RK_S32 chn;
// global flow control flag
RK_U32 frm_eos;
RK_U32 pkt_eos;
RK_U32 frm_pkt_cnt;
RK_S32 frame_num;
RK_S32 frame_count;
RK_U64 stream_size;
/* end of encoding flag when set quit the loop */
volatile RK_U32 loop_end;
// src and dst
FILE *fp_verify;
/* encoder config set */
MppEncCfg cfg;
MppEncPrepCfg prep_cfg;
MppEncRcCfg rc_cfg;
MppEncCodecCfg codec_cfg;
MppEncSliceSplit split_cfg;
MppEncOSDPltCfg osd_plt_cfg;
MppEncOSDPlt osd_plt;
MppEncOSDData osd_data;
RoiRegionCfg roi_region;
MppEncROICfg roi_cfg;
// input / output
MppBufferGroup buf_grp;
MppBuffer frm_buf;
MppBuffer pkt_buf;
MppBuffer md_info;
MppEncSeiMode sei_mode;
MppEncHeaderMode header_mode;
// paramter for resource malloc
RK_U32 width;
RK_U32 height;
RK_U32 hor_stride;
RK_U32 ver_stride;
MppFrameFormat fmt;
MppCodingType type;
RK_S32 loop_times;
// int inputType;
MppEncRoiCtx roi_ctx;
// resources
size_t header_size;
size_t frame_size;
size_t mdinfo_size;
/* NOTE: packet buffer may overflow */
size_t packet_size;
RK_U32 osd_enable;
RK_U32 osd_mode;
RK_U32 split_mode;
RK_U32 split_arg;
RK_U32 split_out;
RK_U32 user_data_enable;
RK_U32 roi_enable;
// rate control runtime parameter
RK_S32 fps_in_flex;
RK_S32 fps_in_den;
RK_S32 fps_in_num;
RK_S32 fps_out_flex;
RK_S32 fps_out_den;
RK_S32 fps_out_num;
RK_S32 bps;
RK_S32 bps_max;
RK_S32 bps_min;
RK_S32 rc_mode;
RK_S32 gop_mode;
RK_S32 gop_len;
RK_S32 vi_len;
RK_S64 first_frm;
RK_S64 first_pkt;
} MpiEncTestData;
/* For each instance thread return value */
typedef struct
{
float frame_rate;
RK_U64 bit_rate;
RK_S64 elapsed_time;
RK_S32 frame_count;
RK_S64 stream_size;
RK_S64 delay;
} MpiEncMultiCtxRet;
typedef struct
{
// MpiEncTestArgs *cmd; // pointer to global command line info
RK_S32 chn;
pthread_t thd; // thread for for each instance
MpiEncTestData ctx; // context of encoder
MpiEncMultiCtxRet ret; // return of encoder
} MpiEncMultiCtxInfo;
struct RkH264EncodePara
{
char **Buf;
int BufCount;
int key;
int input_type;
};
class RkH264Encode
{
private:
int mThreadState;
VIDEO_CHN_E mEnVeChnNo;
HST_VENC_ATTR_S mVencAttr;
MpiEncMultiCtxInfo *mCtxs = NULL;
MpiEncTestData *p;
RK_U32 mWidth;
RK_U32 mHeight;
MppFrameFormat mFmt;
MppBuffer mCam_buf = NULL;
unsigned char *mImageBuf = NULL;
MppFrame mFrame = NULL;
char **mBuf = NULL;
void *buf;
int mKey = 0;
int mInputType = IMAGER_INPUT;
int mBufCount = 0;
CallWriteVQueue mWriteFunc = NULL;
unsigned char mSpsPpsData[1024];
int mSpsPpsPos[3];
MPP_RET Deinit();
MPP_RET work(MpiEncMultiCtxInfo *info);
MPP_RET test_ctx_init(MpiEncMultiCtxInfo *info);
MPP_RET test_mpp_enc_cfg_setup(MpiEncMultiCtxInfo *info);
void LogMpp_enc_cfg_set_s32(MppEncCfg cfg, const char *name, RK_S32 val);
MppEncRcMode GetRcMode(HST_RC_E mode);
void GetPicSize(HST_PIC_SIZE_E size, RK_U32 *width, RK_U32 *height);
unsigned long long GetSystemTimeus(void);
MPP_RET read_with_pixel_width(RK_U8 *buf, RK_S32 width, RK_S32 height,
RK_S32 hor_stride, RK_S32 pix_w, char *fp);
RK_S32 mpi_enc_width_default_stride(RK_S32 width, MppFrameFormat fmt);
public:
void setVeChnNo(VIDEO_CHN_E enVeChnNo);
RkH264Encode(char **Buf, int BufCount, int key, int input_type);
RkH264Encode();
RK_S32 Init();
void start();
void stop();
void *codeThread(void *p);
RkH264Encode &operator=(RkH264EncodePara *);
RkH264Encode &operator=(HST_VENC_ATTR_S *VencAttr);
HST_VENC_ATTR_S *GetVencAttr();
void RegisterOutFun(CallWriteVQueue pWrite);
void UnRegisterOutFun();
};
RkH264Encode.cpp
//RkH264Encode.cpp
/*
* Copyright 2015 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define MODULE_TAG "CameraReader"
#include "mpp_log.h"
#include "mpp_mem.h"
#include "RkH264Encode.h"
RkH264Encode::RkH264Encode(char **Buf, int BufCount, int Key, int inputType)
{
mBuf = Buf;
mBufCount = BufCount;
mKey = Key;
mInputType = inputType;
mWriteFunc = NULL;
mThreadState = THREADSTOP;
}
RkH264Encode::RkH264Encode()
{
mWriteFunc = NULL;
mThreadState = THREADSTOP;
}
RkH264Encode &RkH264Encode::operator=(RkH264EncodePara *rkH264EncodePara)
{
mBuf = rkH264EncodePara->Buf;
mBufCount = rkH264EncodePara->BufCount;
mKey = rkH264EncodePara->key;
mInputType = rkH264EncodePara->input_type;
}
RkH264Encode &RkH264Encode::operator=(HST_VENC_ATTR_S *VencAttr)
{
memcpy(&mVencAttr, VencAttr, sizeof(HST_VENC_ATTR_S));
return *this;
}
void RkH264Encode::GetPicSize(HST_PIC_SIZE_E size, RK_U32 *width, RK_U32 *height)
{
switch (size)
{
case HST_PIC_QCIF:
*width = 176;
*height = 144;
break;
case HST_PIC_CIF:
*width = 352;
*height = 288;
break;
case HST_PIC_D1:
*width = 704;
*height = 576;
break;
case HST_PIC_QVGA: /* 320 * 240 */
*width = 320;
*height = 240;
break;
case HST_PIC_VGA: /* 640 * 480 */
*width = 640;
*height = 480;
break;
case HST_PIC_XGA: /* 1024 * 768 */
*width = 1024;
*height = 768;
break;
case HST_PIC_SXGA: /* 1400 * 1050 */
*width = 1400;
*height = 1050;
break;
case HST_PIC_UXGA: /* 1600 * 1200 */
*width = 1600;
*height = 1200;
break;
case HST_PIC_QXGA: /* 2048 * 1536 */
*width = 2048;
*height = 1536;
break;
case HST_PIC_WVGA: /* 854 * 480 */
*width = 854;
*height = 480;
break;
case HST_PIC_WSXGA: /* 1680 * 1050 */
*width = 1680;
*height = 1050;
break;
case HST_PIC_WUXGA: /* 1920 * 1200 */
*width = 1920;
*height = 1200;
break;
case HST_PIC_WQXGA: /* 2560 * 1600 */
*width = 2560;
*height = 1600;
break;
case HST_PIC_HD720: /* 1280 * 720 */
*width = 1280;
*height = 720;
break;
case HST_PIC_HD1080: /* 1920 * 1080 */
*width = 1920;
*height = 1080;
break;
case HST_PIC_qHD: /*960 * 540*/
*width = 960;
*height = 540;
break;
case HST_PIC_UHD4K: /* 3840*2160 */
*width = 3840;
*height = 2160;
break;
case HST_PIC_640_360: /**640*360 16:9 **/
*width = 640;
*height = 360;
break;
case HST_PIC_768_432: /**768*432 16:9**/
*width = 768;
*height = 432;
break;
case HST_PIC_800_600: /**800*600 **/
*width = 800;
*height = 600;
break;
case HST_PIC_1024_768: /**1024*768 **/
*width = 1024;
*height = 768;
break;
default:
*width = 1280;
*height = 720;
break;
}
}
MppEncRcMode RkH264Encode::GetRcMode(HST_RC_E mode)
{
MppEncRcMode ret = MPP_ENC_RC_MODE_AVBR;
switch (mode)
{
case HST_RC_CBR:
ret = MPP_ENC_RC_MODE_CBR;
break;
case HST_RC_VBR:
ret = MPP_ENC_RC_MODE_VBR;
break;
case HST_RC_FIXQP:
ret = MPP_ENC_RC_MODE_FIXQP;
break;
}
return ret;
}
MPP_RET RkH264Encode::test_ctx_init(MpiEncMultiCtxInfo *info)
{
MpiEncTestData *p = &info->ctx;
MPP_RET ret = MPP_OK;
// get paramter from cmd
GetPicSize(mVencAttr.enSize, &p->width, &p->height);
printf("mVencAttr.enSize=%d,p->width=%d, p->height=%d\n", mVencAttr.enSize, p->width, p->height);
p->fmt = MPP_FMT_YUV420SP;
p->hor_stride = mpi_enc_width_default_stride(p->width, p->fmt);
p->ver_stride = p->height;
p->type = MPP_VIDEO_CodingAVC;
p->bps = mVencAttr.u32SetBitRate * 1024;
p->bps_min = p->bps / 10;
p->bps_max = p->bps;
p->rc_mode = MPP_ENC_RC_MODE_AVBR; // GetRcMode(mVencAttr.enRcMode);//RC_CVBR//MPP_ENC_RC_MODE_AVBR
p->gop_mode = 1;
p->gop_len = mVencAttr.u32SetGop;
p->vi_len = 0;
p->fps_in_flex = 0;
p->fps_in_den = 1;
p->fps_in_num = p->fps_out_num = mVencAttr.u32SetFps;
p->mdinfo_size = (MPP_ALIGN(p->hor_stride, 64) >> 6) * (MPP_ALIGN(p->ver_stride, 16) >> 4) * 8;
// update resource parameter
switch (p->fmt & MPP_FRAME_FMT_MASK)
{
case MPP_FMT_YUV420SP:
case MPP_FMT_YUV420P:
{
p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->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:
{
p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->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:
{
p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64);
}
break;
default:
{
p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64) * 4;
}
break;
}
if (MPP_FRAME_FMT_IS_FBC(p->fmt))
{
if ((p->fmt & MPP_FRAME_FBC_MASK) == MPP_FRAME_FBC_AFBC_V1)
p->header_size = MPP_ALIGN(MPP_ALIGN(p->width, 16) * MPP_ALIGN(p->height, 16) / 16, SZ_4K);
else
p->header_size = MPP_ALIGN(p->width, 16) * MPP_ALIGN(p->height, 16) / 16;
}
else
{
p->header_size = 0;
}
return ret;
}
// Create a new context to capture frames from .
// Returns NULL on error.
RK_S32 RkH264Encode::Init()
{
printf(" RkH264Encode Init in\n");
MPP_RET ret;
mCtxs = mpp_calloc(MpiEncMultiCtxInfo, 1);
if (NULL == mCtxs)
{
printf("failed to alloc context for instances\n");
return MPP_NOK;
}
p = &mCtxs->ctx;
MpiEncMultiCtxRet *enc_ret = &mCtxs->ret;
MppPollType timeout = MPP_POLL_BLOCK;
RK_S64 t_s = 0;
RK_S64 t_e = 0;
ret = test_ctx_init(mCtxs);
if (ret)
{
printf("test data init failed ret %d\n", ret);
goto MPP_TEST_OUT;
}
ret = mpp_buffer_group_get_internal(&p->buf_grp, MPP_BUFFER_TYPE_DRM);
if (ret)
{
printf("failed to get mpp buffer group ret %d\n", ret);
goto MPP_TEST_OUT;
}
printf("p->frame_size=%d,p->header_size=%d\n", p->frame_size, p->header_size);
ret = mpp_buffer_get(p->buf_grp, &p->frm_buf, p->frame_size + p->header_size);
if (ret)
{
printf("failed to get buffer for input frame ret %d\n", ret);
goto MPP_TEST_OUT;
}
ret = mpp_buffer_get(p->buf_grp, &p->pkt_buf, p->frame_size);
if (ret)
{
printf("failed to get buffer for output packet ret %d\n", ret);
goto MPP_TEST_OUT;
}
ret = mpp_buffer_get(p->buf_grp, &p->md_info, p->mdinfo_size);
if (ret)
{
printf("failed to get buffer for motion info output packet ret %d\n", ret);
goto MPP_TEST_OUT;
}
// encoder demo
ret = mpp_create(&p->ctx, &p->mpi);
if (ret)
{
printf("mpp_create failed ret %d\n", ret);
goto MPP_TEST_OUT;
}
// mpp_log_q(quiet, "%p encoder test start w %d h %d type %d\n",
// p->ctx, p->width, p->height, p->type);
ret = p->mpi->control(p->ctx, MPP_SET_OUTPUT_TIMEOUT, &timeout);
if (MPP_OK != ret)
{
printf("mpi control set output timeout %d ret %d\n", timeout, ret);
goto MPP_TEST_OUT;
}
ret = mpp_init(p->ctx, MPP_CTX_ENC, p->type);
if (ret)
{
printf("mpp_init failed ret %d\n", ret);
goto MPP_TEST_OUT;
}
ret = mpp_enc_cfg_init(&p->cfg);
if (ret)
{
printf("mpp_enc_cfg_init failed ret %d\n", ret);
goto MPP_TEST_OUT;
}
ret = test_mpp_enc_cfg_setup(mCtxs); // 锟斤拷锟矫憋拷锟斤拷锟斤拷锟??
if (ret)
{
printf("test mpp setup failed ret %d\n", ret);
goto MPP_TEST_OUT;
}
enc_ret->elapsed_time = t_e - t_s;
enc_ret->frame_count = p->frame_count;
enc_ret->stream_size = p->stream_size;
enc_ret->frame_rate = (float)p->frame_count * 1000000 / enc_ret->elapsed_time;
enc_ret->bit_rate = (p->stream_size * 8 * (p->fps_out_num / p->fps_out_den)) / p->frame_count;
enc_ret->delay = p->first_pkt - p->first_frm;
printf(" RkH264Encode Init out\n");
return MPP_OK;
MPP_TEST_OUT:
if (p->ctx)
{
mpp_destroy(p->ctx);
p->ctx = NULL;
}
if (p->cfg)
{
mpp_enc_cfg_deinit(p->cfg);
p->cfg = NULL;
}
if (p->frm_buf)
{
mpp_buffer_put(p->frm_buf);
p->frm_buf = NULL;
}
if (p->pkt_buf)
{
mpp_buffer_put(p->pkt_buf);
p->pkt_buf = NULL;
}
if (p->md_info)
{
mpp_buffer_put(p->md_info);
p->md_info = NULL;
}
if (p->osd_data.buf)
{
mpp_buffer_put(p->osd_data.buf);
p->osd_data.buf = NULL;
}
if (p->buf_grp)
{
mpp_buffer_group_put(p->buf_grp);
p->buf_grp = NULL;
}
if (p->roi_ctx)
{
mpp_enc_roi_deinit(p->roi_ctx);
p->roi_ctx = NULL;
}
return MPP_NOK;
}
void RkH264Encode::LogMpp_enc_cfg_set_s32(MppEncCfg cfg, const char *name, RK_S32 val)
{
printf("Log,%s = %d\n", name, val);
mpp_enc_cfg_set_s32(cfg, name, val);
}
MPP_RET RkH264Encode::test_mpp_enc_cfg_setup(MpiEncMultiCtxInfo *info)
{
// MpiEncTestArgs *cmd = info->cmd;
MpiEncTestData *p = &info->ctx;
MppApi *mpi = p->mpi;
MppCtx ctx = p->ctx;
MppEncCfg cfg = p->cfg;
// RK_U32 quiet = cmd->quiet;
MPP_RET ret;
/* setup default parameter */
if (p->fps_in_den == 0)
p->fps_in_den = 1;
if (p->fps_in_num == 0)
p->fps_in_num = 30;
if (p->fps_out_den == 0)
p->fps_out_den = 1;
if (p->fps_out_num == 0)
p->fps_out_num = 30;
if (!p->bps)
p->bps = p->width * p->height / 8 * (p->fps_out_num / p->fps_out_den);
LogMpp_enc_cfg_set_s32(cfg, "prep:width", p->width);
LogMpp_enc_cfg_set_s32(cfg, "prep:height", p->height);
LogMpp_enc_cfg_set_s32(cfg, "prep:hor_stride", p->hor_stride);
LogMpp_enc_cfg_set_s32(cfg, "prep:ver_stride", p->ver_stride);
LogMpp_enc_cfg_set_s32(cfg, "prep:format", p->fmt);
LogMpp_enc_cfg_set_s32(cfg, "rc:mode", p->rc_mode); // here mark
/* fix input / output frame rate */
LogMpp_enc_cfg_set_s32(cfg, "rc:fps_in_flex", p->fps_in_flex);
LogMpp_enc_cfg_set_s32(cfg, "rc:fps_in_num", p->fps_in_num);
LogMpp_enc_cfg_set_s32(cfg, "rc:fps_in_denorm", p->fps_in_den);
LogMpp_enc_cfg_set_s32(cfg, "rc:fps_out_flex", p->fps_out_flex);
LogMpp_enc_cfg_set_s32(cfg, "rc:fps_out_num", p->fps_out_num);
LogMpp_enc_cfg_set_s32(cfg, "rc:fps_out_denorm", p->fps_out_den);
LogMpp_enc_cfg_set_s32(cfg, "rc:gop", p->gop_len ? p->gop_len : p->fps_out_num * 2);
/* drop frame or not when bitrate overflow */
LogMpp_enc_cfg_set_s32(cfg, "rc:drop_mode", MPP_ENC_RC_DROP_FRM_DISABLED);
LogMpp_enc_cfg_set_s32(cfg, "rc:drop_thd", 20); /* 20% of max bps */
LogMpp_enc_cfg_set_s32(cfg, "rc:drop_gap", 1); /* Do not continuous drop frame */
/* setup bitrate for different rc_mode */
LogMpp_enc_cfg_set_s32(cfg, "rc:bps_target", p->bps);
switch (p->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 */
LogMpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 17 / 16);
LogMpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 15 / 16);
}
break;
case MPP_ENC_RC_MODE_VBR:
case MPP_ENC_RC_MODE_AVBR:
{
/* VBR mode has wide bound */
LogMpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 17 / 16);
LogMpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 1 / 16); // 1 / 16 mark
}
break;
default:
{
/* default use CBR mode */
LogMpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 17 / 16);
LogMpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 15 / 16);
}
break;
}
/* setup qp for different codec and rc_mode */
switch (p->type)
{
case MPP_VIDEO_CodingAVC:
case MPP_VIDEO_CodingHEVC:
{
switch (p->rc_mode)
{
case MPP_ENC_RC_MODE_FIXQP:
{
RK_S32 fix_qp = 26;
LogMpp_enc_cfg_set_s32(cfg, "rc:qp_init", fix_qp);
LogMpp_enc_cfg_set_s32(cfg, "rc:qp_max", fix_qp);
LogMpp_enc_cfg_set_s32(cfg, "rc:qp_min", fix_qp);
LogMpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", fix_qp);
LogMpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", fix_qp);
LogMpp_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:
{
LogMpp_enc_cfg_set_s32(cfg, "rc:qp_init", -1);
LogMpp_enc_cfg_set_s32(cfg, "rc:qp_max", 51);
LogMpp_enc_cfg_set_s32(cfg, "rc:qp_min", 10);
LogMpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", 51);
LogMpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", 10);
LogMpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 2);
}
break;
default:
{
printf("unsupport encoder rc mode %d\n", p->rc_mode);
}
break;
}
}
break;
case MPP_VIDEO_CodingVP8:
{
/* vp8 only setup base qp range */
LogMpp_enc_cfg_set_s32(cfg, "rc:qp_init", 40);
LogMpp_enc_cfg_set_s32(cfg, "rc:qp_max", 127);
LogMpp_enc_cfg_set_s32(cfg, "rc:qp_min", 0);
LogMpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", 127);
LogMpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", 0);
LogMpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 6);
}
break;
case MPP_VIDEO_CodingMJPEG:
{
/* jpeg use special codec config to control qtable */
LogMpp_enc_cfg_set_s32(cfg, "jpeg:q_factor", 80);
LogMpp_enc_cfg_set_s32(cfg, "jpeg:qf_max", 99);
LogMpp_enc_cfg_set_s32(cfg, "jpeg:qf_min", 1);
}
break;
default:
{
}
break;
}
/* setup codec */
LogMpp_enc_cfg_set_s32(cfg, "codec:type", p->type);
switch (p->type)
{
case MPP_VIDEO_CodingAVC:
{
RK_U32 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 / [email protected] / cif@15fps / cif@30fps
* 20 / 21 / 22 - cif@30fps / half-D1@@25fps / [email protected]
* 30 / 31 / 32 - D1@25fps / 720p@30fps / 720p@60fps
* 40 / 41 / 42 - 1080p@30fps / 1080p@30fps / 1080p@60fps
* 50 / 51 / 52 - 4K@30fps
*/
LogMpp_enc_cfg_set_s32(cfg, "h264:level", 12); // chenjx mark
LogMpp_enc_cfg_set_s32(cfg, "h264:cabac_en", 1);
LogMpp_enc_cfg_set_s32(cfg, "h264:cabac_idc", 0);
LogMpp_enc_cfg_set_s32(cfg, "h264:trans8x8", 1);
mpp_env_get_u32("constraint_set", &constraint_set, 0);
if (constraint_set & 0x3f0000)
LogMpp_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:
{
printf("unsupport encoder coding type %d\n", p->type);
}
break;
}
p->split_mode = 0;
p->split_arg = 0;
p->split_out = 0;
mpp_env_get_u32("split_mode", &p->split_mode, MPP_ENC_SPLIT_NONE);
mpp_env_get_u32("split_arg", &p->split_arg, 0);
mpp_env_get_u32("split_out", &p->split_out, 0);
if (p->split_mode)
{
// mpp_log_q(quiet, "%p split mode %d arg %d out %d\n", ctx,
// p->split_mode, p->split_arg, p->split_out);
LogMpp_enc_cfg_set_s32(cfg, "split:mode", p->split_mode);
LogMpp_enc_cfg_set_s32(cfg, "split:arg", p->split_arg);
LogMpp_enc_cfg_set_s32(cfg, "split:out", p->split_out);
}
ret = mpi->control(ctx, MPP_ENC_SET_CFG, cfg);
if (ret)
{
printf("mpi control enc set cfg failed ret %d\n", ret);
return ret;
}
/* optional */
{
RK_U32 sei_mode;
mpp_env_get_u32("sei_mode", &sei_mode, MPP_ENC_SEI_MODE_ONE_FRAME);
p->sei_mode = (MppEncSeiMode)sei_mode;
ret = mpi->control(ctx, MPP_ENC_SET_SEI_CFG, &p->sei_mode);
if (ret)
{
printf("mpi control enc set sei cfg failed ret %d\n", ret);
return ret;
}
}
if (p->type == MPP_VIDEO_CodingAVC || p->type == MPP_VIDEO_CodingHEVC)
{
p->header_mode = MPP_ENC_HEADER_MODE_EACH_IDR;
ret = mpi->control(ctx, MPP_ENC_SET_HEADER_MODE, &p->header_mode);
if (ret)
{
printf("mpi control enc set header mode failed ret %d\n", ret);
return ret;
}
}
RK_U32 gop_mode = p->gop_mode;
mpp_env_get_u32("gop_mode", &gop_mode, gop_mode);
if (gop_mode)
{
MppEncRefCfg ref;
mpp_enc_ref_cfg_init(&ref);
if (p->gop_mode < 4)
mpi_enc_gen_ref_cfg(ref, gop_mode);
else
mpi_enc_gen_smart_gop_ref_cfg(ref, p->gop_len, p->vi_len);
ret = mpi->control(ctx, MPP_ENC_SET_REF_CFG, ref);
if (ret)
{
printf("mpi control enc set ref cfg failed ret %d\n", ret);
return ret;
}
mpp_enc_ref_cfg_deinit(&ref);
}
/* setup test mode by env */
mpp_env_get_u32("osd_enable", &p->osd_enable, 0);
mpp_env_get_u32("osd_mode", &p->osd_mode, MPP_ENC_OSD_PLT_TYPE_DEFAULT);
mpp_env_get_u32("roi_enable", &p->roi_enable, 0);
mpp_env_get_u32("user_data_enable", &p->user_data_enable, 0);
if (p->roi_enable)
{
mpp_enc_roi_init(&p->roi_ctx, p->width, p->height, p->type, 4);
mpp_assert(p->roi_ctx);
}
return ret;
}
int findNextNal(unsigned char *ptr, int startPos, int size)
{
int zeroNum = 0;
for (int i = startPos; i < size; i++)
{
if (ptr[i] == 0)
zeroNum++;
else if (zeroNum >= 2 && ptr[i] == 1)
{ // 0 0 1鎴? 0 0 0 1
return i - zeroNum;
}
else
zeroNum = 0;
}
return -1;
}
RK_S32 RkH264Encode::mpi_enc_width_default_stride(RK_S32 width, MppFrameFormat fmt)
{
RK_S32 stride = 0;
switch (fmt & MPP_FRAME_FMT_MASK)
{
case MPP_FMT_YUV420SP:
case MPP_FMT_YUV420SP_VU:
{
stride = MPP_ALIGN(width, 8);
}
break;
case MPP_FMT_YUV420P:
{
/* NOTE: 420P need to align to 16 so chroma can align to 8 */
stride = MPP_ALIGN(width, 16);
}
break;
case MPP_FMT_YUV422P:
case MPP_FMT_YUV422SP:
case MPP_FMT_YUV422SP_VU:
{
/* NOTE: 422 need to align to 8 so chroma can align to 16 */
stride = MPP_ALIGN(width, 8);
}
break;
case MPP_FMT_YUV444SP:
case MPP_FMT_YUV444P:
{
stride = MPP_ALIGN(width, 8);
}
break;
case MPP_FMT_RGB565:
case MPP_FMT_BGR565:
case MPP_FMT_RGB555:
case MPP_FMT_BGR555:
case MPP_FMT_RGB444:
case MPP_FMT_BGR444:
case MPP_FMT_YUV422_YUYV:
case MPP_FMT_YUV422_YVYU:
case MPP_FMT_YUV422_UYVY:
case MPP_FMT_YUV422_VYUY:
{
/* NOTE: for vepu limitation */
stride = MPP_ALIGN(width, 8) * 2;
}
break;
case MPP_FMT_RGB888:
case MPP_FMT_BGR888:
{
/* NOTE: for vepu limitation */
stride = MPP_ALIGN(width, 8) * 3;
}
break;
case MPP_FMT_RGB101010:
case MPP_FMT_BGR101010:
case MPP_FMT_ARGB8888:
case MPP_FMT_ABGR8888:
case MPP_FMT_BGRA8888:
case MPP_FMT_RGBA8888:
{
/* NOTE: for vepu limitation */
stride = MPP_ALIGN(width, 8) * 4;
}
break;
default:
{
mpp_err_f("do not support type %d\n", fmt);
}
break;
}
return stride;
}
MPP_RET RkH264Encode::read_with_pixel_width(RK_U8 *buf, RK_S32 width, RK_S32 height,
RK_S32 hor_stride, RK_S32 pix_w, char *fp)
{
RK_S32 row;
MPP_RET ret = MPP_OK;
if (hor_stride < width * pix_w)
{
mpp_err_f("invalid %dbit color config: hor_stride %d is smaller then width %d multiply by 4\n",
8 * pix_w, hor_stride, width, pix_w);
mpp_err_f("width should be defined by pixel count\n");
mpp_err_f("stride should be defined by byte count\n");
hor_stride = width * pix_w;
}
int offset = 0;
for (row = 0; row < height; row++)
{
memcpy(buf + row * hor_stride, fp + offset, width * pix_w);
offset += width * pix_w;
}
return ret;
}
MPP_RET RkH264Encode::work(MpiEncMultiCtxInfo *info)
{
// MpiEncTestArgs *cmd = info->cmd;
MpiEncTestData *p = &info->ctx;
MppApi *mpi = p->mpi;
MppCtx ctx = p->ctx;
// RK_U32 quiet = cmd->quiet;
RK_S32 chn = info->chn;
RK_U32 cap_num = 0;
DataCrc checkcrc;
MPP_RET ret = MPP_OK;
int findSps = 0;
RkImgData imgData;
memset(&checkcrc, 0, sizeof(checkcrc));
checkcrc.sum = mpp_malloc(RK_ULONG, 512);
if (p->type == MPP_VIDEO_CodingAVC || p->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, p->pkt_buf);
/* NOTE: It is important to clear output packet length!! */
mpp_packet_set_length(packet, 0);
ret = mpi->control(ctx, MPP_ENC_GET_HDR_SYNC, packet);
if (ret)
{
printf("mpi control enc get extra info failed\n");
goto RET;
}
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(mSpsPpsData, (unsigned char *)ptr, len);
const MppPktSeg *h264Seg = mpp_packet_get_segment_info(packet);
for (int i = 0; h264Seg != NULL && i < 2; h264Seg = h264Seg->next)
{
mSpsPpsPos[i++] = h264Seg->offset;
}
// mSpsPpsPos[0]=0;
// mSpsPpsPos[1]=max(0,findNextNal((unsigned char*)ptr, 2, len));
mSpsPpsPos[2] = len;
printf("mSpsPpsPos:%d,%d,%d\n", mSpsPpsPos[0], mSpsPpsPos[1], mSpsPpsPos[2]);
// ImagePool *imagePool = DataManager::GetInstance()->GetNewImagePool(mKey, len);
// memcpy(imagePool->mBuf, ptr, len);
}
mpp_packet_deinit(&packet);
}
while (!p->pkt_eos && mThreadState == THREADRUN)
{
MppMeta meta = NULL;
MppFrame frame = NULL;
MppPacket packet = NULL;
imgData = CameraManager::GetInstance()->GetImg(mVencAttr.u32PhyChn, imgData.ID);
if (imgData.Data == NULL)
{
usleep(10000);
continue;
}
buf = mpp_buffer_get_ptr(p->frm_buf);
RK_S32 cam_frm_idx = -1;
RK_U32 eoi = 1;
int len = mpp_buffer_get_size(p->frm_buf);
/*
if (imgData.Width == p->width && imgData.Height == p->height)
RgaContronl::GetInstance()->CopyImage((char *)imgData.Data,
imgData.Width,
imgData.Height,
RK_FORMAT_YCbCr_420_SP,
(char *)buf);
else
{
RgaContronl::GetInstance()->ResizeImage((char *)imgData.Data,
imgData.Width, imgData.Height,
RK_FORMAT_YCbCr_420_SP,
(char *)buf, p->width, p->height,
RK_FORMAT_YCbCr_420_SP);
}
RkOsdttfManager::GetInstance()->OsdOverImage((char *)buf,
p->width,
p->height,
RK_FORMAT_YCbCr_420_SP,
mEnVeChnNo);
*/
// buf是编码需要用到的图像数据,自行填充
ret = mpp_frame_init(&frame);
if (ret)
{
printf("mpp_frame_init failed\n");
goto RET;
}
mpp_frame_set_width(frame, p->width);
mpp_frame_set_height(frame, p->height);
mpp_frame_set_hor_stride(frame, p->hor_stride);
mpp_frame_set_ver_stride(frame, p->ver_stride);
mpp_frame_set_fmt(frame, p->fmt);
mpp_frame_set_eos(frame, p->frm_eos);
/*if (mInputType == CAMERA_INPUT)
mpp_frame_set_buffer(frame, mCam_buf);
else if (mInputType == IMAGER_INPUT)
mpp_frame_set_buffer(frame, p->frm_buf);*/
mpp_frame_set_buffer(frame, p->frm_buf);
meta = mpp_frame_get_meta(frame);
mpp_packet_init_with_buffer(&packet, p->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, p->md_info);
if (p->osd_enable || p->user_data_enable || p->roi_enable)
{
if (p->user_data_enable)
{
MppEncUserData user_data;
char *str = "this is user data\n";
if ((p->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 (p->osd_enable)
{
/* gen and cfg osd plt */
mpi_enc_gen_osd_plt(&p->osd_plt, p->frame_count);
p->osd_plt_cfg.change = MPP_ENC_OSD_PLT_CFG_CHANGE_ALL;
p->osd_plt_cfg.type = MPP_ENC_OSD_PLT_TYPE_USERDEF;
p->osd_plt_cfg.plt = &p->osd_plt;
ret = mpi->control(ctx, MPP_ENC_SET_OSD_PLT_CFG, &p->osd_plt_cfg);
if (ret)
{
printf("mpi control enc set osd plt failed ret %d\n", ret);
goto RET;
}
/* gen and cfg osd plt */
mpi_enc_gen_osd_data(&p->osd_data, p->buf_grp, p->width,
p->height, p->frame_count);
mpp_meta_set_ptr(meta, KEY_OSD_DATA, (void *)&p->osd_data);
}
if (p->roi_enable)
{
RoiRegionCfg *region = &p->roi_region;
/* calculated in pixels */
region->x = MPP_ALIGN(p->width / 8, 16);
region->y = MPP_ALIGN(p->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(p->roi_ctx, region);
region->x = MPP_ALIGN(p->width / 2, 16);
region->y = MPP_ALIGN(p->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(p->roi_ctx, region);
/* send roi info by metadata */
mpp_enc_roi_setup_meta(p->roi_ctx, meta);
}
}
if (!p->first_frm)
p->first_frm = mpp_time();
/*
* 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 = mpi->encode_put_frame(ctx, frame);
if (ret)
{
printf("chn %d encode put frame failed\n", chn);
mpp_frame_deinit(&frame);
goto RET;
}
mpp_frame_deinit(&frame);
do
{
ret = mpi->encode_get_packet(ctx, &packet);
if (ret)
{
printf("chn %d encode get packet failed\n", chn);
goto RET;
}
mpp_assert(packet);
if (packet)
{
// write packet to file here
unsigned char *ptr = (unsigned char *)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 (!p->first_pkt)
p->first_pkt = mpp_time();
p->pkt_eos = mpp_packet_get_eos(packet);
// ImagePool *imagePool = DataManager::GetInstance()->GetNewImagePool(mKey, len);
// memcpy(imagePool->mBuf, ptr, len);
// mWriteFunc(mEnVeChnNo, imagePool->mBuf);
// printf("pid=%lld,size=%d,data=%02x %02x %02x %02x %02x %02x %02x %02x \n",imgData.ID,len,ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7]);
if (NULL != mWriteFunc)
{
const MppPktSeg *h264Seg = mpp_packet_get_segment_info(packet);
HST_VENC_STREAM_S l_stHstVencStream;
HST_VENC_PACK_S l_astVencPack[5];
int pos[6] = {0};
int nalNum = 0;
int nalType = ptr[4] & 0x1F;
int segSize = 0;
for (; h264Seg != NULL && nalNum < 5; h264Seg = h264Seg->next)
{
pos[nalNum++] = h264Seg->offset;
segSize += h264Seg->len;
}
pos[nalNum++] = segSize;
pos[nalNum] = len;
/*if (nalType == 7)
{
findSps = 1;
printf("findSps=%d", findSps);
}
printf("nal type = %d\n", nalType);
if (nalType == 7 || nalType == 6 || nalType == 5)
{ // sps
int k = 1;
for (; k < 5; k++)
{
pos[k] = findNextNal(ptr, pos[k - 1] + 2, len);
if (pos[k] < 0)
break;
int nalType = ptr[pos[k] + 4] & 0x1F;
printf("nal type = %d\n", nalType);
nalNum++;
if (nalType == 7)
{
findSps = 1;
printf("findSps=%d", findSps);
}
if (nalType == 5)
break;
}
}
pos[nalNum] = len;*/
for (int i = 0; i < nalNum; i++)
{
l_astVencPack[i].bFrameEnd = (HST_BOOL)1;
l_astVencPack[i].pu8Addr = ptr + pos[i];
l_astVencPack[i].u32DataNum = 0;
l_astVencPack[i].u32Len = pos[i + 1] - pos[i];
l_astVencPack[i].u32Offset = 0;
l_astVencPack[i].u32PhyAddr = 0;
l_astVencPack[i].u64PTS = imgData.Time;
}
if (nalType == 6 || nalType == 5)
{
for (int i = nalNum - 1; i >= 0; i--)
{
l_astVencPack[i + 2] = l_astVencPack[i];
}
for (int i = 0; i < 2; i++)
{
l_astVencPack[i].bFrameEnd = (HST_BOOL)1;
l_astVencPack[i].pu8Addr = mSpsPpsData + mSpsPpsPos[i];
l_astVencPack[i].u32DataNum = 0;
l_astVencPack[i].u32Len = mSpsPpsPos[i + 1] - mSpsPpsPos[i];
l_astVencPack[i].u32Offset = 0;
l_astVencPack[i].u32PhyAddr = 0;
l_astVencPack[i].u64PTS = imgData.Time;
}
nalNum += 2;
}
// static FILE *fp = NULL;
// for (int i = 0; i < nalNum; i++)
// {
// if (fp == NULL)
// {
// fp = fopen("/data/local/tmp/osd.h264", "wb+");
// fwrite(l_astVencPack[i].pu8Addr, l_astVencPack[i].u32Len, 1, fp);
// }
// else
// {
// fwrite(l_astVencPack[i].pu8Addr, l_astVencPack[i].u32Len, 1, fp);
// }
// }
l_stHstVencStream.pstPack = l_astVencPack;
l_stHstVencStream.u32PackCount = nalNum;
l_stHstVencStream.u32Seq = p->frame_count; // id++
// printf("[%s,%d]====%u\n",__FILE__,__LINE__,g_stStream[VencChn].u32PackCount);
// printf("[%s,%d]====%d\n",__FILE__,__LINE__,s32Ret);
// printf("callback channel:%d\n",mEnVeChnNo);
// if (findSps == 1)
{
mWriteFunc((HST_U32)mEnVeChnNo, (void *)&l_stHstVencStream);
}
// else
{
// printf("?no find sps,findSps=%d\n", findSps);
}
}
log_len += snprintf(log_buf + log_len, log_size - log_len,
"encoded frame %-4d", p->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", p->frm_pkt_cnt);
p->frm_pkt_cnt = (eoi) ? (0) : (p->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, <_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);
}
mpp_packet_deinit(&packet);
p->stream_size += len;
p->frame_count += eoi;
if (p->pkt_eos)
{
mpp_assert(p->frm_eos);
}
}
} while (!eoi);
if (p->frame_num > 0 && p->frame_count >= p->frame_num)
break;
if (p->loop_end)
break;
if (p->frm_eos && p->pkt_eos)
break;
}
RET:
MPP_FREE(checkcrc.sum);
printf("RkH264Encode::test_mpp_run");
return ret;
}
unsigned long long RkH264Encode::GetSystemTimeus(void)
{
long long lFrameTimestamp = 0;
struct timeval tvTime;
gettimeofday(&tvTime, NULL);
lFrameTimestamp = (unsigned long long)tvTime.tv_sec * 1000000 + (unsigned long long)tvTime.tv_usec;
return lFrameTimestamp;
}
void RkH264Encode::setVeChnNo(VIDEO_CHN_E enVeChnNo)
{
mEnVeChnNo = enVeChnNo;
}
// Free a context to capture frames from .
// Returns NULL on error.
MPP_RET RkH264Encode::Deinit()
{
mWriteFunc = NULL;
if (p->cfg)
{
mpp_enc_cfg_deinit(p->cfg);
p->cfg = NULL;
}
if (p->frm_buf)
{
mpp_buffer_put(p->frm_buf);
p->frm_buf = NULL;
}
if (p->pkt_buf)
{
mpp_buffer_put(p->pkt_buf);
p->pkt_buf = NULL;
}
if (p->md_info)
{
mpp_buffer_put(p->md_info);
p->md_info = NULL;
}
if (p->osd_data.buf)
{
mpp_buffer_put(p->osd_data.buf);
p->osd_data.buf = NULL;
}
if (p->buf_grp)
{
mpp_buffer_group_put(p->buf_grp);
p->buf_grp = NULL;
}
if (p->roi_ctx)
{
mpp_enc_roi_deinit(p->roi_ctx);
p->roi_ctx = NULL;
}
return MPP_OK;
}
HST_VENC_ATTR_S *RkH264Encode::GetVencAttr()
{
return &mVencAttr;
}
void RkH264Encode::RegisterOutFun(CallWriteVQueue pWrite)
{
if (mWriteFunc == NULL)
mWriteFunc = pWrite;
}
void RkH264Encode::UnRegisterOutFun()
{
mWriteFunc = NULL;
}
template
void *tempcodeThread(void *param)
{
TYPE *This = (TYPE *)(param);
This->codeThread((void *)(This));
return NULL;
}
void *RkH264Encode::codeThread(void *p)
{
work(mCtxs);
Deinit();
mThreadState = THREADSTOP;
return NULL;
}
void RkH264Encode::start()
{
if (mThreadState == THREADRUN)
return;
mThreadState = THREADRUN;
if (RK_OK != Init())
{
mThreadState = THREADSTOP;
return;
}
pthread_t tid;
if (pthread_create(&tid, NULL, tempcodeThread, this) != 0)
{
mThreadState = THREADREADYSTOP;
return;
}
pthread_detach(tid);
}
void RkH264Encode::stop()
{
if (mThreadState == THREADSTOP)
return;
mThreadState = THREADREADYSTOP;
int n = 0;
while (mThreadState != THREADSTOP && n++ < 400)
{
usleep(10000);
}
if (mThreadState != THREADSTOP)
{
printf("!#!#!#!#!#!#,encode stop error!");
mThreadState = THREADSTOP;
}
}