mfc_instance.c

来自「6410BSP3」· C语言 代码 · 共 1,233 行 · 第 1/4 页

C
1,233
字号

//
// Function Name: MFCInst_PowerOnState
// Description
//      It turns on the flag indicating 6410 MFC's power-off.
// Parameters
//      ctx[IN]: MFCInstCtx
//
void MFCInst_PowerOnState(MFCInstCtx *ctx)
{
    MFCINST_STATE_PWR_OFF_FLAG_CLEAR(ctx);
}


//
// Function Name: MFCInst_Dec_Init
// Description
//      It initializes the 6410 MFC instance for decoding with the appropriate config stream.
//      The config stream must be copied into STRM_BUF before this function.
// Parameters
//      ctx[IN]: MFCInstCtx
//      codec_mode[IN]: codec mode specifying H.264/MPEG4/H.263.
//      strm_leng[IN]: stream size (especially it should be the config stream.)
//
int MFCInst_Dec_Init(MFCInstCtx *ctx, MFC_CODECMODE codec_mode, unsigned long strm_leng)
{
    unsigned int    i;

    S3C6410_MFC_SFR    *mfc_sfr;        // MFC SFR pointer

    unsigned char    *pPARAM_BUF;    // PARAM_BUF in BITPROC_BUF
    int              nFramBufSize;    // Required size in FRAM_BUF
    int              frame_size;    // width * height

    static S3C6410_MFC_PARAM_REG_DEC_SEQ_INIT    *pPARAM_SEQ_INIT;        // Parameter of SEQ_INIT command
    static S3C6410_MFC_PARAM_REG_SET_FRAME_BUF   *pPARAM_SET_FRAME_BUF;    // Parameter of SET_FRAME_BUF command

    int                last_unit = 0;
    int                garbage_size = 0;


    ////////////////////////////
    ///    STATE checking    ///
    ////////////////////////////
    if (!MFCINST_STATE_CHECK(ctx, MFCINST_STATE_CREATED)) {
        LOG_MSG(LOG_ERROR, "MFCInst_Init", "Init function was called at an incorrect point.\r\n");
        return MFCINST_ERR_STATE_CHK;
    }


    // codec_mode
    ctx->codec_mode = codec_mode;

    // Stream size checking
    if (strm_leng > MFC_LINE_BUF_SIZE_PER_INSTANCE) {
        LOG_MSG(LOG_ERROR, "MFCInst_Init", "Input buffer size is too small to hold the input stream.\r\n");
        return MFCINST_ERR_ETC;
    }


    //////////////////////////////////////////////
    //                                          //
    // 2. Copy the Config Stream into STRM_BUF. //
    //                                          //
    //////////////////////////////////////////////
    // config stream needs to be in the STRM_BUF a priori.
    // RD_PTR & WR_PTR is set to point the start and end address of STRM_BUF.
    // If WR_PTR is set to [start + config_leng] instead of [end address of STR_BUF],
    // then MFC is not initialized when MPEG4 decoding.

    LOG_MSG(LOG_TRACE, "MFCInst_Init", "strm_leng : %d\n",  strm_leng);

    mfc_sfr = (S3C6410_MFC_SFR *) GetMfcSfrVirAddr();
    mfc_sfr->BIT_STR_BUF_RW_ADDR[ctx->inst_no].BITS_RD_PTR = ctx->phyadrStrmBuf;
    mfc_sfr->BIT_STR_BUF_RW_ADDR[ctx->inst_no].BITS_WR_PTR = ctx->phyadrStrmBuf  +  strm_leng;//MFC_LINE_BUF_SIZE_PER_INSTANCE;

    LOG_MSG(LOG_TRACE, "MFCInst_Init", "  ctx->phyadrStrmBuf   = 0x%X\n", ctx->phyadrStrmBuf);
    LOG_MSG(LOG_TRACE, "MFCInst_Init", "  ctx->phyadrStrmBuf + = 0x%X\n", ctx->phyadrStrmBuf + strm_leng);


    ///////////////////////////////////////////////////////////////////
    //                                                               //
    // 3. Issue the SEQ_INIT command                                 //
    //     (width/height of frame will be obtained)                  //
    //                                                               //
    ///////////////////////////////////////////////////////////////////
    // Set the Parameters for SEQ_INIT command.
    pPARAM_SEQ_INIT = (S3C6410_MFC_PARAM_REG_DEC_SEQ_INIT *)  MfcGetCmdParamRegion();
    pPARAM_SEQ_INIT->DEC_SEQ_BIT_BUF_ADDR   = ctx->phyadrStrmBuf;
        pPARAM_SEQ_INIT->DEC_SEQ_BIT_BUF_SIZE   = MFC_LINE_BUF_SIZE_PER_INSTANCE / 1024;
        pPARAM_SEQ_INIT->DEC_SEQ_OPTION         = FILEPLAY_ENABLE | DYNBUFALLOC_ENABLE;
        pPARAM_SEQ_INIT->DEC_SEQ_START_BYTE     = 0;

    LOG_MSG(LOG_TRACE, "MFCInst_Init", "  ctx->inst_no     = %d\n", ctx->inst_no);
    LOG_MSG(LOG_TRACE, "MFCInst_Init", "  ctx->codec_mode  = %d\n", ctx->codec_mode);
    LOG_MSG(LOG_TRACE, "MFCInst_Init", "  SEQ_BIT_BUF_SIZE = %d (KB)\n", pPARAM_SEQ_INIT->DEC_SEQ_BIT_BUF_SIZE);


    // SEQ_INIT command
    if (MfcIssueCmd(ctx->inst_no, ctx->codec_mode, SEQ_INIT) == FALSE) {
        LOG_MSG(LOG_ERROR, "MFCInst_Init", "SEQ_INIT failed.\n");
        return MFCINST_ERR_DEC_INIT_CMD_FAIL;
    }

    if (pPARAM_SEQ_INIT->RET_SEQ_SUCCESS == TRUE) {

        LOG_MSG(LOG_TRACE, "MFCInst_Init", "\tRET_DEC_SEQ_SRC_SIZE         = %d\n", pPARAM_SEQ_INIT->RET_DEC_SEQ_SRC_SIZE);
        LOG_MSG(LOG_TRACE, "MFCInst_Init", "\tRET_DEC_SEQ_SRC_FRAME_RATE   = %d\n", pPARAM_SEQ_INIT->RET_DEC_SEQ_SRC_FRAME_RATE);
        LOG_MSG(LOG_TRACE, "MFCInst_Init", "\tRET_DEC_SEQ_FRAME_NEED_COUNT = %d\n", pPARAM_SEQ_INIT->RET_DEC_SEQ_FRAME_NEED_COUNT);
        LOG_MSG(LOG_TRACE, "MFCInst_Init", "\tRET_DEC_SEQ_FRAME_DELAY      = %d\n", pPARAM_SEQ_INIT->RET_DEC_SEQ_FRAME_DELAY);
    }
    else {
        LOG_MSG(LOG_ERROR, "MFCInst_Init", "SEQ_INIT failed. [%d]\n", pPARAM_SEQ_INIT->RET_SEQ_SUCCESS);
        return MFCINST_ERR_DEC_INIT_CMD_FAIL;
    }

    // width & height are obtained from return value of SEQ_INIT command
    // stride value is multiple of 16.
    ctx->height = (pPARAM_SEQ_INIT->RET_DEC_SEQ_SRC_SIZE      ) & 0x03FF;
    ctx->width  = (pPARAM_SEQ_INIT->RET_DEC_SEQ_SRC_SIZE >> 10) & 0x03FF;

    // If codec mode is VC1_DEC,
    // width & height value are not from return value of SEQ_INIT command
    // but extracting from config stream.
    if (ctx->codec_mode == VC1_DEC) {
        Mem_Cpy(&(ctx->height), ctx->pStrmBuf + 12, 4);
        Mem_Cpy(&(ctx->width), ctx->pStrmBuf + 16, 4);        
    }

    if ((ctx->width & 0x0F) == 0)    // 16 aligned (ctx->width%16 == 0)
        ctx->buf_width  = ctx->width;
    else
        ctx->buf_width  = (ctx->width  & 0xFFFFFFF0) + 16;
    if ((ctx->height & 0x0F) == 0)    // 16 aligned (ctx->height%16 == 0)
        ctx->buf_height = ctx->height;
    else
        ctx->buf_height = (ctx->height & 0xFFFFFFF0) + 16;            

#if (defined(DIVX_ENABLE) && (DIVX_ENABLE == 1))
    ctx->buf_width  += 2*ctx->paddingSize;
    ctx->buf_height += 2*ctx->paddingSize;

    ctx->RET_DEC_SEQ_INIT_BAK_MP4ASP_VOP_TIME_RES   = pPARAM_SEQ_INIT->RET_DEC_SEQ_TIME_RES;
#endif

    LOG_MSG(LOG_TRACE, "MFCInst_Init", "SEQ_SRC_SIZE, (width=%d) (height=%d) (stride=%d)\r\n",     \
            ctx->width, ctx->height, ctx->buf_width);


    ////////////////////////////////////////////////
    //                                            //
    // 4. Getting FRAME_BUF for this instance     //
    //                                            //
    ////////////////////////////////////////////////
    // nFramBufSize is (YUV420 frame size) * (required frame buffer count)
#if (MFC_ROTATE_ENABLE == 1)
    // If rotation is enabled, one more YUV buffer is required.
    nFramBufSize = ((ctx->buf_width * ctx->buf_height * 3) >> 1)  *  (pPARAM_SEQ_INIT->RET_DEC_SEQ_FRAME_NEED_COUNT + 1);

#else
    nFramBufSize = ((ctx->buf_width * ctx->buf_height * 3) >> 1)  *  pPARAM_SEQ_INIT->RET_DEC_SEQ_FRAME_NEED_COUNT;
#endif
    nFramBufSize += 60000;//27540;    // 27,540 bytes = MV(25,920) + MBTypes(1,620)

    LOG_MSG(LOG_TRACE, "MFCInst_Init", "nFramBufSize = %d\r\n", nFramBufSize);
    LOG_MSG(LOG_TRACE, "MFCInst_Init", "nFramBufSize for 4K align = %d\r\n", ((nFramBufSize & 0xFFFFF000) + 0x1000));

    if ( Get_MfcFramBufAddr(ctx, ((nFramBufSize & 0xFFFFF000) + 0x1000)) == FALSE ) {
        LOG_MSG(LOG_ERROR, "MFCInst_Init", "MFC Instance init failed! (required frame buffer size = %d)\r\n", nFramBufSize);
        return MFCINST_ERR_ETC;
    }
    ctx->framBufAllocated = 1;
    ctx->frambufCnt       = pPARAM_SEQ_INIT->RET_DEC_SEQ_FRAME_NEED_COUNT;
    ctx->mv_mbyte_addr    = ctx->phyadrFramBuf + (nFramBufSize - 60000/*27540*/);

    //////////////////////////////////////////////////////////////////////
    //                                                                  //
    // 5. Set the Parameters in the PARA_BUF for SET_FRAME_BUF command. //
    //                                                                  //
    //////////////////////////////////////////////////////////////////////
    // Buffer address of Y, Cb, Cr will be set in PARAM_BUF before issuing SET_FRAME_BUF command.

    pPARAM_BUF = (unsigned char *)GetParamBufVirAddr();
    frame_size = ctx->buf_width * ctx->buf_height;
#if (defined(DIVX_ENABLE) && (DIVX_ENABLE == 1))
    // s/w divx use padding area, so mfc frame buffer must have stride.
    for (i=0; i<pPARAM_SEQ_INIT->RET_DEC_SEQ_FRAME_NEED_COUNT; i++)
    {
        *((int *) (pPARAM_BUF + i*3*4))      = ctx->phyadrFramBuf + i * ((frame_size * 3) >> 1) + (ctx->buf_width)*ctx->paddingSize+ ctx->paddingSize;
        *((int *) (pPARAM_BUF + i*3*4 + 4))  = ctx->phyadrFramBuf + i * ((frame_size * 3) >> 1) + frame_size + ((ctx->buf_width)/2)*(ctx->paddingSize/2)+ (ctx->paddingSize/2);
        *((int *) (pPARAM_BUF + i*3*4 + 8))  = ctx->phyadrFramBuf + i * ((frame_size * 3) >> 1) + frame_size + (frame_size >> 2) + ((ctx->buf_width)/2)*(ctx->paddingSize/2)+ (ctx->paddingSize/2);
        LOG_MSG(LOG_TRACE, "MFCInst_Init", "Address of YUV (Ref.Num=%d) (Y=0x%X) (U=0x%X) (V=0x%X) \r\n",i,*((int *) (pPARAM_BUF + i*3*4)),*((int *) (pPARAM_BUF + i*3*4 + 4)),*((int *) (pPARAM_BUF + i*3*4 + 8)));  
    }
#else
    for (i=0; i<pPARAM_SEQ_INIT->RET_DEC_SEQ_FRAME_NEED_COUNT; i++)
    {
        *((int *) (pPARAM_BUF + i*3*4))      = ctx->phyadrFramBuf + i * ((frame_size * 3) >> 1);
        *((int *) (pPARAM_BUF + i*3*4 + 4))  = ctx->phyadrFramBuf + i * ((frame_size * 3) >> 1) + frame_size;
        *((int *) (pPARAM_BUF + i*3*4 + 8))  = ctx->phyadrFramBuf + i * ((frame_size * 3) >> 1) + frame_size + (frame_size >> 2);
        LOG_MSG(LOG_TRACE, "MFCInst_Init", "Address of YUV (Ref.Num=%d) (Y=0x%X) (U=0x%X) (V=0x%X) \r\n",i,*((int *) (pPARAM_BUF + i*3*4)),*((int *) (pPARAM_BUF + i*3*4 + 4)),*((int *) (pPARAM_BUF + i*3*4 + 8)));
    }
#endif




    ////////////////////////////////////////
    //                                    //
    // 6. Issue the SET_FRAME_BUF command //
    //                                    //
    ////////////////////////////////////////
    // 'SET_FRAME_BUF_NUM' must be greater than or equal to RET_DEC_SEQ_FRAME_NEED_COUNT.
    pPARAM_SET_FRAME_BUF = (S3C6410_MFC_PARAM_REG_SET_FRAME_BUF *)  MfcGetCmdParamRegion();
    pPARAM_SET_FRAME_BUF->SET_FRAME_BUF_NUM    = pPARAM_SEQ_INIT->RET_DEC_SEQ_FRAME_NEED_COUNT;
    pPARAM_SET_FRAME_BUF->SET_FRAME_BUF_STRIDE = ctx->buf_width;


    MfcIssueCmd(ctx->inst_no, ctx->codec_mode, SET_FRAME_BUF);


    ////////////////////////////
    ///    STATE changing    ///
    ////////////////////////////
    // Change the state to MFCINST_STATE_DEC_INITIALIZED
    // If the input stream data is less than the 2 PARTUNITs size,
    // then the state is changed to MFCINST_STATE_DEC_PIC_RUN_RING_BUF_LAST_UNITS.
    MFCINST_STATE_TRANSITION(ctx, MFCINST_STATE_DEC_INITIALIZED);

    LOG_MSG(LOG_TRACE, "MFCInst_Init", "After init state : %d\n", ctx->state_var);


    return MFCINST_RET_OK;
}


int MFCInst_Enc_Init(MFCInstCtx *ctx, MFC_CODECMODE codec_mode, enc_info_t *enc_info)
{
    int              i;

    S3C6410_MFC_SFR    *mfc_sfr;        // MFC SFR pointer

    unsigned char    *pPARAM_BUF;    // PARAM_BUF in BITPROC_BUF
    int              nFramBufSize;    // Required size in FRAM_BUF
    int              frame_size;    // width * height
    int              num_mbs;        // Number of MBs
    int              slices_mb;        // MB number of slice (only if SLICE_MODE_MULTIPLE is selected.)

    static S3C6410_MFC_PARAM_REG_ENC_SEQ_INIT    *pPARAM_SEQ_INIT;        // Parameter of SEQ_INIT command
    static S3C6410_MFC_PARAM_REG_SET_FRAME_BUF   *pPARAM_SET_FRAME_BUF;    // Parameter of SET_FRAME_BUF command


    // check parameters from user application
    if ( (enc_info->width & 0x0F) || (enc_info->height & 0x0F) ) {
        LOG_MSG(LOG_ERROR, "MFCInst_Enc_Init", "Source picture width and height must be a multiple of 16. width : %d, height : %d\n", \
            enc_info->width, enc_info->height);

        return MFCINST_ERR_INVALID_PARAM;
    }

    if (codec_mode < 0 || codec_mode > 6)
    {
        LOG_MSG(LOG_ERROR, "MFCInst_Enc_Init", "MFC encoder supports MPEG4, H.264 and H.263.\n");
        return MFCINST_ERR_INVALID_PARAM;
    }


    if (enc_info->gopNum > 60) {
        LOG_MSG(LOG_ERROR, "MFCInst_Enc_Init", "Maximum GOP number is 60.  GOP number = %d\n", enc_info->gopNum);

        return MFCINST_ERR_INVALID_PARAM;
    }

    ctx->width            = enc_info->width;
    ctx->height        = enc_info->height;
    ctx->frameRateRes    = enc_info->frameRateRes;
    ctx->frameRateDiv    = enc_info->frameRateDiv;
    ctx->gopNum        = enc_info->gopNum;
    ctx->bitrate        = enc_info->bitrate;

    ctx->intraqp        = enc_info->intraqp;
    ctx->qpmax        = enc_info->qpmax;
    ctx->gamma        = enc_info->gamma;

// Add For VideoEditor
    if((ctx->vopTimeIncResol >0) && (ctx->vopTimeIncResol <30000))
    {
		ctx->frameRateDiv = (ctx->vopTimeIncResol / ctx->frameRateRes) - 1;
		ctx->frameRateRes = ctx->vopTimeIncResol;
    }

    LOG_MSG(LOG_TRACE, "MFCInst_Enc_Init", "  ctx->frameRateDiv = %d\r\n", ctx->frameRateDiv);
    LOG_MSG(LOG_TRACE, "MFCInst_Enc_Init", "  ctx->frameRateRes = %d\r\n", ctx->frameRateRes);

    /*
     * At least 2 frame buffers are needed.
     * These buffers are used for input buffer in encoder case
     */
    ctx->frambufCnt        = 2;
    ctx->buf_width = ctx->width;
    ctx->buf_height = ctx->height;
    ctx->codec_mode = codec_mode;

    LOG_MSG(LOG_TRACE, "MFCInst_Enc_Init", "  ctx->inst_no = %d\n", ctx->inst_no);
    LOG_MSG(LOG_TRACE, "MFCInst_Enc_Init", "  ctx->codec_mode = %d\n", ctx->codec_mode);


    /*
     * set stream buffer read/write pointer
     * At first, stream buffer is empty. so write pointer points start of buffer and read pointer points end of buffer

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?