本过滤器输出几种常用编码方式的视频,视频内容为迈克尔杰克逊歌曲,时长4分48秒。创建了8个引脚。1个音频引脚,媒体类型为PCM;7个视频引脚,媒体类型分别为DX50,FLV1,H264,MJPG,XVID,WMV2,WMV3。本过滤器用于测试其它过滤器输入媒体类型。过滤器图片如下:







视频定位后没有直接找关键帧,定位后搜索指定样本反应速度不是很快,代码还有改进的空间。初次创建过滤器耗时比较长。下载本过滤器DLL。
过滤器DLL的全部代码
DLL.h
cpp
#ifndef DLL_FILE
#define DLL_FILE
#include "strmbase10.h"//过滤器基础类定义文件
#if _DEBUG
#pragma comment(lib, "strmbasd10.lib")//过滤器基础类实现文件调试版本
#else
#pragma comment(lib, "strmbase10.lib")//过滤器基础类实现文件发布版本
#endif
#include "resource.h"
#include "dvdmedia.h"
#include "wmcodecdsp.h"
// {FC685FD7-17B1-4D08-84E7-A573726F9F66}
DEFINE_GUID(CLSID_Source,
0xfc685fd7, 0x17b1, 0x4d08, 0x84, 0xe7, 0xa5, 0x73, 0x72, 0x6f, 0x9f, 0x66);
DEFINE_GUID(DX50,
0x30355844, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
DEFINE_GUID(FLV1,
0x31564c46, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
DEFINE_GUID(XVID,
0x44495658, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
class CFilter;
class CVideoPin : public CSourceStream
{
friend class CFilter;
public:
CVideoPin(HRESULT *phr, CSource *pParent, LPCWSTR pPinName, int mType);
~CVideoPin();
HRESULT OnThreadCreate();
HRESULT OnThreadStartPlay(void);
HRESULT OnThreadDestroy(void);
HRESULT FillBuffer(IMediaSample *pms);
HRESULT DecideBufferSize(IMemAllocator * pAlloc, ALLOCATOR_PROPERTIES * pRequest);//确定缓冲区大小
HRESULT SetMediaType(const CMediaType *pMediaType);
HRESULT CheckMediaType(const CMediaType *pMediaType);
HRESULT GetMediaType(int iPosition, CMediaType *pmt);
HRESULT BreakConnect();
HRESULT CompleteConnect(IPin *pReceivePin);
CFilter* pCFilter;//过滤器指针
int type;//引脚索引
HGLOBAL hMem;
BYTE* pStar = NULL;//视频样本起始内存位置
BYTE* pEnd = NULL;//视频样本结束内存位置
BYTE* pCur = NULL;//当前读取位置内存指针
};
class CAudioPin : public CSourceStream
{
friend class CFilter;
public:
CAudioPin(HRESULT *phr, CSource *pParent, LPCWSTR pPinName);
~CAudioPin();
HRESULT OnThreadCreate();
HRESULT OnThreadStartPlay(void);
HRESULT OnThreadDestroy(void);
HRESULT FillBuffer(IMediaSample *pms);
HRESULT DecideBufferSize(IMemAllocator * pAlloc, ALLOCATOR_PROPERTIES * pRequest);//确定缓冲区大小
HRESULT SetMediaType(const CMediaType *pMediaType);
HRESULT CheckMediaType(const CMediaType *pMediaType);
HRESULT GetMediaType(int iPosition, CMediaType *pmt);
CFilter* pCFilter;//过滤器指针
BYTE* pStar = NULL;//音频数据起始地址
BYTE* pEnd = NULL;//音频样本结束内存位置
HGLOBAL hMem; //资源句柄
BYTE* pCur;//音频数据当前读取位置
LONGLONG star, end;//音频样本时间戳
};
class CFilter : public CSource, public IMediaSeeking
{
public:
CFilter(LPUNKNOWN pUnk, HRESULT *phr);
~CFilter();
static CUnknown * WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);
DECLARE_IUNKNOWN
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
DWORD m_dwSeekingCaps = AM_SEEKING_CanSeekForwards | AM_SEEKING_CanSeekBackwards | AM_SEEKING_CanSeekAbsolute | AM_SEEKING_CanGetStopPos | AM_SEEKING_CanGetDuration;
HRESULT STDMETHODCALLTYPE CheckCapabilities(DWORD *pCapabilities);
HRESULT STDMETHODCALLTYPE ConvertTimeFormat(LONGLONG *pTarget, const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat);
HRESULT STDMETHODCALLTYPE GetAvailable(LONGLONG *pEarliest, LONGLONG *pLatest);
HRESULT STDMETHODCALLTYPE GetCapabilities(DWORD *pCapabilities);
HRESULT STDMETHODCALLTYPE GetCurrentPosition(LONGLONG *pCurrent);
HRESULT STDMETHODCALLTYPE GetDuration(LONGLONG *pDuration);
HRESULT STDMETHODCALLTYPE GetPositions(LONGLONG *pCurrent, LONGLONG *pStop);
HRESULT STDMETHODCALLTYPE GetPreroll(LONGLONG *pllPreroll);
HRESULT STDMETHODCALLTYPE GetRate(double *pdRate);
HRESULT STDMETHODCALLTYPE GetStopPosition(LONGLONG *pStop);
HRESULT STDMETHODCALLTYPE GetTimeFormat(GUID *pFormat);
HRESULT STDMETHODCALLTYPE IsFormatSupported(const GUID *pFormat);
HRESULT STDMETHODCALLTYPE IsUsingTimeFormat(const GUID *pFormat);
HRESULT STDMETHODCALLTYPE QueryPreferredFormat(GUID *pFormat);
HRESULT STDMETHODCALLTYPE SetPositions(LONGLONG *pCurrent, DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags);
HRESULT STDMETHODCALLTYPE SetRate(double dRate);
HRESULT STDMETHODCALLTYPE SetTimeFormat(const GUID *pFormat);
CVideoPin* pDX50;//DX50视频输出引脚
CVideoPin* pFLV1;//FLV1视频输出引脚
CVideoPin* pH264;//H264视频输出引脚
CVideoPin* pMJPG;//MJPG视频输出引脚
CVideoPin* pXVID;//XVID视频输出引脚
CVideoPin* pWMV2;//WMV2视频输出引脚
CVideoPin* pWMV3;//WMV2视频输出引脚
CAudioPin* pPCM;//PCM音频输出引脚
int Connected = -1;//已连接引脚的索引
LONGLONG DUR;//视频时长。单位110纳秒
LONGLONG CUR;//当前位置。单位110纳秒
LONGLONG ResetPos = 0;//新位置
};
#endif //DLL_FILE
CFilter.cpp
cpp
#include "DLL.h"
CFilter::CFilter(LPUNKNOWN lpunk, HRESULT *phr) : CSource(NAME("RGB视频源"), lpunk, CLSID_Source)
{
pDX50 = new CVideoPin(phr, this, L"DX50", 0);//创建DX50视频输出引脚
pFLV1 = new CVideoPin(phr, this, L"FLV1", 1);//创建FLV1视频输出引脚
pH264 = new CVideoPin(phr, this, L"H264", 2);//创建H264视频输出引脚
pMJPG = new CVideoPin(phr, this, L"MJPG", 3);//创建MJPG视频输出引脚
pXVID = new CVideoPin(phr, this, L"XVID", 4);//创建XVID视频输出引脚
pWMV2 = new CVideoPin(phr, this, L"WMV2", 5);//创建WMV2视频输出引脚
pWMV3 = new CVideoPin(phr, this, L"WMV3", 6);//创建WMV3视频输出引脚
pPCM = new CAudioPin(phr, this, L"PCM");//创建音频输出引脚
DUR = 2881000000;//视频时长,单位100纳秒
}
CFilter::~CFilter()
{
}
STDMETHODIMP CFilter::NonDelegatingQueryInterface(REFIID iid, void ** ppv)
{
if (iid == IID_IMediaSeeking)
{
return GetInterface(static_cast<IMediaSeeking*>(this), ppv);
}
else
return CBaseFilter::NonDelegatingQueryInterface(iid, ppv);
}
CUnknown * WINAPI CFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr)
{
return new CFilter(pUnk, phr);//创建过滤器
}
HRESULT STDMETHODCALLTYPE CFilter::CheckCapabilities(DWORD *pCapabilities)//查询流是否具有指定的Seek功能
{
CheckPointer(pCapabilities, E_POINTER);
return (~m_dwSeekingCaps & *pCapabilities) ? S_FALSE : S_OK;
}
HRESULT STDMETHODCALLTYPE CFilter::ConvertTimeFormat(LONGLONG *pTarget, const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat)//从一种时间格式转换为另一种时间格式
{
CheckPointer(pTarget, E_POINTER);
if (pTargetFormat == 0 || *pTargetFormat == TIME_FORMAT_MEDIA_TIME)
{
*pTarget = Source;
return S_OK;
}
return E_INVALIDARG;
}
HRESULT STDMETHODCALLTYPE CFilter::GetAvailable(LONGLONG *pEarliest, LONGLONG *pLatest)//获取有效Seek的时间范围
{
if (pEarliest)
{
*pEarliest = 0;
}
if (pLatest)
{
CAutoLock lock(m_pLock);
*pLatest = DUR;
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE CFilter::GetCapabilities(DWORD *pCapabilities)//检索流的所有Seek功能
{
CheckPointer(pCapabilities, E_POINTER);
*pCapabilities = m_dwSeekingCaps;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CFilter::GetCurrentPosition(LONGLONG *pCurrent)//获取相对于流总持续时间的当前位置
{
*pCurrent = CUR;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CFilter::GetDuration(LONGLONG *pDuration)//获取流的持续时间
{
CheckPointer(pDuration, E_POINTER);
CAutoLock lock(m_pLock);
*pDuration = DUR;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CFilter::GetPositions(LONGLONG *pCurrent, LONGLONG *pStop)//获取相对于流总持续时间的当前位置和停止位置
{
CheckPointer(pCurrent, E_POINTER); CheckPointer(pStop, E_POINTER);
*pCurrent = CUR; *pStop = DUR;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CFilter::GetPreroll(LONGLONG *pllPreroll)//获取将在开始位置之前排队的数据量
{
CheckPointer(pllPreroll, E_POINTER);
*pllPreroll = 0;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CFilter::GetRate(double *pdRate)//获取播放速率
{
CheckPointer(pdRate, E_POINTER);
CAutoLock lock(m_pLock);
*pdRate = 1.0;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CFilter::GetStopPosition(LONGLONG *pStop)//获取相对于流的持续时间的停止播放时间
{
CheckPointer(pStop, E_POINTER);
CAutoLock lock(m_pLock);
*pStop = DUR;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CFilter::GetTimeFormat(GUID *pFormat)//获取当前用于Seek操作的时间格式
{
CheckPointer(pFormat, E_POINTER);
*pFormat = TIME_FORMAT_MEDIA_TIME;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CFilter::IsFormatSupported(const GUID *pFormat)//确定Seek操作是否支持指定的时间格式
{
CheckPointer(pFormat, E_POINTER);
return *pFormat == TIME_FORMAT_MEDIA_TIME ? S_OK : S_FALSE;
}
HRESULT STDMETHODCALLTYPE CFilter::IsUsingTimeFormat(const GUID *pFormat)//确定Seek操作当前是否使用指定的时间格式
{
CheckPointer(pFormat, E_POINTER);
return *pFormat == TIME_FORMAT_MEDIA_TIME ? S_OK : S_FALSE;
}
HRESULT STDMETHODCALLTYPE CFilter::QueryPreferredFormat(GUID *pFormat)//获取首选的Seek时间格式
{
CheckPointer(pFormat, E_POINTER);
*pFormat = TIME_FORMAT_MEDIA_TIME;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CFilter::SetPositions(LONGLONG *pCurrent, DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags)//设置当前位置和停止位置
{
CheckPointer(pCurrent, E_POINTER); HRESULT hr;
DWORD dwCurrentPos = dwCurrentFlags & AM_SEEKING_PositioningBitsMask;
if (dwCurrentPos == AM_SEEKING_AbsolutePositioning && *pCurrent >= 0 && *pCurrent < DUR)
{
ResetPos = *pCurrent; *pStop = DUR - *pCurrent;
CVideoPin* pVideoPin = NULL;
switch (Connected)
{
case 0:
pVideoPin = pDX50;
break;
case 1:
pVideoPin = pFLV1;
break;
case 2:
pVideoPin = pH264;
break;
case 3:
pVideoPin = pMJPG;
break;
case 4:
pVideoPin = pXVID;
break;
case 5:
pVideoPin = pWMV2;
break;
case 6:
pVideoPin = pWMV3;
break;
}
if (pVideoPin)
{
hr = pVideoPin->DeliverBeginFlush(); hr = pPCM->DeliverBeginFlush();
hr = pVideoPin->Stop(); hr = pPCM->Stop();
hr = pVideoPin->DeliverEndFlush(); hr = pPCM->DeliverEndFlush();
hr = pVideoPin->Run(); hr = pPCM->Run();
}
return S_OK;
}
return E_INVALIDARG;
}
HRESULT STDMETHODCALLTYPE CFilter::SetRate(double dRate)//设置播放速率
{
if (dRate == 1.0)return S_OK;
else return S_FALSE;
}
HRESULT STDMETHODCALLTYPE CFilter::SetTimeFormat(const GUID *pFormat)//设置后续Seek操作的时间格式
{
CheckPointer(pFormat, E_POINTER);
return *pFormat == TIME_FORMAT_MEDIA_TIME ? S_OK : E_INVALIDARG;
}
CAudioPin.cpp
cpp
#include "DLL.h"
CAudioPin::CAudioPin(HRESULT *phr, CSource *pParent, LPCWSTR pPinName) : CSourceStream(NAME("PCM"), phr, pParent, pPinName)
{
pCFilter = (CFilter*)pParent;
}
CAudioPin::~CAudioPin()
{
FreeResource(hMem);//释放音频数据占用的内存
}
HRESULT CAudioPin::GetMediaType(int iPosition, CMediaType *pmt)//在枚举输出引脚,连接引脚时调用
{
if (iPosition == 0)
{
pmt->majortype = MEDIATYPE_Audio;//主要类型
pmt->subtype = MEDIASUBTYPE_PCM;//子类型
pmt->formattype = FORMAT_WaveFormatEx;//格式类型
pmt->bFixedSizeSamples = TRUE;//样本是固定大小
pmt->bTemporalCompression = FALSE;//使用时间压缩
pmt->lSampleSize = 0;//样本大小
pmt->pUnk = NULL;//IUnknown指针
pmt->cbFormat = sizeof(WAVEFORMATEX);//格式块的大小
WAVEFORMATEX* p = (WAVEFORMATEX*)CoTaskMemAlloc(sizeof(WAVEFORMATEX));//为格式块分配内存
pmt->pbFormat = (BYTE*)p;//格式块的指针
p->wFormatTag = WAVE_FORMAT_PCM;//编码方式
p->nChannels = 2;//声道数
p->nSamplesPerSec = 44100;//采样率
p->nAvgBytesPerSec = 44100 * 4;//数据传输率
p->nBlockAlign = 4;//块对齐
p->wBitsPerSample = 16;//样本位数
p->cbSize = 0;//附加信息大小
return S_OK;
}
return VFW_S_NO_MORE_ITEMS;
}
HRESULT CAudioPin::DecideBufferSize(IMemAllocator * pAlloc, ALLOCATOR_PROPERTIES * pRequest)
{
HRESULT hr;
pRequest->cBuffers = 1;//1个缓冲区
pRequest->cbBuffer = 44100 * 4;//缓冲区的大小为1秒音频数据大小
ALLOCATOR_PROPERTIES Actual;
hr = pAlloc->SetProperties(pRequest, &Actual);
if (FAILED(hr))return hr;
if (Actual.cbBuffer < pRequest->cbBuffer)// 这个分配器是否不合适
{
return E_FAIL;
}
return NOERROR;
}
HRESULT CAudioPin::SetMediaType(const CMediaType *pMediaType)
{
return CSourceStream::SetMediaType(pMediaType);
}
HRESULT CAudioPin::CheckMediaType(const CMediaType *pMediaType)
{
if (pMediaType->majortype == MEDIATYPE_Audio && pMediaType->subtype == MEDIASUBTYPE_PCM && pMediaType->formattype == FORMAT_WaveFormatEx)
return S_OK;
return S_FALSE;
}
HRESULT CAudioPin::OnThreadCreate()
{
HRSRC hRes = FindResource(g_hInst, MAKEINTRESOURCE(IDR_DAT1), L"DAT");
hMem = LoadResource(g_hInst, hRes);//加载资源到内存
pStar = (BYTE*)LockResource(hMem);//获取音频数据的起始内存地址
pEnd = pStar + SizeofResource(g_hInst, hRes);//获取音频数据的结束位置地址
pCFilter->ResetPos = 0;
return S_OK;
}
HRESULT CAudioPin::OnThreadStartPlay(void)
{
pCur = pStar;
star = pCFilter->ResetPos / 10000000; end = star + 10000000;
pCur += pCFilter->ResetPos / 10000000 * 44100 * 4;
return DeliverNewSegment(0, pCFilter->DUR - pCFilter->ResetPos, 1.0);
}
HRESULT CAudioPin::FillBuffer(IMediaSample *pms)
{
if (pCur >= pEnd )//如果到达末尾
{
DeliverEndOfStream();
return S_FALSE;//流结束
}
long len;
if (pEnd - pCur < 44100 * 4)//如果剩余的音频数据不足44100 * 4字节大小
{
len = pEnd - pCur;
}
else
{
len= 44100 * 4;
}
BYTE* pData = NULL;
pms->GetPointer(&pData);
CopyMemory(pData, pCur, len);
pms->SetTime(&star, &end);//设置引脚样本时间戳
pms->SetSyncPoint(TRUE);//设置同步点标志
pms->SetActualDataLength(len);//设置有效数据大小
star += 10000000; end += 10000000; pCur += 44100 * 4;
return S_OK;
}
HRESULT CAudioPin::OnThreadDestroy(void)
{
FreeResource(hMem);//释放内存中的资源
return S_OK;
};
CVideoPin.cpp
cpp
#include "DLL.h"
CVideoPin::CVideoPin(HRESULT *phr, CSource *pParent, LPCWSTR pPinName, int mType) : CSourceStream(L"视频源", phr, pParent, pPinName)
{
pCFilter = (CFilter*)pParent; type = mType;
}
CVideoPin::~CVideoPin()
{
}
HRESULT CVideoPin::GetMediaType(int iPosition, CMediaType *pmt)//在枚举输出引脚,连接引脚时调用
{
if (iPosition == 0)
{
VIDEOINFOHEADER* p = NULL; MPEG2VIDEOINFO* p0 = NULL; VIDEOINFOHEADER2* p1 = NULL;
DWORD dw[39] = { 16777216, 524307815, 1074222742, 585157527, 196608, 50331650, 1092308992, 7375376, 1744896000, 8404174, 3707764736, 951041123, 2147489024, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989, 3722304989 };//序列头数组,H264使用
BYTE pB[4] = { 167, 255, 180, 128 };//WMV2使用
BYTE pC[5] = { 75, 249, 72, 1, 32 };//WMV3使用
switch (type)
{
case 0://DX50
pmt->majortype = MEDIATYPE_Video;
pmt->subtype = DX50;
pmt->formattype = FORMAT_VideoInfo2;
pmt->bFixedSizeSamples = FALSE;
pmt->bTemporalCompression = TRUE;
pmt->lSampleSize = 1633920;
pmt->pUnk = NULL;
pmt->cbFormat = 112;
p1 = (VIDEOINFOHEADER2*)CoTaskMemAlloc(pmt->cbFormat);
pmt->pbFormat = (BYTE*)p1;//格式块的指针
p1->rcSource = { 0,0,0,0 };
p1->rcTarget = { 0,0,0,0 };
p1->dwBitRate = 0;
p1->dwBitErrorRate = 0;
p1->AvgTimePerFrame = 500000;
p1->dwInterlaceFlags = 1;
p1->dwControlFlags = 0;
p1->dwPictAspectRatioX = 0;// 115;
p1->dwPictAspectRatioY = 0;// 74;
p1->dwControlFlags = 0;
p1->dwReserved1 = 0;
p1->dwReserved2 = 0;
p1->bmiHeader.biSize = 40;//图像信息结构大小
p1->bmiHeader.biWidth = 920;//图像宽度
p1->bmiHeader.biHeight = 592;//图像高度
p1->bmiHeader.biPlanes = 1;//平面数
p1->bmiHeader.biBitCount = 24;//每个像素位数
p1->bmiHeader.biCompression = 808802372;//编码方式
p1->bmiHeader.biSizeImage = 1633920;//图像的字节大小
p1->bmiHeader.biXPelsPerMeter = 0;//水平分辨率
p1->bmiHeader.biYPelsPerMeter = 0;//垂直分辨率
p1->bmiHeader.biClrUsed = 0;//颜色表中颜色数量
p1->bmiHeader.biClrImportant = 0;//重要颜色数量
return S_OK;
case 1://FLV1
pmt->majortype = MEDIATYPE_Video;
pmt->subtype = FLV1;
pmt->formattype = FORMAT_VideoInfo2;
pmt->bFixedSizeSamples = FALSE;
pmt->bTemporalCompression = TRUE;
pmt->lSampleSize = 1633920;
pmt->pUnk = NULL;
pmt->cbFormat = 112;
p1 = (VIDEOINFOHEADER2*)CoTaskMemAlloc(pmt->cbFormat);
pmt->pbFormat = (BYTE*)p1;//格式块的指针
p1->rcSource = { 0,0,0,0 };
p1->rcTarget = { 0,0,0,0 };
p1->dwBitRate = 0;
p1->dwBitErrorRate = 0;
p1->AvgTimePerFrame = 500000;
p1->dwInterlaceFlags = 1;
p1->dwControlFlags = 0;
p1->dwPictAspectRatioX = 115;
p1->dwPictAspectRatioY = 74;
p1->dwControlFlags = 0;
p1->dwReserved1 = 0;
p1->dwReserved2 = 0;
p1->bmiHeader.biSize = 40;//图像信息结构大小
p1->bmiHeader.biWidth = 920;//图像宽度
p1->bmiHeader.biHeight = 592;//图像高度
p1->bmiHeader.biPlanes = 1;//平面数
p1->bmiHeader.biBitCount = 24;//每个像素位数
p1->bmiHeader.biCompression = 827739206;//编码方式
p1->bmiHeader.biSizeImage = 1633920;//图像的字节大小
p1->bmiHeader.biXPelsPerMeter = 0;//水平分辨率
p1->bmiHeader.biYPelsPerMeter = 0;//垂直分辨率
p1->bmiHeader.biClrUsed = 0;//颜色表中颜色数量
p1->bmiHeader.biClrImportant = 0;//重要颜色数量
return S_OK;
case 2://H264
pmt->majortype = MEDIATYPE_Video;
pmt->subtype = MEDIASUBTYPE_H264;
pmt->formattype = FORMAT_MPEG2_VIDEO;
pmt->bFixedSizeSamples = FALSE;
pmt->bTemporalCompression = TRUE;
pmt->lSampleSize = 1;
pmt->pUnk = NULL;
pmt->cbFormat = 175;
p0 = (MPEG2VIDEOINFO*)CoTaskMemAlloc(pmt->cbFormat);
pmt->pbFormat = (BYTE*)p0;//格式块的指针
p0->hdr.rcSource = { 0,0,0,0 };//源矩形
p0->hdr.rcTarget = { 0,0,0,0 };//目标矩形
p0->hdr.dwBitRate = 0;//数据传输率
p0->hdr.dwBitErrorRate = 0;//数据错误率
p0->hdr.AvgTimePerFrame = 500000;//帧显示时间
p0->hdr.dwInterlaceFlags = 0;//扫描方式标志
p0->hdr.dwCopyProtectFlags = 0;//限制流的复制
p0->hdr.dwPictAspectRatioX = 0;//以英寸为单位的图像宽度
p0->hdr.dwPictAspectRatioY = 0;//以英寸为单位的图像高度
p0->hdr.dwControlFlags = 0;//控制标志
p0->hdr.dwReserved1 = 0;
p0->hdr.dwReserved2 = 0;
p0->hdr.bmiHeader.biSize = 40;//图像信息结构大小
p0->hdr.bmiHeader.biWidth = 920;//图像宽度
p0->hdr.bmiHeader.biHeight = 592;//图像高度
p0->hdr.bmiHeader.biPlanes = 1;//平面数
p0->hdr.bmiHeader.biBitCount = 0;//每个像素位数
p0->hdr.bmiHeader.biCompression=875967048;//编码方式
p0->hdr.bmiHeader.biSizeImage = 0;//图像的字节大小
p0->hdr.bmiHeader.biXPelsPerMeter = 0;//水平分辨率
p0->hdr.bmiHeader.biYPelsPerMeter = 0;//垂直分辨率
p0->hdr.bmiHeader.biClrUsed = 0;//颜色表中颜色数量
p0->hdr.bmiHeader.biClrImportant = 0;//重要颜色数量
p0->dwStartTimeCode = 0;//开始时间码
p0->cbSequenceHeader = 39;//序列头的长度
p0->dwProfile = 77;//配置文件类型
p0->dwLevel = 0;//级别类型
p0->dwFlags = 0;//标志
CopyMemory(&p0->dwSequenceHeader, dw, 39);
return S_OK;
case 3://MJPG
pmt->majortype = MEDIATYPE_Video;
pmt->subtype = MEDIASUBTYPE_MJPG;
pmt->formattype = FORMAT_VideoInfo2;
pmt->bFixedSizeSamples = FALSE;
pmt->bTemporalCompression = FALSE;
pmt->lSampleSize = 1633920;
pmt->pUnk = NULL;
pmt->cbFormat = 112;
p1 = (VIDEOINFOHEADER2*)CoTaskMemAlloc(pmt->cbFormat);
pmt->pbFormat = (BYTE*)p1;//格式块的指针
p1->rcSource = { 0,0,0,0 };
p1->rcTarget = { 0,0,0,0 };
p1->dwBitRate = 0;
p1->dwBitErrorRate = 0;
p1->AvgTimePerFrame = 500000;
p1->dwInterlaceFlags = 1;
p1->dwControlFlags = 0;
p1->dwPictAspectRatioX = 115;
p1->dwPictAspectRatioY = 74;
p1->dwControlFlags = 0;
p1->dwReserved1 = 0;
p1->dwReserved2 = 0;
p1->bmiHeader.biSize = 40;//图像信息结构大小
p1->bmiHeader.biWidth = 920;//图像宽度
p1->bmiHeader.biHeight = 592;//图像高度
p1->bmiHeader.biPlanes = 1;//平面数
p1->bmiHeader.biBitCount = 24;//每个像素位数
p1->bmiHeader.biCompression = 1196444237;//编码方式
p1->bmiHeader.biSizeImage = 1633920;//图像的字节大小
p1->bmiHeader.biXPelsPerMeter = 0;//水平分辨率
p1->bmiHeader.biYPelsPerMeter = 0;//垂直分辨率
p1->bmiHeader.biClrUsed = 0;//颜色表中颜色数量
p1->bmiHeader.biClrImportant = 0;//重要颜色数量
return S_OK;
case 4://XVID
pmt->majortype = MEDIATYPE_Video;
pmt->subtype = XVID;
pmt->formattype = FORMAT_VideoInfo;
pmt->bFixedSizeSamples = FALSE;
pmt->bTemporalCompression = TRUE;
pmt->lSampleSize = 0;
pmt->pUnk = NULL;
pmt->cbFormat = sizeof(VIDEOINFOHEADER);
p = (VIDEOINFOHEADER*)CoTaskMemAlloc(pmt->cbFormat);
pmt->pbFormat = (BYTE*)p;//格式块的指针
p->rcSource = { 0,0,0,0 };
p->rcTarget = { 0,0,0,0 };
p->dwBitRate = 0;
p->dwBitErrorRate = 0;
p->AvgTimePerFrame = 500000;
p->bmiHeader.biSize = 40;//图像信息结构大小
p->bmiHeader.biWidth = 920;//图像宽度
p->bmiHeader.biHeight = 592;//图像高度
p->bmiHeader.biPlanes = 1;//平面数
p->bmiHeader.biBitCount = 12;//每个像素位数
p->bmiHeader.biCompression = 1145656920;//编码方式
p->bmiHeader.biSizeImage = 0;//图像的字节大小
p->bmiHeader.biXPelsPerMeter = 0;//水平分辨率
p->bmiHeader.biYPelsPerMeter = 0;//垂直分辨率
p->bmiHeader.biClrUsed = 0;//颜色表中颜色数量
p->bmiHeader.biClrImportant = 0;//重要颜色数量
return S_OK;
case 5://WMV2
pmt->majortype = MEDIATYPE_Video;
pmt->subtype = MEDIASUBTYPE_WMV2;
pmt->formattype = FORMAT_VideoInfo2;
pmt->bFixedSizeSamples = FALSE;
pmt->bTemporalCompression = TRUE;
pmt->lSampleSize = 1633920;
pmt->pUnk = NULL;
pmt->cbFormat = 116;
p1 = (VIDEOINFOHEADER2*)CoTaskMemAlloc(pmt->cbFormat);
pmt->pbFormat = (BYTE*)p1;//格式块的指针
p1->rcSource = { 0,0,0,0 };
p1->rcTarget = { 0,0,0,0 };
p1->dwBitRate = 0;
p1->dwBitErrorRate = 0;
p1->AvgTimePerFrame = 500000;
p1->dwInterlaceFlags = 1;
p1->dwControlFlags = 0;
p1->dwPictAspectRatioX = 115;
p1->dwPictAspectRatioY = 74;
p1->dwControlFlags = 0;
p1->dwReserved1 = 0;
p1->dwReserved2 = 0;
p1->bmiHeader.biSize = 44;//图像信息结构大小
p1->bmiHeader.biWidth = 920;//图像宽度
p1->bmiHeader.biHeight = 592;//图像高度
p1->bmiHeader.biPlanes = 1;//平面数
p1->bmiHeader.biBitCount = 24;//每个像素位数
p1->bmiHeader.biCompression = 844516695;//编码方式
p1->bmiHeader.biSizeImage = 1633920;//图像的字节大小
p1->bmiHeader.biXPelsPerMeter = 0;//水平分辨率
p1->bmiHeader.biYPelsPerMeter = 0;//垂直分辨率
p1->bmiHeader.biClrUsed = 0;//颜色表中颜色数量
p1->bmiHeader.biClrImportant = 0;//重要颜色数量
CopyMemory(pmt->pbFormat + 112, pB, 4);
return S_OK;
case 6://WMV3
pmt->majortype = MEDIATYPE_Video;
pmt->subtype = MEDIASUBTYPE_WMV3;
pmt->formattype = FORMAT_VideoInfo2;
pmt->bFixedSizeSamples = FALSE;
pmt->bTemporalCompression = TRUE;
pmt->lSampleSize = 0;
pmt->pUnk = NULL;
pmt->cbFormat = 117;
p1 = (VIDEOINFOHEADER2*)CoTaskMemAlloc(pmt->cbFormat);
pmt->pbFormat = (BYTE*)p1;//格式块的指针
p1->rcSource = { 0,0,0,0 };
p1->rcTarget = { 0,0,0,0 };
p1->dwBitRate = 3000000;
p1->dwBitErrorRate = 0;
p1->AvgTimePerFrame = 500000;
p1->dwInterlaceFlags = 0;
p1->dwControlFlags = 0;
p1->dwPictAspectRatioX = 115;
p1->dwPictAspectRatioY = 74;
p1->dwControlFlags = 0;
p1->dwReserved1 = 0;
p1->dwReserved2 = 0;
p1->bmiHeader.biSize = 45;//图像信息结构大小
p1->bmiHeader.biWidth = 920;//图像宽度
p1->bmiHeader.biHeight = 592;//图像高度
p1->bmiHeader.biPlanes = 1;//平面数
p1->bmiHeader.biBitCount = 0;//每个像素位数
p1->bmiHeader.biCompression = 861293911;//编码方式
p1->bmiHeader.biSizeImage = 0;//图像的字节大小
p1->bmiHeader.biXPelsPerMeter = 0;//水平分辨率
p1->bmiHeader.biYPelsPerMeter = 0;//垂直分辨率
p1->bmiHeader.biClrUsed = 0;//颜色表中颜色数量
p1->bmiHeader.biClrImportant = 0;//重要颜色数量
CopyMemory(pmt->pbFormat + 112, pC, 5);
return S_OK;
}
}
return S_FALSE;
}
HRESULT CVideoPin::DecideBufferSize(IMemAllocator * pAlloc, ALLOCATOR_PROPERTIES * pRequest)
{
HRESULT hr;
pRequest->cBuffers = 1;//1个缓冲区
pRequest->cbBuffer = 10000000;//设置缓冲区10M大小
ALLOCATOR_PROPERTIES Actual;
hr = pAlloc->SetProperties(pRequest, &Actual);
if (FAILED(hr))return hr;
if (Actual.cbBuffer < pRequest->cbBuffer)// 这个分配器是否不合适
{
return E_FAIL;
}
return NOERROR;
}
HRESULT CVideoPin::SetMediaType(const CMediaType *pMediaType)
{
return CSourceStream::SetMediaType(pMediaType);
}
HRESULT CVideoPin::CheckMediaType(const CMediaType *pMediaType)
{
if (pCFilter->Connected != -1)return S_FALSE;//确保只连接1个视频引脚
if (pMediaType->majortype == MEDIATYPE_Video )
{
switch (type)
{
case 0://DX50
if (pMediaType->subtype == DX50 && pMediaType->formattype == FORMAT_VideoInfo2)
return S_OK;
break;
case 1://FLV1
if (pMediaType->subtype == FLV1 && pMediaType->formattype == FORMAT_VideoInfo2)
return S_OK;
break;
case 2://H264
if (pMediaType->subtype == MEDIASUBTYPE_H264 && pMediaType->formattype == FORMAT_MPEG2Video)
return S_OK;
break;
case 3://MJPG
if (pMediaType->subtype == MEDIASUBTYPE_MJPG && pMediaType->formattype == FORMAT_VideoInfo2)
return S_OK;
break;
case 4://XVID
if (pMediaType->subtype == XVID && pMediaType->formattype == FORMAT_VideoInfo)
return S_OK;
break;
case 5://WMV2
if (pMediaType->subtype == MEDIASUBTYPE_WMV2 && pMediaType->formattype == FORMAT_VideoInfo2)
return S_OK;
break;
case 6://WMV3
if (pMediaType->subtype == MEDIASUBTYPE_WMV3 && pMediaType->formattype == FORMAT_VideoInfo2)
return S_OK;
break;
}
}
return S_FALSE;
}
HRESULT CVideoPin::BreakConnect()//断开连接时调用
{
BOOL B0 = pCFilter->pDX50->IsConnected();
BOOL B1 = pCFilter->pFLV1->IsConnected();
BOOL B2 = pCFilter->pH264->IsConnected();
BOOL B3 = pCFilter->pMJPG->IsConnected();
BOOL B4 = pCFilter->pXVID->IsConnected();
BOOL B5 = pCFilter->pWMV2->IsConnected();
BOOL B6 = pCFilter->pWMV3->IsConnected();
if (!B0 && !B1 && !B2 && !B3 && !B4 && !B5 && !B6)//如果没有1个视频引脚完成连接
pCFilter->Connected = -1;
return CSourceStream::BreakConnect();
}
HRESULT CVideoPin::CompleteConnect(IPin *pReceivePin)//完成连接时调用
{
if (wcscmp(Name(), L"DX50") == 0)pCFilter->Connected = 0;
if (wcscmp(Name(), L"FLV1") == 0)pCFilter->Connected = 1;
if (wcscmp(Name(), L"H264") == 0)pCFilter->Connected = 2;
if (wcscmp(Name(), L"MJPG") == 0)pCFilter->Connected = 3;
if (wcscmp(Name(), L"XVID") == 0)pCFilter->Connected = 4;
if (wcscmp(Name(), L"WMV2") == 0)pCFilter->Connected = 5;
if (wcscmp(Name(), L"WMV3") == 0)pCFilter->Connected = 6;
return CSourceStream::CompleteConnect(pReceivePin);
}
HRESULT CVideoPin::OnThreadCreate()
{
DeliverBeginFlush();
HRSRC hRes;
switch (type)
{
case 0://DX50
hRes = FindResource(g_hInst, MAKEINTRESOURCE(IDR_DAT9), L"DAT");//DX50样本
break;
case 1://FLV1
hRes = FindResource(g_hInst, MAKEINTRESOURCE(IDR_DAT10), L"DAT");//DX50样本
break;
case 2://H264
hRes = FindResource(g_hInst, MAKEINTRESOURCE(IDR_DAT6), L"DAT");//H264样本
break;
case 3://MJPG
hRes = FindResource(g_hInst, MAKEINTRESOURCE(IDR_DAT11), L"DAT");//MJPG样本
break;
case 4://XVID
hRes = FindResource(g_hInst, MAKEINTRESOURCE(IDR_DAT5), L"DAT");//XVID样本
break;
case 5://WMV2
hRes = FindResource(g_hInst, MAKEINTRESOURCE(IDR_DAT7), L"DAT");//WMV2样本
break;
case 6://WMV3
hRes = FindResource(g_hInst, MAKEINTRESOURCE(IDR_DAT8), L"DAT");//WMV3样本
break;
}
hMem = LoadResource(g_hInst, hRes);
pStar = (BYTE*)LockResource(hMem);//获取视频样本的起始内存地址
pEnd = pStar + SizeofResource(g_hInst, hRes);
DeliverEndFlush();
pCFilter->ResetPos = 0;
return S_OK;
}
HRESULT CVideoPin::OnThreadStartPlay(void)
{
pCur = pStar;
if (pCFilter->ResetPos)
{
Agan:
LONGLONG star;
CopyMemory(&star, pCur, 8); //时间戳开始时间
pCur += 16;
BYTE K;
CopyMemory(&star, &K, 1); //关键帧标志
pCur += 1;
long Len;
CopyMemory(&Len, pCur, 4);//样本大小
pCur += 4 + Len;
if (star < pCFilter->ResetPos)goto Agan;//在内存中搜索定位后的样本开始位置
}
return DeliverNewSegment(0, pCFilter->DUR-pCFilter->ResetPos, 1.0);
}
HRESULT CVideoPin::FillBuffer(IMediaSample *pms)
{
LONGLONG star, end;
CopyMemory(&star, pCur, 8); //时间戳开始时间
pCur += 8;
CopyMemory(&end, pCur, 8);//时间戳结束时间
pCur += 8;
BYTE SP;
CopyMemory(&SP, pCur, 1);//关键帧标志
pCur += 1;
long Len;
CopyMemory(&Len, pCur, 4);//样本大小
pCur += 4;
BYTE* pBuffer = NULL;
pms->GetPointer(&pBuffer);
CopyMemory(pBuffer, pCur, Len);//从内存复制样本
pCur += Len;
star -= pCFilter->ResetPos; end -= pCFilter->ResetPos;
pms->SetTime(&star, &end);//设置样本时间戳
pms->SetSyncPoint(SP);//设置同步点标志
pms->SetActualDataLength(Len);//设置样本有效数据大小
if (pCur >= pEnd)//如果读取到末尾
{
DeliverEndOfStream();//发送流结束通知
return S_FALSE;//流结束
}
return S_OK;
}
HRESULT CVideoPin::OnThreadDestroy(void)
{
FreeResource(hMem);//释放内存中的资源
return S_OK;
};