我想创建我自己的过滤器并在DirectShow库中使用它。过滤器看起来可以写,但在创建图形时出现了问题。我的代码基于"Creating an Audio Capture Graph"文章。在最后,它说文章"Add a Filter by CLSID"和"Connect Two Filters"中的函数也被使用。我重写了最相似的函数,但代码不起作用。
我用许多个“!"指示错误的位置。
项目Project1.exe引发了异常类AEccessViolation,并返回消息“模块”Project1.exe“中地址0045 AAA 8处存在访问冲突。读取地址0000000”。进程已停止。请使用步骤或“运行”继续。
一般来说,我有以下代码:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, DirectShow9,ActiveX,BaseClass, DirectInput,
StdCtrls,DirectSound, DirectSetup, DirectPlay8, DirectMusic,
Dialogs;
type
TForm1 = class(TForm)
Button1: TButton;
ListBox2: TListBox;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
function AddFilterByCLSID(pGraphA: IGraphBuilder; clsid: TGUID; wazName: PWideChar; ppF: IBaseFilter): HRESULT;
function ConnectFilter( pGraph: IGraphBuilder; pSrc: IBaseFilter; pdest: IBaseFilter): HRESULT;
function GetUnconnectedPin(pFilter: IBaseFilter; PinDir: PIN_DIRECTION; ppPin: IPin): HRESULT;
function ConnectFilterPin( pGraph: IGraphBuilder; pOut: IPin; pdest: IBaseFilter): HRESULT;
end;
var
PropertyName:IPropertyBag;
pSrc, pWaveDest, pWriter: IBaseFilter;
pSink: IFileSinkFilter;
pGraph: IGraphBuilder;
FMediaControl: IMediaControl;
pDevEnum: ICreateDevEnum;
pEnum: IEnumMoniker;
pMoniker: IMoniker;
MArray1,MArray2: array of IMoniker;
hr: HRESULT;
DeviceName:OleVariant;
FAudioCaptureFilter: IBaseFilter;
const
CLSID_WavDest : TGUID = '{3C78B8E2-6C4D-11d1-ADE2-0000F8754B99}';
CLSID_CRleFilter: TGUID = '{BEBCF0A3-2673-42A7-82F2-5D4FC3126171}'; //My Filter.
IID_ICRleFilter: TGUID = '{35C0AC80-C3E4-4EEA-A1F5-049401E29400}'; //Myfilter
var
Form1: TForm1;
implementation
{$R *.dfm}
function TForm1.AddFilterByCLSID(pGraphA: IGraphBuilder; clsid: TCLSID;
wazName: PWideChar; ppF: IBaseFilter): HRESULT;
var
pF: IBaseFilter;
begin
CoCreateInstance(clsid, nil, CLSCTX_INPROC_SERVER, IID_IBaseFilter, pF);
hr:=pGraph.AddFilter(pF, WazName);
if hr<> S_OK then
begin
ShowMessage('фильтр вавдеста не добавился');
end;
PPf:= pF;
// pF._Release;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
pOut: IPin;
begin
HR:= CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, pGraph);
if hr<> S_OK then
begin
ShowMessage('Граф не создался');
end;
HR:= CoCreateInstance(CLSID_SystemDeviceEnum, NIL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, pDevEnum);
if hr<> S_OK then
begin
ShowMessage('перечеслитель не создался');
Exit;
end;
HR:=pDevEnum.CreateClassEnumerator(CLSID_AudioInputDeviceCategory, pEnum, 0);
if HR<>S_OK then EXIT;
//Обнуляем массив в списке моникеров
setlength(MArray2,0);
//Пускаем массив по списку устройств
while (S_OK=pEnum.Next(1,pMoniker,Nil)) do
begin
setlength(MArray2,length(MArray2)+1); //Увеличиваем массив на единицу
MArray2[length(MArray2)-1]:=pMoniker; //Запоминаем моникер в масиве
HR:=pMoniker.BindToStorage(NIL, NIL, IPropertyBag, PropertyName); //Линкуем моникер устройства к формату хранения IPropertyBag
if FAILED(HR) then Continue;
HR:=PropertyName.Read('FriendlyName', DeviceName, NIL); //Получаем имя устройства
if FAILED(HR) then Continue;
//Добавляем имя устройства в списки
Listbox2.Items.Add(DeviceName);
end;
Listbox2.ItemIndex:=0;
MArray2[Listbox2.ItemIndex].BindToObject(NIL, NIL, IID_IBaseFilter, FAudioCaptureFilter);
//добавляем устройство в граф фильтров
Pgraph.AddFilter(FAudioCaptureFilter, 'AudioCaptureFilter');
// pGraph.AddFilter(pSrc, 'Capture');
AddfilterByCLSID(pGraph, CLSID_CRleFilter, '_CRleFilter', pWaveDest);
ConnectFilter(pGraph, pWaveDest, pWriter); // This is where the mistakes start !!!!!!!!!!!!!!!!!
pGraph.QueryInterface(IID_IMediaControl, FMediaControl);
FMediaControl.Run();
end;
{
There is no function overloading in Delphi, so I named the functions differently
}
function TForm1.ConnectFilterPin(pGraph: IGraphBuilder; pOut: IPin;
pdest: IBaseFilter): HRESULT;
var
pIn : IPin;
begin
pIn:= nil;
GetUnconnectedPin(pdest, PINDIR_OUTPUT, pIn);
pGraph.Connect(pOut, pin);
end;
function TForm1.ConnectFilter(pGraph: IGraphBuilder; pSrc: IBaseFilter;
pdest: IBaseFilter): HRESULT;
var
pOut: IPin;
begin
//pOut:= 0;
GetUnconnectedPin(pSrc, PINDIR_OUTPUT, pOut);
ConnectFilterPin(pGraph, pOut, pdest);
end;
function TForm1.GetUnconnectedPin(pFilter: IBaseFilter;
PinDir: PIN_DIRECTION; ppPin: IPin): HRESULT;
var
pEnum: IEnumPins;
pPin: IPin;
hr: HRESULT;
ThisPinDir : PIN_DIRECTION;
pTmp: IPin;
begin
pTmp:=nil;
ppPin:= nil;
// pEnum:= nil;
pPin:= nil;
hr:= pFilter.EnumPins(pEnum); // This is where the error occurs !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if hr<> S_OK then
begin
ShowMessage('перечесление пинов: не равно S_OK');
end;
while pEnum.Next(1, pPin, nil) = S_OK do
begin
pPin.QueryDirection(ThisPinDir);
if ThisPinDir = PinDir then
begin
hr:= pPin.ConnectedTo(pTmp);
if Succeeded(hr) then
begin
pTmp._Release;
end else
begin
pEnum._Release;
ppPin:= pPin;
Result := S_OK;
Exit;
end;
end;
end;
pPin._Release;
ShowMessage('ошибка: не правильный код');
Result:= E_FAIL;
// ShowMessage('ошибка: не правильный код');
end;
end.
我希望错误是由指针引起的,或者更确切地说是指针的缺失。我试图把它们放在绝对所有的组合中,但这并没有导致期望的结果。此外,在 Delphi 中到处都根本没有使用指针。也许函数中的某个地方参数没有正确传递。我检查了所有的函数5次,试图找到错误,但这并不管用,指针也不管用。
我知道这个错误很小,很容易纠正,但我不知道它在哪里。
1条答案
按热度按时间olhwl3o21#
错误不在指针中。
Connect Filter
函数的用途是连接两个筛选器。结构看起来像ConnectFilter(Graph, Filter 1, Filter 2);
。我只向项目添加了一个筛选器。结果是,没有任何东西被发送到函数而不是第二个过滤器。有一个地址阅读错误,很难捕捉。如果我使用各种各样的检查,可能会很容易发现错误。由于C使用指针,而 Delphi 不使用,我以为错误是在指针中,因为我没有使用它们。但修复结果更简单:你需要添加第二个过滤器,并将其作为第三个参数发送。从这些错误中我们可以得出结论:1.即使是在实验代码中,也值得进行尽可能多的检查。
1.仔细观看和阅读。
1.从其他函数调用的函数应该在这些函数之上。没有错误,但在Flenov M.E. The Bible of Delphi (第三版),chapter 5.4中指出: Delphi 中的程序和函数。其他错误的解决方法也在那里描述。
1.与C不同, Delphi 不需要给新变量赋值
nil
,Delphi自己就可以完成。1.您也不需要自己调用
Release
。我重写了代码,纠正了我注意到的所有错误。我将它留在下面: