There was a rumour in the German forum, that MovieInfo() doesn't return correct values for the fps.
Therefore here are two procedures, one for MPEG, and one for AVI-files to get Width, Height, Fps etc. of the movie.
Remark the information given by GetAspectRatioStr and GetPicRateStr, it was damn hard to find any information about this coding scheme. At wotsit there's even cursing wrong information.
Code: Select all
;-----------------------------------------------------------------------------------------------------
;- MPEG-Header-Reader 1.0
;-----------------------------------------------------------------------------------------------------
;-
;- Reads in the video-related data
;- from the sequence header of an MPEG-video
;-
;- Seems to work with .mpg .mpeg .m1v .vob (MPEG I+II)
;-
;- by Froggerprogger 02.06.04
;-
;-----------------------------------------------------------------------------------------------------
;- USAGE:
;-----------------------------------------------------------------------------------------------------
;- GetMPEGHeaderInformation( p_filename.s,
;- *p_struct.MPEG_SeqHeader_Video,
;- p_forceHeaderSearch.l)
;-
;- p_filename.s : the filename of the file in which to search the mpeg-info
;- *p_struct.MPEG_MainInfo : pointer to an empty MPEG_SeqHeader_Video-Structure to be filled
;- p_forceHeaderSearch.l : a flag (#True|#False) to force searching for a sequence header
;- bytealigned (slow), if there's noone found in the typical (fast) way.
;-
;- RETURNS #True, if the file could be opened and a sequence-header could be found,
;- or #False otherwise. (you might try another call with p_forceHeaderSearch = #True then e.g.)
;-
;-
;-----------------------------------------------------------------------------------------------------
;- GetAspectRatioStr(p_aspectRatioID.l)
;- REQUESTS the ID that is filled into MPEG_SeqHeader_Video\aspectRatio by GetMPEGHeaderInformation()
;- RETURNS a string identifiing the aspect ratio. You might use ValF() on the result to get it's
;- numerical float-value or 0.0 if it was no valid ID.
;-
;-
;-----------------------------------------------------------------------------------------------------
;- GetPicRateStr(p_picRate.l)
;- REQUESTS the ID that is filled into MPEG_SeqHeader_Video\picRate by GetMPEGHeaderInformation()
;- RETURNS a string identifiing the picture rate. You might use ValF() on the result to get it's
;- numerical float-value or 0.0 if it was no valid ID.
;-
;-
#File_Temp = 0
Structure MPEG_SeqHeader_Video
width.l ; 12 bits in sequence header
height.l ; 12 bits in sequence header
aspectRatio.l ; 4 bits in sequence header
picRate.l ; 4 bits in sequence header
EndStructure
Declare.s GetAspectRatioStr(p_aspectRatioID.l)
Declare.s GetPicRateStr(p_picRate.l)
Declare.l GetMPEGHeaderInformation(p_filename.s, *p_struct.MPEG_SeqHeader_Video, p_forceHeaderSearch.l)
Procedure.s GetAspectRatioStr(p_aspectRatioID.l)
Select p_aspectRatioID
Case 01 : ProcedureReturn "1.0000 VGA etc."
Case 02 : ProcedureReturn "0.6735"
Case 03 : ProcedureReturn "0.7031 16:9 - 625 lines"
Case 04 : ProcedureReturn "0.7615"
Case 05 : ProcedureReturn "0.8055"
Case 06 : ProcedureReturn "0.8437 16:9 - 525 lines"
Case 07 : ProcedureReturn "0.8935"
Case 08 : ProcedureReturn "0.9375 CCIR 601 - 625 lines"
Case 09 : ProcedureReturn "0.9815"
Case 10 : ProcedureReturn "1.0255"
Case 11 : ProcedureReturn "1.0695"
Case 12 : ProcedureReturn "1.1250 CCIR 601 - 525 lines"
Case 13 : ProcedureReturn "1.1575"
Case 14 : ProcedureReturn "1.2015"
Case 15 : ProcedureReturn "reserved"
Default : ProcedureReturn "error - no valid ID for aspect ratio"
EndSelect
EndProcedure
Procedure.s GetPicRateStr(p_picRate.l)
Select p_picRate
Case 01 : ProcedureReturn "23.976"
Case 02 : ProcedureReturn "24"
Case 03 : ProcedureReturn "25"
Case 04 : ProcedureReturn "29.97"
Case 05 : ProcedureReturn "30"
Case 06 : ProcedureReturn "50"
Case 07 : ProcedureReturn "59.94"
Case 08 : ProcedureReturn "60"
Default : ProcedureReturn "error - no valid ID for picture rate"
EndSelect
EndProcedure
Procedure.l GetMPEGHeaderInformation(p_filename.s, *p_struct.MPEG_SeqHeader_Video, p_forceHeaderSearch.l)
Protected tempL.l
If ReadFile(#File_Temp, p_filename) ; open file for read-only
tempL = ReadLong(#File_Temp) ; read in the first 32 bit
If p_forceHeaderSearch = #False And tempL <> $B3010000 And tempL <> $BA010000
ProcedureReturn #False ; return if not a common MPEG-file and no forceHeaderSearch is set
ElseIf tempL <> $B3010000
Repeat ; search bytealigned for a (possible) sequence-header (simply straight forward, no chunk-jumps here)
tempL = ReadLong(#File_Temp)
FileSeek(#File_Temp, Loc(#File_Temp)-3)
Until Eof(#File_Temp) Or tempL = $B3010000 ; until fileend reached or sequenceheader found
If tempL = $B3010000
FileSeek(#File_Temp, Loc(#File_Temp) + 3) ; set the filepointer back
Else
ProcedureReturn #False ; there's no sequence header in this file
EndIf
EndIf
If tempL = $B3010000 ; in fact, at this point tempL is $B3010000 in ALL cases
tempL = ReadLong(#File_Temp) ; copy the next 32 bit into tempL
; mirror the order of the bytes (MSB/LSB) :
tempL = ((tempL & $FF000000) >> 24 & $FF) | (tempL & $FF) << 24 | (tempL & $FF00) << 8 | (tempL & $FF0000) >> 8
*p_struct\width = (tempL & $FFF00000) >> 20 ; width is in the first 12 bit
*p_struct\height = (tempL & $000FFF00) >> 8 ; height in the next 12 bit
*p_struct\aspectRatio = (tempL & $000000F0) >> 4 ; aspectRatio in the next 4 bit
*p_struct\picRate = (tempL & $0000000F) ; picRate in the last 4 bit
CloseFile(#File_Temp)
ProcedureReturn #True
EndIf
Else
ProcedureReturn #False
EndIf
EndProcedure
;-
;- an example
;-
Global myMPEG_Data.MPEG_SeqHeader_Video
Global resultstr.s
filename.s = OpenFileRequester("Choose an MPG:", "G:\Videos\", "*.mpg;*.mpeg;*.m1v;*.vob|*.mpg;*.mpeg;*.m1v;*.vob|*.mpg|*.mpg|*.mpeg|*.mpeg|*.m1v|*.m1v|*.vob|*.vob|*.*|*.*", 0)
If filename <> ""
If GetMPEGHeaderInformation(filename, @myMPEG_Data, #False) = #False
If MessageRequester("MPEG-Header-Reader", "Error: The file doesn't seem to be a valid mpg-file - search for the MPEG-Header anyway ?", #MB_ICONERROR|#MB_YESNO) = #IDNO
End
EndIf
EndIf
If GetMPEGHeaderInformation(filename, @myMPEG_Data, #True) = #False ; enable 'force searching in any file'
MessageRequester("MPEG-Header-Reader", "Error: There's no MPEG-Header in this file", #MB_ICONERROR)
End
Else
; prepare the output
resultstr + "File: " + filename + Chr(13) + Chr(10)
resultstr + "Width: " + Str(myMPEG_Data\width) + Chr(13) + Chr(10)
resultstr + "Height: " + Str(myMPEG_Data\height) + Chr(13) + Chr(10)
resultstr + "aspect ratio: " + Str(myMPEG_Data\aspectRatio) + " ( " + GetAspectRatioStr(myMPEG_Data\aspectRatio) + " )" + Chr(13) + Chr(10)
resultstr + "picture rate: " + Str(myMPEG_Data\picRate) + " ( " + GetPicRateStr(myMPEG_Data\picRate) + " fps )" + Chr(13) + Chr(10)
MessageRequester("MPEG-Header-Reader", resultstr, #MB_ICONINFORMATION)
EndIf
EndIf
Code: Select all
;-----------------------------------------------------------------------------------------------------
;- 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(#File_Temp) <> 'FFIR' ; "RIFF" ?
ProcedureReturn #False
EndIf
ReadLong(#File_Temp) ; (not interesting) size of RIFF-chunk
If ReadLong(#File_Temp) <> ' IVA' ; "AVI " ?
ProcedureReturn #False
EndIf
Repeat
tempL = ReadLong(#File_Temp) ; read in the actual Long-value (4 Bytes)
FileSeek(#File_Temp, Loc(#File_Temp)-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(#File_Temp, Loc(#File_Temp) + 7) ; go on 3 because the above and further 4 because of the not intersting chunksize
ReadData(#File_Temp, *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
EndIf