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

📄 mfc_instance.c

📁 Samsung公司S3C6400芯片的BSP源码包
💻 C
📖 第 1 页 / 共 3 页
字号:
//      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 + -