这里赞叹一下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类似视频的,我就不赘述了。
后面我们讨论音视频数据的处理。