DirectShow过滤器开发-ALAW压缩过滤器

下载本过滤器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;
}

下载本过滤器DLL

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

h3974

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值