I found a Stack Overflow post with a sample showing how to get the duration of an AVI file:
I modified it for my purposes in my Delphi 6 app and created the code below. Initially I removed the line that nukes the IAviFile pointer before calling AviFileExit(). But when I did that I got an Access Violation when AviFileExit() is called. I restored the line and the access violation went away.
Why is it necessary to nuke the IAviFile reference before calling AviFileExit()? Is this a memory leak? I would think normal interface reference counting would work properly here but obviously it does not. Is there another way to eliminate the error like calling AviStreamRelease() or the like?
Here's my code:
function getAviDurationSecs(theAviFilename: string): Extended;
var
aviFileInfo : TAVIFILEINFOW;
intfAviFile : IAVIFILE;
framesPerSecond : Extended;
begin
intfAviFile := nil;
AVIFileInit;
try
// Open the AVI file.
if AVIFileOpen(intfAviFile, PChar(theAviFilename), OF_READ, nil) <> AVIERR_OK then
raise Exception.Create('(getAviDurationSecs) Error opening the AVI file: ' + theAviFilename);
try
// Get the AVI file information.
if AVIFileInfoW(intfAviFile, aviFileInfo, sizeof(aviFileInfo)) <> AVIERR_OK then
raise Exception.Create('(getAviDurationSecs) Unable to get file information record from the AVI file: ' + theAviFilename);
// Zero divide protection.
if aviFileInfo.dwScale < 1 then
raise Exception.Create('(getAviDurationSecs) Invalid dwScale value found in the AVI file information record: ' + theAviFilename);
// Calculate the frames per second.
framesPerSecond := aviFileInfo.dwRate / aviFileInfo.dwScale;
Result := aviFileInfo.dwLength / framesPerSecond;
finally
AVIFileRelease(intfAviFile);
// Commenting out the line below that nukes the IAviFile
// interface reference leads to an access violation when
// AVIFileExit() is called.
Pointer(intfAviFile) := nil;
end;
finally
AVIFileExit;
end;
end;
You have to clear your variable manually because Delphi does not know that
AVIFileRelease()
released the interface.AVIFileRelease()
does not set the variable tonil
for you, so the variable still has a non-nil value to it. If you don't clear it manally , Delphi will try to callRelease()
on the variable when it goes out of scope (after theAVIFileExit()
call) and crash.The
IAVIFile
interface is anIUknown
descendant, so I don't know why Microsoft created theAVIFileRelease()
function in the first place. It decrements the interface's reference count and perform cleanup if the count falls to zero. The implementation behind the interface could simply have handled that internally without needing an explicit function. So that's Microsoft's bad.