当前位置: 首页 > article >正文

DirectShow过滤器开发-写MP3音频文件过滤器(再写 写MP3)

下载本过滤器DLL
本过滤器将MP3音频流写到MP3音频文件。

过滤器信息

过滤器名称:写MP3_2
过滤器GUID:{AE46BC15-71E5-471C-8540-3B73094111EC}
DLL注册函数名:DllRegisterServer
删除注册函数名:DllUnregisterServer
过滤器有1个输入引脚。

输入引脚标识:In
输入引脚媒体类型:
主要类型:MEDIATYPE_Audio
子类型:{0x00000055, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
格式类型:FORMAT_WaveFormatEx

过滤器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

// {AE46BC15-71E5-471C-8540-3B73094111EC}
DEFINE_GUID(CLSID_WriteMP3,
	0xae46bc15, 0x71e5, 0x471c, 0x85, 0x40, 0x3b, 0x73, 0x9, 0x41, 0x11, 0xec);

DEFINE_GUID(MEDIASUBTYPE_MP3,
	0x00000055, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);

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


class CFilter;

class CInputPin : public CBaseInputPin
{
	friend class CFilter;
	CFilter *pCFilter;
public:
	CInputPin(CFilter *pFilter, HRESULT *phr, LPCWSTR pPinName);
	~CInputPin();
	HRESULT CheckMediaType(const CMediaType *pmt);
	STDMETHODIMP Receive(IMediaSample *pSample);
	HRESULT Active();
	HRESULT Inactive();
	HANDLE hFile = NULL;//输出文件句柄
};

class CFilter : public CBaseFilter, public CCritSec, public IFileSinkFilter
{
	friend class CInputPin;
public:
	CFilter(LPWSTR lpName, LPUNKNOWN pUnk, HRESULT *phr);
	virtual ~CFilter();
	DECLARE_IUNKNOWN
	STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
	virtual HRESULT STDMETHODCALLTYPE  SetFileName(LPCOLESTR pszFileName, const AM_MEDIA_TYPE *pmt);
	virtual HRESULT STDMETHODCALLTYPE  GetCurFile(LPOLESTR * ppszFileName, AM_MEDIA_TYPE *pmt);
	static CUnknown * WINAPI CreateInstance(LPUNKNOWN, HRESULT *);
	int GetPinCount();
	CBasePin *GetPin(int n);
	STDMETHODIMP Run(REFERENCE_TIME tStart);
	CInputPin *m_pInputPin;   //输入引脚指针
	WCHAR* m_pFileName = NULL;//要创作的MP3文件路径
};

#endif //DLL_FILE

DLL.cpp

#include "DLL.h"

const AMOVIESETUP_MEDIATYPE sudPinTypes =
{
	&MEDIATYPE_Audio,              //主要类型
	&MEDIASUBTYPE_MP3              //子类型
};

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

const AMOVIESETUP_FILTER WriteMP3 = //过滤器的注册信息
{
	&CLSID_WriteMP3,                //过滤器的类标识
	L"写MP3_2",                     //过滤器的名称
	MERIT_DO_NOT_USE,               //过滤器优先值
	1,                              //引脚数量
	&sudPin                        //引脚信息
};

CFactoryTemplate g_Templates[] = {
	{
		L"写MP3_2"                   //对象(这里为过滤器)名称
		, &CLSID_WriteMP3            //对象CLSID的指针
	    , CFilter::CreateInstance    //创建对象实例的函数的指针
	    , NULL                       //指向从DLL入口点调用的函数的指针
	    , &WriteMP3                  //指向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"
#include "strsafe.h"

CFilter::CFilter(LPWSTR lpName, LPUNKNOWN pUnk, HRESULT *phr) : CBaseFilter(lpName, pUnk, (CCritSec *) this, CLSID_WriteMP3)
{
	m_pInputPin = new CInputPin(this, phr, L"In");//创建输入引脚
}

CFilter::~CFilter()
{
	if (m_pFileName != NULL)delete[] m_pFileName;
}

CUnknown * WINAPI CFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr)
{
	return new CFilter(L"写MP3_2", pUnk, phr);//创建过滤器
}

int CFilter::GetPinCount()
{
	return 1;
}

CBasePin *CFilter::GetPin(int n)
{
	if (n != 0)
	{
		return NULL;
	}
	return m_pInputPin;
}

STDMETHODIMP CFilter::NonDelegatingQueryInterface(REFIID iid, void ** ppv)
{
	if (iid == IID_IFileSinkFilter)
	{
		return GetInterface(static_cast<IFileSinkFilter*>(this), ppv);
	}
	else
		return CBaseFilter::NonDelegatingQueryInterface(iid, ppv);
}

HRESULT CFilter::GetCurFile(LPOLESTR *ppszFileName, AM_MEDIA_TYPE *pmt)
{
	CheckPointer(ppszFileName, E_POINTER);
	*ppszFileName = NULL;
	if (m_pFileName != NULL)
	{
		size_t len = 1 + lstrlenW(m_pFileName);
		*ppszFileName = (LPOLESTR)QzTaskMemAlloc(sizeof(WCHAR) * (len));
		if (*ppszFileName != NULL)
		{
			HRESULT hr = StringCchCopyW(*ppszFileName, len, m_pFileName);
		}
	}
	if (pmt)
	{
		ZeroMemory(pmt, sizeof(*pmt));
		pmt->majortype = MEDIATYPE_NULL;
		pmt->subtype = MEDIASUBTYPE_NULL;
	}
	return S_OK;
}

HRESULT CFilter::SetFileName(LPCOLESTR pszFileName, const AM_MEDIA_TYPE *pmt)
{
	CheckPointer(pszFileName, E_POINTER);
	if (wcslen(pszFileName) > MAX_PATH || wcslen(pszFileName)<4)
		return ERROR_FILENAME_EXCED_RANGE;
	size_t len = 1 + lstrlenW(pszFileName);
	m_pFileName = new WCHAR[len];
	if (m_pFileName == 0)
		return E_OUTOFMEMORY;
	HRESULT hr = StringCchCopyW(m_pFileName, len, pszFileName);
	if (m_pFileName[len - 2] != '3' || m_pFileName[len - 3] != 'p' || m_pFileName[len - 4] != 'm' || m_pFileName[len - 5] != '.')//如果不是MP3文件
	{
		delete[] m_pFileName; m_pFileName = NULL;
		return VFW_E_INVALID_FILE_FORMAT;//设置文件名失败
	}
	return S_OK;
}

STDMETHODIMP CFilter::Run(REFERENCE_TIME tStart)
{
	if (m_pFileName == NULL)
	{
		MessageBox(NULL, L"未指定输出文件", L"写MP3_2", MB_OK); return S_FALSE;
	}
	return CBaseFilter::Run(tStart);
}

CInputPin.cpp

#include "DLL.h"
#include "mmreg.h"

CInputPin::CInputPin(CFilter *pFilter, HRESULT *phr, LPCWSTR pPinName) : CBaseInputPin(NAME("In"), pFilter, pFilter, phr, pPinName)
{
	pCFilter = pFilter;
}

CInputPin::~CInputPin()//输入引脚析构函数
{

}

HRESULT CInputPin::CheckMediaType(const CMediaType *pmt)
{
	if (pmt->majortype == MEDIATYPE_Audio && pmt->subtype == MEDIASUBTYPE_MP3 && pmt->formattype == FORMAT_WaveFormatEx)
	{
		WAVEFORMATEX* p = (WAVEFORMATEX*)pmt->pbFormat;
		if (p->wFormatTag != 85)return S_FALSE;
		return S_OK;
	}
	else
		return S_FALSE;
}

HRESULT CInputPin::Receive(IMediaSample * pSample)//接收函数
{
	HRESULT hr;
	BYTE* pBy = NULL;
	hr = pSample->GetPointer(&pBy);//获取引脚样本缓冲区指针
	long len = pSample->GetActualDataLength();//获取有效数据长度
	if (hFile)
	{
		WriteFile(hFile, pBy, len, NULL, NULL);//写MP3数据
	}
	return S_OK;
}

HRESULT CInputPin::Active()
{
	if (pCFilter->m_pFileName == NULL)
	{
		MessageBox(0, L"没有指定输出文件", L"写MP3_2", MB_OK); return S_FALSE;
	}
	hFile = CreateFile(pCFilter->m_pFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);//创建输出文件
	if (INVALID_HANDLE_VALUE == hFile)
	{
		MessageBox(0, L"创建输出文件失败", L"写MP3_2", MB_OK); return S_FALSE;
	}
	char chID[3] = { 'I','D','3' };
	WriteFile(hFile, chID, 3, NULL, NULL);//写标识
	BYTE by1 = 3;
	WriteFile(hFile, &by1, 1, NULL, NULL);//写版本号:ID3V2.3
	BYTE by2 = 0;
	WriteFile(hFile, &by2, 1, NULL, NULL);//写副版本号
	BYTE by3 = 0;
	WriteFile(hFile, &by3, 1, NULL, NULL);//写标志
	DWORD mSize = 0;
	WriteFile(hFile, &mSize, 4, NULL, NULL);//写标签大小
	return CBaseInputPin::Active();
}

HRESULT CInputPin::Inactive()
{
	CloseHandle(hFile);//关闭输出文件
	hFile = NULL;
	return CBaseInputPin::Inactive();
}

下载本过滤器DLL


http://www.kler.cn/a/374894.html

相关文章:

  • 【Java SE】类型转换
  • NPOI 操作详解(操作Excel)
  • 解决rabbitmq-plugins enable rabbitmq_delayed_message_exchange :plugins_not_found
  • 入门 | Kafka数据使用vector消费到Loki中使用grafana展示
  • 深度学习数学基础之梯度
  • Solidity智能合约中的异常处理error、require、assert
  • 鸿蒙系统的优势 不足以及兼容性与未来发展前景分析
  • C++基础_类的基本理解
  • 『 Linux 』网络传输层 - TCP(二)
  • NLP算法工程师精进之路:顶会论文研读精华
  • Rust整合Elasticsearch
  • el-tree展开子节点后宽度没有撑开,溢出内容隐藏了,不显示横向滚动条
  • 使用LangChain控制大模型的输出——解析器Parser
  • 人工智能:塑造未来生活的强大力量
  • 计组-层次化存储结构
  • uniapp+vite配置环境变量
  • Docker | 将本地项目发布到阿里云的实现流程
  • 第3关:命题逻辑推理
  • TQ15EG开发板教程:fmcomms8两片ADRV9009同步采集测试
  • SpringBoot后端开发常用工具详细介绍——flyway数据库版本控制工具
  • MyBatisPlus 中 LambdaQueryWrapper使用
  • ffmpeg+vue2
  • C++STL详解(九)map和set的使用
  • 探索高效办公新利器 ——ONLYOFFICE
  • TON 区块链开发的深入概述#TON链开发#DAPP开发#交易平台#NFT#Gamefi链游
  • django校园兼职系统-计算机毕业设计源码95561