【发布时间】:2021-03-14 12:00:30
【问题描述】:
我想写一个简单的(只有一个 exe)音乐播放器。 如果我想播放 mp3,播放器就可以使用,但如果我想使用 MadFLAC 过滤器,播放器就无法使用。 我无法连接 MadFLAC 引脚。总是丢弃 0x80040207 错误。 (我认为,MadFLAC 过滤器已正确加载,我可以毫无错误地添加到 GraphBuilder 并在 EnumFilters 中查看。)
我不坚持使用 MadFLAC。我对所有其他选项都很感兴趣,我可以通过 DirectShow 播放 FLAC 文件,而无需将编解码器包安装到客户端 PC。
这是我的简化代码:
#include <windows.h>
#include <strmif.h>
#include <control.h>
#include <uuids.h>
#pragma comment(lib, "strmiids.lib")
IPin* GetPin(IBaseFilter *bFilter, PIN_DIRECTION pindir)
{
IEnumPins *EnumPin;
bFilter->EnumPins(&EnumPin);
unsigned long int num;
IPin *TempPin = NULL;
do {
EnumPin->Next(1, &TempPin, &num);
if (num != 0)
{
PIN_INFO PinInfo;
TempPin->QueryPinInfo(&PinInfo);
if (PinInfo.dir == pindir) break;
}
} while (num != 0);
return TempPin;
}
typedef HRESULT __stdcall DLLGETCLASSOBJECT(REFCLSID rclsid, REFIID riid, void **ppv);
HRESULT CreateFilterFromFile(HINSTANCE hLibInst, GUID TGUID, void **Filter) {
IClassFactory * ClassFactory;
HRESULT Result = S_FALSE;
FARPROC func;
func = GetProcAddress(hLibInst, "DllGetClassObject");
if (func != NULL)
{
IClassFactory *classFactory;
DLLGETCLASSOBJECT *dllGetClassObject = (DLLGETCLASSOBJECT*)func;
Result = dllGetClassObject(TGUID, IID_IClassFactory, (void**)&classFactory);
if (SUCCEEDED(Result))
{
Result = classFactory->CreateInstance(NULL, IID_IBaseFilter, Filter);
classFactory->Release();
}
}
return Result;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
void Player(bool isFlac) {
IGraphBuilder * player;
IMediaControl * mcontrol;
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&player);
player->QueryInterface(IID_IMediaControl, (void **)&mcontrol);
IBaseFilter *ARS = NULL;
HRESULT hr = CoCreateInstance(CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&ARS);
IBaseFilter * AudioDecoderFilter = NULL;
if (isFlac) {
hr = player->AddSourceFilter(L"D:\\test.flac", L"Async Reader Source", &ARS);
GUID CLSID_MadFlacAudioDecoder;
CLSIDFromString(L"{6B257121-CBB6-46B3-ABFA-B14DFA98C4A6}", &CLSID_MadFlacAudioDecoder);
HINSTANCE FHMPCAudioFilterInst = CoLoadLibrary(L"d:\\_MadFlac\\madFlac.ax", true);
if (FHMPCAudioFilterInst != 0) {
hr = CreateFilterFromFile(FHMPCAudioFilterInst, CLSID_MadFlacAudioDecoder, (void **)&AudioDecoderFilter);
if (AudioDecoderFilter != NULL) {
player->AddFilter(AudioDecoderFilter, L"MadFLAC Audio decoder (internal)");
}
}
}
else {
hr = player->AddSourceFilter(L"D:\\test.mp3", L"Async Reader Source", &ARS);
hr = CoCreateInstance(CLSID_MPEG1Splitter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&AudioDecoderFilter);
hr = player->AddFilter(AudioDecoderFilter, L"MPEG1Splitter");
}
IBaseFilter *PCM = NULL;
hr = CoCreateInstance(CLSID_ACMWrapper, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&PCM);
hr = player->AddFilter(PCM, L"PCM");
IBaseFilter *DSE = NULL;
hr = CoCreateInstance(CLSID_DSoundRender, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&DSE);
hr = player->AddFilter(DSE, L"Direct Renderer");
//ARS -> AdioDecoder
hr = GetPin(ARS, PINDIR_OUTPUT)->Connect(GetPin(AudioDecoderFilter, PINDIR_INPUT), NULL);
//If I use MadFLAC filter this hresult is 0x80040207
if (FAILED(hr)) MessageBoxA(NULL, "There is no common media type between these pins.", "Error", NULL);
//AudioDecoderFilter -> PCM
hr = GetPin(AudioDecoderFilter, PINDIR_OUTPUT)->Connect(GetPin(PCM, PINDIR_INPUT), NULL);
//PCM -> DSE
hr = GetPin(PCM, PINDIR_OUTPUT)->Connect(GetPin(DSE, PINDIR_INPUT), NULL);
//ListGraph(player);
mcontrol->Run();
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = "Teszt";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc)) { MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); return 0; }
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, "Teszt", "AppName", WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU, CW_USEDEFAULT, CW_USEDEFAULT, 460, 240, NULL, NULL, hInstance, NULL);
if (hwnd == NULL) { MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); return 0; }
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
Player(false);
while (GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
我使用的是 VS2015,原生 C++。
我也会尝试使用 LibFLAC,但我已经被困在那里无法构建,因为它抛出了数百个错误,我最终减少到不到 20 个,但几个小时后我已经放弃了痛苦。
【问题讨论】:
-
为什么不使用微软推荐的WASAPI播放音频?
-
另外,为什么不直接从文件中获取 RAW 样本并编写一个简单的自定义转换例程?
-
Directshow 已过时这就是您使用 VisualStudio 2015 的原因。
-
通常我编写我的应用程序以从 XP 运行到 Win10。据我所知,Wasapi 是与 Vista 一起出现的。这就是为什么我想使用 Directshow 来解决它。如何从 FLAC 中获取 RAW 样本? “简单的自定义转换例程”您可以链接到示例,看看它是什么样子的吗?
标签: c++ media-player directshow flac