Windows下的實時編碼,並且推送到FMS上(一)

 

    這裏讚歎一下FFmpeg和X264,太牛了。

    我在I5的機器上對視頻爲720P和1080P的數據進行編碼,並且保存成文件,通過RTMP發送到FMS上。在720P的情況下,2M碼流,CPU佔用率僅有20%左右,1080P也不到50%。這樣看來X264很是強勁啊。

 

    實現一個音頻處理Filter和一個視頻處理Filter,通過回調函數將音視頻數據回調到指定的應用程序中。

    這裏我們以視頻處理Filter爲例:

    回調函數:

    typedef void (CALLBACK* pSampleCallFun)(AM_MEDIA_TYPE *pMt, BYTE *pBuf, long bufSize, REFERENCE_TIME startTime, REFERENCE_TIME endTime);


    添加兩個接口函數:

        virtual HRESULT STDMETHODCALLTYPE GetMediaType( 
            /* [out] */ AM_MEDIA_TYPE __RPC_FAR **ppmt) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE SetSampleCallBackFun( 
            /* [in] */ pSampleCallFun pPF) = 0;


 

    在input Pin中重寫CheckMediaType函數:

HRESULT CXInputPin::CheckMediaType(const CMediaType *pmt)
{
    CAutoLock lock_it(m_pLock);

    // If we are already inside checkmedia type for this pin, return NOERROR
    // It is possble to hookup two of the tee filters and some other filter
    // like the video effects sample to get into this situation. If we don't
    // detect this situation, we will carry on looping till we blow the stack

#ifdef DEBUG
	// Display the type of the media for debugging perposes
	DisplayMediaType(TEXT("Input Pin Checking"), pmt);
#endif

	if(	(pmt->majortype	== MEDIATYPE_Video		&&
		pmt->subtype	== MEDIASUBTYPE_RGB24	&&
		pmt->formattype == FORMAT_VideoInfo)
		|| (pmt->majortype	== MEDIATYPE_Video		&&
		pmt->subtype	== MEDIASUBTYPE_YUY2	&&
		pmt->formattype == FORMAT_VideoInfo)
		|| (pmt->majortype	== MEDIATYPE_Video		&&
		pmt->subtype	== MEDIASUBTYPE_RGB32	&&
		pmt->formattype == FORMAT_VideoInfo))
	{

		// ....

 

    在inputPin的Receive函數中調用我們的回調函數:

HRESULT CXInputPin::Receive(IMediaSample *pSample)
{
    ASSERT(pSample);
    CAutoLock lock_it(m_pLock);

    // Check that all is well with the base class
    HRESULT hr = NOERROR;
    hr = CBaseInputPin::Receive(pSample);
    if(hr != NOERROR)
        return hr;

	{

		BYTE *pBuf = NULL;
		pSample->GetPointer(&pBuf);

		REFERENCE_TIME startTime, endTime;
		pSample->GetTime(&startTime, &endTime);

		// DbgLog((LOG_TRACE, 0, TEXT("Receive ---> size %d, %I64u, %I64u"), pSample->GetSize(), startTime, endTime));

		// 這裏獲取這個 Sample 的相關信息
		if (m_pFlt)
		{
			m_pFlt->xxIMediaSample(pSample);
		}
	}

 

void CFlt::xxIMediaSample(IMediaSample *pSample)
{
	if (m_pSampleCallFun == NULL)
	{
		return;
	}

	AM_MEDIA_TYPE *pMediaType = NULL;
	pSample->GetMediaType(&pMediaType);

	BYTE *pBuf = NULL;
	pSample->GetPointer(&pBuf);

	REFERENCE_TIME startTime, endTime;
	pSample->GetTime(&startTime, &endTime);

//	DbgLog((LOG_TRACE, 0, TEXT("size %d, %I64u, %I64u"), pSample->GetSize(), startTime, endTime));

	m_pSampleCallFun(pMediaType, pBuf, pSample->GetSize(), startTime, endTime);
}

    這樣我們就完成了一個我們的視頻處理Filter。在鏈路構建完成後,我們可以在應用程序的回調函數中得到每一個Sample。

    音頻Filter類似視頻的,我就不贅述了。

    後面我們討論音視頻數據的處理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章