Hi,
weiß jemand, wie ich die AVIMakeCompressedStream aus Avifil32.dll aktivieren kann?
Ich kann die AVIWriter.au3 benutzen, um z.B. eine AVI Datei mit Screenshots vom Desktop zu erstellen. Aber das Problem ist, dass die AVI Datei relativ groß wird.
Nun gibt es die Funktion AVIMakeCompressedStream aus Avifil32.dll, um diesen Stream zu komprimieren, aber irgendwie kriege ich es nicht gebacken.
Hier die modifizierte AVIWriter.au3 mit einem Beispiel, um 1 Sekunde vom aktiven Fenster aufzunehmen:
Spoiler anzeigen
#AutoIt3Wrapper_UseX64=n
#include <WinAPI.au3>
#region AVIWriter UDF
;Global Const $mmioFOURCC_M_S_V_C = _Create_mmioFOURCC("MSVC") ;1129730893
Global Const $BITMAPFILEHEADER = "align 2;char magic[2];int size;short res1;short res2;ptr offset;"
Global Const $BITMAPINFOHEADER = "dword biSize;long biWidth;long biHeight;short biPlanes;short biBitCount;" & _
"dword biCompression;dword biSizeImage;long biXPelsPerMeter;long biYPelsPerMeter;dword biClrUsed;dword biClrImportant;"
Global Const $OF_CREATE = 0x00001000
Global Const $AVIIF_KEYFRAME = 0x00000010
Global Const $ICMF_CHOOSE_KEYFRAME = 1, $ICMF_CHOOSE_DATARATE = 2
Global Const $AVIERR_UNSUPPORTED = 0x80044065
Global Const $AVIERR_MEMORY = 0x80044067
Global Const $AVIERR_NOCOMPRESSOR = 0x80044071
Global Const $AVIERR_CANTCOMPRESS = 0x80044075
Global Const $AVIERR_ERROR = 0x800440C7
Global Const $AVIERR_OK = 0
Global $Avi32_Dll
;http://msdn.microsoft.com/en-us/library/ms899423.aspx
Global Const $AVISTREAMINFO = "dword fccType;dword fccHandler;dword dwFlags;dword dwCaps;short wPriority;short wLanguage;dword dwScale;" & _
"dword dwRate;dword dwStart;dword dwLength;dword dwInitialFrames;dword dwSuggestedBufferSize;dword dwQuality;" & _
"dword dwSampleSize;int rleft;int rtop;int rright;int rbottom;dword dwEditCount;dword dwFormatChangeCount;wchar[64];"
;http://msdn.microsoft.com/en-us/library/…1(v=VS.85).aspx
Global Const $AVICOMPRESSOPTIONS = "DWORD fccType;DWORD fccHandler;DWORD dwKeyFrameEvery;DWORD dwQuality;DWORD dwBytesPerSecond;" & _
"DWORD dwFlags;PTR lpFormat;DWORD cbFormat;PTR lpParms;DWORD cbParms;DWORD dwInterleaveEvery;"
Func _Create_mmioFOURCC($FOURCC) ;http://www.fourcc.org/codecs.php
If StringLen($FOURCC) <> 4 Then Return SetError(1, 0, 0)
Local $aFOURCC = StringSplit($FOURCC, "", 2)
Return BitOR(Asc($aFOURCC[0]), BitShift(Asc($aFOURCC[1]), -8), BitShift(Asc($aFOURCC[2]), -16), BitShift(Asc($aFOURCC[3]), -24))
EndFunc ;==>_Create_mmioFOURCC
Func _DecodeFOURCC($iFOURCC)
If Not IsInt($iFOURCC) Then Return SetError(1, 0, 0)
Return Chr(BitAND($iFOURCC, 0xFF)) & Chr(BitShift(BitAND(0x0000FF00, $iFOURCC), 8)) & Chr(BitShift(BitAND(0x00FF0000, $iFOURCC), 16)) & Chr(BitShift($iFOURCC, 24))
EndFunc ;==>_DecodeFOURCC
; monoceres, Prog@ndy
Func _CreateAvi($sFilename, $FrameRate, $Width, $Height, $BitCount = 24, $mmioFOURCC = "MSVC")
Local $RetArr[5] ; avi file handle, stream handle, bitmap count, BitmapInfoheader, Stride
Local $aRet, $pfile, $asi, $aco, $pstream, $psCompressed
[/autoit] [autoit][/autoit] [autoit]$aRet = DllCall($Avi32_Dll, "int", "AVIFileOpenW", "ptr*", 0, "wstr", $sFilename, "uint", $OF_CREATE, "ptr", 0)
$pfile = $aRet[1]
Local $stride = BitAND(($Width * ($BitCount / + 3), BitNOT(3))
[/autoit] [autoit][/autoit] [autoit]Local $bi = DllStructCreate($BITMAPINFOHEADER)
DllStructSetData($bi, "biSize", DllStructGetSize($bi))
DllStructSetData($bi, "biWidth", $Width)
DllStructSetData($bi, "biHeight", $Height)
DllStructSetData($bi, "biPlanes", 1)
DllStructSetData($bi, "biBitCount", $BitCount)
DllStructSetData($bi, "biSizeImage", $stride * $Height)
$asi = DllStructCreate($AVISTREAMINFO)
DllStructSetData($asi, "fccType", _Create_mmioFOURCC("vids"))
DllStructSetData($asi, "fccHandler", _Create_mmioFOURCC($mmioFOURCC))
DllStructSetData($asi, "dwScale", 1)
DllStructSetData($asi, "dwRate", $FrameRate)
;~ DllStructSetData($asi, "dwQuality", $Quality) ;Quality is represented as a number between 0 and 10,000. For compressed data, this typically represents the value of the quality parameter passed to the compression software. If set to –1, drivers use the default quality value.
DllStructSetData($asi, "rright", $Width)
DllStructSetData($asi, "rbottom", $Height)
;~ DllStructSetData($asi, "dwSuggestedBufferSize", $stride * $Height)
$aco = DllStructCreate($AVICOMPRESSOPTIONS)
$aRet = DllCall($Avi32_Dll, "int", "AVIFileCreateStream", "ptr", $pfile, "ptr*", 0, "ptr", DllStructGetPtr($asi))
$pstream = $aRet[2]
ConsoleWrite(DllStructGetData($AVICOMPRESSOPTIONS, "fccHandler") & @CRLF)
[/autoit] [autoit][/autoit] [autoit]Local $hWnd= GUICreate("")
$aRet = DllCall($Avi32_Dll, "int_ptr", "AVISaveOptions", "hwnd", $hWnd, "uint", BitOR($ICMF_CHOOSE_DATARATE, $ICMF_CHOOSE_KEYFRAME), "int", 1, "ptr*", $pstream, "ptr*", DllStructGetPtr($aco))
GUIDelete($hWnd)
If $aRet[0] <> 1 Then
$RetArr[0] = $pfile
$RetArr[1] = $pstream
Return SetError(1, 0, $RetArr)
EndIf
ConsoleWrite(_DecodeFOURCC(DllStructGetData($aco, "fccHandler")) & @CRLF)
[/autoit] [autoit][/autoit] [autoit]$aRet = DllCall($Avi32_Dll, "int", "AVIMakeCompressedStream", "ptr*", 0, "ptr", $pstream, "ptr", DllStructGetPtr($aco), "ptr*", 0)
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $aRet = ' & Hex($aRet[0]) & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
$psCompressed = $aRet[2]
; The format for the stream is the same as BITMAPINFOHEADER
$aRet = DllCall($Avi32_Dll, "int", "AVIStreamSetFormat", "ptr", $psCompressed, "long", 0, "ptr", DllStructGetPtr($bi), "long", DllStructGetSize($bi))
$RetArr[0] = $pfile
$RetArr[1] = $psCompressed
$RetArr[2] = 0
$RetArr[3] = $bi
$RetArr[4] = $stride
Return $RetArr
EndFunc ;==>_CreateAvi
; Adds a bitmap file to an already opened avi file.
; monoceres, Prog@ndy
Func _AddHBitmapToAvi(ByRef $Avi_Handle, $hBitmap)
Local $DC = _WinAPI_GetDC(0)
Local $hDC = _WinAPI_CreateCompatibleDC($DC)
_WinAPI_ReleaseDC(0, $DC)
Local $OldBMP = _WinAPI_SelectObject($hDC, $hBitmap)
Local $bits = DllStructCreate("byte[" & DllStructGetData($Avi_Handle[3], "biSizeImage") & "]")
_WinAPI_GetDIBits($hDC, $hBitmap, 0, Abs(DllStructGetData($Avi_Handle[3], "biHeight")), DllStructGetPtr($bits), DllStructGetPtr($Avi_Handle[3]), 0)
_WinAPI_SelectObject($hDC, $OldBMP)
_WinAPI_DeleteDC($hDC)
DllCall($Avi32_Dll, "int", "AVIStreamWrite", "ptr", $Avi_Handle[1], "long", $Avi_Handle[2], "long", 1, "ptr", DllStructGetPtr($bits), _
"long", DllStructGetSize($bits), "long", $AVIIF_KEYFRAME, "ptr*", 0, "ptr*", 0)
$Avi_Handle[2] += 1
EndFunc ;==>_AddHBitmapToAvi
; Adds a bitmap file to an already opened avi file.
Func _AddBitmapToAvi(ByRef $Avi_Handle, $sBitmap)
Local $bm = LoadBitmap($sBitmap, True)
DllCall($Avi32_Dll, "int", "AVIStreamWrite", "ptr", $Avi_Handle[1], "long", $Avi_Handle[2], "long", 1, "ptr", DllStructGetPtr($bm[2]), _
"long", DllStructGetSize($bm[2]), "long", $AVIIF_KEYFRAME, "ptr*", 0, "ptr*", 0)
$Avi_Handle[2] += 1
EndFunc ;==>_AddBitmapToAvi
; Returns array with 3 elements
; [0]=BITMAPFILEHEADER
; [1]=BITMAPINFOHEADER
; [2]=Bitmap data buffer (if specified)
Func LoadBitmap($sFilename, $LoadData = False)
Local $RetArr[3]
Local $byref
Local $bih, $bfh, $buffer, $fhandle
$bfh = DllStructCreate($BITMAPFILEHEADER)
$bih = DllStructCreate($BITMAPINFOHEADER)
$fhandle = _WinAPI_CreateFile($sFilename, 2, 2, 0, 0)
_WinAPI_ReadFile($fhandle, DllStructGetPtr($bfh), DllStructGetSize($bfh), $byref)
_WinAPI_ReadFile($fhandle, DllStructGetPtr($bih), DllStructGetSize($bih), $byref)
$RetArr[0] = $bfh
$RetArr[1] = $bih
If Not $LoadData Then
_WinAPI_CloseHandle($fhandle)
Return $RetArr
EndIf
$buffer = DllStructCreate("byte[" & DllStructGetData($bfh, "size") - 54 & "]")
$RetArr[2] = $buffer
_WinAPI_ReadFile($fhandle, DllStructGetPtr($buffer), DllStructGetSize($buffer), $byref)
_WinAPI_CloseHandle($fhandle)
Return $RetArr
EndFunc ;==>LoadBitmap
; Init the avi library
Func _StartAviLibrary()
$Avi32_Dll = DllOpen("Avifil32.dll")
DllCall($Avi32_Dll, "none", "AVIFileInit")
;~ MsgBox(0,"",@error)
EndFunc ;==>_StartAviLibrary
; Release the library
Func _StopAviLibrary()
DllCall($Avi32_Dll, "none", "AVIFileExit")
DllClose($Avi32_Dll)
EndFunc ;==>_StopAviLibrary
Func _CloseAvi($Avi_Handle)
DllCall($Avi32_Dll, "int", "AVIStreamRelease", "ptr", $Avi_Handle[1])
DllCall($Avi32_Dll, "int", "AVIFileRelease", "ptr", $Avi_Handle[0])
EndFunc ;==>_CloseAvi
#endregion
#region example
#include <Array.au3>
#include <Memory.au3>
#include <ScreenCapture.au3>
_GDIPlus_Startup()
HotKeySet("{ESC}", "close")
Break(0)
[/autoit] [autoit][/autoit] [autoit]FileDelete(@ScriptDir & "\test.avi")
[/autoit] [autoit][/autoit] [autoit]$tPoint = DllStructCreate($tagPOINT)
$aMPos = MouseGetPos()
DllStructSetData($tPoint, 1, $aMPos[0])
DllStructSetData($tPoint, 2, $aMPos[1])
$hWin = _WinAPI_WindowFromPoint($tPoint)
$hWinAncestor = _WinAPI_GetAncestor($hWin, 2)
$hWnd = HWnd($hWinAncestor)
$aPos = WinGetPos($hWnd)
$rec_duration = 1000 * 1
[/autoit] [autoit][/autoit] [autoit]ConsoleWrite("Starting...." & @CRLF)
[/autoit] [autoit][/autoit] [autoit]_StartAviLibrary()
$aAVI = _CreateAvi(@ScriptDir & "\test.avi", 15, $aPos[2], $aPos[3])
If @error Then close()
$t = TimerInit()
[/autoit] [autoit][/autoit] [autoit]Do
$hBmp = _ScreenCapture_CaptureWnd("", $hWnd)
$hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hBmp)
_AddHBitmapToAvi($aAVI, $hBmp)
_WinAPI_DeleteObject($hBmp)
If TimerDiff($t) > $rec_duration Then close()
Until False
Func close()
_GDIPlus_Shutdown()
_CloseAvi($aAVI)
_StopAviLibrary()
Exit
EndFunc ;==>close
#endregion
Es gibt unmengen an Quellen, aber irgendwie bekomme ich das in AutoIt nicht hin, z.B. BMPs to Avi.
Hat jemand noch eine Idee?
Gruß,
UEZ