获取 AVI 文件持续时间时出错 [英] Error on getting AVI file duration
问题描述
我在 WinAPI 上使用来自 JEDI 包装器的 VFW 单元.
I am using VFW unit from JEDI wrapper on WinAPI.
我正在编写的代码旨在搜索用户驱动器并检测warez.我们做 MP3、WMA 和一些图形文件搜索.现在我们要检测非法电影.我想打开 AVI 文件,从中读取一些详细信息并关闭它.我有以下代码:
The code I am writing is intended to search user drives and detect warez. We do MP3, WMA and some graphic file search. Now we want to detect illegal movies. I want to open AVI file, read some details from it and close it. I have the following code:
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;
有两个问题:
- lLenMinutes 是相等的到 98 而电影大约是两个小时.dwRate 是 100 万,并且dwScale 是 40k,所以 FPS 是完美 25. MSDN 说:单位由 dwRate 和 dwScale 定义".
- 代码在 FreeAndNil 行上崩溃.为什么?我认为我有责任释放 lFile(至少我觉得应该释放文件).没有与 FreeAndNil 一致,我有访问权限退出程序时的违规行为.
- The lLenMinutes is something equal to 98 while the movie is about two hours. dwRate is 1 million and dwScale is 40k, so the FPS is perfectly 25. MSDN says: "The units are defined by dwRate and dwScale".
- The code crashes on FreeAndNil line. Why? I assume I am responsible for freeing lFile (and at least I feel supposed to release file). Without line with FreeAndNil, I have Acces Violation on exit from a procedure.
那么,您知道如何从 AVI 文件中正确获取电影时长吗?为什么会崩溃?
So, do you have any clue how to correctly obtain movie duration from AVI file? And why the crash?
编辑
电影是 2 小时一分钟,所以结果应该非常接近 120.lFile 在 Jedi 中声明为:
The movie is 2hours one minute, so the result should be really close to 120.The lFile is declared in Jedi as:
IAVIFile = interface(IUnknown)
AVIFileOpen 在 JEDI 中声明为:
the AVIFileOpen is declared in JEDI as:
function AVIFileOpen(var ppfile: IAVIFILE; szFile: LPCWSTR; uMode: UINT; lpHandler: PCLSID): HResult;标准调用;外部 AVIFILDLL 名称 'AVIFileOpenW';
function AVIFileOpen(var ppfile: IAVIFILE; szFile: LPCWSTR; uMode: UINT; lpHandler: PCLSID): HResult; stdcall; external AVIFILDLL name 'AVIFileOpenW';
在 MSDN 中:
STDAPI AVIFileOpen(PAVIFILE *ppfile,LPCTSTR szFile,UINT 模式,CLSID pclsidHandler);
STDAPI AVIFileOpen( PAVIFILE *ppfile, LPCTSTR szFile, UINT mode, CLSID pclsidHandler );
MSDN 说:
"AVIFileOpen 函数打开一个 AVI文件并返回文件的地址用于访问它的接口."
"The AVIFileOpen function opens an AVI file and returns the address of a file interface used to access it."
所以我假设对象是由这个函数创建的.
so I assume object is created by this function.
编辑 2
avi 文件长度已移至新问题,因为 mghie 回答了这个问题.
The avi file length has been move to new question, since mghie answered this question.
推荐答案
函数是成对的,AVIFileOpen()
和 AVIFileRelease()
属于一起.在 AVIFileOpen()
被调用之前,lFile
变量是 nil
,之后(如果一切顺利)它包含一个接口指针.它的引用计数为 1.在调用 AVIFileRelease()
之后,变量应该再次包含 nil
,但它没有.现在,当您的方法退出编译器提供的用于释放接口指针的代码时,将尝试递减已释放接口的引用计数.
The functions are paired, AVIFileOpen()
and AVIFileRelease()
belong together. Before AVIFileOpen()
is called the lFile
variable is nil
, afterwards (if all went well) it contains an interface pointer. It has the reference count 1. After calling AVIFileRelease()
the variable should again contain nil
, but it doesn't. Now when your method exits the compiler-provided code to release interface pointers will try to decrement the reference count of the already released interface.
您基本上有两种方法可以解决此问题:
You have basically two ways to fix this:
在
AVIFileOpen()
之后增加接口指针的引用计数.
Increment the reference count of the interface pointer after
AVIFileOpen()
.
重置变量而不尝试减少引用计数.对指针使用类型转换:
Reset the variable without trying to decrement the reference count. Use a typecast to a pointer:
指针(lFile) := nil;
pointer(lFile) := nil;
此外,添加对 AVIFileExit()
的调用以匹配您对 AVIFileInit()
的调用.
Also, add a call to AVIFileExit()
to match your call to AVIFileInit()
.
这篇关于获取 AVI 文件持续时间时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!