Delphi 获取AVI文件持续时间时出错
我在WinAPI上使用绝地包装器中的VFW单元 我正在编写的代码旨在搜索用户驱动器并检测warez。我们做MP3,WMA和一些图形文件搜索。现在我们想检测非法电影。我想打开AVI文件,从中读取一些细节并关闭它。我有以下代码:Delphi 获取AVI文件持续时间时出错,delphi,winapi,metadata,multimedia,avi,Delphi,Winapi,Metadata,Multimedia,Avi,我在WinAPI上使用绝地包装器中的VFW单元 我正在编写的代码旨在搜索用户驱动器并检测warez。我们做MP3,WMA和一些图形文件搜索。现在我们想检测非法电影。我想打开AVI文件,从中读取一些细节并关闭它。我有以下代码: uses WFV; //from JEDI api wrappers procedure TForm1.Button1Click(Sender: TObject); var lInfo : TAVIFILEINFO lFile : IAVIFILE; l
uses WFV; //from JEDI api wrappers
procedure TForm1.Button1Click(Sender: TObject);
var
lInfo : TAVIFILEINFO lFile : IAVIFILE;
lFileType : string;
lLenMinutes : integer;
lFPS : integer;
begin
{init file}
AVIFileInit;
{Open file - note: since we search for warez this is perfely "warezy" file}
AVIFileOpen(lFile, 'e:\Sideways KLAXXON\Sideways KLAXXON.avi', OF_READ, nil);
{Get file info}
AVIFileInfoW(lFile, lInfo, sizeof(lInfo));
lFPS:=Round(lInfo.dwRate /lInfo.dwScale);
lLenMinutes := Round(lInfo.dwLength / lFPS / 60);
lFileType := lInfo.szFileType;
{just for show: prepare some memo to see what we get}
memo1.Lines.Clear;
memo1.Lines.Add('File lenght [min]: ' + IntToStr(lLenMinutes));
memo1.Lines.Add('Width: ' + IntToStr(lInfo.dwWidth));
memo1.Lines.Add('Height: ' + IntToStr(lInfo.dwHeight));
memo1.Lines.Add('File type: ' + lFileType);
{Closing the file}
AVIFileRelease (lFile);
{and here goes the crash}
FreeAndNil(lFile);
end;
有两个问题:
IAVIFile = interface(IUnknown)
在《绝地武士》中,AVIFileOpen被宣布为:
函数AVIFileOpen(var-ppfile:IAVIFILE;szFile:LPCWSTR;uMode:UINT;lpHandler:PCLSID):HResult;stdcall;外部AVIFILDLL名称“AVIFileOpenW”
在MSDN中:
STDAPI文件打开(
PAVIFILE*ppfile,
LPCTSTR文件,
UINT模式,
CLSID pclsidHandler
);
MSDN说:
“AVIFileOpen函数打开一个AVI
文件,并返回文件的地址
用于访问它的接口。“
所以我假设对象是由这个函数创建的
编辑2
自mghie回答此问题后,avi文件长度已移动到。98分钟是一小时38分钟。什么是“大约两小时” 至于FreeAndNil()上的崩溃,它被设计为释放一个TObject子体,并将包含它的变量设置为nil。在代码中,在哪里创建TObject子体?似乎
lFile
是一个接口,因此简单地将变量设置为nil就足以减少引用计数:
lFile := nil;
调用Free inside FreeAndNil()可能是导致崩溃的原因
编辑:根据对原始问题的编辑,显然上述内容不正确。但是,我怀疑对AVIFileRelease()
的调用已经释放了接口,因此没有什么可以做的了lFile
无论如何都将超出范围,引用计数将自动递减
至于
AVIFileOpen()
上的MSDN引号,请注意它表示“返回文件接口的地址”。这是一个COM接口,它的形状或形式决不是DelphiToObject
的后代。绝地密码的片段也这么说,因为它说,IAviFile
是一个接口(IUnknown)
98分钟是一小时38分钟。什么是“大约两小时”
至于FreeAndNil()上的崩溃,它被设计为释放一个TObject子体,并将包含它的变量设置为nil。在代码中,在哪里创建TObject子体?似乎lFile
是一个接口,因此简单地将变量设置为nil就足以减少引用计数:
lFile := nil;
调用Free inside FreeAndNil()可能是导致崩溃的原因
编辑:根据对原始问题的编辑,显然上述内容不正确。但是,我怀疑对AVIFileRelease()
的调用已经释放了接口,因此没有什么可以做的了lFile
无论如何都将超出范围,引用计数将自动递减
至于
AVIFileOpen()
上的MSDN引号,请注意它表示“返回文件接口的地址”。这是一个COM接口,它的形状或形式决不是DelphiToObject
的后代。绝地密码中的代码片段也这么说,因为它说,IAviFile
是一个接口(IUnknown)
函数是成对的,AVIFileOpen()
和AVIFileRelease()
属于一对。在调用AVIFileOpen()
之前,lFile
变量是nil
,之后(如果一切顺利)它包含一个接口指针。它的引用计数为1。调用AVIFileRelease()
后,变量应再次包含nil
,但它不包含。现在,当您的方法退出时,编译器提供的用于释放接口指针的代码将尝试减少已释放接口的引用计数
基本上有两种方法可以解决此问题:
- 在
之后增加接口指针的引用计数AVIFileOpen()
- 重置变量而不尝试减少引用计数。对指针使用类型转换: 指针(lFile):=nil
另外,添加对
AVIFileExit()
的调用,以匹配对AVIFileInit()
的调用。这些函数是成对的,AVIFileOpen()
和AVIFileRelease()
属于一起。在调用AVIFileOpen()
之前,lFile
变量是nil
,之后(如果一切顺利)它包含一个接口指针。它的引用计数为1。调用AVIFileRelease()
后,变量应再次包含nil
,但它不包含。现在,当您的方法退出时,编译器提供的用于释放接口指针的代码将尝试减少已释放接口的引用计数
基本上有两种方法可以解决此问题:
- 在
之后增加接口指针的引用计数AVIFileOpen()
- 重置变量而不尝试减少引用计数。对指针使用类型转换: 指针(lFile):=nil
AVIFileExit()
的调用