DirectShow过滤器开发-RGB视频源过滤器

下载本过滤器DLL。

我们在对过滤器的测试中(不管是默认过滤器或自己编写的过滤器),可能会使用到视频源过滤器。本视频源过滤器创建了6个视频引脚,媒体类型分别为ARGB32,RGB32,RGB24,RGB565,RGB555,RGB8。和1个音频引脚,媒体类型为PCM。视频引脚只可连接其中1个,试图再连接其它视频引脚会失败。

过滤器从CSource类派生,实现了IMediaSeeking接口。过滤器的图片如下:

本过滤器将1个视频编码方式为XVID,音频编码方式为PCM的avi视频文件,添加到资源;创建过滤器时,根据该资源创建1个视频临时文件,使用媒体基础对象(源读取器)进行读取,将读取到的样本分发到连接的引脚。RGB8样本不是来自源读取器,而是使用另一个资源并加载到内存,该资源有700多兆大小。

下面是本过滤器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


// {836C74F0-8A6F-45A9-8274-07E2C3A7CCB5}
DEFINE_GUID(CLSID_Source,
	0x836c74f0, 0x8a6f, 0x45a9, 0x82, 0x74, 0x7, 0xe2, 0xc3, 0xa7, 0xcc, 0xb5);

#include "mfapi.h"
#pragma comment(lib, "mfplat")
#include "mfidl.h"
#include "mfreadwrite.h"
#pragma comment(lib, "mfreadwrite")
#pragma comment(lib, "mfuuid")

#include "resource.h"

class CFilter;

class CVideoPin : public CSourceStream
{
	friend class CFilter;
public:
	CVideoPin(HRESULT *phr, CSource *pParent, LPCWSTR pPinName, int mType);
	~CVideoPin();
	HRESULT OnThreadStartPlay(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;//过滤器指针
	LONGLONG Cur;//当前样本的显示时间
	int type;//引脚索引
	HGLOBAL hMem;
	BYTE* pStar = NULL;
	BYTE* pRGB8Data = NULL;
	DWORD dwSize;//RGB8数据的大小
	LONGLONG Star = 0;
};

class CAudioPin : public CSourceStream
{
	friend class CFilter;
public:
	CAudioPin(HRESULT *phr, CSource *pParent, LPCWSTR pPinName);
	~CAudioPin();
	HRESULT OnThreadStartPlay(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;//过滤器指针
};

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* pARGB32;//ARGB32视频输出引脚
	CVideoPin* pRGB32;//RGB32视频输出引脚
	CVideoPin* pRGB24;//RGB24视频输出引脚
	CVideoPin* pRGB565;//RGB565视频输出引脚
	CVideoPin* pRGB555;//RGB555视频输出引脚
	CVideoPin* pRGB8;//RGB8视频输出引脚
	CAudioPin* pPCM;//PCM音频输出引脚
	int Connected = -1;//已连接引脚的索引
	WCHAR FilePath[MAX_PATH];//RGB视频源临时文件路径
	IMFSourceReader* pIMFSourceReader = NULL;//源读取器接口指针
	LONGLONG DUR;//视频时长。单位110纳秒
	LONGLONG CUR;//当前位置。单位110纳秒
	LONGLONG ResetPos=0;//新位置
};

template <class T> void SafeRelease(T** ppT)
{
	if (*ppT)
	{
		(*ppT)->Release();
		*ppT = NULL;
	}
}


#endif //DLL_FILE

DLL.cpp

cpp 复制代码
#include "DLL.h"


const AMOVIESETUP_MEDIATYPE Type1 =
{
	&MEDIATYPE_Video,             //主要类型
	&MEDIASUBTYPE_ARGB32          //子类型
};

const AMOVIESETUP_MEDIATYPE Type2 =
{
	&MEDIATYPE_Video,             //主要类型
	&MEDIASUBTYPE_RGB32           //子类型
};

const AMOVIESETUP_MEDIATYPE Type3 =
{
	&MEDIATYPE_Video,             //主要类型
	&MEDIASUBTYPE_RGB24           //子类型
};

const AMOVIESETUP_MEDIATYPE Type4 =
{
	&MEDIATYPE_Video,             //主要类型
	&MEDIASUBTYPE_RGB565          //子类型
};

const AMOVIESETUP_MEDIATYPE Type5 =
{
	&MEDIATYPE_Video,             //主要类型
	&MEDIASUBTYPE_RGB555          //子类型
};

const AMOVIESETUP_MEDIATYPE Type6 =
{
	&MEDIATYPE_Video,             //主要类型
	&MEDIASUBTYPE_RGB8            //子类型
};

const AMOVIESETUP_MEDIATYPE Type7 =
{
	&MEDIATYPE_Audio,             //主要类型
	&MEDIASUBTYPE_PCM             //子类型
};

const AMOVIESETUP_PIN Pins[] =    //引脚信息
{
	{
		L"ARGB32",                //引脚名称
		FALSE,                    //渲染引脚
	    TRUE,                     //输出引脚
	    FALSE,                    //具有该引脚的零个实例
	    FALSE,                    //可以创建一个以上引脚的实例
	    &CLSID_NULL,              //该引脚连接的过滤器的类标识
	    NULL,                     //该引脚连接的引脚名称
	    1,                        //引脚支持的媒体类型数
	    &Type1                    //媒体类型信息
	},
	{
		L"RGB32",                  //引脚名称
		FALSE,                     //渲染引脚
	    TRUE,                      //输出引脚
	    FALSE,                     //具有该引脚的零个实例
	    FALSE,                     //可以创建一个以上引脚的实例
	    &CLSID_NULL,               //该引脚连接的过滤器的类标识
	    NULL,                      //该引脚连接的引脚名称
	    1,                         //引脚支持的媒体类型数
	    &Type2                     //媒体类型信息
	},
	{
		L"RGB24",                  //引脚名称
		FALSE,                     //渲染引脚
	    TRUE,                      //输出引脚
	    FALSE,                     //具有该引脚的零个实例
	    FALSE,                     //可以创建一个以上引脚的实例
	    &CLSID_NULL,               //该引脚连接的过滤器的类标识
	    NULL,                      //该引脚连接的引脚名称
	    1,                         //引脚支持的媒体类型数
	    &Type3                     //媒体类型信息
	},
	{
		L"RGB565",                 //引脚名称
		FALSE,                     //渲染引脚
	    TRUE,                      //输出引脚
	    FALSE,                     //具有该引脚的零个实例
	    FALSE,                     //可以创建一个以上引脚的实例
	    &CLSID_NULL,               //该引脚连接的过滤器的类标识
	    NULL,                      //该引脚连接的引脚名称
	    1,                         //引脚支持的媒体类型数
	    &Type4                     //媒体类型信息
	},
	{
		L"RGB555",                 //引脚名称
		FALSE,                     //渲染引脚
	    TRUE,                      //输出引脚
	    FALSE,                     //具有该引脚的零个实例
	    FALSE,                     //可以创建一个以上引脚的实例
	    &CLSID_NULL,               //该引脚连接的过滤器的类标识
	    NULL,                      //该引脚连接的引脚名称
	    1,                         //引脚支持的媒体类型数
	    &Type5                     //媒体类型信息
	},
	{
		L"RGB8",                   //引脚名称
		FALSE,                     //渲染引脚
	    TRUE,                      //输出引脚
	    FALSE,                     //具有该引脚的零个实例
	    FALSE,                     //可以创建一个以上引脚的实例
	    &CLSID_NULL,               //该引脚连接的过滤器的类标识
	    NULL,                      //该引脚连接的引脚名称
	    1,                         //引脚支持的媒体类型数
	    &Type6                     //媒体类型信息
	},
	{
		L"PCM",                    //引脚名称
		FALSE,                     //渲染引脚
	    TRUE,                      //输出引脚
	    FALSE,                     //具有该引脚的零个实例
	    FALSE,                     //可以创建一个以上引脚的实例
	    &CLSID_NULL,               //该引脚连接的过滤器的类标识
	    NULL,                      //该引脚连接的引脚名称
	    1,                         //引脚支持的媒体类型数
	    &Type7                     //媒体类型信息
	}
};

const AMOVIESETUP_FILTER FilterInfo =  //过滤器的注册信息
{
	&CLSID_Source,                     //过滤器的类标识
	L"RGB视频源",                      //过滤器的名称
	MERIT_DO_NOT_USE,                  //过滤器优先值
	7,                                 //引脚数量
	Pins                               //引脚信息
};

CFactoryTemplate g_Templates[] =   //类工厂模板数组
{
	{
		L"RGB视频源",               //对象(这里为过滤器)名称
		&CLSID_Source,              //对象CLSID的指针
	    CFilter::CreateInstance,    //创建对象实例的函数的指针
	    NULL,                       //指向从DLL入口点调用的函数的指针
	    &FilterInfo                 //指向AMOVIESETUP_FILTER结构的指针
	}
};

int g_cTemplates = 1;//模板数组大小

STDAPI DllRegisterServer()//注册DLL
{
	return AMovieDllRegisterServer2(TRUE);
}

STDAPI DllUnregisterServer()//删除DLL注册
{
	return AMovieDllRegisterServer2(FALSE);
}

extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);

BOOL APIENTRY DllMain(HANDLE hModule, DWORD  dwReason, LPVOID lpReserved)
{
	return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}

CFilter.cpp

cpp 复制代码
#include "DLL.h"


CFilter::CFilter(LPUNKNOWN lpunk, HRESULT *phr) : CSource(NAME("RGB视频源"), lpunk, CLSID_Source)
{
	pARGB32 = new CVideoPin(phr, this, L"ARGB32",0);//创建ARGB32视频输出引脚
	pRGB32 = new CVideoPin(phr, this, L"RGB32",1);//创建RGB32视频输出引脚
	pRGB24 = new CVideoPin(phr, this, L"RGB24",2);//创建RGB24视频输出引脚
	pRGB565 = new CVideoPin(phr, this, L"RGB565",3);//创建RGB565视频输出引脚
	pRGB555 = new CVideoPin(phr, this, L"RGB555",4);//创建RGB555视频输出引脚
	pRGB8 = new CVideoPin(phr, this, L"RGB8",5);//创建RGB8视频输出引脚
	pPCM = new CAudioPin(phr, this, L"PCM");//创建音频输出引脚
	HRSRC hRes = FindResource(g_hInst, MAKEINTRESOURCE(IDR_DAT1), L"DAT");
	HGLOBAL hMem = LoadResource(g_hInst, hRes);
	BYTE* pb = (BYTE*)LockResource(hMem);//获取视频数据的起始内存地址
	DWORD dwSize = SizeofResource(g_hInst, hRes);//获取视频数据的大小
	HMODULE hModule = GetModuleHandle(L"RGB视频源.dll");
	GetModuleFileName(hModule, FilePath, MAX_PATH);
	size_t sz1 = wcslen(FilePath);
	size_t sz2 = wcslen(L"dll");
	FilePath[sz1 - sz2] = 0;//删除"dll"
	wcscat_s(FilePath, MAX_PATH, L"avi");//在字符串末尾追加"avi"
	HANDLE hFile = CreateFile(FilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);//在dll路径下创建"RGB视频源.avi"视频文件
	WriteFile(hFile, pb, dwSize, NULL, NULL);
	CloseHandle(hFile);
	GlobalUnlock(hMem);
	FreeResource(hMem);//最后释放数据占用的内存
	HRESULT hr = MFStartup(MF_VERSION);
	IMFAttributes* pIMFAttributes = NULL;
	hr = MFCreateAttributes(&pIMFAttributes, 0);
	if (SUCCEEDED(hr))
	{
		hr = pIMFAttributes->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, (UINT32)1);//使用基于硬件的媒体基础转换
		hr = pIMFAttributes->SetUINT32(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING, (UINT32)1);//启用源读取器的高级视频处理
	}
	if (SUCCEEDED(hr))
	{
		hr = MFCreateSourceReaderFromURL(FilePath, pIMFAttributes, &pIMFSourceReader);//创建源读取器
	}
	SafeRelease(&pIMFAttributes);
	PROPVARIANT var;
	PropVariantInit(&var);
	if (SUCCEEDED(hr))
	{
		hr = pIMFSourceReader->GetPresentationAttribute(MF_SOURCE_READER_MEDIASOURCE, MF_PD_DURATION, &var);//获取媒体时间长度,100纳秒单位
	}
	if (SUCCEEDED(hr))
	{
		DUR = (LONGLONG)var.uhVal.QuadPart;
	}
	PropVariantClear(&var);
	IMFMediaType* pAudioMTA = NULL;
	if (SUCCEEDED(hr))
	{
		hr = MFCreateMediaType(&pAudioMTA);//创建空的媒体类型
		hr = pAudioMTA->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);//设置主要类型音频
		hr = pAudioMTA->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM);//设置子类型PCM
		hr = pAudioMTA->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, (UINT32)16);//设置样本16位
		hr = pAudioMTA->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, (UINT32)44100);//设置样本采样率44100
		hr = pAudioMTA->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, (UINT32)2);//设置2声道
	}
	if (SUCCEEDED(hr))
	{
		hr = pIMFSourceReader->SetCurrentMediaType(MF_SOURCE_READER_FIRST_AUDIO_STREAM, NULL, pAudioMTA);//设置音频输出媒体类型
	}
	SafeRelease(&pAudioMTA);
}

CFilter::~CFilter()
{
	SafeRelease(&pIMFSourceReader);
	MFShutdown();//关闭媒体基础
	DeleteFile(FilePath);
}

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)
	{
		if (pSourceFormat == 0 || *pSourceFormat == 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 = pARGB32;
			break;
		case 1:
			pVideoPin = pRGB32;
			break;
		case 2:
			pVideoPin = pRGB24;
			break;
		case 3:
			pVideoPin = pRGB565;
			break;
		case 4:
			pVideoPin = pRGB555;
			break;
		case 5:
			pVideoPin = pRGB8;
			break;
		}
		if (pVideoPin)
		{
			hr = pVideoPin->DeliverBeginFlush();       hr= pPCM->DeliverNewSegment(0, DUR - ResetPos, 1.0);
			hr = pVideoPin->Stop();                                    
			hr = pVideoPin->DeliverEndFlush();          
			hr = pVideoPin->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;
}

CVideoPin.cpp

cpp 复制代码
#include "DLL.h"


CVideoPin::CVideoPin(HRESULT *phr, CSource *pParent, LPCWSTR pPinName, int mType) : CSourceStream(NAME("RGB32"), phr, pParent, pPinName)
{
	pCFilter = (CFilter*)pParent; type = mType;
	HRSRC hRes = FindResource(g_hInst, MAKEINTRESOURCE(IDR_DAT2), L"DAT");
	hMem = LoadResource(g_hInst, hRes);
	pStar = (BYTE*)LockResource(hMem);//获取RGB8视频数据的起始内存地址
	dwSize = SizeofResource(g_hInst, hRes);//获取RGB8视频数据的大小
}

CVideoPin::~CVideoPin()
{
	FreeResource(hMem);
}

HRESULT CVideoPin::GetMediaType(int iPosition, CMediaType *pmt)//在枚举输出引脚,连接引脚时调用
{
	if (iPosition < 1)
	{
		pmt->majortype = MEDIATYPE_Video;//主要类型
		pmt->formattype = FORMAT_VideoInfo; //格式类型
		pmt->bFixedSizeSamples = TRUE;//样本是固定大小
		pmt->bTemporalCompression = FALSE;//使用时间压缩
		pmt->pUnk = NULL;//IUnknown指针
		switch (type)
		{
		case 0://ARGB32
		{
			pmt->subtype = MEDIASUBTYPE_ARGB32;//子类型
			pmt->lSampleSize = 1024 * 576 * 4;//样本大小
			pmt->cbFormat = 88;//格式块的大小
			VIDEOINFOHEADER* p = (VIDEOINFOHEADER*)CoTaskMemAlloc(88);//为格式块分配内存
			pmt->pbFormat = (BYTE*)p;//格式块的指针
			p->rcSource.left = 0; p->rcSource.top = 0; p->rcSource.right = 0; p->rcSource.bottom = 0;//源矩形
			p->rcTarget.left = 0; p->rcTarget.top = 0; p->rcTarget.right = 0; p->rcTarget.bottom = 0;//目标矩形
			p->dwBitRate = 0;//数据传输率
			p->dwBitErrorRate = 0;//数据错误率
			p->AvgTimePerFrame = 416666;//帧显示时间
			p->bmiHeader.biSize = 40;//图像信息结构大小
			p->bmiHeader.biWidth = 1024;//图像宽度
			p->bmiHeader.biHeight = 576;//图像高度
			p->bmiHeader.biPlanes = 1;//平面数
			p->bmiHeader.biBitCount = 32;//每个像素位数
			p->bmiHeader.biCompression = 0;//编码方式
			p->bmiHeader.biSizeImage = 1024 * 576 * 4;//图像的字节大小
			p->bmiHeader.biXPelsPerMeter = 0;//水平分辨率
			p->bmiHeader.biYPelsPerMeter = 0;//垂直分辨率
			p->bmiHeader.biClrUsed = 0;//颜色表中颜色数量
			p->bmiHeader.biClrImportant = 0;//重要颜色数量
			return S_OK;
		}
		case 1://RGB32
		{
			pmt->subtype = MEDIASUBTYPE_RGB32;//子类型
			pmt->lSampleSize = 1024 * 576 * 4;//样本大小
			pmt->cbFormat = 88;//格式块的大小
			VIDEOINFOHEADER* p = (VIDEOINFOHEADER*)CoTaskMemAlloc(88);//为格式块分配内存
			pmt->pbFormat = (BYTE*)p;//格式块的指针
			p->rcSource.left = 0; p->rcSource.top = 0; p->rcSource.right = 0; p->rcSource.bottom = 0;//源矩形
			p->rcTarget.left = 0; p->rcTarget.top = 0; p->rcTarget.right = 0; p->rcTarget.bottom = 0;//目标矩形
			p->dwBitRate = 0;//数据传输率
			p->dwBitErrorRate = 0;//数据错误率
			p->AvgTimePerFrame = 416666;//帧显示时间
			p->bmiHeader.biSize = 40;//图像信息结构大小
			p->bmiHeader.biWidth = 1024;//图像宽度
			p->bmiHeader.biHeight = 576;//图像高度
			p->bmiHeader.biPlanes = 1;//平面数
			p->bmiHeader.biBitCount = 32;//每个像素位数
			p->bmiHeader.biCompression = 0;//编码方式
			p->bmiHeader.biSizeImage = 1024 * 576 * 4;//图像的字节大小
			p->bmiHeader.biXPelsPerMeter = 0;//水平分辨率
			p->bmiHeader.biYPelsPerMeter = 0;//垂直分辨率
			p->bmiHeader.biClrUsed = 0;//颜色表中颜色数量
			p->bmiHeader.biClrImportant = 0;//重要颜色数量
			return S_OK;
		}
		case 2://RGB24
		{
			pmt->subtype = MEDIASUBTYPE_RGB24;//子类型
			pmt->lSampleSize = 1024 * 576 * 3;//样本大小
			pmt->cbFormat = 88;//格式块的大小
			VIDEOINFOHEADER* p = (VIDEOINFOHEADER*)CoTaskMemAlloc(88);//为格式块分配内存
			pmt->pbFormat = (BYTE*)p;//格式块的指针
			p->rcSource.left = 0; p->rcSource.top = 0; p->rcSource.right = 0; p->rcSource.bottom = 0;//源矩形
			p->rcTarget.left = 0; p->rcTarget.top = 0; p->rcTarget.right = 0; p->rcTarget.bottom = 0;//目标矩形
			p->dwBitRate = 0;//数据传输率
			p->dwBitErrorRate = 0;//数据错误率
			p->AvgTimePerFrame = 416666;//帧显示时间
			p->bmiHeader.biSize = 40;//图像信息结构大小
			p->bmiHeader.biWidth = 1024;//图像宽度
			p->bmiHeader.biHeight = 576;//图像高度
			p->bmiHeader.biPlanes = 1;//平面数
			p->bmiHeader.biBitCount = 24;//每个像素位数
			p->bmiHeader.biCompression = 0;//编码方式
			p->bmiHeader.biSizeImage = 1024 * 576 * 3;//图像的字节大小
			p->bmiHeader.biXPelsPerMeter = 0;//水平分辨率
			p->bmiHeader.biYPelsPerMeter = 0;//垂直分辨率
			p->bmiHeader.biClrUsed = 0;//颜色表中颜色数量
			p->bmiHeader.biClrImportant = 0;//重要颜色数量
			return S_OK;
		}
		case 3://RGB565
		{
			pmt->subtype = MEDIASUBTYPE_RGB565;//子类型
			pmt->lSampleSize = 1024 * 576 * 2;//样本大小
			pmt->cbFormat = 100;//格式块的大小
			VIDEOINFOHEADER* p = (VIDEOINFOHEADER*)CoTaskMemAlloc(100);//为格式块分配内存
			pmt->pbFormat = (BYTE*)p;//格式块的指针
			p->rcSource.left = 0; p->rcSource.top = 0; p->rcSource.right = 0; p->rcSource.bottom = 0;//源矩形
			p->rcTarget.left = 0; p->rcTarget.top = 0; p->rcTarget.right = 0; p->rcTarget.bottom = 0;//目标矩形
			p->dwBitRate = 0;//数据传输率
			p->dwBitErrorRate = 0;//数据错误率
			p->AvgTimePerFrame = 416666;//帧显示时间
			p->bmiHeader.biSize = 40;//图像信息结构大小
			p->bmiHeader.biWidth = 1024;//图像宽度
			p->bmiHeader.biHeight = 576;//图像高度
			p->bmiHeader.biPlanes = 1;//平面数
			p->bmiHeader.biBitCount = 16;//每个像素位数
			p->bmiHeader.biCompression = 3;//编码方式
			p->bmiHeader.biSizeImage = 1024 * 576 * 2;//图像的字节大小
			p->bmiHeader.biXPelsPerMeter = 0;//水平分辨率
			p->bmiHeader.biYPelsPerMeter = 0;//垂直分辨率
			p->bmiHeader.biClrUsed = 0;//颜色表中颜色数量
			p->bmiHeader.biClrImportant = 0;//重要颜色数量
			DWORD Rflags = 0x0000F800;//红色位掩码
			CopyMemory(pmt->pbFormat + 88, &Rflags, 4);
			DWORD Gflags = 0x000007E0; //绿色位掩码
			CopyMemory(pmt->pbFormat + 88 + 4, &Gflags, 4);
			DWORD Bflags = 0x0000001F; //蓝色位掩码
			CopyMemory(pmt->pbFormat + 88 + 4 + 4, &Bflags, 4);
			return S_OK;
		}
		case 4://RGB555
		{
			pmt->subtype = MEDIASUBTYPE_RGB555;//子类型
			pmt->lSampleSize = 1024 * 576 * 2;//样本大小
			pmt->cbFormat = 100;//格式块的大小
			VIDEOINFOHEADER* p = (VIDEOINFOHEADER*)CoTaskMemAlloc(100);//为格式块分配内存
			pmt->pbFormat = (BYTE*)p;//格式块的指针
			p->rcSource.left = 0; p->rcSource.top = 0; p->rcSource.right = 0; p->rcSource.bottom = 0;//源矩形
			p->rcTarget.left = 0; p->rcTarget.top = 0; p->rcTarget.right = 0; p->rcTarget.bottom = 0;//目标矩形
			p->dwBitRate = 0;//数据传输率
			p->dwBitErrorRate = 0;//数据错误率
			p->AvgTimePerFrame = 416666;//帧显示时间
			p->bmiHeader.biSize = 40;//图像信息结构大小
			p->bmiHeader.biWidth = 1024;//图像宽度
			p->bmiHeader.biHeight = 576;//图像高度
			p->bmiHeader.biPlanes = 1;//平面数
			p->bmiHeader.biBitCount = 16;//每个像素位数
			p->bmiHeader.biCompression = 3;//编码方式
			p->bmiHeader.biSizeImage = 1024 * 576 * 2;//图像的字节大小
			p->bmiHeader.biXPelsPerMeter = 0;//水平分辨率
			p->bmiHeader.biYPelsPerMeter = 0;//垂直分辨率
			p->bmiHeader.biClrUsed = 0;//颜色表中颜色数量
			p->bmiHeader.biClrImportant = 0;//重要颜色数量
			DWORD Rflags = 0x00007C00;//红色位掩码
			CopyMemory(pmt->pbFormat + 88, &Rflags, 4);
			DWORD Gflags = 0x000003E0; //绿色位掩码
			CopyMemory(pmt->pbFormat + 88 + 4, &Gflags, 4);
			DWORD Bflags = 0x0000001F; //蓝色位掩码
			CopyMemory(pmt->pbFormat + 88 + 4 + 4, &Bflags, 4);
			return S_OK;
		}
		case 5://RGB8
		{
			pmt->subtype = MEDIASUBTYPE_RGB8;//子类型
			pmt->lSampleSize = 1024 * 576;//样本大小
			pmt->cbFormat = 88 + 256 * 4;//格式块的大小
			VIDEOINFOHEADER* p = (VIDEOINFOHEADER*)CoTaskMemAlloc(88 + 256*4);//为格式块分配内存
			pmt->pbFormat = (BYTE*)p;//格式块的指针
			p->rcSource.left = 0; p->rcSource.top = 0; p->rcSource.right = 0; p->rcSource.bottom = 0;//源矩形
			p->rcTarget.left = 0; p->rcTarget.top = 0; p->rcTarget.right = 0; p->rcTarget.bottom = 0;//目标矩形
			p->dwBitRate = 0;//数据传输率
			p->dwBitErrorRate = 0;//数据错误率
			p->AvgTimePerFrame = 416666;//帧显示时间
			p->bmiHeader.biSize = 40;//图像信息结构大小
			p->bmiHeader.biWidth = 1024;//图像宽度
			p->bmiHeader.biHeight = 576;//图像高度
			p->bmiHeader.biPlanes = 1;//平面数
			p->bmiHeader.biBitCount = 8;//每个像素位数
			p->bmiHeader.biCompression = 0;//编码方式
			p->bmiHeader.biSizeImage = 1024 * 576;//图像的字节大小
			p->bmiHeader.biXPelsPerMeter = 0;//水平分辨率
			p->bmiHeader.biYPelsPerMeter = 0;//垂直分辨率
			p->bmiHeader.biClrUsed = 256;//颜色表中颜色数量
			p->bmiHeader.biClrImportant = 256;//重要颜色数量
			BYTE ColorTable[4 * 256] = {//颜色表
				0, 0, 0, 0,
				0, 0, 128, 0,
				0, 128, 0, 0,
				0, 128, 128, 0,
				128, 0, 0, 0,
				128, 0, 128, 0,
				128, 128, 0, 0,
				192, 192, 192, 0,
				192, 220, 192, 0,
				240, 202, 166, 0,
				1, 1, 1, 0,
				1, 1, 51, 0,
				1, 1, 102, 0,
				1, 1, 153, 0,
				1, 1, 204, 0,
				1, 1, 254, 0,
				1, 51, 1, 0,
				1, 51, 51, 0,
				1, 51, 102, 0,
				1, 51, 153, 0,
				1, 51, 204, 0,
				1, 51, 254, 0,
				1, 102, 1, 0,
				1, 102, 51, 0,
				1, 102, 102, 0,
				1, 102, 153, 0,
				1, 102, 204, 0,
				1, 102, 254, 0,
				1, 153, 1, 0,
				1, 153, 51, 0,
				1, 153, 102, 0,
				1, 153, 153, 0,
				1, 153, 204, 0,
				1, 153, 254, 0,
				1, 204, 1, 0,
				1, 204, 51, 0,
				1, 204, 102, 0,
				1, 204, 153, 0,
				1, 204, 204, 0,
				1, 204, 254, 0,
				1, 254, 1, 0,
				1, 254, 51, 0,
				1, 254, 102, 0,
				1, 254, 153, 0,
				1, 254, 204, 0,
				1, 254, 254, 0,
				51, 1, 1, 0,
				51, 1, 51, 0,
				51, 1, 102, 0,
				51, 1, 153, 0,
				51, 1, 204, 0,
				51, 1, 254, 0,
				51, 51, 1, 0,
				51, 51, 51, 0,
				51, 51, 102, 0,
				51, 51, 153, 0,
				51, 51, 204, 0,
				51, 51, 254, 0,
				51, 102, 1, 0,
				51, 102, 51, 0,
				51, 102, 102, 0,
				51, 102, 153, 0,
				51, 102, 204, 0,
				51, 102, 254, 0,
				51, 153, 1, 0,
				51, 153, 51, 0,
				51, 153, 102, 0,
				51, 153, 153, 0,
				51, 153, 204, 0,
				51, 153, 254, 0,
				51, 204, 1, 0,
				51, 204, 51, 0,
				51, 204, 102, 0,
				51, 204, 153, 0,
				51, 204, 204, 0,
				51, 204, 254, 0,
				51, 254, 1, 0,
				51, 254, 51, 0,
				51, 254, 102, 0,
				51, 254, 153, 0,
				51, 254, 204, 0,
				51, 254, 254, 0,
				102, 1, 1, 0,
				102, 1, 51, 0,
				102, 1, 102, 0,
				102, 1, 153, 0,
				102, 1, 204, 0,
				102, 1, 254, 0,
				102, 51, 1, 0,
				102, 51, 51, 0,
				102, 51, 102, 0,
				102, 51, 153, 0,
				102, 51, 204, 0,
				102, 51, 254, 0,
				102, 102, 1, 0,
				102, 102, 51, 0,
				102, 102, 102, 0,
				102, 102, 153, 0,
				102, 102, 204, 0,
				102, 102, 254, 0,
				102, 153, 1, 0,
				102, 153, 51, 0,
				102, 153, 102, 0,
				102, 153, 153, 0,
				102, 153, 204, 0,
				102, 153, 254, 0,
				102, 204, 1, 0,
				102, 204, 51, 0,
				102, 204, 102, 0,
				102, 204, 153, 0,
				102, 204, 204, 0,
				102, 204, 254, 0,
				102, 254, 1, 0,
				102, 254, 51, 0,
				102, 254, 102, 0,
				102, 254, 153, 0,
				102, 254, 204, 0,
				102, 254, 254, 0,
				153, 1, 1, 0,
				153, 1, 51, 0,
				153, 1, 102, 0,
				153, 1, 153, 0,
				153, 1, 204, 0,
				153, 1, 254, 0,
				153, 51, 1, 0,
				153, 51, 51, 0,
				153, 51, 102, 0,
				153, 51, 153, 0,
				153, 51, 204, 0,
				153, 51, 254, 0,
				153, 102, 1, 0,
				153, 102, 51, 0,
				153, 102, 102, 0,
				153, 102, 153, 0,
				153, 102, 204, 0,
				153, 102, 254, 0,
				153, 153, 1, 0,
				153, 153, 51, 0,
				153, 153, 102, 0,
				153, 153, 153, 0,
				153, 153, 204, 0,
				153, 153, 254, 0,
				153, 204, 1, 0,
				153, 204, 51, 0,
				153, 204, 102, 0,
				153, 204, 153, 0,
				153, 204, 204, 0,
				153, 204, 254, 0,
				153, 254, 1, 0,
				153, 254, 51, 0,
				153, 254, 102, 0,
				153, 254, 153, 0,
				153, 254, 204, 0,
				153, 254, 254, 0,
				204, 1, 1, 0,
				204, 1, 51, 0,
				204, 1, 102, 0,
				204, 1, 153, 0,
				204, 1, 204, 0,
				204, 1, 254, 0,
				204, 51, 1, 0,
				204, 51, 51, 0,
				204, 51, 102, 0,
				204, 51, 153, 0,
				204, 51, 204, 0,
				204, 51, 254, 0,
				204, 102, 1, 0,
				204, 102, 51, 0,
				204, 102, 102, 0,
				204, 102, 153, 0,
				204, 102, 204, 0,
				204, 102, 254, 0,
				204, 153, 1, 0,
				204, 153, 51, 0,
				204, 153, 102, 0,
				204, 153, 153, 0,
				204, 153, 204, 0,
				204, 153, 254, 0,
				204, 204, 1, 0,
				204, 204, 51, 0,
				204, 204, 102, 0,
				204, 204, 153, 0,
				204, 204, 204, 0,
				204, 204, 254, 0,
				204, 254, 1, 0,
				204, 254, 51, 0,
				204, 254, 102, 0,
				204, 254, 153, 0,
				204, 254, 204, 0,
				204, 254, 254, 0,
				254, 1, 1, 0,
				254, 1, 51, 0,
				254, 1, 102, 0,
				254, 1, 153, 0,
				254, 1, 204, 0,
				254, 1, 254, 0,
				254, 51, 1, 0,
				254, 51, 51, 0,
				254, 51, 102, 0,
				254, 51, 153, 0,
				254, 51, 204, 0,
				254, 51, 254, 0,
				254, 102, 1, 0,
				254, 102, 51, 0,
				254, 102, 102, 0,
				254, 102, 153, 0,
				254, 102, 204, 0,
				254, 102, 254, 0,
				254, 153, 1, 0,
				254, 153, 51, 0,
				254, 153, 102, 0,
				254, 153, 153, 0,
				254, 153, 204, 0,
				254, 153, 254, 0,
				254, 204, 1, 0,
				254, 204, 51, 0,
				254, 204, 102, 0,
				254, 204, 153, 0,
				254, 204, 204, 0,
				254, 204, 254, 0,
				254, 254, 1, 0,
				254, 254, 51, 0,
				254, 254, 102, 0,
				254, 254, 153, 0,
				254, 254, 204, 0,
				254, 254, 254, 0,
				8, 141, 173, 1,
				168, 220, 168, 7,
				168, 220, 168, 7,
				8, 141, 173, 1,
				168, 220, 168, 7,
				168, 220, 168, 7,
				8, 141, 173, 1,
				168, 220, 168, 7,
				168, 220, 168, 7,
				8, 141, 173, 1,
				168, 220, 168, 7,
				168, 220, 168, 7,
				8, 141, 173, 1,
				168, 220, 168, 7,
				168, 220, 168, 7,
				8, 141, 173, 1,
				168, 220, 168, 7,
				168, 220, 168, 7,
				8, 141, 173, 1,
				168, 220, 168, 7,
				168, 220, 168, 7,
				8, 141, 173, 1,
				168, 220, 168, 7,
				168, 220, 168, 7,
				8, 141, 173, 1,
				168, 220, 168, 7,
				168, 220, 168, 7,
				8, 141, 173, 1,
				168, 220, 168, 7,
				168, 220, 168, 7
			};
			CopyMemory(pmt->pbFormat + 88, ColorTable, 256 * 4);//复制颜色表
			return S_OK;
		}
		}
	}
	else
		return VFW_S_NO_MORE_ITEMS;//索引超出范围
	return E_INVALIDARG;//索引小于零
}

HRESULT CVideoPin::DecideBufferSize(IMemAllocator * pAlloc, ALLOCATOR_PROPERTIES * pRequest)
{
	HRESULT hr;
	pRequest->cBuffers = 1;//1个缓冲区
	pRequest->cbBuffer = 1024 * 576 * 4;//缓冲区的大小。这里使用ARGB32和RGB32样本缓冲区大小
	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)
{
	HRESULT hr; IMFMediaType* pVideoMT = NULL; 
	hr = MFCreateMediaType(&pVideoMT);//创建空的媒体类型
	hr = pVideoMT->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);//设置主要类型为视频
	switch (type)
	{
	case 0://ARGB32
		hr = pVideoMT->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_ARGB32);//设置子类型ARGB32
		break;
	case 1://RGB24
		hr = pVideoMT->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32);//设置子类型RGB32
		break;
	case 2://RGB24
		hr = pVideoMT->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24);//设置子类型RGB24
		break;
	case 3://RGB565
		hr = pVideoMT->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565);//设置子类型RGB565
		break;
	case 4://RGB555
		hr = pVideoMT->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555);//设置子类型RGB555
		break;
	case 5://RGB8
		SafeRelease(&pVideoMT);
		return CSourceStream::SetMediaType(pMediaType);
	}
	hr = pVideoMT->SetUINT32(MF_MT_INTERLACE_MODE, (UINT32)2);//设置交错模式,无交错
	hr = pVideoMT->SetUINT32(MF_MT_COMPRESSED, (UINT32)0);//没有压缩
	hr = pVideoMT->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, (UINT32)1);//样本独立于其他样本
	hr = pCFilter->pIMFSourceReader->SetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, NULL, pVideoMT);//设置源读取器视频媒体类型
	SafeRelease(&pVideoMT);
	return CSourceStream::SetMediaType(pMediaType);
}

HRESULT CVideoPin::CheckMediaType(const CMediaType *pMediaType)
{
	if(pCFilter->Connected != -1)return S_FALSE;//确保只连接1个视频引脚
	if (pMediaType->majortype == MEDIATYPE_Video && pMediaType->formattype == FORMAT_VideoInfo)
	{
		switch (type)
		{
		case 0://ARGB32
			if (pMediaType->subtype == MEDIASUBTYPE_ARGB32)
				return S_OK;
			break;
		case 1://RGB32
			if (pMediaType->subtype == MEDIASUBTYPE_RGB32)
				return S_OK;
		case 2://RGB24
			if (pMediaType->subtype == MEDIASUBTYPE_RGB24)
				return S_OK;
			break;
		case 3://RGB565
			if (pMediaType->subtype == MEDIASUBTYPE_RGB565)
				return S_OK;
			break;
		case 4://RGB555
			if (pMediaType->subtype == MEDIASUBTYPE_RGB555)
				return S_OK;
			break;
		case 5://RGB8
			if (pMediaType->subtype == MEDIASUBTYPE_RGB8)
				return S_OK;
			break;
		}
	}
	return S_FALSE;
}

HRESULT CVideoPin::BreakConnect()//断开连接时调用
{
	BOOL B0 = pCFilter->pARGB32->IsConnected();
	BOOL B1 = pCFilter->pRGB32->IsConnected();
	BOOL B2 = pCFilter->pRGB24->IsConnected();
	BOOL B3 = pCFilter->pRGB565->IsConnected();
	BOOL B4 = pCFilter->pRGB555->IsConnected();
	BOOL B5 = pCFilter->pRGB8->IsConnected();
	if (!B0 && !B1 && !B2 && !B3 && !B4 && !B5)//如果没有1个视频引脚完成连接
		pCFilter->Connected = -1;
	return CSourceStream::BreakConnect();
}

HRESULT CVideoPin::CompleteConnect(IPin *pReceivePin)//完成连接时调用
{
	if (wcscmp(Name(), L"ARGB32")==0)pCFilter->Connected = 0;
	if (wcscmp(Name(), L"RGB32") == 0)pCFilter->Connected = 1;
	if (wcscmp(Name(), L"RGB24") == 0)pCFilter->Connected = 2;
	if (wcscmp(Name(), L"RGB565") == 0)pCFilter->Connected = 3;
	if (wcscmp(Name(), L"RGB555") == 0)pCFilter->Connected = 4;
	if (wcscmp(Name(), L"RGB8") == 0)pCFilter->Connected = 5;
	return CSourceStream::CompleteConnect(pReceivePin);
}

void CopyData(BYTE* pD, BYTE* pS, int Connected)//pD目标缓冲区;pS源缓冲区
{
	switch (Connected)
	{
	case 0://ARGB32
		for (int h = 0; h < 576; h++)//上下翻转图像复制数据
		{
			CopyMemory(pD + h * 1024 * 4, pS + (575 - h) * 1024 * 4, 1024 * 4);
		}
		break;
	case 1://RGB32
		for (int h = 0; h < 576; h++)//上下翻转图像复制数据
		{
			CopyMemory(pD + h * 1024 * 4, pS + (575 - h) * 1024 * 4, 1024 * 4);
		}
		break;
	case 2://RGB24
		for (int h = 0; h < 576; h++)//上下翻转图像复制数据
		{
			CopyMemory(pD + h * 1024 * 3, pS + (575 - h) * 1024 * 3, 1024 * 3);
		}
		break;
	case 3://RGB565
		for (int h = 0; h < 576; h++)//上下翻转图像复制数据
		{
			CopyMemory(pD + h * 1024 * 2, pS + (575 - h) * 1024 * 2, 1024 * 2);
		}
		break;
	case 4://RGB555
		for (int h = 0; h < 576; h++)//上下翻转图像复制数据
		{
			CopyMemory(pD + h * 1024 * 2, pS + (575 - h) * 1024 * 2, 1024 * 2);
		}
		break;
	}
}

HRESULT CVideoPin::OnThreadStartPlay(void)
{
	HRESULT hr;
	if (pCFilter->Connected == 5)//如果是RGB8
	{
		Star = pCFilter->ResetPos; pRGB8Data = pStar + pCFilter->ResetPos / 416666 * (1024 * 576);//获取定位的时间和内存位置
		if (pRGB8Data > pStar + dwSize - 1024 * 576)//防止读取内存越界
		{
			pRGB8Data = pStar + dwSize - 1024 * 576;
			Star = pCFilter->DUR - 416666;
		}
	}
	hr = pCFilter->pIMFSourceReader->Flush(MF_SOURCE_READER_ALL_STREAMS);//刷新所有流
	PROPVARIANT var;
	PropVariantInit(&var);
	var.vt = 20; var.hVal.QuadPart = pCFilter->ResetPos;
	hr = pCFilter->pIMFSourceReader->SetCurrentPosition(GUID_NULL, var);//更改源读取器位置
	PropVariantClear(&var);
	return DeliverNewSegment(0, pCFilter->DUR - pCFilter->ResetPos, 1.0);
}

HRESULT CVideoPin::FillBuffer(IMediaSample *pms)
{
	if (pCFilter->Connected == 5)//如果是RGB8
	{
		BYTE* pData = NULL;
		pms->GetPointer(&pData);//获取引脚样本缓冲区
		CopyMemory(pData, pRGB8Data, 1024 * 576); 
		pCFilter->CUR = Star;//获取视频播放的当前位置
		LONGLONG End = Star + 416666;
		pms->SetTime(&Star, &End); Star += 416666;
		pms->SetSyncPoint(TRUE);
		pms->SetActualDataLength(1024 * 576);
		pRGB8Data += 1024 * 576;//移动指针1个RGB8数据的位置
		if (pRGB8Data > pStar+ dwSize- 1024 * 576)
		{
			DeliverEndOfStream();//发送流结束通知
			return S_FALSE;//流结束
		}
	}
	else
	{
	Agan:
		IMFSample* pMFSample = NULL; DWORD flags = 0;
		HRESULT hr = pCFilter->pIMFSourceReader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, NULL, &flags, NULL, &pMFSample);//读取视频样本
		if (flags & MF_SOURCE_READERF_ENDOFSTREAM)//如果到达末尾
		{
			DeliverEndOfStream();//发送流结束通知
			return S_FALSE;//流结束
		}
		if (pMFSample == NULL)
		{
			Sleep(1); goto Agan;
		}
		LONGLONG Cur, Dur;
		hr = pMFSample->GetSampleTime(&Cur);//获取显示时间
		pCFilter->CUR = Cur;//获取视频播放的当前位置
		hr = pMFSample->GetSampleDuration(&Dur);//获取持续时间
		DWORD Lt;
		hr = pMFSample->GetTotalLength(&Lt);//获取有效长度
		DWORD count;
		hr = pMFSample->GetBufferCount(&count);//获取缓冲区数量
		IMFMediaBuffer* pMFBuffer = NULL;
		if (count == 1)//如果只有1个缓冲区
		{
			hr = pMFSample->GetBufferByIndex(0, &pMFBuffer);
		}
		else//如果有多个缓冲区
		{
			hr = pMFSample->ConvertToContiguousBuffer(&pMFBuffer);
		}
		LONGLONG star = Cur, end = Cur + Dur;//引脚样本时间戳
		BYTE* pData = NULL;
		pms->GetPointer(&pData);//获取引脚样本缓冲区
		BYTE* pSB = NULL;
		hr = pMFBuffer->Lock(&pSB, NULL, NULL);//锁定缓冲区
		CopyData(pData, pSB, pCFilter->Connected);//复制媒体基础样本到引脚样本
		hr = pMFBuffer->Unlock();//解锁缓冲区
		pms->SetTime(&star, &end);
		pms->SetSyncPoint(TRUE);
		pms->SetActualDataLength(Lt);
		SafeRelease(&pMFBuffer); SafeRelease(&pMFSample);
	}
	return S_OK;
}

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()
{

}

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 = 1000000;//缓冲区的大小
	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::OnThreadStartPlay(void)
{
	return DeliverNewSegment(0, pCFilter->DUR - pCFilter->ResetPos, 1.0);
}

HRESULT CAudioPin::FillBuffer(IMediaSample *pms)
{
	IMFSample* pMFSample = NULL; DWORD flags;
	HRESULT hr = pCFilter->pIMFSourceReader->ReadSample(MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, NULL, &flags, NULL, &pMFSample);//读取音频样本
	if (flags & MF_SOURCE_READERF_ENDOFSTREAM)//如果到达末尾
	{
		DeliverEndOfStream();
		return S_FALSE;//流结束
	}
	LONGLONG Cur, Dur;
	hr = pMFSample->GetSampleTime(&Cur);//获取显示时间
	hr = pMFSample->GetSampleDuration(&Dur);//获取持续时间
	DWORD Lt;
	hr = pMFSample->GetTotalLength(&Lt);//获取有效长度
	DWORD count;
	hr = pMFSample->GetBufferCount(&count);//获取缓冲区数量
	IMFMediaBuffer* pMFBuffer = NULL;
	if (count == 1)//如果只有1个缓冲区
	{
		hr = pMFSample->GetBufferByIndex(0, &pMFBuffer);
	}
	else//如果有多个缓冲区
	{
		hr = pMFSample->ConvertToContiguousBuffer(&pMFBuffer);
	}
	LONGLONG star = Cur, end = Cur + Dur;//引脚样本时间戳
	BYTE* pSB = NULL;
	hr = pMFBuffer->Lock(&pSB, NULL, NULL);//锁定缓冲区
	BYTE* pData = NULL;
	pms->GetPointer(&pData);
	CopyMemory(pData, pSB, Lt); 
	hr = pMFBuffer->Unlock();//解锁缓冲区
	pms->SetTime(&star, &end);
	pms->SetSyncPoint(TRUE);
	pms->SetActualDataLength(Lt);
	SafeRelease(&pMFBuffer); SafeRelease(&pMFSample);//释放接口
	return S_OK;
}