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 + -
显示快捷键?