Delphi 获取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

我在WinAPI上使用绝地包装器中的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;
有两个问题:

  • lLenMinutes是相等的 到98岁,而这部电影大约是2岁 小时。数据速率为100万,并且 dwScale为40k,因此FPS为 完美的25.:“单位 由dwRate和dwScale定义
  • 代码在FreeAndNil行上崩溃。 为什么?我想我应该对这件事负责 释放我的文件(至少我觉得 应该发布文件)。没有 与FreeAndNil连线,我有权限 退出程序时的违规行为
  • 那么,你有什么线索可以从AVI文件中正确获取电影的持续时间吗?为什么会坠机

    编辑

    这部电影是2小时1分钟,所以结果应该接近120。在《绝地武士》中,这个文件被宣布为:

    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接口,它的形状或形式决不是Delphi
    ToObject
    的后代。绝地密码的片段也这么说,因为它说,
    IAviFile
    是一个
    接口(IUnknown)
    98分钟是一小时38分钟。什么是“大约两小时”

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

    lFile := nil;
    
    调用Free inside FreeAndNil()可能是导致崩溃的原因

    编辑:根据对原始问题的编辑,显然上述内容不正确。但是,我怀疑对
    AVIFileRelease()
    的调用已经释放了接口,因此没有什么可以做的了
    lFile
    无论如何都将超出范围,引用计数将自动递减


    至于
    AVIFileOpen()
    上的MSDN引号,请注意它表示“返回文件接口的地址”。这是一个COM接口,它的形状或形式决不是Delphi
    ToObject
    的后代。绝地密码中的代码片段也这么说,因为它说,
    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

    另外,向ma添加对
    AVIFileExit()
    的调用