www.pudn.com > H264RtpSource.rar > RtpSourceOutPin.cpp
#include "StdAfx.h"
#include ".\rtpsourceoutpin.h"
#include "H264Source.h"
#include "initguid.h"
#include "FilterGuid.h"
#include "Queue.h"
#include "AllProtocol.h"
//定义一些图象格式的常数
const unsigned char GPF_SUBQCIF = 1; //GoldPictureFomat_.....
const unsigned char GPF_QCIF = 2;
const unsigned char GPF_CIF = 3;
const unsigned char GPF_4CIF = 4;
const unsigned char GPF_VGA = 5;
const unsigned char GPF_D1 = 6;
CRtpSourceOutPin::CRtpSourceOutPin(char *pName,HRESULT *phr,CH264Source *pFilter,LPCWSTR ppName)
:CSourceStream(pName,phr,pFilter,ppName)
,m_cFormat(0)
,AvgTimePerFrame(0)
,FrameRate(25)
,m_Protocol(NULL)
{
m_rtSampleTime =0;
}
CRtpSourceOutPin::~CRtpSourceOutPin(void)
{
}
//得到媒体类型
HRESULT CRtpSourceOutPin::GetMediaType(CMediaType *pMediaType)
{
CheckPointer(pMediaType,E_POINTER);
CAutoLock cAutoLock(m_pFilter->pStateLock());
//设置媒体类型
pMediaType->SetType(&MEDIATYPE_Video);
pMediaType->SetSubtype(&Clsid_HaisiH264);
pMediaType->SetFormatType(&FORMAT_VideoInfo); //包含头
pMediaType->SetTemporalCompression(TRUE); //要压缩
//分配空间
VIDEOINFO *pvi=NULL;
pvi = (VIDEOINFO*)pMediaType -> AllocFormatBuffer(sizeof(VIDEOINFO));
if (pvi==NULL)return E_OUTOFMEMORY;
//确定图象大小
int m_iImageWidth;
int m_iImageHeight;
switch(m_cFormat)
{
case GPF_QCIF:
m_iImageWidth = 176;
m_iImageHeight = 144;
AvgTimePerFrame = 10000000/FrameRate;
break;
case GPF_CIF:
m_iImageWidth = 352;
m_iImageHeight = 288;
AvgTimePerFrame = 10000000/FrameRate;
break;
case GPF_VGA:
m_iImageWidth = 640;
m_iImageHeight = 480;
AvgTimePerFrame = 10000000/FrameRate;
break;
case GPF_D1:
m_iImageWidth = 720;
m_iImageHeight = 576;
AvgTimePerFrame = 10000000/FrameRate;
break;
default:
m_iImageWidth = 352;
m_iImageHeight = 288;
AvgTimePerFrame = 10000000/FrameRate;
break;
}
////////////////////////////////////////
ZeroMemory(pvi,sizeof(VIDEOINFO));
//真正设置属性的地方
pvi->bmiHeader.biSize = sizeof(BITMAPCOREHEADER);
pvi->bmiHeader.biWidth = m_iImageWidth;
pvi->bmiHeader.biHeight = m_iImageHeight;
pvi->bmiHeader.biPlanes = 1;
pvi->bmiHeader.biBitCount = 16;
pvi->bmiHeader.biCompression = mmioFOURCC('H','2','6','4');
pvi->bmiHeader.biSizeImage = m_iImageWidth*m_iImageHeight*16>>3;
pvi->AvgTimePerFrame = AvgTimePerFrame;
pMediaType->SetSampleSize(pvi->bmiHeader.biSizeImage);
return S_OK;
}
//决定分配内存的大小
HRESULT CRtpSourceOutPin::DecideBufferSize(IMemAllocator * pAlloc, ALLOCATOR_PROPERTIES * ppropInputRequest)
{
//判断指针正确否
CheckPointer(pAlloc,E_POINTER);
CheckPointer(ppropInputRequest,E_POINTER);
//保护这段代码
CAutoLock cAutoLock(m_pFilter->pStateLock());
int m_iImageWidth;
int m_iImageHeight;
switch(m_cFormat)
{
case GPF_QCIF:
m_iImageWidth = 176;
m_iImageHeight = 144;
break;
case GPF_CIF:
m_iImageWidth = 352;
m_iImageHeight = 288;
break;
case GPF_VGA:
m_iImageWidth = 640;
m_iImageHeight = 480;
break;
case GPF_D1:
m_iImageWidth=720;
m_iImageHeight=576;
break;
default:
m_iImageWidth = 352;
m_iImageHeight = 288;
break;
}
ppropInputRequest->cBuffers = 1;
ppropInputRequest->cbBuffer = m_iImageHeight*m_iImageWidth*16>>3;
//实际分配内存的情况
ALLOCATOR_PROPERTIES Actual;
if (!pAlloc->SetProperties(ppropInputRequest,&Actual))return S_FALSE;
if (Actual.cbBuffercbBuffer)return S_FALSE;
return S_OK;
}
//分配内存的大小
HRESULT CRtpSourceOutPin::FillBuffer(IMediaSample *pSamp)
{
//这个函数返回s_false的时候,线程将会停止
BYTE *pData; //Data Buffer指针
long cbData; //一帧数据大小
int framelen;
CGoldNode *pVideNode = NULL;
CAllProtocol *m_Pro = NULL;
CheckPointer(pSamp, E_POINTER);
CAutoLock cAutoLockShared(m_pFilter->pStateLock());
//Access the sample's data buffer
pSamp->GetPointer(&pData);
cbData = pSamp->GetSize();
if (m_Protocol == NULL)
{
pSamp->SetActualDataLength(0);
return S_OK;
}
m_Pro = m_Protocol;
//如果没有读到数据
pVideNode = m_Pro->GetFrame();
if (pVideNode==NULL)
{
//OutputDebugString("....没有数据.....");
Sleep(10);
pSamp->SetActualDataLength(0);
return S_OK;
}
framelen = pVideNode->GetVideoFrame(pData);
//视频播放速度
CRefTime rtStart = m_rtSampleTime;
m_rtSampleTime += AvgTimePerFrame/*/(long)m_dRateSeeking*/;
CRefTime rtStop = m_rtSampleTime;
pSamp->SetActualDataLength(framelen);
pSamp->SetTime((REFERENCE_TIME *)&rtStart, (REFERENCE_TIME *)&rtStop);
if (pVideNode != NULL)
{
delete pVideNode;
pVideNode = NULL;
}
return S_OK;
}
//要得到视频数据,只能重CAllProtocol中得到,但是在这个pin中,
//我们不new新的实例,所以需要重别的地方得到CAllProtocol的实例
void CRtpSourceOutPin::SetProtocolPtr(CAllProtocol* pAllProtocol)
{
/*if (pAllProtocol==NULL)return;*/
m_Protocol = pAllProtocol;
}