Log in

View Full Version : Frame size in byte


martina
13th June 2005, 01:35
Hello,
I'm quite new so forgive me if I'm asking a silly question.
I would like to perform some stats on a video file and I need to know the size of each video frame in number of bytes, so that I can know the space that each video frame uses on the storage memory.
is there a function that allows me to do this?
thanks a lot.
martina

stickboy
13th June 2005, 03:39
Uncompressed?

framewidth * frameheight * bits/pixel * 1 byte/8 bits (plus some overhead)

The number of bits/pixel depends on which colorspace you're working in:
RGB32: 32 bits/pixel
RGB24: 24 bits/pixel
YUY2: average of 16 bits/pixel
YV12: average of 12 bits/pixel

martina
13th June 2005, 16:28
Thanks, but i need to know the frame size in byte for compressed video.
for uncompressed video the frame size in byte is not so interesting, while for compressed video you can have several information.
For instance for an MPEG video you can know the size of all the I/P/B frames.

Any idea?
thanks
Martina

Seed
13th June 2005, 17:28
but i need to know the frame size in byte for compressed video.

(file size) / (total number of frames) = average frame size

Else, load the avi file in Virtualdub, then [File] menu ---> File information

martina
14th June 2005, 15:54
Yes, I know how to compute the average frame size in byte, but I need to compute the frame size (in byte) for each frame of the video stream.
VB gives me only the Max/ave/min information about all the video frames and does not give my the information for each video frame.
Is there any way to get the frame size in byte for every frame of the video?
thanks
martina

gircobain
14th June 2005, 16:42
ffdshow's OSD gives the instant input bitrate for each frame
May be of some help to you

Inc
14th June 2005, 17:13
To me this seems more a programming/developing issue?

In case of avi you can directly parse out the bitmapinfoheader or bitmapfileheader, lets do some googling ....

typedef struct tagBITMAPINFOHEADER{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER, *PBITMAPFILEHEADER;
typedef struct tagBITMAPCOREHEADER {
DWORD bcSize;
WORD bcWidth;
WORD bcHeight;
WORD bcPlanes;
WORD bcBitCount;
} BITMAPCOREHEADER, *PBITMAPCOREHEADER;



So u have to do some coding ....
Heres an example how to parse out headerparts out of an avifile.
Its Purebasic (thats what I do use) but can also be found in delphi/vb/c++ areas.

;-----------------------------------------------------------------------------------------------------
;- AVI-Header-Reader 1.0
;-----------------------------------------------------------------------------------------------------
;-
;-
;- simply streams an AVI for the header and reads out it's data
;- REQUESTS a filename and an empty MainAVIHeader-structure to be filled
;- RETURN #True if all is OK, or #False if not
;-
;- see the comments and the example on how to interpretate the data
;-
;- by Froggerprogger 02.06.04
;-
#File_Temp = 0

Structure MainAVIHeader
* dwMicroSecPerFrame.l ; use this to calculate the AVIs framerate (fps = 1.000.000 / dwMicroSecPerFrame)
* dwMaxBytesPerSec.l
* dwReserved1.l
* dwFlags.l
* dwTotalFrames.l ; use this one to calculate the film's length (secs = dwTotalFrames / fps)
* dwInitialFrames.l
* dwStreams.l
* dwSuggestedBufferSize.l
* dwWidth.l
* dwHeight.l
* dwScale.l
* dwRate.l* ; a lot of AVIs let this value at 0, so use dwMicroSecPerFrame instead
* dwStart.l ; this is also set to 0 very often
* dwLength.l ; this is also set to 0 very often
EndStructure

Procedure.l GetAVIHeaderInformation(p_filename.s, *p_struct.MainAVIHeader)
* Protected tempL.l
* If ReadFile(#File_Temp, p_filename) ; open the file
* *
* * If ReadLong() <> 'FFIR'* *; "RIFF" ?
* * * ProcedureReturn #False
* * EndIf
* * ReadLong()* * * * * * * * ; (not interesting) size of RIFF-chunk
* * If ReadLong() <> ' IVA'* *; "AVI " ?
* * * ProcedureReturn #False
* * EndIf
* *
* * Repeat
* * * tempL = ReadLong() ; read in the actual Long-value (4 Bytes)
* * * FileSeek(Loc()-3) ; go back 3 Bytes, because perhaps "avih" isn't 4-Byte-aligned
* * Until Eof(#File_Temp) Or tempL = 'hiva' ; "avih" ?
* *
* * If tempL = 'hiva'
* * * FileSeek(Loc() + 7) ; go on 3 because the above and further 4 because of the not intersting chunksize
* * * ReadData(*p_struct, SizeOf(MainAVIHeader)) ; copy the whole header
* * * CloseFile(#File_Temp)
* * * ProcedureReturn #True
* * Else
* * * CloseFile(#File_Temp)
* * * ProcedureReturn #False
* * EndIf

* Else
* * ProcedureReturn #False
* EndIf
EndProcedure


;- an example
myAVI_Data.MainAVIHeader

filename.s = OpenFileRequester("Choose an AVI:", "G:\Videos", "*.avi|*.avi", 0)
If filename <> ""
* If GetAVIHeaderInformation(filename, @myAVI_Data) = #False
* * MessageRequester("AVI-Header-Reader:", "Error during GetAVIHeaderInformation!", #MB_ICONERROR)
* Else
* * result.s = filename + ":" + Chr(13) + Chr(10)
* * result + "(W/H)* " +* Str(myAVI_Data\dwWidth) + " / " + Str(myAVI_Data\dwHeight) + Chr(13) + Chr(10)
* * result + StrF(1000000.0 / myAVI_Data\dwMicroSecPerFrame, 2) + " fps" + Chr(13) + Chr(10)
* * result + Str(myAVI_Data\dwTotalFrames) + " frames total" + Chr(13) + Chr(10)
* * MessageRequester("AVI-Header-Reader:", result, #MB_ICONINFORMATION)
* EndIf


And heres a code where u can see how to use API to parse out Streaminformations via vfw.
So u have to search at m$ for the structures/Headers u want to read out.

#streamtypeVIDEO = $73646976
#AVIGETFRAMEF_BESTDISPLAYFMT = 1
#AVI_ERR_OK = 0
#Lib = 0

Procedure READOUTAVI (avifile.s)
*
Structure AVIFILEINFO
* * dwMaxBytesPerSec.l
* * dwFlags.l
* * dwCaps.l
* * dwStreams.l
* * dwSuggestedBufferSize.l
* * dwWidth.l
* * dwHeight.l
* * dwScale.l
* * dwRate.l
* * dwLength.l
* * dwEditCount.l
* * szFileType.b[64]* * *
EndStructure

res = CallFunction( #Lib, "AVIFileOpen", @pAVIFile, @avifile.s, #OF_SHARE_DENY_WRITE, 0 )

* res = CallFunction( #Lib, "AVIFileGetStream", pAVIFile, @pAVIStream, #streamtypeVIDEO, 0 )
* * *
* * * * firstFrame = CallFunction( #Lib, "AVIStreamStart", pAVIStream )
* * * * numFrames* = CallFunction( #Lib, "AVIStreamLength", pAVIStream )
* * * *
* * * * Result=CallFunction( #LIB, "AVIFileInfo", pAVIFile, @AVIFILEINFO1.AVIFILEINFO, SizeOf(AVIFILEINFO))
* *
* * CallFunction( #Lib, "AVIFileRelease", pAVIFile )
* * MessageRequester( "AVI Info", "Das Avi: "+avifile.s+" besitzt "+Str(numFrames)+" Frames* " +Str(AVIFILEINFO1\dwWidth)+"/"+ Str(AVIFILEINFO1\dwHeight),* 0 )

;EndIf

EndProcedure


OpenLibrary* ( #Lib , "AVIFIL32.DLL")
CallFunction ( #Lib,* "AVIFileInit" )
*
;avifile.s = OpenFileRequester ( "Select AVi File", "", "Video|*.avi", 0 )
avifile.s="I:\srings\video\test2.avi"

If avifile*
*READOUTAVI( avifile.s)
EndIf

CallFunction( #Lib, "AVIFileExit" )
CloseLibrary( #Lib )

stephanV
14th June 2005, 17:23
if you want to code this you should not look at the headers, but at the index since there the byte start positions for each chunk are given.

dont ask me how though