Rk系列 将RK编码功能demo封装为一个类

//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;
    }
}

你可能感兴趣的:(C++,Rk开发(RK3568),firefly-RK3288,c++,linux)