DirectShow过滤器开发-AAC编码器

下载本过滤器DLL
本过滤器将PCM音频流编码为AAC音频流,由输出引脚输出。

过滤器信息

过滤器名称:AAC编码器
过滤器GUID:{59FB3C29-4C37-47D9-AA73-1DFEDC0DDF71}
DLL注册函数名:DllRegisterServer
删除注册函数名:DllUnregisterServer
过滤器有1个输入引脚和1个输出引脚。

输入引脚标识:In
输入引脚媒体类型:
主要类型:MEDIATYPE_Audio
子类型:MEDIASUBTYPE_PCM
格式类型:FORMAT_WaveFormatEx
样本为固定大小。
不使用时间压缩。
样本为16位。
采样率:48000,44100。

输出引脚标识:Out
输出引脚媒体类型:
主要类型:MEDIATYPE_Audio
子类型:MEDIASUBTYPE_MPEG_HEAAC
格式类型:FORMAT_WaveFormatEx

AAC编码器开发信息

过滤器从CCritSec,CBaseFilter,ISpecifyPropertyPages接口和自定义接口IMy009派生。ISpecifyPropertyPages接口用于显示属性页。自定义接口IMy009用于获取和指定编码输出比特率。
输入引脚从CBaseInputPin类派生。输出引脚从CBaseOutputPin派生,实现了IMediaSeeking接口查询,实现了CPosPassThru对象,用于向上游过滤器输出引脚传递Seek命令。
创建了两个属性页。输入属性页,在输入引脚没有连接时,属性页列表显示所有允许的输入媒体类型;如果连接了输入引脚,属性页列表显示输入引脚当前媒体类型。输出属性页,在输入引脚没有连接时,属性页列表显示所有允许的输出媒体类型;如果连接了输入引脚,属性页列表显示输出引脚将使用的媒体类型。
使用CoCreateInstance函数创建AAC音频编码器对象,其为媒体基础转换,接口为IMFTransform。在输入引脚的接收函数中,将引脚样本转换为媒体基础样本,使用IMFTransform接口的ProcessInput方法,向AAC音频编码器传递输入数据;使用IMFTransform接口的ProcessOutput方法获取AAC编码器输出数据。输出为媒体基础样本,将其转换为引脚样本,由输出引脚输出。AAC编码器一次输入将获得多个输出,通过检测ProcessOutput返回值,确定是否还可获取输出。

AAC编码器DLL的所有代码

DLL头文件:DLL.h

#ifndef  DLL_FILE
#define DLL_FILE

#include "strmbase10.h"//过滤器基础类定义文件

#if _DEBUG
#pragma comment(lib, "strmbasd10.lib")//过滤器基础类实现文件调试版本
#else
#pragma comment(lib, "strmbase10.lib")//过滤器基础类实现文件发布版本
#endif

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

#include "wmcodecdsp.h"

// {59FB3C29-4C37-47D9-AA73-1DFEDC0DDF71}
DEFINE_GUID(CLSID_AACEncoder,//过滤器GUID
	0x59fb3c29, 0x4c37, 0x47d9, 0xaa, 0x73, 0x1d, 0xfe, 0xdc, 0xd, 0xdf, 0x71);

// {CC9CB4BE-FCD2-487A-9931-5421309DE1CC}
DEFINE_GUID(CLSID_PropertyPage1,//属性页1GUID
	0xcc9cb4be, 0xfcd2, 0x487a, 0x99, 0x31, 0x54, 0x21, 0x30, 0x9d, 0xe1, 0xcc);

// {4833A54C-2384-40D0-8F53-EC35C7521006}
DEFINE_GUID(CLSID_PropertyPage2,//属性页2GUID
	0x4833a54c, 0x2384, 0x40d0, 0x8f, 0x53, 0xec, 0x35, 0xc7, 0x52, 0x10, 0x6);

// {D98A6504-F492-44F1-9EC6-643A33C054B5}
DEFINE_GUID(IID_IMy009,
	0xd98a6504, 0xf492, 0x44f1, 0x9e, 0xc6, 0x64, 0x3a, 0x33, 0xc0, 0x54, 0xb5);


interface IMy009 : public IUnknown
{
   
	virtual HRESULT MyGet(UINT32* mBytes) = 0;
	virtual HRESULT MySet(UINT32 mBytes) = 0;
};


class COutPin;
class CFilter;

class CInPin : public CBaseInputPin
{
   
	friend class COutPin;
	friend class CFilter;
public:
	CInPin(CFilter *pFilter, HRESULT *phr, LPCWSTR pPinName);
	~CInPin();
	HRESULT CheckMediaType(const CMediaType *pmt);
	HRESULT SetMediaType(const CMediaType *pmt);
	STDMETHODIMP Receive(IMediaSample *pSample);
	STDMETHODIMP EndOfStream();
	STDMETHODIMP BeginFlush();
	STDMETHODIMP EndFlush();
	STDMETHODIMP NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
	HRESULT GetOut();
	CFilter *pCFilter;
	ULONGLONG CUR = 0;//当前样本的起始时间,单位毫秒
	ULONGLONG STAR = 0;//段起始时间,单位毫秒
	ULONGLONG DUR = 0;//单个样本持续时间,单位毫秒
};

class COutPin : public CBaseOutputPin
{
   
	friend class CInPin;
	friend class CFilter;
	IUnknown   *m_pPosition = NULL;
	COutputQueue *m_pOutputQueue = NULL;//样本队列
public:
	COutPin(CFilter *pFilter, HRESULT *phr, LPCWSTR pPinName);
	~COutPin();
	STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppvoid);
	HRESULT GetMediaType(int iPosition, CMediaType *pMediaType);
	HRESULT CheckMediaType(const CMediaType *pmt);
	HRESULT DecideBufferSize(IMemAllocator *pMemAllocator, ALLOCATOR_PROPERTIES * ppropInputRequest);
	HRESULT Active();
	HRESULT Inactive();
	HRESULT Deliver(IMediaSample *pMediaSample);
	HRESULT DeliverEndOfStream();
	HRESULT DeliverBeginFlush();
	HRESULT DeliverEndFlush();
	HRESULT DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
	STDMETHODIMP Notify(IBaseFilter *pSender, Quality q);
	CFilter *pCFilter = NULL;
	IMFMediaType* pOutType = NULL;
};

class CFilter : public CCritSec, public CBaseFilter, public ISpecifyPropertyPages, public IMy009
{
   
	friend class CInPin;
	friend class COutPin;
public:
	CFilter(TCHAR* pName, LPUNKNOWN pUnk, HRESULT* hr);
	~CFilter();
	CBasePin* GetPin(int n);
	int GetPinCount();
	static CUnknown* WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT* phr);
	DECLARE_IUNKNOWN
	STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
	virtual HRESULT Get(CBaseFilter** ppF);
	STDMETHODIMP GetPages(CAUUID *pPages)
	{
   
		if (pPages == NULL) return E_POINTER;
		pPages->cElems = 2;
		pPages->pElems = (GUID*)CoTaskMemAlloc(sizeof(GUID) * 2);
		if (pPages->pElems == NULL)
		{
   
			return E_OUTOFMEMORY;
		}
		pPages->pElems[0] = CLSID_PropertyPage1;
		pPages->pElems[1] = CLSID_PropertyPage2;
		return S_OK;
	}
	HRESULT MyGet(UINT32* mBytes);
	HRESULT MySet(UINT32 mBytes);
	CInPin* pCInPin = NULL;
	COutPin* pCOutPin = NULL;
	IMFTransform *pAACEncoder = NULL;
	UINT32 SAMPLES_PER_SECOND = 0;//采样率要求值
	UINT32 NUM_CHANNELS = 0;//声道数要求值
	UINT32 BYTES_PER_SECOND = 0;//传输率要求值
	ULONGLONG SCUR = 0;//“当前时间”公共变量
};

class CPropertyPage1 : public CBasePropertyPage
{
   
	friend class CFilter;
	friend class CInPin;
public:
	CPropertyPage1(IUnknown *pUnk);
	~CPropertyPage1();
	static CUnknown * WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr);
	virtual HRESULT OnConnect(IUnknown *pUnknown);
	virtual HRESULT OnDeactivate();
	virtual HRESULT OnActivate();//用于初始化属性页对话框
	virtual INT_PTR OnReceiveMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);//接收属性页对话框的消息
	WCHAR* DefineFromGUID(GUID guid);//获取GUID定义字符串
	LPWSTR GetFormatString(WAVEFORMATEX* p);//获取格式块描述字符串
	CFilter *pCFilter = NULL;
	HWND hList, hEdit, hText1, hText2, hText3;
	HFONT hFont1, hFont2;
	HWND hE1;//“当前位置“”编辑框窗口句柄
	HWND hE2;//“当前样本”编辑框窗口句柄
	HANDLE hThread = NULL;
};

class CPropertyPage2 : public CBasePropertyPage
{
   
	friend class CFilter;
	CFilter* pCFilter = NULL;
public:
	CPropertyPage2(IUnknown *pUnk);
	~CPropertyPage2();
	static CUnknown * WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr);
	virtual HRESULT OnConnect(IUnknown *pUnknown);
	virtual HRESULT OnActivate();//用于初始化属性页对话框
	virtual INT_PTR OnReceiveMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);//接收属性页对话框的消息
	LPWSTR DefineFromGUID(GUID guid);//获取GUID定义字符串
	LPWSTR GetFormatString(WAVEFORMATEX* p, LPWSTR& lPChannels, LPWSTR& lPAvgBytesPerSec);//获取格式块描述字符串
	HRESULT GetOutAvailableType(BOOL Init);//获取输出允许类型,参数为TRUE,标记初始化组合框2;FALSE不对组合框2进行任何操作
	void SetList(AM_MEDIA_TYPE* PMT, WAVEFORMATEX* PWF, BOOL Init);
	void SetDirty()
	{
   
		m_bDirty = TRUE;
		if (m_pPageSite)
		{
   
			m_pPageSite->OnStatusChange(PROPPAGESTATUS_DIRTY);
		}
	}
	HRESULT OnApplyChanges(void);
	UINT32 NUM_CHANNELS = 0;
	UINT32 SAMPLES_PER_SECOND = 0;
	UINT32 BYTES_PER_SECOND = 0;
	HWND hList, hEdit, hCombox1, hCombox2, hText1, hText2;//
	HFONT hFont1, hFont2;
};


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

#endif //DLL_FILE

DLL源文件:DLL.cpp

#include "DLL.h"



const AMOVIESETUP_MEDIATYPE InPinType =   // 输入引脚媒体类型
{
   
	&MEDIATYPE_Audio,             //主要类型
	&MEDIASUBTYPE_PCM             //子类型
};

const AMOVIESETUP_MEDIATYPE OutPinType =   // 输出引脚媒体类型
{
   
	&MEDIATYPE_Audio,              //主要类型
	&MEDIASUBTYPE_MPEG_HEAAC       //子类型
};

const AMOVIESETUP_PIN sudPins[] =  // 引脚信息
{
   
	{
   
		(LPWSTR)"In",                 //引脚名称
		FALSE,                        //渲染过滤器
	    FALSE,                        //输出引脚
	    FALSE,                        //具有该引脚的零个实例
	    FALSE,                        //可以创建一个以上引脚的实例
	    &CLSID_NULL,                  //该引脚连接的过滤器的类标识
	    NULL,                         //该引脚连接的引脚名称
	    1,                            //引脚支持的媒体类型数
	    &InPinType                    //媒体类型信息
	},
	{
   
		(LPWSTR)"Out",                //引脚名称
		FALSE,                        //渲染过滤器
	    TRUE,                         //输出引脚
	    FALSE,                        //具有该引脚的零个实例
	    FALSE,                        //可以创建一个以上引脚的实例
	    &CLSID_NULL,                  //该引脚连接的过滤器的类标识
	    NULL,                         //该引脚连接的引脚名称
	    1,                            //引脚支持的媒体类型数
	    &OutPinType                   //媒体类型信息
	}
};

const AMOVIESETUP_FILTER AACEncoder =  //过滤器的注册信息
{
   
	&CLSID_AACEncoder,                 //过滤器的类标识
	L"AAC编码器",                      //过滤器的名称
	MERIT_DO_NOT_USE,                 //过滤器优先值
	2,                                //引脚数量
	sudPins                           //引脚信息
};

CFactoryTemplate g_Templates[] =   //类工厂模板数组
{
   
	{
   
		L"AAC编码器",                //过滤器名称
		&CLSID_AACEncoder,          //过滤器CLSID的指针
	    CFilter::CreateInstance,    //创建过滤器实例的函数的指针
	    NULL,                       //指向从DLL入口点调用的函数的指针
	    &AACEncoder                 //指向AMOVIESETUP_FILTER结构的指针
	},
	{
   
		L"属性页1",                            //对象名称
		&CLSID_PropertyPage1,                 //对象CLSID的指针
	    CPropertyPage1::CreateInstance,       //对象创建函数
	    NULL,                                 //DLL入口点调用的函数
	    NULL                                  //包含注册信息的AMOVIESETUP_FILTER结构
	},
	{
   
		L"属性页2",                            //对象名称
		&CLSID_PropertyPage2,                 //对象CLSID的指针
	    CPropertyPage2::CreateInstance,       //对象创建函数
	    NULL,                                 //DLL入口点调用的函数
	    NULL                                  //包含注册信息的AMOVIESETUP_FILTER结构
	}
};

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

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

#include "DLL.h"

CFilter::CFilter(TCHAR *pName, LPUNKNOWN pUnk, HRESULT *phr) : CBaseFilter(NAME("AAC编码器"), pUnk, this, CLSID_AACEncoder)
{
   
	HRESULT hr = MFStartup(MF_VERSION);//初始化媒体基础
	if (hr != S_OK)
	{
   
		MessageBox(NULL, L"初始化媒体基础失败", L"AAC编码器", MB_OK); return;
	}
	GUID CLSID_AACEncoderMft = {
    0x93af0c51, 0x2275, 0x45d2, 0xa3, 0x5b, 0xf2, 0xba, 0x21, 0xca, 0xed, 0x00 };//AAC编码器的类标识符
	hr = CoCreateInstance(CLSID_AACEncoderMft, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pAACEncoder));//创建AAC音频编码器(媒体基础转换)
	if (hr != S_OK)
	{
   
		MessageBox(NULL, L"AAC音频编码器创建失败", L"AAC编码器", MB_OK); return;
	}
	pCInPin = new 

你可能感兴趣的:(aac,c++,windows,音视频)