📄 mfc_instance.c
字号:
*/
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 + -