📄 mfc_instance.c
字号:
// It deletes the 6400 MFC instance.
// Parameters
// ctx[IN]: MFCInstCtx
//
void MFCInst_Delete(MFCInstCtx *ctx)
{
////////////////////////////
/// STATE checking ///
////////////////////////////
if (MFCINST_STATE_CHECK(ctx, MFCINST_STATE_DELETED)) {
LOG_MSG(LOG_ERROR, "MFCInst_Delete", "MFC instance is already deleted.\r\n");
return;
}
MfcInstPool_Release(ctx->inst_no);
FramBufMgrFree(ctx->inst_no);
FramBufMgrFree(ctx->inst_no + MFC_NUM_INSTANCES_MAX);
MFCINST_STATE_TRANSITION(ctx, MFCINST_STATE_DELETED);
}
//
// Function Name: MFCInst_Invalidate
// Description
// It invalidates the 6400 MFC instance.
// Parameters
// ctx[IN]: MFCInstCtx
//
void MFCInst_Invalidate(MFCInstCtx *ctx)
{
MFCINST_STATE_TRANSITION(ctx, MFCINST_STATE_INVALIDATED);
}
//
// Function Name: MFCInst_Init
// Description
// It initializes the 6400 MFC instance 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_Init(MFCInstCtx *ctx, MFC_CODECMODE codec_mode, unsigned long strm_leng)
{
unsigned int i;
S3C6400_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 S3C6400_MFC_PARAM_REG_DEC_SEQ_INIT *pPARAM_SEQ_INIT; // Parameter of SEQ_INIT command
static S3C6400_MFC_PARAM_REG_SET_FRAME_BUF *pPARAM_SET_FRAME_BUF; // Parameter of SET_FRAME_BUF command
int last_unit = 0;
int garbage_size = 0;
unsigned int offset = 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;
// inbuf_type checking
if (ctx->inbuf_type == DEC_INBUF_NOT_SPECIFIED) {
LOG_MSG(LOG_ERROR, "MFCInst_Init", "Input buffer type is not specified.\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 = (S3C6400_MFC_SFR *) GetMfcSfrVirAddr();
mfc_sfr->BIT_STR_BUF_RW_ADDR[ctx->inst_no].BITS_RD_PTR = ctx->phyadrStrmBuf;
if (ctx->inbuf_type == DEC_INBUF_LINE_BUF) // In 'fileplay' mode, set the WR_PTR to the end of STRM_BUF
strm_leng = MFC_LINE_BUF_SIZE_PER_INSTANCE;
else if (ctx->inbuf_type == DEC_INBUF_RING_BUF) {
if (strm_leng < (MFC_RING_BUF_PARTUNIT_SIZE << 1)) {
if (strm_leng & 0x1FF) {
garbage_size = strm_leng;
strm_leng = (strm_leng + 512) & 0xFFFFFE00;
garbage_size = strm_leng - garbage_size;
Mem_Set((char *)(ctx->pStrmBuf + strm_leng - garbage_size), 0, garbage_size);
}
last_unit = 1;
}
// In the SEQ_INIT phase, the stream length should be more than 5
// since it must contain the CONFIG stream at the least.
if (strm_leng < 5) {
LOG_MSG(LOG_ERROR, "MFCInst_Init", "Size of buffer fill is too small.\r\n");
return MFCINST_ERR_DEC_BUF_FILL_SIZE_WRONG;
}
MFCINST_STATE_BUF_FILL_REQ_CLEAR(ctx);
}
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 = (S3C6400_MFC_PARAM_REG_DEC_SEQ_INIT *) MfcGetCmdParamRegion();
pPARAM_SEQ_INIT->DEC_SEQ_BIT_BUF_ADDR = ctx->phyadrStrmBuf;
if (ctx->inbuf_type == DEC_INBUF_LINE_BUF) { // Other than VC-1 decode
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 | REORDER_ENABLE;
pPARAM_SEQ_INIT->DEC_SEQ_OPTION = FILEPLAY_ENABLE | DYNBUFALLOC_ENABLE;
pPARAM_SEQ_INIT->DEC_SEQ_START_BYTE = 0;
}
else if (ctx->inbuf_type == DEC_INBUF_RING_BUF) { // VC-1 decode case
pPARAM_SEQ_INIT->DEC_SEQ_BIT_BUF_SIZE = MFC_RING_BUF_SIZE / 1024;
pPARAM_SEQ_INIT->DEC_SEQ_OPTION = MP4_DBK_ENABLE;//(0<<6);//REORDER_ENABLE;
pPARAM_SEQ_INIT->DEC_SEQ_START_BYTE = 0;
}
else {
LOG_MSG(LOG_ERROR, "MFCInst_Init", "Input buffer type is not specified.\r\n");
return MFCINST_ERR_ETC;
}
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
MfcIssueCmd(ctx->inst_no, ctx->codec_mode, SEQ_INIT);
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 ((ctx->width & 0x0F) == 0) // 16 aligned (ctx->width%16 == 0)
ctx->stride = ctx->width;
else
ctx->stride = (ctx->width & 0xFFFFFFF0) + 16;
// 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);
ctx->stride = ctx->width;
}
LOG_MSG(LOG_TRACE, "MFCInst_Init", "SEQ_SRC_SIZE, (width=%d) (height=%d) (stride=%d)\r\n", \
ctx->width, ctx->height, ctx->stride);
////////////////////////////////////////////////
// //
// 4. Getting FRAME_BUF for this instance //
// //
////////////////////////////////////////////////
// nFramBufSize is (YUV420 frame size) * (required frame buffer count)
nFramBufSize = ((ctx->width * ctx->height * 3) >> 1) * pPARAM_SEQ_INIT->RET_DEC_SEQ_FRAME_NEED_COUNT;
if ( Get_MfcFramBufAddr(ctx, nFramBufSize) == 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;
//////////////////////////////////////////////////////////////////////
// //
// 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->width * ctx->height;
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);
}
////////////////////////////////////////
// //
// 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 = (S3C6400_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->stride;
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);
if (last_unit) {
MFCINST_STATE_TRANSITION(ctx, MFCINST_STATE_DEC_PIC_RUN_RING_BUF_LAST_UNITS);
MfcSetEos();
}
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;
S3C6400_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 S3C6400_MFC_PARAM_REG_ENC_SEQ_INIT *pPARAM_SEQ_INIT; // Parameter of SEQ_INIT command
static S3C6400_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 (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;
/*
* At least 2 frame buffers are needed.
* These buffers are used for input buffer in encoder case
*/
ctx->frambufCnt = 2;
// This part is not required since the width and the height are checked to be multiples of 16
// in the beginning of this function.
if ((ctx->width & 0x0F) == 0) // 16 aligned (ctx->width%16 == 0)
ctx->stride = ctx->width;
else
ctx->stride = (ctx->width & 0xFFFFFFF0) + 16;
// codec_mode
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
*/
mfc_sfr = (S3C6400_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 = 0x8; // 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 = (S3C6400_MFC_PARAM_REG_ENC_SEQ_INIT *) MfcGetCmdParamRegion();
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;
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_ENABLE << 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;
switch(ctx->codec_mode) {
case MP4_ENC:
pPARAM_SEQ_INIT->ENC_SEQ_COD_STD = MPEG4_ENCODE;
pPARAM_SEQ_INIT->ENC_SEQ_MP4_PARA = ~(0x1F);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -