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

📄 mfc_instance.c

📁 SAMSUNG S3C6410 CPU BSP for winmobile6
💻 C
📖 第 1 页 / 共 4 页
字号:

    ////////////////////////////
    ///    STATE changing    ///
    ////////////////////////////
    if (MFCINST_STATE_CHECK(ctx, MFCINST_STATE_DEC_INITIALIZED))
        MFCINST_STATE_TRANSITION(ctx, MFCINST_STATE_DEC_PIC_RUN_RING_BUF);


    if (strm_leng) {

        // If the input stream length is less than 'MFC_RING_BUF_PARTUNIT_SIZE',
        // this block of input stream is considered as the last unit.
        // MFC instance will not accept any more input stream data,
        // when the state is changed to MFCINST_STATE_DEC_PIC_RUN_RING_BUF_LAST_UNITS.
        // The state is now changing to MFCINST_STATE_DEC_PIC_RUN_RING_BUF_LAST_UNITS.
        if (strm_leng < MFC_RING_BUF_PARTUNIT_SIZE) {
            if (strm_leng & 0x1FF) {
                garbage_size = strm_leng;
                strm_leng = (strm_leng + 512) & 0xFFFFFE00;
                garbage_size = strm_leng - garbage_size;
            }
            MFCINST_STATE_TRANSITION(ctx, MFCINST_STATE_DEC_PIC_RUN_RING_BUF_LAST_UNITS);
            MfcSetEos(0);
        }
        else if (strm_leng == MFC_RING_BUF_PARTUNIT_SIZE) {
            // state change to MFCINST_STATE_DEC_PIC_RUN_RING_BUF
            MFCINST_STATE_TRANSITION(ctx, MFCINST_STATE_DEC_PIC_RUN_RING_BUF);
        }
        else {    // strm_leng > MFC_RING_BUF_PARTUNIT_SIZE   => ERROR !!
            LOG_MSG(LOG_ERROR, "Decode_Stream", "Size of buffer fill is more than requested.\r\n");
            return MFCINST_ERR_DEC_BUF_FILL_SIZE_WRONG;
        }

        MFCINST_STATE_BUF_FILL_REQ_CLEAR(ctx);
    }


    // Moving the BITS_WR_PTR value by the amount of strm_leng
    mfc_sfr = (S3C6410_MFC_SFR *) GetMfcSfrVirAddr();
    mfc_sfr->BIT_STR_BUF_RW_ADDR[ctx->inst_no].BITS_WR_PTR += strm_leng;
    if (strm_leng > 0 &&
        ((mfc_sfr->BIT_STR_BUF_RW_ADDR[ctx->inst_no].BITS_WR_PTR - ctx->phyadrStrmBuf)
            >=  MFC_RING_BUF_SIZE)) {

        mfc_sfr->BIT_STR_BUF_RW_ADDR[ctx->inst_no].BITS_WR_PTR -= MFC_RING_BUF_SIZE;
    }

    if ( (strm_leng > 0) && (strm_leng < MFC_RING_BUF_PARTUNIT_SIZE) ) {
        mfc_sfr = (S3C6410_MFC_SFR *) GetMfcSfrVirAddr();
        offset = mfc_sfr->BIT_STR_BUF_RW_ADDR[ctx->inst_no].BITS_WR_PTR - GetDataBufPhyAddr();
        Mem_Set((char *)(GetDataBufVirAddr() + offset - garbage_size), 0, garbage_size);
    }

    //////////////////////////////////////////////////////////////////////
    //                                                                  //
    // 13. Set the Parameters in the PARAM_BUF for PIC_RUN command.     //
    //                                                                  //
    //////////////////////////////////////////////////////////////////////
    pPARAM_DEC_PIC_RUN = (S3C6410_MFC_PARAM_REG_DEC_PIC_RUN *)  MfcGetCmdParamRegion();
    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

    ////////////////////////////////////////
    //                                    //
    // 14. Issue the PIC_RUN command      //
    //                                    //
    ////////////////////////////////////////
    if (!MfcIssueCmd(ctx->inst_no, ctx->codec_mode, PIC_RUN)) {
        LOG_MSG(LOG_TRACE, "Decode_Stream", "Frame num : %d, pPARAM_DEC_PIC_RUN->RET_DEC_PIC_IDX : %d\n", pPARAM_DEC_PIC_RUN->RET_DEC_PIC_FRAME_NUM, pPARAM_DEC_PIC_RUN->RET_DEC_PIC_IDX);
        return MFCINST_ERR_DEC_PIC_RUN_CMD_FAIL;    // BUFFER empty or full interrupt is raised.
    }



    if (pPARAM_DEC_PIC_RUN->RET_DEC_PIC_IDX > 30) {
        if (MFCINST_STATE_CHECK(ctx, MFCINST_STATE_DEC_PIC_RUN_RING_BUF_LAST_UNITS)
            && (pPARAM_DEC_PIC_RUN->RET_DEC_PIC_IDX == 0xFFFFFFFF)) {    // RET_DEC_PIC_IDX == -1

            LOG_MSG(LOG_WARNING, "Decode_Stream", "End of Stream.\r\n");
            return MFCINST_ERR_DEC_EOS;
        }
        else if (pPARAM_DEC_PIC_RUN->RET_DEC_PIC_IDX == 0xFFFFFFFD) {    // RET_DEC_PIC_IDX == -3
            LOG_MSG(LOG_TRACE, "Decode_Stream", "No picture to be displayed.\r\n");
//            return MFCINST_ERR_DEC_DECODE_NO_DISP;
        }
        else {
            LOG_MSG(LOG_ERROR, "Decode_Stream", "Decoding Fail, ret = %d\r\n", pPARAM_DEC_PIC_RUN->RET_DEC_PIC_IDX);
            return MFCINST_ERR_DEC_DECODE_FAIL_ETC;
        }
    }

    ctx->frame_num = pPARAM_DEC_PIC_RUN->RET_DEC_PIC_FRAME_NUM;
    ctx->idx       = pPARAM_DEC_PIC_RUN->RET_DEC_PIC_IDX;

#ifdef CNM_PM
    if( pPARAM_DEC_PIC_RUN->RET_DEC_PIC_ERR_MB_NUM > 0 )
        RETAILMSG( 1, (_T("Report2 MB Error num=%d\r\n"), pPARAM_DEC_PIC_RUN->RET_DEC_PIC_ERR_MB_NUM ) );
#endif

    return MFCINST_RET_OK;
}


int MFCInst_Encode(MFCInstCtx *ctx, int *enc_data_size, int *header_size)
{
    volatile S3C6410_MFC_PARAM_REG_ENC_PIC_RUN    *pPARAM_ENC_PIC_RUN;
    S3C6410_MFC_SFR                        *mfc_sfr;

    int                                  hdr_size, hdr_size2;
    unsigned char                       *hdr_buf_tmp=NULL;

    ////////////////////////////
    ///    STATE checking    ///
    ////////////////////////////
    if (!MFCINST_STATE_CHECK(ctx, MFCINST_STATE_ENC_INITIALIZED) && !MFCINST_STATE_CHECK(ctx, MFCINST_STATE_ENC_PIC_RUN_LINE_BUF)) {

        LOG_MSG(LOG_ERROR, "MFCInst_Encode", "MFC Encoder instance is not initialized or not using the line buffer.\r\n");
        return MFCINST_ERR_STATE_CHK;
    }

    mfc_sfr = (S3C6410_MFC_SFR *) GetMfcSfrVirAddr();


    // The 1st call of this function (MFCInst_Encode) will generate the stream header (mpeg4: VOL, h264: SPS/PPS).
    //
    if (MFCINST_STATE_CHECK(ctx, MFCINST_STATE_ENC_INITIALIZED)) {

        if (ctx->codec_mode == MP4_ENC) {

            //  ENC_HEADER command  //
            MFCInst_EncHeader(ctx, 0, 0, ctx->phyadrStrmBuf, ctx->nStrmBufSize, &hdr_size);    // VOL

            // Backup the stream header in the temporary header buffer.
            hdr_buf_tmp = (unsigned char *) malloc(hdr_size);
            Mem_Cpy(hdr_buf_tmp, ctx->pStrmBuf, hdr_size);
        }
        else if (ctx->codec_mode == AVC_ENC) {

            //  ENC_HEADER command  //
            MFCInst_EncHeader(ctx, 0, 0, ctx->phyadrStrmBuf, ctx->nStrmBufSize, &hdr_size);    // SPS
            MFCInst_EncHeader(ctx, 1, 0, ctx->phyadrStrmBuf + (hdr_size + 3), ctx->nStrmBufSize-(hdr_size+3), &hdr_size2);    // PPS

            // Backup the stream header in the temporary header buffer.
            hdr_buf_tmp = (unsigned char *) malloc(hdr_size + 3 + hdr_size2);
            Mem_Cpy(hdr_buf_tmp, ctx->pStrmBuf, hdr_size);
            Mem_Cpy(hdr_buf_tmp + hdr_size, (void *)((unsigned int)(ctx->pStrmBuf + (hdr_size + 3)) & 0xFFFFFFFC), hdr_size2);
            hdr_size = hdr_size + hdr_size2;
        }
    }


    // SEI message with recovery point
    if ((ctx->enc_pic_option & 0x0F000000) && (ctx->codec_mode == AVC_ENC))
    {
        //  ENC_HEADER command  //
        MFCInst_EncHeader(ctx, 4, ((ctx->enc_pic_option & 0x0F000000) >> 24), ctx->phyadrStrmBuf, ctx->nStrmBufSize, &hdr_size);    // SEI
        // Backup the stream header in the temporary header buffer.
        hdr_buf_tmp = (unsigned char *) malloc(hdr_size);
        Mem_Cpy(hdr_buf_tmp, ctx->pStrmBuf, hdr_size);
    }

    /*
     * Set the address of each component of YUV420
     */
    pPARAM_ENC_PIC_RUN = (S3C6410_MFC_PARAM_REG_ENC_PIC_RUN *) MfcGetCmdParamRegion();
    pPARAM_ENC_PIC_RUN->ENC_PIC_SRC_ADDR_Y  = ctx->phyadrFramBuf;
    pPARAM_ENC_PIC_RUN->ENC_PIC_SRC_ADDR_CB = ctx->phyadrFramBuf  +   ctx->buf_width * ctx->height;
    pPARAM_ENC_PIC_RUN->ENC_PIC_SRC_ADDR_CR = ctx->phyadrFramBuf  + ((ctx->buf_width * ctx->height * 5) >> 2);
    pPARAM_ENC_PIC_RUN->ENC_PIC_ROT_MODE    = 0;
    pPARAM_ENC_PIC_RUN->ENC_PIC_OPTION      = (ctx->enc_pic_option & 0x0000FFFF);
    pPARAM_ENC_PIC_RUN->ENC_PIC_BB_START    = ctx->phyadrStrmBuf;
    pPARAM_ENC_PIC_RUN->ENC_PIC_BB_SIZE     = ctx->nStrmBufSize;


    if (!MfcIssueCmd(ctx->inst_no, ctx->codec_mode, PIC_RUN)) {
        return MFCINST_ERR_ENC_PIC_RUN_CMD_FAIL;
    }

    ctx->enc_pic_option = 0;    // Reset the encoding picture option at every picture
    ctx->idx = 0;

    *enc_data_size = mfc_sfr->BIT_STR_BUF_RW_ADDR[ctx->inst_no].BITS_WR_PTR - ctx->phyadrStrmBuf;    // calculte encoded data size
    *header_size   = 0;

    if (hdr_buf_tmp) {
        memmove(ctx->pStrmBuf + hdr_size, ctx->pStrmBuf, *enc_data_size);
        Mem_Cpy(ctx->pStrmBuf, hdr_buf_tmp, hdr_size);
        Mem_Free(hdr_buf_tmp);

        *enc_data_size += hdr_size;
        *header_size    = hdr_size;
    }

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


    return MFCINST_RET_OK;
}

// hdr_code == 0: SPS
// hdr_code == 1: PPS
// hdr_code == 4: SEI
int MFCInst_EncHeader(MFCInstCtx *ctx, int hdr_code, int hdr_num, unsigned int outbuf_physical_addr, int outbuf_size, int *hdr_size)
{
    volatile S3C6410_MFC_PARAM_REG_ENC_HEADER    *pPARAM_ENC_HEADER;
    S3C6410_MFC_SFR                        *mfc_sfr;


    if (!MFCINST_STATE_CHECK(ctx, MFCINST_STATE_ENC_INITIALIZED) && !MFCINST_STATE_CHECK(ctx, MFCINST_STATE_ENC_PIC_RUN_LINE_BUF)) {

        LOG_MSG(LOG_ERROR, "MFCInst_EncHeader", "MFC Encoder instance is not initialized or not using the line buffer.\r\n");
        return MFCINST_ERR_STATE_CHK;
    }

    if ((ctx->codec_mode != MP4_ENC) && (ctx->codec_mode != AVC_ENC)) {
        return MFCINST_ERR_WRONG_CODEC_MODE;
    }


    /*
     * Set the address of each component of YUV420
     */
    pPARAM_ENC_HEADER = (S3C6410_MFC_PARAM_REG_ENC_HEADER *) MfcGetCmdParamRegion();
    pPARAM_ENC_HEADER->ENC_HEADER_CODE      = hdr_code;
    pPARAM_ENC_HEADER->ENC_HEADER_BB_START  = outbuf_physical_addr & 0xFFFFFFFC;
    pPARAM_ENC_HEADER->ENC_HEADER_BB_SIZE   = outbuf_size; //ctx->nStrmBufSize;
    if (hdr_code == 4)    // SEI recovery point
        pPARAM_ENC_HEADER->ENC_HEADER_NUM   = hdr_num; // recovery point value

    mfc_sfr = (S3C6410_MFC_SFR *) GetMfcSfrVirAddr();


    if (!MfcIssueCmd(ctx->inst_no, ctx->codec_mode, ENC_HEADER)) {
        return MFCINST_ERR_ENC_HEADER_CMD_FAIL;
    }


    *hdr_size = mfc_sfr->BIT_STR_BUF_RW_ADDR[ctx->inst_no].BITS_WR_PTR - pPARAM_ENC_HEADER->ENC_HEADER_BB_START;

    return MFCINST_RET_OK;
}


int MFCInst_EncParamChange(MFCInstCtx *ctx, unsigned int param_change_enable, unsigned int param_change_val)
{
    volatile S3C6410_MFC_PARAM_REG_ENC_PARAM_CHANGE    *pPARAM_ENC_PARAM_CHANGE;


    int              num_mbs;        // Number of MBs
    int              slices_mb;        // MB number of slice (only if SLICE_MODE_MULTIPLE is selected.)


    pPARAM_ENC_PARAM_CHANGE = (S3C6410_MFC_PARAM_REG_ENC_PARAM_CHANGE *) MfcGetCmdParamRegion();

    memset(pPARAM_ENC_PARAM_CHANGE, 0, sizeof(S3C6410_MFC_PARAM_REG_ENC_PARAM_CHANGE));


    pPARAM_ENC_PARAM_CHANGE->ENC_PARAM_CHANGE_ENABLE      = param_change_enable;

    // GOP_NUM
    if (param_change_enable == (1 << 0)) {
        if (param_change_val > 60) {
            LOG_MSG(LOG_ERROR, "MFCInst_EncParamChange", "MFC Encoder Parameter change value is invalid.\r\n");
            return MFCINST_ERR_ENC_PARAM_CHANGE_INVALID_VALUE;
        }
        pPARAM_ENC_PARAM_CHANGE->ENC_PARAM_CHANGE_GOP_NUM        = param_change_val;
    }
    // INTRA_QP
    else if (param_change_enable == (1 << 1)) {
        if (((ctx->codec_mode == MP4_DEC || ctx->codec_mode == H263_DEC) && (param_change_val == 0 || param_change_val > 31))
                || (ctx->codec_mode == AVC_DEC && param_change_val > 51)) {
            LOG_MSG(LOG_ERROR, "MFCInst_EncParamChange", "MFC Encoder Parameter change value is invalid.\r\n");
            return MFCINST_ERR_ENC_PARAM_CHANGE_INVALID_VALUE;
        }
        pPARAM_ENC_PARAM_CHANGE->ENC_PARAM_CHANGE_INTRA_QP       = param_change_val;
    }
    // BITRATE
    else if (param_change_enable == (1 << 2)) {
        if (param_change_val > 0x07FFF) {
            LOG_MSG(LOG_ERROR, "MFCInst_EncParamChange", "MFC Encoder Parameter change value is invalid.\r\n");
            return MFCINST_ERR_ENC_PARAM_CHANGE_INVALID_VALUE;
        }
        pPARAM_ENC_PARAM_CHANGE->ENC_PARAM_CHANGE_BITRATE        = param_change_val;
    }
    // F_RATE
    else if (param_change_enable == (1 << 3)) {
        pPARAM_ENC_PARAM_CHANGE->ENC_PARAM_CHANGE_F_RATE         = param_change_val;
    }
    // INTRA_REFRESH
    else if (param_change_enable == (1 << 4)) {
        if (param_change_val > ((ctx->width * ctx->height) >> 8)) {
            LOG_MSG(LOG_ERROR, "MFCInst_EncParamChange", "MFC Encoder Parameter change value is invalid.\r\n");
            return MFCINST_ERR_ENC_PARAM_CHANGE_INVALID_VALUE;
        }
        pPARAM_ENC_PARAM_CHANGE->ENC_PARAM_CHANGE_INTRA_REFRESH  = param_change_val;
    }
    // SLICE_MODE
    else if (param_change_enable == (1 << 5)) {

        // 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   = (ctx->width >> 4) * (ctx->height >> 4);

        if (param_change_val > 256 || param_change_val > num_mbs) {
            LOG_MSG(LOG_ERROR, "MFCInst_EncParamChange", "MFC Encoder Parameter change value is invalid.\r\n");
            return MFCINST_ERR_ENC_PARAM_CHANGE_INVALID_VALUE;
        }

        if (param_change_val == 0) {
            pPARAM_ENC_PARAM_CHANGE->ENC_PARAM_CHANGE_SLICE_MODE   = SLICE_MODE_ONE;
        }
        else {

            slices_mb = (num_mbs / param_change_val);
            ctx->enc_num_slices = param_change_val;

            pPARAM_ENC_PARAM_CHANGE->ENC_PARAM_CHANGE_SLICE_MODE   = SLICE_MODE_MULTIPLE | (1 << 1) | (slices_mb<< 2);;
        }
    }

    if (!MfcIssueCmd(ctx->inst_no, ctx->codec_mode, ENC_PARAM_CHANGE)) {
        return MFCINST_ERR_ENC_HEADER_CMD_FAIL;
    }

    return MFCINST_RET_OK;
}

⌨️ 快捷键说明

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