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; 
}