⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mfc_instance.c

📁 6410BSP3
💻 C
📖 第 1 页 / 共 4 页
字号:
     */
    mfc_sfr = (S3C6410_MFC_SFR *) GetMfcSfrVirAddr();
    mfc_sfr->BIT_STR_BUF_RW_ADDR[ctx->inst_no].BITS_WR_PTR = ctx->phyadrStrmBuf;
    mfc_sfr->BIT_STR_BUF_RW_ADDR[ctx->inst_no].BITS_RD_PTR = ctx->phyadrStrmBuf  +  MFC_LINE_BUF_SIZE_PER_INSTANCE;
    mfc_sfr->STRM_BUF_CTRL = 0x1C;    // bit stream buffer is reset at every picture encoding / decoding command

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


    ///////////////////////////////////////////////////////////////////
    //                                                               //
    // 3. Issue the SEQ_INIT command                                 //
    //     (frame width/height will be returned.)                    //
    //                                                               //
    ///////////////////////////////////////////////////////////////////
    // Set the Parameters for SEQ_INIT command.
    pPARAM_SEQ_INIT = (S3C6410_MFC_PARAM_REG_ENC_SEQ_INIT *) MfcGetCmdParamRegion();
    memset(pPARAM_SEQ_INIT, 0, sizeof(S3C6410_MFC_PARAM_REG_ENC_SEQ_INIT));
    pPARAM_SEQ_INIT->ENC_SEQ_BIT_BUF_ADDR    = ctx->phyadrStrmBuf;
    pPARAM_SEQ_INIT->ENC_SEQ_BIT_BUF_SIZE    = MFC_LINE_BUF_SIZE_PER_INSTANCE / 1024;
    pPARAM_SEQ_INIT->ENC_SEQ_OPTION        = MB_BIT_REPORT_DISABLE | SLICE_INFO_REPORT_DISABLE | AUD_DISABLE | MB_QP_REPORT_DISABLE | CONST_QP_DISABLE;
    pPARAM_SEQ_INIT->ENC_SEQ_SRC_SIZE        = ~(0xFFFFF);
    pPARAM_SEQ_INIT->ENC_SEQ_SRC_SIZE        = (ctx->width << 10) | ctx->height;
    pPARAM_SEQ_INIT->ENC_SEQ_SRC_F_RATE        = ~(0xFFFFFFFF);
    pPARAM_SEQ_INIT->ENC_SEQ_SRC_F_RATE        = (ctx->frameRateDiv << 16) | ctx->frameRateRes;
    pPARAM_SEQ_INIT->ENC_SEQ_SLICE_MODE        = SLICE_MODE_ONE;
    pPARAM_SEQ_INIT->ENC_SEQ_GOP_NUM        = ~(0x3F);
    pPARAM_SEQ_INIT->ENC_SEQ_GOP_NUM        = ctx->gopNum;
    pPARAM_SEQ_INIT->ENC_SEQ_RC_PARA        = ~(0xFFFFFFFF);
    pPARAM_SEQ_INIT->ENC_SEQ_RC_PARA        = RC_ENABLE | (ctx->bitrate << 1) | (SKIP_DISABLE << 31);    // set rate control
    pPARAM_SEQ_INIT->ENC_SEQ_INTRA_MB        = 0x0;        // Intra MB refresh is not used
    pPARAM_SEQ_INIT->ENC_SEQ_FMO        = FMO_DISABLE;

    pPARAM_SEQ_INIT->ENC_SEQ_INTRA_QP        = ctx->intraqp;
    
    if (ctx->gamma < 0 || ctx->gamma > 1)
    {
        pPARAM_SEQ_INIT->ENC_SEQ_RC_OPTION = USE_GAMMA_DISABLE;
        pPARAM_SEQ_INIT->ENC_SEQ_RC_GAMMA    = (float)MFCINST_GAMMA_FACTOR * MFCINST_GAMMA_FACTEE;
    }
    else
    {
        pPARAM_SEQ_INIT->ENC_SEQ_RC_OPTION = USE_GAMMA_ENABLE;
        pPARAM_SEQ_INIT->ENC_SEQ_RC_GAMMA    = ctx->gamma * MFCINST_GAMMA_FACTEE;
    }

    switch(ctx->codec_mode)
    {
        case MP4_ENC:
            pPARAM_SEQ_INIT->ENC_SEQ_COD_STD    = MPEG4_ENCODE;
            pPARAM_SEQ_INIT->ENC_SEQ_MP4_PARA    = ~(0x1F);
            pPARAM_SEQ_INIT->ENC_SEQ_MP4_PARA    = DATA_PART_DISABLE;

            break;

        case H263_ENC:
            pPARAM_SEQ_INIT->ENC_SEQ_COD_STD    = H263_ENCODE;
            pPARAM_SEQ_INIT->ENC_SEQ_263_PARA    = ctx->h263_annex;    //ANNEX_T_ON | ANNEX_J_OFF | ANNEX_K_ON | ANNEX_I_OFF;

            if (ctx->enc_num_slices) {
                // MB size is 16x16. -> width & height are divided by 16 to get number of MBs. (Division by 16 == shift right by 4-bit)
                num_mbs   = (enc_info->width >> 4) * (enc_info->height >> 4);
                slices_mb = (num_mbs / ctx->enc_num_slices);
                pPARAM_SEQ_INIT->ENC_SEQ_SLICE_MODE    = SLICE_MODE_MULTIPLE | (1 << 1) | (slices_mb<< 2);
            }

            break;

        case AVC_ENC:
            pPARAM_SEQ_INIT->ENC_SEQ_COD_STD    = H264_ENCODE;
            pPARAM_SEQ_INIT->ENC_SEQ_264_PARA    = ~(0xFFFF);

            if (ctx->enc_num_slices) {
                // MB size is 16x16. -> width & height are divided by 16 to get number of MBs. (Division by 16 == shift right by 4-bit)
                num_mbs   = (enc_info->width >> 4) * (enc_info->height >> 4);
                slices_mb = (num_mbs / ctx->enc_num_slices);
                pPARAM_SEQ_INIT->ENC_SEQ_SLICE_MODE    = SLICE_MODE_MULTIPLE | (1 << 1) | (slices_mb<< 2);
            }

            break;
    }

    switch(ctx->codec_mode)
    {
        case MP4_ENC:
        case H263_ENC:
            
            if (ctx->intraqp < MFCINST_MP4_QPMIN || ctx->intraqp > MFCINST_MP4_QPMAX)
                return MFCINST_ERR_INVALID_PARAM;

            if (ctx->qpmax < MFCINST_MP4_QPMIN || ctx->qpmax > MFCINST_MP4_QPMAX)
            {
                pPARAM_SEQ_INIT->ENC_SEQ_RC_OPTION    = USER_QP_MAX_DISABLE;
                pPARAM_SEQ_INIT->ENC_SEQ_RC_QP_MAX    = MFCINST_MP4_QPMIN;
            }
            else
            {
                pPARAM_SEQ_INIT->ENC_SEQ_RC_OPTION    = USER_QP_MAX_ENABLE;
                pPARAM_SEQ_INIT->ENC_SEQ_RC_QP_MAX    = ctx->qpmax;
            }

            break;

        case AVC_ENC:
            
            if (ctx->intraqp < MFCINST_H264_QPMIN || ctx->intraqp > MFCINST_H264_QPMAX)
                return MFCINST_ERR_INVALID_PARAM;

            if (ctx->qpmax < MFCINST_H264_QPMIN || ctx->qpmax > MFCINST_H264_QPMAX)
            {
                pPARAM_SEQ_INIT->ENC_SEQ_RC_OPTION    = USER_QP_MAX_DISABLE;
                pPARAM_SEQ_INIT->ENC_SEQ_RC_QP_MAX    = MFCINST_H264_QPMIN;
            }
            else
            {
                pPARAM_SEQ_INIT->ENC_SEQ_RC_OPTION    = USER_QP_MAX_ENABLE;
                pPARAM_SEQ_INIT->ENC_SEQ_RC_QP_MAX    = ctx->qpmax;
            }
            
            break;
    }


    // SEQ_INIT command
    MfcIssueCmd(ctx->inst_no, ctx->codec_mode, SEQ_INIT);

    if (pPARAM_SEQ_INIT->RET_ENC_SEQ_SUCCESS == TRUE)
    {
        LOG_MSG(LOG_TRACE, "MFCInst_Enc_Init", "ENC SEQ INIT success\n");
    }
    else {
        LOG_MSG(LOG_ERROR, "MFCInst_Enc_Init", "ENC SEQ INIT Fail\n");
        return MFCINST_ERR_ENC_INIT_CMD_FAIL;
    }

    // nFramBufSize is (YUV420 frame size) * (required frame buffer count)
    nFramBufSize = ((ctx->width * ctx->height * 3) >> 1) * (ctx->frambufCnt + 1);

    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_Enc_Init", "Initialization of MFC Instance failed!\r\n");
        LOG_MSG(LOG_ERROR, "MFCInst_Enc_Init", "MFC Instance init failed! (required frame buffer size = %d)\r\n", nFramBufSize);
        return MFCINST_ERR_ETC;
    }
    ctx->framBufAllocated = 1;

    //////////////////////////////////////////////////////////////////////
    //                                                                  //
    // 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.
    pPARAM_BUF = (unsigned char *)GetParamBufVirAddr();
    frame_size = ctx->width * ctx->height;
    for (i=0; i < ctx->frambufCnt; i++)
    {
        *((int *) (pPARAM_BUF + i*3*4))      = ctx->phyadrFramBuf + (i + 1) * ((frame_size * 3) >> 1);
        *((int *) (pPARAM_BUF + i*3*4 + 4))  = ctx->phyadrFramBuf + (i + 1) * ((frame_size * 3) >> 1) + frame_size;
        *((int *) (pPARAM_BUF + i*3*4 + 8))  = ctx->phyadrFramBuf + (i + 1) * ((frame_size * 3) >> 1) + frame_size + (frame_size >> 2);
        LOG_MSG(LOG_TRACE, "MFCInst_Enc_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)));  
    }


    ////////////////////////////////////////
    //                                    //
    // 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    = ctx->frambufCnt;
    pPARAM_SET_FRAME_BUF->SET_FRAME_BUF_STRIDE = ctx->buf_width;
    MfcIssueCmd(ctx->inst_no, ctx->codec_mode, SET_FRAME_BUF);


    ////////////////////////////
    ///    STATE changing    ///
    ////////////////////////////
    // state change to MFCINST_STATE_ENC_INITIALIZED
    MFCINST_STATE_TRANSITION(ctx, MFCINST_STATE_ENC_INITIALIZED);

    return MFCINST_RET_OK;
}


void MFCInst_Get_Frame_size(MFCInstCtx *ctx, int arg)
{
    MFC_DECODED_FRAME_INFO tmp;

    tmp.width    = ctx->width;
    tmp.height    = ctx->height;

    Copy_To_User( (MFC_DECODED_FRAME_INFO *)arg, &tmp, sizeof(MFC_DECODED_FRAME_INFO) );
}



//
// Function Name: MFCInst_Decode
// Description
//      This function decodes the input stream and put the decoded frame into the FRAM_BUF.
// Parameters
//      ctx[IN]: MFCInstCtx
//      strm_leng[IN]: stream size
//
int MFCInst_Decode(MFCInstCtx *ctx, unsigned long strm_leng)
{
    volatile S3C6410_MFC_PARAM_REG_DEC_PIC_RUN    *pPARAM_DEC_PIC_RUN;
    S3C6410_MFC_SFR                        *mfc_sfr;

#if (MFC_ROTATE_ENABLE == 1)
    int              frame_size;    // width * height
#endif

    ////////////////////////////
    ///    STATE checking    ///
    ////////////////////////////
    if (MFCINST_STATE_CHECK(ctx, MFCINST_STATE_DELETED)) {
        LOG_MSG(LOG_ERROR, "MFCInst_Decode", "MFC instance is deleted.\r\n");
        return MFCINST_ERR_STATE_DELETED;
    }
    if (MFCINST_STATE_PWR_OFF_FLAG_CHECK(ctx)) {
        LOG_MSG(LOG_ERROR, "MFCInst_Decode", "MFC instance is in Power-Off state.\r\n");
        return MFCINST_ERR_STATE_POWER_OFF;
    }
    if (MFCINST_STATE_CHECK(ctx, MFCINST_STATE_CREATED)) {
        LOG_MSG(LOG_ERROR, "MFCInst_Decode", "MFC instance is not initialized.\r\n");
        return MFCINST_ERR_STATE_CHK;
    }


    pPARAM_DEC_PIC_RUN = (S3C6410_MFC_PARAM_REG_DEC_PIC_RUN *)  MfcGetCmdParamRegion();

    // (strm_leng > 0) means that the video stream is waiting for being decoded in the STRM_LINE_BUF.
    // Otherwise, no more video streams are available and the decode command will flush the decoded YUV data
    // which are postponed because of B-frame (VC-1) or reordering (H.264).
    if (strm_leng > 0) {

        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;


        //////////////////////////////////////////////////////////////////////
        //                                                                  //
        // 13. Set the Parameters in the PARAM_BUF for PIC_RUN command.     //
        //                                                                  //
        //////////////////////////////////////////////////////////////////////
        pPARAM_DEC_PIC_RUN->DEC_PIC_ROT_MODE = ctx->PostRotMode;
#if (MFC_ROTATE_ENABLE == 1)
        if (ctx->PostRotMode & 0x0010) {    // The bit of 'PostRotEn' is 1.

            frame_size = ctx->buf_width * ctx->buf_height;

            pPARAM_DEC_PIC_RUN->DEC_PIC_ROT_ADDR_Y  = ctx->phyadrFramBuf + ctx->frambufCnt * ((frame_size * 3) >> 1);
            pPARAM_DEC_PIC_RUN->DEC_PIC_ROT_ADDR_CB = pPARAM_DEC_PIC_RUN->DEC_PIC_ROT_ADDR_Y + frame_size;
            pPARAM_DEC_PIC_RUN->DEC_PIC_ROT_ADDR_CR = pPARAM_DEC_PIC_RUN->DEC_PIC_ROT_ADDR_Y + frame_size + (frame_size >> 2);

            // Rotate Angle
            switch (ctx->PostRotMode & 0x0003) {
            case 0:    // 0   degree counterclockwise rotate
            case 2:    // 180 degree counterclockwise rotate
                pPARAM_DEC_PIC_RUN->DEC_PIC_ROT_STRIDE  = ctx->buf_width;
                break;

            case 1:    // 90  degree counterclockwise rotate
            case 3:    // 270 degree counterclockwise rotate
                pPARAM_DEC_PIC_RUN->DEC_PIC_ROT_STRIDE  = ctx->buf_height;
                break;
            }
        }
#endif

        // DEC_PIC_OPTION was newly added for MP4ASP.
        frame_size = ctx->buf_width * ctx->buf_height;
        pPARAM_DEC_PIC_RUN->DEC_PIC_OPTION       = 0x7;//(ctx->dec_pic_option & 0x00000007);
        pPARAM_DEC_PIC_RUN->DEC_PIC_MV_ADDR      = ctx->mv_mbyte_addr;
        pPARAM_DEC_PIC_RUN->DEC_PIC_MBTYPE_ADDR  = pPARAM_DEC_PIC_RUN->DEC_PIC_MV_ADDR + 25920;// '25920' is the maximum MV size (=45*36*16)

        pPARAM_DEC_PIC_RUN->DEC_PIC_BB_START     = ctx->phyadrStrmBuf & 0xFFFFFFFC;
        pPARAM_DEC_PIC_RUN->DEC_PIC_START_BYTE   = ctx->phyadrStrmBuf & 0x00000003;
        pPARAM_DEC_PIC_RUN->DEC_PIC_CHUNK_SIZE   = strm_leng;
    }
    else {
        pPARAM_DEC_PIC_RUN->DEC_PIC_CHUNK_SIZE  = strm_leng;

        MfcSetEos(1);
    }

    ////////////////////////////////////////
    //                                    //
    // 14. Issue the PIC_RUN command      //
    //                                    //
    ////////////////////////////////////////
    if (!MfcIssueCmd(ctx->inst_no, ctx->codec_mode, PIC_RUN)) {
        return MFCINST_ERR_DEC_PIC_RUN_CMD_FAIL;
    }
    if (pPARAM_DEC_PIC_RUN->RET_DEC_PIC_SUCCESS != 1) {
        LOG_MSG(LOG_WARNING, "Decode", "RET_DEC_PIC_SUCCESS is not value of 1(%d=SUCCESS).\r\n", pPARAM_DEC_PIC_RUN->RET_DEC_PIC_SUCCESS);
    }
    if (pPARAM_DEC_PIC_RUN->RET_DEC_PIC_IDX > 30) {

        if (pPARAM_DEC_PIC_RUN->RET_DEC_PIC_IDX == 0xFFFFFFFF) {        // RET_DEC_PIC_IDX == -1
            LOG_MSG(LOG_WARNING, "Decode", "End of Stream.\r\n");
            return MFCINST_ERR_DEC_EOS;
        }

⌨️ 快捷键说明

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