获取AVI文件持续时间时出错

时间:2009-11-19 19:14:57

标签: delphi winapi metadata multimedia avi

我在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;

有两个问题:

  1. lLenMinutes是平等的 到98年,电影大约是两部 小时。 dwRate是100万和 dwScale是40k,所以FPS是 完美的25. MSDN says:“单位 由dwRate和dwScale定义“。
  2. 代码在FreeAndNil行崩溃。 为什么?我认为我有责任 释放lFile(至少我觉得 应该发布文件)。没有 与FreeAndNil一致,我有Acces 退出程序时违反。
  3. 那么,您是否有任何线索如何从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回答了这个问题。

2 个答案:

答案 0 :(得分:3)

这些功能已配对,AVIFileOpen()AVIFileRelease()属于一起。在调用AVIFileOpen()之前,lFile变量为nil,之后(如果一切顺利)它包含一个接口指针。它具有引用计数1.在调用AVIFileRelease()之后,该变量应该再次包含nil,但它不会。现在,当您的方法退出编译器提供的代码以释放接口指针时,将尝试减少已发布接口的引用计数。

您基本上有两种解决方法:

  • AVIFileOpen()之后增加接口指针的引用计数。

  • 重置变量而不尝试减少引用计数。对指针使用类型转换:

    指针(lFile):= nil;

另外,添加一个与AVIFileExit()的通话,以匹配您对AVIFileInit()的通话。

答案 1 :(得分:1)

98分钟是1小时38分钟。什么是“大约两个小时”?

对于FreeAndNil()的崩溃,它被设计为释放TObject后代并将包含它的变量设置为nil。你在哪里创建代码中的TObject后代?似乎lFile是一个接口,所以简单地将变量设置为nil就足以减少引用计数:

lFile := nil;

对FreeAndNil()内部Free的调用可能是导致崩溃的原因。

编辑:基于对原始问题的编辑,显然上述情况并不正确。但是,我怀疑对AVIFileRelease()的调用已经释放了界面,因此没有什么可以让你做的。无论如何lFile超出了范围,引用计数将自动递减。

AVIFileOpen()上的MSDN引用而言,请注意它表示“返回文件接口的地址”。这是一个COM接口,它的形状或形式绝不是Delphi TObject后代。来自JEDI代码的片段也是这样说的,因为它说IAviFileinterface(IUnknown)