mfcdriver.cpp

来自「SAMSUNG S3C6410 CPU BSP for winmobile6」· C++ 代码 · 共 847 行 · 第 1/2 页

CPP
847
字号
		LOG_MSG(LOG_TRACE, "MFC_IOControl", "OpenHandle == NULL\n");
		return FALSE;
	}
	if (pInBuf == NULL){
		LOG_MSG(LOG_TRACE, "MFC_IOControl", "pInBuf == NULL\n");
		return FALSE;
	}
	if (nInBufSize <= 0){
		LOG_MSG(LOG_TRACE, "MFC_IOControl", "nInBufSize <= 0\n");
		return FALSE;
	}
	if ((pOutBuf != NULL) || (nOutBufSize != 0) || (pBytesReturned != NULL)){
		LOG_MSG(LOG_TRACE, "MFC_IOControl", "others.....\n");
		return FALSE;
	}

	handle   = (MFC_HANDLE *) OpenHandle;
	pMfcInst = handle->mfc_inst;
/*
	///////////////////
	// MFC_CTX check //
	///////////////////
	if (MfcCtxIsValid(pMfcInst) == FALSE)
		return FALSE;
*/


	// IOCTL argument
	args = (MFC_ARGS *) pInBuf;

	MFC_Mutex_Lock();

	switch ( dwIoControlCode ) {

	case IOCTL_MFC_MPEG4_ENC_INIT:
	case IOCTL_MFC_H264_ENC_INIT:
	case IOCTL_MFC_H263_ENC_INIT:

		if (dwIoControlCode == IOCTL_MFC_MPEG4_ENC_INIT)
			codec_mode = MP4_ENC;
		else if (dwIoControlCode == IOCTL_MFC_H264_ENC_INIT)
			codec_mode = AVC_ENC;
		else
			codec_mode = H263_ENC;

		// Input arguments for IOCTL_MFC_xxx_ENC_INIT
		enc_info.width         = args->enc_init.in_width;;
		enc_info.height        = args->enc_init.in_height;;
		enc_info.frameRateRes  = args->enc_init.in_frameRateRes;
		enc_info.frameRateDiv  = args->enc_init.in_frameRateDiv;
		enc_info.gopNum        = args->enc_init.in_gopNum;;
		enc_info.bitrate       = args->enc_init.in_bitrate;;

		///////////////////////////////////
		///   Initialize MFC Instance   ///
		///////////////////////////////////
		Mfc_Clk_On();
		ret = MFCInst_Enc_Init(pMfcInst, codec_mode, &enc_info);
		Mfc_Clk_Off();

		// Output arguments for IOCTL_MFC_xxx_ENC_INIT
		args->enc_init.ret_code = ret;

		break;

	case IOCTL_MFC_MPEG4_ENC_EXE:
	case IOCTL_MFC_H264_ENC_EXE:
	case IOCTL_MFC_H263_ENC_EXE:

		// nStrmLen is size of output stream data
		Mfc_Clk_On();
		ret = MFCInst_Encode(pMfcInst, &nStrmLen, &nHdrLen);
		Mfc_Clk_Off();

		// Output arguments for IOCTL_MFC_xxx_ENC_EXE
		args->enc_exe.ret_code = ret;
		if (ret == MFCINST_RET_OK) {
			args->enc_exe.out_encoded_size = nStrmLen;
			args->enc_exe.out_header_size  = nHdrLen;
		}

		break;

	case IOCTL_MFC_MPEG4_DEC_INIT:
	case IOCTL_MFC_H263_DEC_INIT:
	case IOCTL_MFC_H264_DEC_INIT:
	case IOCTL_MFC_VC1_DEC_INIT:

		if (dwIoControlCode == IOCTL_MFC_MPEG4_DEC_INIT) {
			codec_mode = MP4_DEC;
		}
		else if (dwIoControlCode == IOCTL_MFC_H263_DEC_INIT) {
			codec_mode = MP4_DEC;
		}
		else if (dwIoControlCode == IOCTL_MFC_H264_DEC_INIT) {
			codec_mode = AVC_DEC;
		}
		else {
			codec_mode = VC1_DEC;
		}

		/////////////////////////////
		//   MFCInst::Initialize   //
		/////////////////////////////
		Mfc_Clk_On();
		ret = MFCInst_Init(pMfcInst, codec_mode, args->dec_init.in_strmSize);
		Mfc_Clk_Off();

		// Output arguments for IOCTL_MFC_xxx_DEC_INIT
		args->dec_init.ret_code = ret;
		if (ret == MFCINST_RET_OK) {
			args->dec_init.out_width  = pMfcInst->width;
			args->dec_init.out_height = pMfcInst->height;
		}

		break;

	case IOCTL_MFC_MPEG4_DEC_EXE:
	case IOCTL_MFC_H263_DEC_EXE:
	case IOCTL_MFC_H264_DEC_EXE:
	case IOCTL_MFC_VC1_DEC_EXE:

		if (pMfcInst->inbuf_type == DEC_INBUF_LINE_BUF) {
			Mfc_Clk_On();
			ret = MFCInst_Decode(pMfcInst, args->dec_exe.in_strmSize);
			Mfc_Clk_Off();
		}
		else if (pMfcInst->inbuf_type == DEC_INBUF_RING_BUF) {
			Mfc_Clk_On();
			ret = MFCInst_Decode_Stream(pMfcInst, args->dec_exe.in_strmSize);
			Mfc_Clk_Off();
		}
		else {
			RETAILMSG(1, (L"[MFC ERROR] Buffer type is not defined.\n"));
			MFC_Mutex_Release();
			args->dec_exe.ret_code = -1;
			return FALSE;
		}

		// Output arguments for IOCTL_MFC_xxx_DEC_EXE
		args->dec_exe.ret_code = ret;

		break;


	case IOCTL_MFC_GET_RING_BUF_ADDR:

		ret = MFCInst_GetRingBuf(pMfcInst, &p_buf, &n_bufsize);

		// Output arguments for IOCTL_MFC_xxx_DEC_EXE
		args->get_buf_addr.ret_code = ret;

		if (ret != MFCINST_RET_OK) {
			break;
		}

#if (_WIN32_WCE >= 600)
		// If the virtual address of the RING_BUF in user process's view is NULL,
		// call the VirtualAllocCopyEx.
		if (handle->pStrmBuf == NULL) {
			if (!args->get_buf_addr.in_usr_data) {
				RETAILMSG(1, (L"[MFC ERROR] HANDLE for user process is not valid. (0x%X)", (DWORD) args->get_buf_addr.in_usr_data));
				MFC_Mutex_Release();
				return FALSE;
			}
			handle->hUsrProc = (HANDLE) args->get_buf_addr.in_usr_data;

			handle->pStrmBuf
			   = (PBYTE) VirtualAllocCopyEx((HANDLE) GetCurrentProcessId(),		// HANDLE hSrcProc
			                                handle->hUsrProc,					// HANDLE hDstProc
			                                p_buf,								// LPVOID pAddr
			                                MFC_RING_BUF_SIZE,					// DWORD cbSize
			                                PAGE_READWRITE);					// DWORD dwProtect

			p_buf = handle->pStrmBuf;
		}
		else {
			p_buf = handle->pStrmBuf + ((int)p_buf - (int)pMfcInst->pStrmBuf);
		}
#endif

		// Output arguments for IOCTL_MFC_GET_RING_BUF_ADDR
		args->get_buf_addr.out_buf_addr   = (int) p_buf;
		args->get_buf_addr.out_buf_size   = n_bufsize;

		break;


	case IOCTL_MFC_GET_LINE_BUF_ADDR:

		ret = MFCInst_GetLineBuf(pMfcInst, &p_buf, &n_bufsize);

		// Output arguments for IOCTL_MFC_xxx_DEC_EXE
		args->get_buf_addr.ret_code = ret;

		if (ret != MFCINST_RET_OK) {
			break;
		}

#if (_WIN32_WCE >= 600)
		if (handle->pStrmBuf == NULL) {
			if (!args->get_buf_addr.in_usr_data) {
				MFC_Mutex_Release();
				RETAILMSG(1, (L"[MFC ERROR] HANDLE for user process is not valid. (0x%X)", (DWORD) args->get_buf_addr.in_usr_data));
				return FALSE;
			}
			handle->hUsrProc = (HANDLE) args->get_buf_addr.in_usr_data;

			handle->pStrmBuf
			   = (PBYTE) VirtualAllocCopyEx((HANDLE) GetCurrentProcessId(),		// HANDLE hSrcProc
			                                handle->hUsrProc,					// HANDLE hDstProc
			                                p_buf,								// LPVOID pAddr
			                                n_bufsize,							// DWORD cbSize
			                                PAGE_READWRITE);					// DWORD dwProtect

		}

		p_buf = handle->pStrmBuf;
#endif

		// Output arguments for IOCTL_MFC_GET_LINE_BUF_ADDR
		args->get_buf_addr.out_buf_addr   = (int) p_buf;
		args->get_buf_addr.out_buf_size   = n_bufsize;

		break;

	case IOCTL_MFC_GET_FRAM_BUF_ADDR:

		// Decoder case
		ret = MFCInst_GetFramBuf(pMfcInst, &p_buf, &n_bufsize);

		// Output arguments for IOCTL_MFC_xxx_DEC_EXE
		args->get_buf_addr.ret_code = ret;

		if (ret != MFCINST_RET_OK) {
			break;
		}

		// Output arguments for IOCTL_MFC_GET_FRAM_BUF_ADDR
		args->get_buf_addr.out_buf_addr   = (int) p_buf;
		args->get_buf_addr.out_buf_size   = n_bufsize;

#if (_WIN32_WCE >= 600)
		if (handle->pFramBuf == NULL) {
			if (!args->get_buf_addr.in_usr_data) {
				MFC_Mutex_Release();
				RETAILMSG(1, (L"[MFC ERROR] HANDLE for user process is not valid. (0x%X)", (DWORD) args->get_buf_addr.in_usr_data));
				return FALSE;
			}
			handle->hUsrProc = (HANDLE) args->get_buf_addr.in_usr_data;

			handle->pFramBuf
			   = (PBYTE) VirtualAllocCopyEx((HANDLE) GetCurrentProcessId(),		// HANDLE hSrcProc
			                                handle->hUsrProc,					// HANDLE hDstProc
			                                pMfcInst->pFramBuf,					// LPVOID pAddr
			                                pMfcInst->nFramBufSize,				// DWORD cbSize
			                                PAGE_READWRITE);					// DWORD dwProtect
		}

		if (pMfcInst->idx >= 0) {
			args->get_buf_addr.out_buf_addr  = (int) (handle->pFramBuf + (pMfcInst->idx * n_bufsize));

#if (MFC_ROTATE_ENABLE == 1)
			// If PostRotMode is enabled, then the output YUV buffer will be different.
			// In VC-1 mode, the rotated output will be the original one.
			if ( (pMfcInst->codec_mode != VC1_DEC) && (pMfcInst->PostRotMode & 0x0010) )
				args->get_buf_addr.out_buf_addr = (int) (handle->pFramBuf + (pMfcInst->frambufCnt * n_bufsize));
#endif
		}
		else
			args->get_buf_addr.out_buf_addr  = 0;
#endif
		break;

	case IOCTL_MFC_GET_PHY_FRAM_BUF_ADDR:

		// Decoder case
		ret = MFCInst_GetFramBufPhysical(pMfcInst, &p_buf, &n_bufsize);

		// Output arguments for IOCTL_MFC_xxx_DEC_EXE
		args->get_buf_addr.ret_code = ret;

		if (ret != MFCINST_RET_OK) {
			break;
		}

		// Output arguments for IOCTL_MFC_GET_FRAM_BUF_ADDR
		args->get_buf_addr.out_buf_addr   = (int) p_buf;
		args->get_buf_addr.out_buf_size   = n_bufsize;

		break;

	case IOCTL_MFC_GET_CONFIG:

		ret = MFC_GetConfigParams(pMfcInst, args);

		break;

	case IOCTL_MFC_SET_CONFIG:

		ret = MFC_SetConfigParams(pMfcInst, args);

		break;

	default:
		RETAILMSG(1, (L"[MFC IOControl] Requested ioctl command is not defined. (ioctl cmd=0x%X", dwIoControlCode));
		MFC_Mutex_Release();
		return FALSE;
	}

	MFC_Mutex_Release();


	switch (ret) {
	case MFCINST_RET_OK:
		return TRUE;
	default:
		return FALSE;
	}
	return FALSE;
}


BOOL MFC_PowerUp(DWORD InitHandle)
{
	return TRUE;
}

BOOL MFC_PowerDown(DWORD InitHandle)
{
	return TRUE;
}



static HANDLE gMfcIntrEvent;
static HANDLE gMfcIntrThread;


UINT32 g_MfcIrq     = IRQ_MFC;
UINT32 g_MfcSysIntr = SYSINTR_UNDEFINED;


extern "C"
static DWORD MFC_IntrThread(void)
{
	unsigned int intr_reason;

	while (1)
	{
		// Wait for MFC Interrupt
		WaitForSingleObject(gMfcIntrEvent, INFINITE);

		// Only SEQ_INIT, SEQ_END, PIC_RUN and BUFFER EMPTY/FULL interrupts
		// will be processed.
		intr_reason = MfcIntrReason();
		RETAILMSG(0, (L"(( MFC Interrupt ) reason = 0x%X\n", intr_reason));
//		if (intr_reason & 0xC02E) {
		if (intr_reason & 0xC00E) {
			// On the MFC Interrupt,
			// MFC command completion event will be sent.
			// This event wakes up the task in WaitInterruptNotification() function.
			SendInterruptNotification(intr_reason);
		}

		// Clearing MFC interrupt bit
		MfcClearIntr();

		// Notify to Kernel that MFC Interrupt processing is completed.
		InterruptDone(g_MfcSysIntr);
    }

}

static BOOL InitializeIST()
{
	BOOL r;

	gMfcIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	if (!gMfcIntrEvent) {
		ERRORMSG(1, (L"Unable to create interrupt event"));
		return(FALSE);
	}
	if (!CreateInterruptNotification()) {
		ERRORMSG(1, (L"Unable to create interrupt event"));
		return(FALSE);
	}

	r = KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR,
	                    &g_MfcIrq,     sizeof(UINT32),
	                    &g_MfcSysIntr, sizeof(UINT32),
	                    NULL);
	if (r != TRUE) {
		ERRORMSG(1, (L"ERROR: PwrButton: Failed to request sysintr value for sw_reset button interrupt.\r\n"));
		return(0);
	}


	r = InterruptInitialize(g_MfcSysIntr, gMfcIntrEvent, NULL, 0);
	if (r != TRUE) {
		ERRORMSG(1, (L"Unable to initialize output interrupt"));
		return FALSE;
	}

	gMfcIntrThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL,
	                              0,
	                              (LPTHREAD_START_ROUTINE)MFC_IntrThread,
	                              0,
	                              0,
	                              NULL);
	if (!gMfcIntrThread) {
		ERRORMSG(1, (L"Unable to create interrupt thread"));
		return FALSE;
	}

	// Bump up the priority since the interrupt must be serviced immediately.
	CeSetThreadPriority(gMfcIntrThread, 100);

	RETAILMSG(1, (L"MFC Interrupt has been initialized.\n"));

	return TRUE;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?