获取 AVI 文件持续时间时出错 [英] Error on getting AVI file duration

查看:91
本文介绍了获取 AVI 文件持续时间时出错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

有两个问题:

  1. lLenMinutes 是相等的到 98 而电影大约是两个小时.dwRate 是 100 万,并且dwScale 是 40k,所以 FPS 是完美 25. MSDN 说:单位由 dwRate 和 dwScale 定义".
  2. 代码在 FreeAndNil 行上崩溃.为什么?我认为我有责任释放 lFile(至少我觉得应该释放文件).没有与 FreeAndNil 一致,我有访问权限退出程序时的违规行为.
  1. 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".
  2. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆