下载本过滤器DLL
本过滤器将PCM音频流压缩为ALAW音频流。
过滤器信息
过滤器名称:ALAW压缩
过滤器GUID:{3CF4A19B-E1B4-4DCC-9FAC-61B619202523}
DLL注册函数名:DllRegisterServer
删除注册函数名:DllUnregisterServer
过滤器有1个输入引脚和1个输出引脚。
输入引脚标识:In
输入引脚媒体类型:
主要类型:MEDIATYPE_Audio
子类型:MEDIASUBTYPE_PCM
格式类型:FORMAT_WaveFormatEx
样本为16位。
输出引脚标识:Out
输出引脚媒体类型:
主要类型:MEDIATYPE_Audio
子类型:{0x00000006, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
格式类型:FORMAT_WaveFormatEx
样本为8位。
ALAW压缩过滤器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
// {3CF4A19B-E1B4-4DCC-9FAC-61B619202523}
DEFINE_GUID(CLSID_ALAW,//过滤器GUID
0x3cf4a19b, 0xe1b4, 0x4dcc, 0x9f, 0xac, 0x61, 0xb6, 0x19, 0x20, 0x25, 0x23);
DEFINE_GUID(MEDIASUBTYPE_ALAW,//
0x00000006, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
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);
CFilter *pCFilter;
};
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 *pmt);
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;
};
class CFilter : public CCritSec, public CBaseFilter
{
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);
CInPin* pCInPin = NULL;
COutPin* pCOutPin = NULL;
WAVEFORMATEX wf;
UINT OutSize = 0;
};
template <class T> void SafeRelease(T** ppT)
{
if (*ppT)
{
(*ppT)->Release();
*ppT = NULL;
}
}
#endif //DLL_FILE
DLL.cpp
#include "DLL.h"
const AMOVIESETUP_MEDIATYPE InPinType = // 输入引脚媒体类型
{
&MEDIATYPE_Audio, //主要类型
&MEDIASUBTYPE_PCM //子类型
};
const AMOVIESETUP_MEDIATYPE OutPinType = //输出引脚媒体类型
{
&MEDIATYPE_Audio, //主要类型
&MEDIASUBTYPE_ALAW //子类型
};
const AMOVIESETUP_PIN sudPins[] = // 引脚信息
{
{
L"In", //引脚名称
FALSE, //渲染引脚
FALSE, //输出引脚
FALSE, //具有该引脚的零个实例
FALSE, //可以创建一个以上引脚的实例
&CLSID_NULL, //该引脚连接的过滤器的类标识
NULL, //该引脚连接的引脚名称
1, //引脚支持的媒体类型数
&InPinType //媒体类型信息
},
{
L"Out", //引脚名称
FALSE, //渲染引脚
TRUE, //输出引脚
FALSE, //具有该引脚的零个实例
FALSE, //可以创建一个以上引脚的实例
&CLSID_NULL, //该引脚连接的过滤器的类标识
NULL, //该引脚连接的引脚名称
1, //引脚支持的媒体类型数
&OutPinType //媒体类型信息
}
};
const AMOVIESETUP_FILTER ALAW = //过滤器的注册信息
{
&CLSID_ALAW, //过滤器的类标识
L"ALAW压缩", //过滤器的名称
MERIT_DO_NOT_USE, //过滤器优先值
2, //引脚数量
sudPins //引脚信息
};
CFactoryTemplate g_Templates[] = //类工厂模板数组
{
{
L"ALAW压缩", //对象(这里为过滤器)名称
&CLSID_ALAW, //对象CLSID的指针
CFilter::CreateInstance, //创建对象实例的函数的指针
NULL, //指向从DLL入口点调用的函数的指针
&ALAW //指向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
#include "DLL.h"
CFilter::CFilter(TCHAR *pName, LPUNKNOWN pUnk, HRESULT *phr) : CBaseFilter(NAME("ALAW压缩"), pUnk, this, CLSID_ALAW)
{
pCInPin = new CInPin(this, phr, L"In");//创建输入引脚
pCOutPin = new COutPin(this, phr, L"Out");//创建输出引脚
}
CFilter::~CFilter()
{
}
CBasePin *CFilter::GetPin(int n)
{
if (n == 0)return pCInPin;
if (n == 1)return pCOutPin;
return NULL;
}
int CFilter::GetPinCount()
{
return 2;
}
CUnknown * WINAPI CFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr)
{
return new CFilter(NAME("ALAW压缩"), pUnk, phr);
}
CInPin.cpp
#include "DLL.h"
CInPin::CInPin(CFilter *pFilter, HRESULT *phr, LPCWSTR pPinName) : CBaseInputPin(NAME("In"), pFilter, pFilter, phr, pPinName)
{
pCFilter = pFilter;
}
CInPin::~CInPin()
{
}
HRESULT CInPin::CheckMediaType(const CMediaType *pmt)
{
if (pmt->majortype == MEDIATYPE_Audio && pmt->subtype == MEDIASUBTYPE_PCM && pmt->formattype == FORMAT_WaveFormatEx && !pmt->bTemporalCompression)
{
WAVEFORMATEX* pwf = (WAVEFORMATEX*)pmt->pbFormat;
if (pwf->wFormatTag != 1 || pwf->wBitsPerSample != 16)return S_FALSE;
return S_OK;
}
return S_FALSE;
}
HRESULT CInPin::SetMediaType(const CMediaType *pmt)
{
WAVEFORMATEX* p = (WAVEFORMATEX*)pmt->pbFormat;
CopyMemory(&pCFilter->wf, p, sizeof(WAVEFORMATEX));
pCFilter->OutSize = pmt->GetSampleSize() / 2;
return CBasePin::SetMediaType(pmt);
}
unsigned char linear2alaw(int pcm_val);
STDMETHODIMP CInPin::Receive(IMediaSample *pSample)
{
HRESULT hr;
BYTE* pBy = NULL;
hr = pSample->GetPointer(&pBy);//获取引脚样本缓冲区指针
long len = pSample->GetActualDataLength();//获取有效数据长度
REFERENCE_TIME star, end;
hr = pSample->GetTime(&star, &end);//获取样本时间戳
if (pCFilter->pCOutPin->IsConnected())//如果输出引脚已连接
{
IMediaSample *pOutSample = NULL;
hr = pCFilter->pCOutPin->GetDeliveryBuffer(&pOutSample, NULL, NULL, 0);//获取一个空的输出引脚样本
if (hr == S_OK)
{
BYTE* pOutBuffer = NULL;
hr = pOutSample->GetPointer(&pOutBuffer);//获取输出引脚样本缓冲区指针
short sh; BYTE data;
for (int i = 0; i < len / 2; i++)//将PCM音频数据转换为ALAW数据
{
CopyMemory(&sh, pBy + i * 2, 2);
data = linear2alaw(sh);
CopyMemory(pOutBuffer + i, &data, 1);
}
hr = pOutSample->SetTime(&star, &end);//设置输出引脚样本时间戳
hr = pOutSample->SetActualDataLength(len/2);//设置输出引脚样本有效数据长度
hr = pCFilter->pCOutPin->Deliver(pOutSample);//输出引脚向下游发送样本
pOutSample->Release();//释放输出引脚样本
if (hr != S_OK)return hr;
}
}
return S_OK;
}
STDMETHODIMP CInPin::EndOfStream()
{
return pCFilter->pCOutPin->DeliverEndOfStream();
}
STDMETHODIMP CInPin::BeginFlush()
{
HRESULT hr = S_OK;
hr = pCFilter->pCOutPin->DeliverBeginFlush();
if (FAILED(hr))
return hr;
return CBaseInputPin::BeginFlush();
}
STDMETHODIMP CInPin::EndFlush()
{
HRESULT hr = S_OK;
hr = pCFilter->pCOutPin->DeliverEndFlush();
if (FAILED(hr))
return hr;
return CBaseInputPin::EndFlush();
}
STDMETHODIMP CInPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
{
HRESULT hr;
hr = pCFilter->pCOutPin->DeliverNewSegment(tStart, tStop, dRate);
if (FAILED(hr))
return hr;
return CBaseInputPin::NewSegment(tStart, tStop, dRate);
}
#define QUANT_MASK (0xf)
#define SEG_SHIFT (4)
static short seg_end[8] = { 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF };
unsigned char _u2a[128] = {
1, 1, 2, 2, 3, 3, 4, 4,
5, 5, 6, 6, 7, 7, 8, 8,
9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 29, 31, 33, 34, 35, 36,
37, 38, 39, 40, 41, 42, 43, 44,
46, 48, 49, 50, 51, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, 62,
64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79,
81, 82, 83, 84, 85, 86, 87, 88,
89, 90, 91, 92, 93, 94, 95, 96,
97, 98, 99, 100,101,102,103,104,
105,106,107,108,109,110,111,112,
113,114,115,116,117,118,119,120,
121,122,123,124,125,126,127,128
};
unsigned char _a2u[128] = {
1, 3, 5, 7, 9, 11, 13, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31,
32, 32, 33, 33, 34, 34, 35, 35,
36, 37, 38, 39, 40, 41, 42, 43,
44, 45, 46, 47, 48, 48, 49, 49,
50, 51, 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 62, 63, 64, 64,
65, 66, 67, 68, 69, 70, 71, 72,
73, 74, 75, 76, 77, 78, 79, 79,
80, 81, 82, 83, 84, 85, 86, 87,
88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99, 100,101,102,103,
104,105,106,107,108,109,110,111,
112,113,114,115,116,117,118,119,
120,121,122,123,124,125,126,127
};
static int search(int val, short *table, int size)
{
int i;
for (i = 0; i < size; i++) {
if (val <= *table++)
return (i);
}
return (size);
}
unsigned char linear2alaw(int pcm_val)
{
int mask;
int seg;
unsigned char aval;
if (pcm_val >= 0)
{
mask = 0xD5;
}
else
{
mask = 0x55;
pcm_val = -pcm_val - 1;
}
seg = search(pcm_val, seg_end, 8);
if (seg >= 8)
return (0x7F ^ mask);
else
{
aval = seg << SEG_SHIFT;
if (seg < 2)
aval |= (pcm_val >> 4) & QUANT_MASK;
else
aval |= (pcm_val >> (seg + 3)) & QUANT_MASK;
return (aval ^ mask);
}
}
COutPin.cpp
#include "DLL.h"
COutPin::COutPin(CFilter *pFilter, HRESULT *phr, LPCWSTR pPinName) : CBaseOutputPin(NAME("Out"), pFilter, pFilter, phr, pPinName)
{
pCFilter = pFilter;
}
COutPin::~COutPin()
{
SafeRelease(&m_pPosition);
}
STDMETHODIMP COutPin::NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
CheckPointer(ppv, E_POINTER);
ASSERT(ppv);
*ppv = NULL;
HRESULT hr = NOERROR;
if (riid == IID_IMediaPosition || riid == IID_IMediaSeeking)
{
if (m_pPosition == NULL)
{
hr = CreatePosPassThru(GetOwner(), FALSE, (IPin *)pCFilter->pCInPin, &m_pPosition);
if (FAILED(hr)) return hr;
}
return m_pPosition->QueryInterface(riid, ppv);
}
return CBaseOutputPin::NonDelegatingQueryInterface(riid, ppv);
}
HRESULT COutPin::GetMediaType(int iPosition, CMediaType *pmt)
{
if (iPosition < 0)return E_INVALIDARG;
if (iPosition > 0)return VFW_S_NO_MORE_ITEMS;
pmt->SetType(&MEDIATYPE_Audio);//主要类型
pmt->SetSubtype(&MEDIASUBTYPE_ALAW);//子类型
pmt->SetFormatType(&FORMAT_WaveFormatEx);//格式类型
pmt->SetSampleSize(pCFilter->OutSize);//样本大小
pmt->SetTemporalCompression(FALSE);//不使用时间压缩
WAVEFORMATEX* p = (WAVEFORMATEX*)pmt->AllocFormatBuffer(sizeof(WAVEFORMATEX));
p->wFormatTag = 6;//编码方式
p->nChannels = pCFilter->wf.nChannels;//声道数
p->nSamplesPerSec = pCFilter->wf.nSamplesPerSec;//采样率
p->nAvgBytesPerSec = pCFilter->wf.nAvgBytesPerSec/2;//传输率
p->nBlockAlign = pCFilter->wf.nChannels;//块对齐
p->wBitsPerSample = 8;//样本位数
p->cbSize = 0;//附加信息大小
return S_OK;
}
HRESULT COutPin::CheckMediaType(const CMediaType *pmt)
{
if (!pCFilter->pCInPin->IsConnected())
{
MessageBox(0, L"须先连接输入引脚", L"ALAW压缩", MB_OK); return S_FALSE;
}
if (pmt->majortype == MEDIATYPE_Audio && pmt->subtype == MEDIASUBTYPE_ALAW && pmt->formattype == FORMAT_WaveFormatEx)
return S_OK;
return S_FALSE;
}
HRESULT COutPin::DecideBufferSize(IMemAllocator *pMemAllocator, ALLOCATOR_PROPERTIES * ppropInputRequest)//确定输出引脚样本缓冲区大小
{
HRESULT hr = S_OK;
ppropInputRequest->cBuffers = 1;//1个缓冲区
ppropInputRequest->cbBuffer = 1000000;//缓冲区的大小
ALLOCATOR_PROPERTIES Actual;
hr = pMemAllocator->SetProperties(ppropInputRequest, &Actual);
if (FAILED(hr))return hr;
if (Actual.cbBuffer < ppropInputRequest->cbBuffer)// 这个分配器是否不合适
{
return E_FAIL;
}
ASSERT(Actual.cBuffers == 1);// 确保我们只有 1 个缓冲区
return S_OK;
}
HRESULT COutPin::Active()
{
HRESULT hr = NOERROR;
if (m_Connected == NULL)
return NOERROR;
if (m_pOutputQueue == NULL)
{
m_pOutputQueue = new COutputQueue(m_Connected, &hr, TRUE, FALSE);
if (m_pOutputQueue == NULL)
return E_OUTOFMEMORY;
if (FAILED(hr))
{
delete m_pOutputQueue;
m_pOutputQueue = NULL;
return hr;
}
}
CBaseOutputPin::Active();
return NOERROR;
}
HRESULT COutPin::Inactive()
{
if (m_pOutputQueue)
{
delete m_pOutputQueue;
m_pOutputQueue = NULL;
}
CBaseOutputPin::Inactive();
return NOERROR;
}
HRESULT COutPin::Deliver(IMediaSample *pMediaSample)
{
if (m_pOutputQueue == NULL)
return NOERROR;
pMediaSample->AddRef();
return m_pOutputQueue->Receive(pMediaSample);
}
HRESULT COutPin::DeliverEndOfStream()
{
if (m_pOutputQueue == NULL)
return NOERROR;
m_pOutputQueue->EOS();
return NOERROR;
}
HRESULT COutPin::DeliverBeginFlush()
{
if (m_pOutputQueue == NULL)
return NOERROR;
m_pOutputQueue->BeginFlush();
return NOERROR;
}
HRESULT COutPin::DeliverEndFlush()
{
if (m_pOutputQueue == NULL)
return NOERROR;
m_pOutputQueue->EndFlush();
return NOERROR;
}
HRESULT COutPin::DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
{
if (m_pOutputQueue == NULL)
return NOERROR;
m_pOutputQueue->NewSegment(tStart, tStop, dRate);
return NOERROR;
}
STDMETHODIMP COutPin::Notify(IBaseFilter *pSender, Quality q)
{
if (pCFilter->pCInPin->m_pQSink != NULL)
{
return pCFilter->pCInPin->m_pQSink->Notify(pCFilter, q);
}
else
{
HRESULT hr;
IQualityControl * pIQC;
hr = VFW_E_NOT_FOUND;
if (pCFilter->pCInPin->m_Connected)
{
pCFilter->pCInPin->m_Connected->QueryInterface(IID_IQualityControl, (void**)&pIQC);
if (pIQC != NULL)
{
hr = pIQC->Notify(pCFilter, q);
pIQC->Release();
}
}
return hr;
}
return NOERROR;
}