I am using VFW unit from JEDI wrapper on WinAPI.
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;
There are two problems:
So, do you have any clue how to correctly obtain movie duration from AVI file? And why the crash?
Edit
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)
the AVIFileOpen is declared in JEDI as:
function AVIFileOpen(var ppfile: IAVIFILE; szFile: LPCWSTR; uMode: UINT; lpHandler: PCLSID): HResult; stdcall; external AVIFILDLL name 'AVIFileOpenW';
and in MSDN:
STDAPI AVIFileOpen( PAVIFILE *ppfile, LPCTSTR szFile, UINT mode, CLSID pclsidHandler );
MSDN says:
"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.
Edit 2
The avi file length has been move to new question, since mghie answered this question.
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:
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:
pointer(lFile) := nil;
Also, add a call to AVIFileExit()
to match your call to AVIFileInit()
.