這裏讚歎一下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類似視頻的,我就不贅述了。
後面我們討論音視頻數據的處理。