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

📄 mfc_instance.c

📁 s3c6400 video code,you play video smooth with it,it is hardware codec
💻 C
📖 第 1 页 / 共 4 页
字号:
		return MFCINST_ERR_STATE_CHK;
	}


	////////////////////////////
	///    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 = (S3C6400_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 = (S3C6400_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 = (S3C6400_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 S3C6400_MFC_PARAM_REG_ENC_PIC_RUN	*pPARAM_ENC_PIC_RUN;
	S3C6400_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 = (S3C6400_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 *) Mem_Alloc(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 *) Mem_Alloc(hdr_size + 3 + hdr_size2);
			Mem_Cpy(hdr_buf_tmp, ctx->pStrmBuf, hdr_size);
			Mem_Cpy(hdr_buf_tmp + hdr_size, (unsigned char *)((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 *) Mem_Alloc(hdr_size);
		Mem_Cpy(hdr_buf_tmp, ctx->pStrmBuf, hdr_size);
	}

	/*
	 * Set the address of each component of YUV420
	 */
	pPARAM_ENC_PIC_RUN = (S3C6400_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 S3C6400_MFC_PARAM_REG_ENC_HEADER	*pPARAM_ENC_HEADER;
	S3C6400_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 = (S3C6400_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 = (S3C6400_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 S3C6400_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 = (S3C6400_MFC_PARAM_REG_ENC_PARAM_CHANGE *) MfcGetCmdParamRegion();

	Mem_Set((void *)pPARAM_ENC_PARAM_CHANGE, 0, sizeof(S3C6400_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 + -