我在WinAPI上使用JEDI包装器中的VFW单元。
我写的代码旨在搜索用户驱动器并检测warez。我们做MP3,WMA和一些图形文件搜索。现在我们要检测非法电影。我想打开AVI文件,从中读取一些细节并关闭它。我有以下代码:
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;
有两个问题:
那么,您是否有任何线索如何从AVI文件正确获取电影持续时间?崩溃的原因是什么?
修改
电影是2小时一分钟,所以结果应该非常接近120. lFile在绝地宣布为:
IAVIFile = interface(IUnknown)
AVIFileOpen在JEDI中声明为:
函数AVIFileOpen(var ppfile:IAVIFILE; szFile:LPCWSTR; uMode:UINT; lpHandler:PCLSID):HResult; STDCALL;外部AVIFILDLL名称'AVIFileOpenW';
并在MSDN中:
STDAPI AVIFileOpen( PAVIFILE * ppfile, LPCTSTR szFile, UINT模式, CLSID pclsidHandler );
MSDN说:
“AVIFileOpen函数打开AVI file并返回文件的地址 用于访问它的界面。“
所以我假设对象是由这个函数创建的。
修改2
avi文件长度已移至new question,因为mghie回答了这个问题。
答案 0 :(得分:3)
这些功能已配对,AVIFileOpen()
和AVIFileRelease()
属于一起。在调用AVIFileOpen()
之前,lFile
变量为nil
,之后(如果一切顺利)它包含一个接口指针。它具有引用计数1.在调用AVIFileRelease()
之后,该变量应该再次包含nil
,但它不会。现在,当您的方法退出编译器提供的代码以释放接口指针时,将尝试减少已发布接口的引用计数。
您基本上有两种解决方法:
在AVIFileOpen()
之后增加接口指针的引用计数。
重置变量而不尝试减少引用计数。对指针使用类型转换:
指针(lFile):= nil;
另外,添加一个与AVIFileExit()
的通话,以匹配您对AVIFileInit()
的通话。
答案 1 :(得分:1)
对于FreeAndNil()的崩溃,它被设计为释放TObject后代并将包含它的变量设置为nil。你在哪里创建代码中的TObject后代?似乎lFile
是一个接口,所以简单地将变量设置为nil就足以减少引用计数:
lFile := nil;
对FreeAndNil()内部Free的调用可能是导致崩溃的原因。
编辑:基于对原始问题的编辑,显然上述情况并不正确。但是,我怀疑对AVIFileRelease()
的调用已经释放了界面,因此没有什么可以让你做的。无论如何lFile
超出了范围,引用计数将自动递减。
就AVIFileOpen()
上的MSDN引用而言,请注意它表示“返回文件接口的地址”。这是一个COM接口,它的形状或形式绝不是Delphi TObject
后代。来自JEDI代码的片段也是这样说的,因为它说IAviFile
是interface(IUnknown)