PDA

View Full Version : AVIFile Info from AVIFile DLL incompatible with WinXP ?


Darksoul71
20th May 2002, 20:39
Hi !

Strange things have happened here. I was just starting to
add some new functions to my AVISynth generator AVSGen.

Iīve use the function AVIFileInfo to get the resolution from a
source AVI. This was working fine under Win98SE. Now Iīve switched
to WinXP and this function crashes under Delphi.

Iīve tried an MJPEG captured file with 25 gig and a DivX AVI with 400 MB. Both crashed while accessing the AVIFile routine. AVIFileOpen (prior to the AVIFile Info call) worked fine.

Strange: Isnīt AVIFile downward compatible ?

BTW: This is my function declaration:
function AVIFileInfo(pfile : PAVIFile; pfi : PAVIFileInfo; lSize : longint) : integer; safecall; external 'avifil32.dll' name 'AVIFileInfo';

The programm can be compiled without problem. So the function should be there.

Has any1 an idea on how to get AVI res and AVI compression codec from an AVI in delphi ?
I hate to mess around with this VfW stuff :)

Thanx in advance,
D$

ciler
21st May 2002, 09:45
Hello...

Maybe you can try to change the calling convention to stdcall (in spite of safecall).

Can you put here the exact call you make and the associated varaible declarations ?

Edit : I have been reported that my AVI file info parser works fine on XP so yoiu might have a problem elsewhere

Belgabor
21st May 2002, 12:16
Originally posted by Darksoul71

Has any1 an idea on how to get AVI res and AVI compression codec from an AVI in delphi ?
I hate to mess around with this VfW stuff :)

Thanx in advance,
D$

I'll try not forget bringing some source tomorrow :)

Regards
Belgabor

DidzisK
21st May 2002, 14:15
Originally posted by Darksoul71
BTW: This is my function declaration:
function AVIFileInfo(pfile : PAVIFile; pfi : PAVIFileInfo; lSize : longint) : integer; safecall; external 'avifil32.dll' name 'AVIFileInfo';

Fully translated Vfw.h header file is available at
ftp://delphi-jedi.org/api/vfw.zip

And yes, those guys suggest stdcall as mentioned before.

And then - there could be something with Ansi/Unicode (A/W) versions of the function, but I have not researched this.

Darksoul71
21st May 2002, 20:05
Hi !

1st of all: Thanks to all who answered ! :)
@ciler: Iīve used stdcall before trying safecall. It didnīt change anything.

What code is your AVIFile reader written ? Delphi ? If so, then could you send me a code snippet ?

Iīll post my sample of code below because it is quite lengthy :)

@Belgabor: I would be pleased to see some other samples of using AVIFile interface under Delphi. Thanks for your offer.

@DidzisK: Thanks for the link. If anything doesnīt work Iīll have a look into the Delphi translated VfW interface. Iīve downloaded this before but never used it :(

So here is my code (including the translated structs for AVIFileInfo) but itīs quite long:

PAVIFile = pointer;

TAVIFileInfo = record
dwMaxBytesPerSec : longint; // max. transfer rate
dwFlags : longint; // the ever-present flags
dwCaps : longint;
dwStreams : longint;
dwSuggestedBufferSize : longint;

dwWidth : longint;
dwHeight : longint;

dwScale : longint;
dwRate : longint; // dwRate / dwScale == samples/second
dwLength : longint;

dwEditCount : longint;

szFileType : array[0..63] of char; // descriptive string for file type?
end;

PAVIFileInfo = ^TAVIFileInfo;

function AVIFileInfo(pfile : PAVIFile; pfi : PAVIFileInfo; lSize : longint) : integer; safecall; external 'avifil32.dll' name 'AVIFileInfo';


function AVIFileOpen(avifile : pointer; filename : pchar; mode : integer;
CLSID : pointer) : integer; stdcall; external 'avifil32.dll' name 'AVIFileOpen';

function AVIFileRelease(avifile : pointer) : longint; stdcall; external 'avifil32.dll' name 'AVIFileRelease';

Procedure GetAVIRes (Filename : String;VAR Height : LongInt;VAR Width : LongInt;VAR Result : LongInt);
VAR AInfo : TAVIFileInfo;
AVIFile : pointer;
begin
//AVIFileOpen
if (AVIFileOpen(@AVIFile, PChar(Filename), 0, nil) <> NULL) then
begin;
//AVIFileInfo
Try
Result := AVIFileInfo(AVIFile,@AInfo,SizeOf(TAVIFileInfo));
Except
End;
Height := AInfo.dwHeight;
Width := AInfo.dwWidth;
//AVIFileRelease
AVIFileRelease(AVIFile);
end;
end;

Belgabor
22nd May 2002, 08:50
Ok, I was a bit overenthusiastic because several bits of my code dont work for all avis and only gave the right results for the special case I was using it (replacement for AVIDeFreeze), but here you go:


AVIFileInit;
AviOpen := AVIFileOpen(pAVI,pChar(sName),OF_READ,nil);
if 0<>AviOpen then begin
Raise Exception.Create('AVIOpen Failed');
end;

if AVIFILEGetStream(pAVI,pAVIStr,streamtypeVIDEO,0)=AVIERR_NODATA then begin
Raise Exception.Create('No Video Stream');
end;

nFrames:=AVIStreamLength(pAVIStr);
AviStreamInfo(pAVIStr,@AVIInfo,sizeof(TAVISTREAMINFOA));
nFramerate:=AVIInfo.dwRate/AVIInfo.dwScale;
sFOURCC:=fourCC2string(AVIInfo.fccHandler);

// This doesnt work for codecs that cant decompress to RGB (e.g. XviD)
pAVIFrame:=AVIStreamGetFrameOpen(pAVIStr,nil);
if pAVIFrame=nil then begin
Raise Exception.Create('Error in Frameopen');
end;

pBMI:=AVIStreamGetFrame(pAVIFrame,0);

frWidth:=pBMI^.biWidth;
frHeight:=pBMI^.biHeight;

// This %&$%% dosnt work at all like I thought it would :( it only gives something like 'Microsoft RLE Handler'
IC:=ICLocate(mmioFourCC('V','I','D','C'),AVIInfo.fccHandler,pBMI,nil,ICMode_Decompress);
if IC=0 then begin
sHandler:='Handler not found';
end else begin
ICGetInfo(ic, @icinfo, sizeof(tICInfo));
sHandler:=icinfo.szDescription;
end;


While thinking a bit about it, I had the idea of calling the info function of the AViFile Interface directly, perhaps that works on XP (you have to use tAVIFileInfoW in this case I think):


ai = IAviFile(AVIFile);
ai.Info(@AInfo,SizeOf(TAVIFileInfoW));


One last statement: I HATE vfw, it BITCHES at me every single time and gives me lots of errors I have ABSOLUTELY NO IDEA where they come from. (like program gives exception when run from delphi but works fine if started from explorer...) :angry:

Well, perhaps someone with more knowlege can point my errors out (especially why I cant get the correct Handler).

Regards
Belgabor

[Toff]
22nd May 2002, 20:58
Hi,

Here is the code I use (with C++ builder, exe included)
http://christophe.paris.free.fr/sample/avistats.zip
or (direct code access) :
http://christophe.paris.free.fr/sample/main.cpp

It's a simple application that show the struct used by vfw in a treeview.

It must be very easy to port it to delphi.

Edit : Oups, the exe was not compiled with right option, fixed now

Darksoul71
23rd May 2002, 21:15
Hi all !

@[Toff]:

Thanx for the link. Unfortunately I donīt have Borland Builder and the EXE included crashed because it was missing a DLL (CC3250MT.DLL). So this was no option.

Iīve tried the VfW Unit from Delphi-Jedi.org and it worked a lot better. I remove my declarations and changed my GetAVIRes Procedure only a little bit:

Procedure GetAVIRes (Filename : String;VAR Height : LongInt;VAR Width : LongInt;VAR Result : LongInt);
VAR AInfo : TAVIFILEINFO;
AVIFile : IAVIFile;
ErrorMsg : String;
MsgBox : String;
begin
MsgBox := 'AVI Error:';
ErrorMsg := '';
// Init VfW API
AVIFileInit;

//AVIFileOpen
Result := AVIFileOpen(AVIFile,PChar(Filename), OF_READ, nil);
ErrorMsg := 'Bad AVI Format !';
If (Result = AVIERR_BADFORMAT) Then ErrorMsg := 'Bad AVI Format !';
If (Result = AVIERR_MEMORY) Then ErrorMsg := 'Insufficent Memory !';
If (Result = AVIERR_FILEREAD) Then ErrorMsg := 'Error while reading from AVI file !';
If (Result = AVIERR_FILEOPEN) Then ErrorMsg := 'Error while opening AVI file !';
If (Result = REGDB_E_CLASSNOTREG) Then ErrorMsg := 'No process handle !';

If (ErrorMsg <> '') Then
Begin
MessageBox(Form1.Handle,PChar(ErrorMsg),PChar(MsgBox),MB_OK);
End;

// If AVIFile handle available then read AVI File Infos
If (AVIFile <> NIL) Then
begin;
//AVIFileInfo
Result := AVIFileInfo(AVIFile,AInfo,SizeOf(TAVIFILEINFO));
Height := AInfo.dwHeight;
Width := AInfo.dwWidth;
//AVIFileRelease
AVIFileRelease(AVIFile);
AVIFileExit;
end;
end;

I can read resolutions from all AVIs I tried. Be it MJPEG in full PAL or DivX 5.0 in cropped format. Now AVIFileRelease gives me an error. I donīt get this. If I comment out AVIFileRelease everything works but I want to close the AVI before continuing with my program.

BTW: Iīve tried the AVIFile DLL from Aquaplaning (http://aquaplaning.20m.com/). The DLL sample code also crashes if I select a DivX AVI and only works fine with MJPEG captured AVI. Whatīs wrong here ?

Is the VfW interface absolute crap ?

I can only wonder :(

@Belgabor: Iīll now try your AVIStream stuff instead of AVIFile. May be this works better.
Could you please be so kind and post your yourCC2string function ?
Itīs neither part of Delphi, nor of the Windows API.

Thanks in advance,
D$

TheWEF
24th May 2002, 00:44
Originally posted by Belgabor
I HATE vfw, it BITCHES at me every single time and gives me lots of errors I have ABSOLUTELY NO IDEA where they come from. (like program gives exception when run from delphi but works fine if started from explorer...)

actually all you have to do is to adjust you delphi debugger settings:

tools/debugger options/OS exceptions

most likely you just have to set exception
Invalid Handle ($C0000008)
Handled by User Program.
On Resume run handled.

more info in the help file...

wef.

ciler
24th May 2002, 08:17
Originally posted by Darksoul71
Hi all !

@[Toff]:


Iīve tried the VfW Unit from Delphi-Jedi.org and it worked a lot better.
Is the VfW interface absolute crap ?

I can only wonder :(


Thanks in advance,
D$

Hello, there's actually an error un the VFW.pas from Delphi-Jedi. What you should do in order to correct this is
renaming IAVIFile interface into TAVIFile and then create
IAVIFile := ^TAVIFile;

The same apply to streams...

And BTW, I don't know why, but you can't use the interface function ie
MyFile.Release_
thus, AVIFileRelease(MyFile) works just fine...

Belgabor
24th May 2002, 08:55
Originally posted by TheWEF


actually all you have to do is to adjust you delphi debugger settings:

tools/debugger options/OS exceptions

most likely you just have to set exception
Invalid Handle ($C0000008)
Handled by User Program.
On Resume run handled.

more info in the help file...

wef.

This sounds like exactly what I get. Thanks for the hint! :D

@Darksoul: I dun have it here atm, but if i remeber coorectly the fourCC is defined as an Integer. simply typecast it to a array[0..3] of Char and copy it to a string. You might have to reverse the order, not sure about that. I'll have a look when i get back home.
EDIT: Here you go :D

function fourCC2String(fcc:Longint): string;
type conv = array[0..3] of Char;
var l: integer;
begin
for l:=0 to 3 do begin
Result:=Result+conv(fcc)[l];
end;
end;


@ciler: The thing I posted (typecast of a pAVIFile to a IAVIFile) works for me, alas I'm not sure whose vfw.pas I'm using.

@all: Anyone have an idea why I start getting 'Format not supported' on the AVIFileOpen function when I had opened a variable number of avis in my app and try to open the next one? When I close the app and restart it, it works again.

Regards
Belgabor

Darksoul71
25th May 2002, 16:01
Wahooo ! :D

Problem solved !
Iīve changed the VfW Unit as Clier told me:

---------------------------------------------
TAVIFile = interface(IUnknown)
function Info(var pfi: TAVIFileInfoW; iSize: LONG): HResult; stdcall;
function GetStream(var ppStream: IAVISTREAM; fccType: DWORD; lParam: LONG): HResult; stdcall;
function CreateStream(var ppStream: IAVISTREAM; var psi: TAVIStreamInfoW): HResult; stdcall;
function WriteData(ckid: DWORD; lpData: PVOID; cbData: LONG): HResult; stdcall;
function ReadData(ckid: DWORD; lpData: PVOID; lpcbData: PLONG): HResult; stdcall;
function EndRecord: HResult; stdcall;
function DeleteStream(fccType: DWORD; lParam: LONG): HResult; stdcall;
end;

IAVIFile=^TAVIFile;
---------------------------------------------
@Clier: Thanks for pointing out :)
Shouldnīt someone send a note to Jedi-Delphi.org ? I could do so.....

BTW: Iīve change AVIStream the same way as you said.

---------------------------------------------
type
TAVIStream = interface(IUnknown)
function Create(lParam1, lParam2: LPARAM): HResult; stdcall;
function Info(var psi: TAVIStreamInfoW; lSize: LONG): HResult; stdcall;
function FindSample(lPos: LONG; lFlags: LONG): LONG; stdcall;
function ReadFormat(lPos: LONG; lpFormat: PVOID; var lpcbFormat: LONG): HResult; stdcall;
function SetFormat(lPos: LONG; lpFormat: PVOID; cbFormat: LONG): HResult; stdcall;
function Read(lStart: LONG; lSamples: LONG; lpBuffer: PVOID; cbBuffer: LONG; var plBytes, plSamples: LONG): HResult; stdcall;
function Write(lStart: LONG; lSamples: LONG; lpBuffer: PVOID; cbBuffer: LONG; dwFlags: DWORD; var plSampWritten, plBytesWritten: LONG): HResult; stdcall;
function Delete(lStart: LONG; lSamples: LONG): HResult; stdcall;
function ReadData(fcc: DWORD; lp: PVOID; var lpcb: LONG): HResult; stdcall;
function WriteData(fcc: DWORD; lp: PVOID; cb: LONG): HResult; stdcall;
function SetInfo(var lpInfo: TAVIStreamInfoW; cbInfo: LONG): HResult; stdcall;
end;

IAVIStream=^TAVIStream;
---------------------------------------------
So this should be correct. Shouldnīt it ?

Thanx again for anyone helping out.

@Belgabor: Iīll try your FourCC stuff next week but may be you could still be so kind posting your FourCC function.
EDIT: Thanks :)

Anyone have an idea why I start getting 'Format not supported' on the AVIFileOpen function when I had opened a variable number of avis in my app and try to open the next one? When I close the app and restart it, it works again.

Hm, do you have a clue how many open AVI handles are supported by the VfW API ?
May be you should close your AVI and call AVIFileInit/AVIFileExit before opening the next AVI ? As far as I understood the last two functions initialize VfW, donīt they ?

-D$

Belgabor
25th May 2002, 17:48
Originally posted by Darksoul71

Hm, do you have a clue how many open AVI handles are supported by the VfW API ?
May be you should close your AVI and call AVIFileInit/AVIFileExit before opening the next AVI ? As far as I understood the last two functions initialize VfW, donīt they ?

-D$

Ok, I'm dumb. I thought I did exactly that (forgot to mention), but in fact i forgot to call my CloseAVI function (which includes the AVIFileExit call, as well as all the handle/stream closing functions for that matter) before opening then new avi ^^'
(In fact I now wonder why it worked at all)

Regards
Belgabor

Darksoul71
26th May 2002, 16:51
Hi !

@Belgabor:
Iīve used your AVIStream code and modified it a bit. Now Iīm also able to write my own "movie list" generator that I have in mind for some time.

(In fact I now wonder why it worked at all)

Well, thereīs nothing to wonder about. I donīt think that the VfW DLL has some "in use" checking. So with every new initalization with a new AVI file without closing the previous one, you plainly throw away one open handle and open up another one. This work as long as the OS supports open file handles and/or as long open AVI handles are supported by the VfW DLL.

But now you have found your bug :)

BTW: What tool do you develop ?

cu,
D$

Belgabor
27th May 2002, 14:00
Originally posted by Darksoul71

BTW: What tool do you develop ?


Its a replacement for AVIDeFreezer. It kinda works now, but it simply refuses to do the recomression of the frozen frames on some movies and I dont know whats wrong. Another thing which goes along the same line (and uses a lot of the same code) is a mass freeze checker.

Cheers
Belgabor