Jump to content

AVI writing udf


monoceres
 Share

Recommended Posts

has this code been refined at all yet it seems a lil buggy or something..

I recorded my full screen for a while and the video file is pretty big but it only says its like 1-2 secs long and the video plays all weird with strange colors and choppy playblack..

is anyone else experiencing these problems at all..??

is there anyway someone can try and copy the functions of this camstudio-command-line app into AutoIt at all..??

http://camstudio.org/blog/camstudio-comman...ne-v01-released

Link to comment
Share on other sites

  • 4 weeks later...

is anyone still actively developing this code anymore. or has it reached its perfection peak already..??

Last time i tried it out it was pretty buggy from what i said in my above post..

So i was just wondering if anyone had improved the code at all recently..??

Link to comment
Share on other sites

@cypher175

It's still in development phase, it's just that I have been pretty busy lately. School, work, gf, more school, more work. I'll look into adding more when I get the time :)

About the bugs that people are experiencing, are you sure that the avi are corrupt o could it maybe be the player? I good way to check is to load the avi file in VirtualDub and see if it's working.

If it doesn't work then I need info to reproduce the problem and possible a sample file.

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

I've been reading something about AVI's and compression and remembered that it was mentioned here.

Anyway, there are few functions available inside msvfw32.dll for compressing video images (or just images).

monoceres, you have experience with required procedures. Can you make something of it?

Main function is ICCompress.

This is just warm up (ahh... you know what I mean):

$tCOMPVARS = DllStructCreate("dword[16]"); In this simplified form just for demonstration
DllStructSetData($tCOMPVARS, 1, DllStructGetSize($tCOMPVARS))

$a_iCall = DllCall("msvfw32.dll", "int", "ICCompressorChoose", "hwnd", 0, "dword", 8, "ptr", 0, "ptr", 0, "ptr", DllStructGetPtr($tCOMPVARS), "str", "Choose Compressor")

ConsoleWrite(@error & @CRLF)
ConsoleWrite($a_iCall[0] & @CRLF)

I'll buy you a drink if you nailed it. :)

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

  • 1 year later...
  • 1 year later...

Here an extended version of AVIWriter.au3 to enable compression of the AVI stream using build-in codecs:

AVIWriter Extented.au3:

#include-once
#include <WinAPI.au3>

#region AVIWriter UDF
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_BADPARAM = 0x80044066
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

Global Const $ICINFO = _
    "DWORD dwSize;DWORD fccType;DWORD fccHandler;DWORD dwFlags;DWORD dwVersion;DWORD dwVersionICM;" & _
    "WCHAR szName[16];WCHAR szDescription[128];WCHAR szDriver[128];"

;http://msdn.microsoft.com/en-us/library/dd183374(v=vs.85).aspx
Global Const $BITMAPFILEHEADER = "WORD bfType;DWORD bfSize;WORD bfReserved1;WORD bfReserved2;DWORD bfOffBits;"
;~ Global Const $BITMAPFILEHEADER = "align 2;char magic[2];int size;short res1;short res2;ptr offset;"

;http://msdn.microsoft.com/en-us/library/dd183376(v=vs.85).aspx
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;"

;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/dd756791(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;"

;http://www.fourcc.org/codecs.php
Func _Create_mmioFOURCC($FOURCC) ;coded by UEZ
    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);coded by UEZ
    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, UEZ
Func _CreateAvi($sFilename, $FrameRate, $Width, $Height, $BitCount = 24, $mmioFOURCC = "MSVC", $iKeyFrameEvery = 10)
    Local $RetArr[6] ;avi file handle, compressed stream handle, bitmap count, BitmapInfoheader, Stride, stream handle

    Local $aRet, $pFile, $tASI, $tACO, $pStream, $psCompressed

    Local $stride = BitAND(($Width * ($BitCount / 8) + 3), BitNOT(3))

    Local $tBI = DllStructCreate($BITMAPINFOHEADER)
    DllStructSetData($tBI, "biSize", DllStructGetSize($tBI))
    DllStructSetData($tBI, "biWidth", $Width)
    DllStructSetData($tBI, "biHeight", $Height)
    DllStructSetData($tBI, "biPlanes", 1)
    DllStructSetData($tBI, "biBitCount", $BitCount)
    DllStructSetData($tBI, "biSizeImage", $stride * $Height)

    $tASI = DllStructCreate($AVISTREAMINFO)
    DllStructSetData($tASI, "fccType", _Create_mmioFOURCC("vids"))
    DllStructSetData($tASI, "fccHandler", _Create_mmioFOURCC($mmioFOURCC))
    DllStructSetData($tASI, "dwScale", 1)
    DllStructSetData($tASI, "dwRate", $FrameRate)
    DllStructSetData($tASI, "dwQuality", -1) ;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 &#8211;1, drivers use the default quality value.
    DllStructSetData($tASI, "dwSuggestedBufferSize", $stride * $Height)
    DllStructSetData($tASI, "rright", $Width)
    DllStructSetData($tASI, "rbottom", $Height)


;~     $tParms = DllStructCreate($ICINFO)
;~     DllCall("Msvfw32.dll", "BOOL", "ICInfo", "DWORD", _Create_mmioFOURCC("vidc"), "DWORD", _Create_mmioFOURCC($mmioFOURCC), "ptr", DllStructGetPtr($tParms))

;~     $tACO = DllStructCreate($AVICOMPRESSOPTIONS)
;~     DllStructSetData($tACO, "fccType", _Create_mmioFOURCC("vids"))
;~     DllStructSetData($tACO, "fccHandler", _Create_mmioFOURCC($mmioFOURCC))
;~     DllStructSetData($tACO, "dwKeyFrameEvery", 10)
;~     DllStructSetData($tACO, "dwQuality", 10000)
;~     DllStructSetData($tACO, "dwBytesPerSecond", 0)
;~     DllStructSetData($tACO, "dwFlags", 8)
;~     DllStructSetData($tACO, "lpFormat", 0)
;~     DllStructSetData($tACO, "cbFormat", 0)
;~     DllStructSetData($tACO, "lpParms", DllStructGetPtr($tParms))
;~     DllStructSetData($tACO, "cbParms", DllStructGetSize($tParms))
;~     DllStructSetData($tACO, "dwInterleaveEvery", 0)

    $tACO = DllStructCreate($AVICOMPRESSOPTIONS)
    DllStructSetData($tACO, "fccType", _Create_mmioFOURCC("vids"))
    DllStructSetData($tACO, "fccHandler", _Create_mmioFOURCC($mmioFOURCC))
    DllStructSetData($tACO, "dwKeyFrameEvery", $iKeyFrameEvery)


    $aRet = DllCall($Avi32_Dll, "int", "AVIFileOpenW", "ptr*", 0, "wstr", $sFilename, "uint", $OF_CREATE, "ptr", 0)
    $pFile = $aRet[1]

    $aRet = DllCall($Avi32_Dll, "int", "AVIFileCreateStream", "ptr", $pFile, "ptr*", 0, "ptr", DllStructGetPtr($tASI))
    $pStream = $aRet[2]

    $aRet = DllCall($Avi32_Dll, "int_ptr", "AVISaveOptions", "hwnd", 0, "uint", BitOR($ICMF_CHOOSE_DATARATE, $ICMF_CHOOSE_KEYFRAME), "int", 1, "ptr*", $pStream, "ptr*", DllStructGetPtr($tACO))
    If $aRet[0] <> 1 Then
        $RetArr[0] = $pFile
        $RetArr[1] = $pStream
        $RetArr[2] = 0
        $RetArr[3] = $tBI
        $RetArr[4] = $Stride
        $RetArr[5] = $pStream
        Return SetError(1, 0, $RetArr)
    EndIf

;~     ConsoleWrite(_DecodeFOURCC(DllStructGetData($tACO, "fccHandler")) & @CRLF)

    ;http://msdn.microsoft.com/en-us/library/dd756811(v=VS.85).aspx
    $aRet = DllCall($Avi32_Dll, "int", "AVIMakeCompressedStream", "ptr*", 0, "ptr", $pStream, "ptr", DllStructGetPtr($tACO), "ptr", 0)
    If $aRet[0] <> $AVIERR_OK Then
            $RetArr[0] = $pFile
            $RetArr[1] = $pStream
            $RetArr[2] = 0
            $RetArr[3] = $tBI
            $RetArr[4] = $stride
            $RetArr[5] = $pStream
        Return SetError(2, 0, $RetArr)
    EndIf
    $psCompressed = $aRet[1]

    ;The format for the stream is the same as BITMAPINFOHEADER
    $aRet = DllCall($Avi32_Dll, "int", "AVIStreamSetFormat", "ptr", $psCompressed, "long", 0, "ptr", DllStructGetPtr($tBI), "long", DllStructGetSize($tBI))

    $RetArr[0] = $pFile
    $RetArr[1] = $psCompressed
    $RetArr[2] = 0
    $RetArr[3] = $tBI
    $RetArr[4] = $stride
    $RetArr[5] = $pStream
    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 $tBIH, $tBFH, $buffer, $fhandle
    $tBFH = DllStructCreate($BITMAPFILEHEADER)
    $tBIH = DllStructCreate($BITMAPINFOHEADER)
    $fhandle = _WinAPI_CreateFile($sFilename, 2, 2, 0, 0)
    _WinAPI_ReadFile($fhandle, DllStructGetPtr($tBFH), DllStructGetSize($tBFH), $byref)
    _WinAPI_ReadFile($fhandle, DllStructGetPtr($tBIH), DllStructGetSize($tBIH), $byref)
    $RetArr[0] = $tBFH
    $RetArr[1] = $tBIH

    If Not $LoadData Then
        _WinAPI_CloseHandle($fhandle)
        Return $RetArr
    EndIf

    $buffer = DllStructCreate("byte[" & DllStructGetData($tBFH, "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")
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", "AVIStreamRelease", "ptr", $Avi_Handle[5])
    DllCall($Avi32_Dll, "int", "AVIFileRelease", "ptr", $Avi_Handle[0])
EndFunc   ;==>_CloseAvi
#endregion AVIWriter UDF

AVIWriter Extented.au3 (89 downloads previously)

AVIWriter Extented Example.au3 :

#include "AVIWriter Extented.au3"
#include <Misc.au3>
#include <ScreenCapture.au3>
#include <WindowsConstants.au3>

_GDIPlus_Startup()

Global Const $sFile = @ScriptDir & "test.avi"
FileDelete($sFile)

Global $rec_duration = 5 ;5 seconds
Global $fps = 5

Global Const $dll = DllOpen("user32.dll")
Global $hGUI_Grab2AVI = GUICreate("", 0, 0, 0, 0, $WS_POPUP, $WS_EX_TOPMOST + $WS_EX_TOOLWINDOW, WinGetHandle(AutoItWinGetTitle()))
GUISetBkColor(0xFF0000, $hGUI_Grab2AVI)
GUISetState(@SW_SHOW, $hGUI_Grab2AVI)
Global $aMPos, $hWin, $hWinAncestor, $hWnd, $aRet_prev, $aPos
Global Const $frame_size = 3
Global $tPoint = DllStructCreate($tagPOINT)
Global $esc = True
Global $mxo, $myo

While Not _IsPressed("1B", $dll) * Sleep(30)
    $aMPos = MouseGetPos()
    DllStructSetData($tPoint, 1, $aMPos[0])
    DllStructSetData($tPoint, 2, $aMPos[1])
    $hWin = _WinAPI_WindowFromPoint($tPoint)
    $hWinAncestor = _WinAPI_GetAncestor($hWin, 2)
    $hWnd = HWnd($hWinAncestor)
    $aRet_prev = -1
    $aPos  = WinGetPos($hWnd)
    If $hWnd <> $hGUI_Grab2AVI And $hWnd <> $aRet_prev Then
        $aRet_prev = $hWnd
        If $aMPos[0] <> $mxo Or $aMPos[1] <> $myo Then
            WinMove($hGUI_Grab2AVI, "", $aPos[0], $aPos[1], $aPos[2], $aPos[3], 1)
            _GuiHole($hGUI_Grab2AVI, $frame_size, $frame_size, $aPos[2] - 2 * $frame_size, $aPos[3] - 2 * $frame_size, $aPos[2], $aPos[3])
            WinSetOnTop($hGUI_Grab2AVI, 0, 1)
            ToolTip("Press CTRL to start capturing of" & @LF & "marked window to a AVI file!" & @LF & @LF & _
                         "Duration: " & $rec_duration & " seconds @ " & $fps & " fps" & @LF & _
                          "Windows Size: " & $aPos[2] & " x " & $aPos[3], $aMPos[0] + 20, $aMPos[1] + 20)
            $mxo = $aMPos[0]
            $myo = $aMPos[1]
        EndIf
    EndIf
    If _IsPressed("11", $dll) Then
        $esc = False
        ExitLoop
    EndIf
WEnd
ToolTip("")
GUIDelete($hGUI_Grab2AVI)
If $esc Then Exit MsgBox(0, "Information", "Aborted", 10)

_StartAviLibrary()
Global $aAVI = _CreateAvi($sFile, $fps, $aPos[2], $aPos[3])
If @error Then close()

Global $hBmp

Global $fSleep = 1000 / $fps, $t, $td
Global $total_FPS = $rec_duration * $fps, $fps_c = 1
$k32_dll = DllOpen("kernel32.dll")

Do
    $fTimer = TimerInit()

    $hBmp = _ScreenCapture_CaptureWnd("", $hWnd)
    _AddHBitmapToAvi($aAVI, $hBmp)
    _WinAPI_DeleteObject($hBmp)

    $fps_c += 1
    $td = $fSleep - TimerDiff($fTimer)
    If $td > 0 Then
        DllCall($k32_dll, "none", "Sleep", "dword", $td)
    EndIf

    If $fps_c > $total_FPS Then
        Close()
    EndIf

Until False

Func Close()
    DllClose($dll)
    _GDIPlus_Shutdown()
    _CloseAvi($aAVI)
    _StopAviLibrary()
    ConsoleWrite("AVI filesize: " & Round(FileGetSize($sFile) / 1024 ^ 2, 2) & " MB" & @CRLF)
    Exit MsgBox(0, "Information", "Done!", 15)
EndFunc   ;==>close

Func _GuiHole($hWnd, $i_x, $i_y, $i_sizew, $i_sizeh, $width, $height)
    Local $outer_rgn, $inner_rgn, $combined_rgn
    $outer_rgn = _WinAPI_CreateRectRgn(0, 0, $width, $height)
    $inner_rgn = _WinAPI_CreateRectRgn($i_x, $i_y, $i_x + $i_sizew, $i_y + $i_sizeh)
    $combined_rgn = _WinAPI_CreateRectRgn(0, 0, 0, 0)
    _WinAPI_CombineRgn($combined_rgn, $outer_rgn, $inner_rgn, $RGN_DIFF)
    _WinAPI_DeleteObject($outer_rgn)
    _WinAPI_DeleteObject($inner_rgn)
    _WinAPI_SetWindowRgn($hWnd, $combined_rgn)
EndFunc   ;==>_GuiHole

AVIWriter Extented Example.au3 (11 downloads previously)

Just select the area where you want to capture to an AVI file, press CTRL to start it and select codec which should be used for compression.

Current settings: 5 seconds record time @5 fps.

Br,

UEZ

Edit: fixed bug when Abort is pressed at Video Compression window

Edit2: added timing function from Windows Screenshooter for better length calculation

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

  • 1 year later...

Hi UEZ !

Thank you for your UDF, it's really amazing :) I'm trying to use it with one more functionnality but I'm not able to catch the proper values : I try to rebuild the $aco structure without calling the "AVISaveOptions" thing (only one time, at the first launch).

Do you know what is behind the "lpParms" pointer of $aco (in order to marshallizing the data in a file, and rebuild it in an other script) ? There is no real information on MSDN for this.

Thanks for all, and sorry for my speaking, I'm a french user (a frog eater, yes, that's it ^^)

Aurélien / ZDS

PS: I'm using Koepi's Xvid Codec for my tests.

Edited by ZDS
Link to comment
Share on other sites

This question was already asked by Andreik on pm:

Can you try this?

Global Const $ICINFO = _
        "DWORD dwSize;DWORD fccType;DWORD fccHandler;DWORD dwFlags;DWORD dwVersion;DWORD dwVersionICM;" & _
        "WCHAR szName[16];WCHAR szDescription[128];WCHAR szDriver[128];"

    $lpParms = DllStructCreate($ICINFO)
    DllCall("Msvfw32.dll","BOOL","ICInfo","DWORD",_Create_mmioFOURCC("vidc"),"DWORD", _Create_mmioFOURCC($mmioFOURCC),"ptr",DllStructGetPtr($lpParms))

    $aco = DllStructCreate($AVICOMPRESSOPTIONS)
    DllStructSetData($aco, "fccType", _Create_mmioFOURCC("vids"))
    DllStructSetData($aco, "fccHandler", _Create_mmioFOURCC($mmioFOURCC))
    DllStructSetData($aco, "dwKeyFrameEvery", 10)
    DllStructSetData($aco, "dwQuality", 10000)
    DllStructSetData($aco, "dwBytesPerSecond", 0)
    DllStructSetData($aco, "dwFlags", 8)
    DllStructSetData($aco, "lpFormat", 0)
    DllStructSetData($aco, "cbFormat", 0)
    DllStructSetData($aco, "lpParms", DllStructGetPtr($lpParms))
    DllStructSetData($aco, "cbParms", DllStructGetSize($lpParms))
    DllStructSetData($aco, "dwInterleaveEvery", 0)

This is what he did which has worked. Please try it out and let me know whether it worked.

It is a long time since I worked with the udf. ;) and I'm currently very busy at the moment.

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Thanks a lot, I'll try it as soon as I can.

PS: How did you learn the definition of an "ICINFO" structure? I've looked all over the MSDN documentation, but found nothing like that.

In your conversation with Andreik, did you found the same thing for the "lpFormat" attribute?

EDIT: It doesn't seem to work, maybe the structure of lpParms is not enough correct, because in my debug,

- I make a first capture and store it in an array of _screen_capturehwnd elements in order to re-use it multiple times

- I make a first test with XVid Codec with a "10" quality value => 138 Ko for the video

- I copy aco in aco_sav, and choose an another quality value "3" => 256 Ko for the video

- I restore aco_sav in aco, and therefor relaunch the first quality value => 138 Ko

Here is my debug result :

Capture

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Jonction

[

ACO [11] :

- fccType : '0'

- fccHandler : '1684633208'

- dwKeyFrameEvery : '0'

- dwQuality : '0'

- dwBytesPerSecond : '0'

- dwFlags : '8'

- lpFormat : '0x00000000'

- cbFormat : '0'

- lpParms : '0x00897748'

- cbParms : '3540'

- dwInterleaveEvery : '0'

]

[

LPPARMS [9] :

- dwSize : '0'

- fccType : '700'

- fccHandler : '1200'

- dwFlags : '1769364526'

- dwVersion : '779052388'

- dwVersionICM : '1936941424'

- szName : ''

- szDescription : ''

- szDriver : ''

]

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Taille : 138 Ko

Jonction

[

ACO [11] :

- fccType : '0'

- fccHandler : '1684633208'

- dwKeyFrameEvery : '0'

- dwQuality : '0'

- dwBytesPerSecond : '0'

- dwFlags : '8'

- lpFormat : '0x00000000'

- cbFormat : '0'

- lpParms : '0x008A2110'

- cbParms : '3540'

- dwInterleaveEvery : '0'

]

[

LPPARMS [9] :

- dwSize : '0'

- fccType : '700'

- fccHandler : '1200'

- dwFlags : '1769364526'

- dwVersion : '779052388'

- dwVersionICM : '1936941424'

- szName : ''

- szDescription : ''

- szDriver : ''

]

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Taille : 256 Ko

Jonction

[

ACO [11] :

- fccType : '0'

- fccHandler : '1684633208'

- dwKeyFrameEvery : '0'

- dwQuality : '0'

- dwBytesPerSecond : '0'

- dwFlags : '8'

- lpFormat : '0x00000000'

- cbFormat : '0'

- lpParms : '0x00897748'

- cbParms : '3540'

- dwInterleaveEvery : '0'

]

[

LPPARMS [9] :

- dwSize : '0'

- fccType : '700'

- fccHandler : '1200'

- dwFlags : '1769364526'

- dwVersion : '779052388'

- dwVersionICM : '1936941424'

- szName : ''

- szDescription : ''

- szDriver : ''

]

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Taille : 138 Ko

Effacement

As you see the three times the readings of the structures $aco and $aco.lpParms are the same, so it's maybe not enough to differenciate the lpParms values.

Never mind, thanks for your work on this UDF (and your help), it's really amazing to make video/screen captures with AutoIt :)

EDIT: I confirm, this structure definition is not enough, the size of the generated lpParms is 3540, the size or an ICINFO sdd is 568.

Edited by ZDS
Link to comment
Share on other sites

Well, I will install XViD in my VM and make some tests later when I find some spare time.

Here a version which takes the video from 0, 0, 200, 100 with predefinied values.

#include <ScreenCapture.au3>
;~ #include <WinAPI.au3>;~~~

#region
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_BADPARAM = 0x80044066
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

Global Const $ICINFO = _
    "DWORD dwSize;DWORD fccType;DWORD fccHandler;DWORD dwFlags;DWORD dwVersion;DWORD dwVersionICM;" & _
    "WCHAR szName[16];WCHAR szDescription[128];WCHAR szDriver[128];"

;http://msdn.microsoft.com/en-us/library/dd183374(v=vs.85).aspx
Global Const $BITMAPFILEHEADER = "WORD bfType;DWORD bfSize;WORD bfReserved1;WORD bfReserved2;DWORD bfOffBits;"
;~ Global Const $BITMAPFILEHEADER = "align 2;char magic[2];int size;short res1;short res2;ptr offset;"

;http://msdn.microsoft.com/en-us/library/dd183376(v=vs.85).aspx
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;"

;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/dd756791(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;"
#endregion

Global $rec_duration = 10
Global $fps = 5

_StartAviLibrary()
FileDelete(@ScriptDir & "Test.avi")
Global $aAVI = _CreateAvi(@ScriptDir & "Test.avi", $fps, 200, 100)

Global $fSleep = 1000 / $fps, $t, $td
Global $total_FPS = $rec_duration * $fps, $fps_c = 1
$k32_dll = DllOpen("kernel32.dll")

Do
    $fTimer = TimerInit()

    $hBmp = _ScreenCapture_CaptureWnd("", 0, 0, 0, 200, 100)
    _AddHBitmapToAvi($aAVI, $hBmp)
    _WinAPI_DeleteObject($hBmp)

    $fps_c += 1
    $td = $fSleep - TimerDiff($fTimer)
    If $td > 0 Then
        DllCall($k32_dll, "none", "Sleep", "dword", $td)
    EndIf

    If $fps_c > $total_FPS Then
        ExitLoop
    EndIf
Until False

_CloseAvi($aAVI)
_StopAviLibrary()
ConsoleWrite("Done!" & @LF)
DllClose($k32_dll)

Exit

#region AVIWriter UDF
;http://www.fourcc.org/codecs.php
Func _Create_mmioFOURCC($FOURCC) ;coded by UEZ
    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);coded by UEZ
    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, UEZ
Func _CreateAvi($sFilename, $FrameRate, $Width, $Height, $BitCount = 24, $mmioFOURCC = "MSVC", $iKeyFrameEvery = 10)
    Local $RetArr[6] ;avi file handle, compressed stream handle, bitmap count, BitmapInfoheader, Stride, stream handle

    Local $aRet, $pFile, $tASI, $tACO, $pStream, $psCompressed

    Local $stride = BitAND(($Width * ($BitCount / 8) + 3), BitNOT(3))

    Local $tBI = DllStructCreate($BITMAPINFOHEADER)
    DllStructSetData($tBI, "biSize", DllStructGetSize($tBI))
    DllStructSetData($tBI, "biWidth", $Width)
    DllStructSetData($tBI, "biHeight", $Height)
    DllStructSetData($tBI, "biPlanes", 1)
    DllStructSetData($tBI, "biBitCount", $BitCount)
    DllStructSetData($tBI, "biSizeImage", $stride * $Height)

    $tASI = DllStructCreate($AVISTREAMINFO)
    DllStructSetData($tASI, "fccType", _Create_mmioFOURCC("vids"))
    DllStructSetData($tASI, "fccHandler", _Create_mmioFOURCC($mmioFOURCC))
    DllStructSetData($tASI, "dwScale", 1)
    DllStructSetData($tASI, "dwRate", $FrameRate)
    DllStructSetData($tASI, "dwQuality", -1) ;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 &#8211;1, drivers use the default quality value.
    DllStructSetData($tASI, "dwSuggestedBufferSize", $stride * $Height)
    DllStructSetData($tASI, "rright", $Width)
    DllStructSetData($tASI, "rbottom", $Height)


    $tParms = DllStructCreate($ICINFO)
    DllCall("Msvfw32.dll", "BOOL", "ICInfo", "DWORD", _Create_mmioFOURCC("vidc"), "DWORD", _Create_mmioFOURCC($mmioFOURCC), "ptr", DllStructGetPtr($tParms))

    $tACO = DllStructCreate($AVICOMPRESSOPTIONS)
    DllStructSetData($tACO, "fccType", _Create_mmioFOURCC("vids"))
    DllStructSetData($tACO, "fccHandler", _Create_mmioFOURCC($mmioFOURCC))
    DllStructSetData($tACO, "dwKeyFrameEvery", 10)
    DllStructSetData($tACO, "dwQuality", 10000)
    DllStructSetData($tACO, "dwBytesPerSecond", 0)
    DllStructSetData($tACO, "dwFlags", 8)
    DllStructSetData($tACO, "lpFormat", 0)
    DllStructSetData($tACO, "cbFormat", 0)
    DllStructSetData($tACO, "lpParms", DllStructGetPtr($tParms))
    DllStructSetData($tACO, "cbParms", DllStructGetSize($tParms))
    DllStructSetData($tACO, "dwInterleaveEvery", 0)

;~     $tACO = DllStructCreate($AVICOMPRESSOPTIONS)
;~     DllStructSetData($tACO, "fccType", _Create_mmioFOURCC("vids"))
;~     DllStructSetData($tACO, "fccHandler", _Create_mmioFOURCC($mmioFOURCC))
;~     DllStructSetData($tACO, "dwKeyFrameEvery", $iKeyFrameEvery)

    $aRet = DllCall($Avi32_Dll, "int", "AVIFileOpenW", "ptr*", 0, "wstr", $sFilename, "uint", $OF_CREATE, "ptr", 0)
    $pFile = $aRet[1]

    $aRet = DllCall($Avi32_Dll, "int", "AVIFileCreateStream", "ptr", $pFile, "ptr*", 0, "ptr", DllStructGetPtr($tASI))
    $pStream = $aRet[2]

;~     $aRet = DllCall($Avi32_Dll, "int_ptr", "AVISaveOptions", "hwnd", 0, "uint", BitOR($ICMF_CHOOSE_DATARATE, $ICMF_CHOOSE_KEYFRAME), "int", 1, "ptr*", $pStream, "ptr*", DllStructGetPtr($tACO))
;~     If $aRet[0] <> 1 Then
;~      $RetArr[0] = $pFile
;~      $RetArr[1] = $pStream
;~      $RetArr[2] = 0
;~      $RetArr[3] = $tBI
;~      $RetArr[4] = $Stride
;~      $RetArr[5] = $pStream
;~         Return SetError(1, 0, $RetArr)
;~     EndIf

;~     ConsoleWrite(_DecodeFOURCC(DllStructGetData($tACO, "fccHandler")) & @CRLF)

    ;http://msdn.microsoft.com/en-us/library/dd756811(v=VS.85).aspx
    $aRet = DllCall($Avi32_Dll, "int", "AVIMakeCompressedStream", "ptr*", 0, "ptr", $pStream, "ptr", DllStructGetPtr($tACO), "ptr", 0)
    If $aRet[0] <> $AVIERR_OK Then
            $RetArr[0] = $pFile
            $RetArr[1] = $pStream
            $RetArr[2] = 0
            $RetArr[3] = $tBI
            $RetArr[4] = $stride
            $RetArr[5] = $pStream
        Return SetError(2, 0, $RetArr)
    EndIf
    $psCompressed = $aRet[1]

    ;The format for the stream is the same as BITMAPINFOHEADER
    $aRet = DllCall($Avi32_Dll, "int", "AVIStreamSetFormat", "ptr", $psCompressed, "long", 0, "ptr", DllStructGetPtr($tBI), "long", DllStructGetSize($tBI))

    $RetArr[0] = $pFile
    $RetArr[1] = $psCompressed
    $RetArr[2] = 0
    $RetArr[3] = $tBI
    $RetArr[4] = $stride
    $RetArr[5] = $pStream
    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 $tBIH, $tBFH, $buffer, $fhandle
    $tBFH = DllStructCreate($BITMAPFILEHEADER)
    $tBIH = DllStructCreate($BITMAPINFOHEADER)
    $fhandle = _WinAPI_CreateFile($sFilename, 2, 2, 0, 0)
    _WinAPI_ReadFile($fhandle, DllStructGetPtr($tBFH), DllStructGetSize($tBFH), $byref)
    _WinAPI_ReadFile($fhandle, DllStructGetPtr($tBIH), DllStructGetSize($tBIH), $byref)
    $RetArr[0] = $tBFH
    $RetArr[1] = $tBIH

    If Not $LoadData Then
        _WinAPI_CloseHandle($fhandle)
        Return $RetArr
    EndIf

    $buffer = DllStructCreate("byte[" & DllStructGetData($tBFH, "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")
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", "AVIStreamRelease", "ptr", $Avi_Handle[5])
    DllCall($Avi32_Dll, "int", "AVIFileRelease", "ptr", $Avi_Handle[0])
EndFunc   ;==>_CloseAvi
#endregion AVIWriter UDF

Br,

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

  • 4 months later...
  • 4 years later...

I know this is a old topic from but I think there are users who can help me.
I want to use this to make a list of pictures to a video (Timelaps)
How to get the right image to the video?

This is what I Have for now but this produce a black avi and not a slideshow?

#include <ScreenCapture.au3>
#include "AVIWriter.au3"

_StartAviLibrary()

$avi = _CreateAvi(@DesktopDir & "\test.avi", 5, 200, 200)

For $i = 1 To 50
    $hImage = _GDIPlus_BitmapCreateFromFile(@DesktopDir & "\Time_lapse_temp\" & $i & ".jpg")
    $hBMP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
    _AddHBitmapToAvi($avi, $hBMP)
    _WinAPI_DeleteObject($hBmp)
    _GDIPlus_ImageDispose($hImage)
Next

_CloseAvi($avi)
_StopAviLibrary()
Exit

Edit: I think I solved, I forgot to start GDI+
Stupid mistake!

Edited by nend
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...