#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <WinAPI.au3>
#include <GDIPlus.au3>
#include <Memory.au3>
#region Global Vars
Global Const $sProgramTitle = "IP Camera stream + record"
;HERE YOU GO:
Global Const $iIPAddress = "192.168.1.99", $iPort = 99, $shtauth = "yourauth=="
Global Const $STM_SETIMAGE = 0x0172
Global $blRecording = False, $blGUIMinimized = False
Global Const $sRecordDir = @ScriptDir & "\ip_camera_stream"
Global $bRecvtmp = Binary(""), $bStream = $bRecvtmp
Global $iImgLen = 0, $iStreamLen = 0, $iWritten = 0, $iEOH = 0, $iContLenPos = 0, $hImgFile = 0, $pBuffer = 0, $iImgCount = 0
Global Const $iContLengthLen = StringLen("Content-Length: ")
Global $sStream = "", $sTrim2ContLen = ""
Global $hBMP = 0, $hGraphics = 0, $hHBITMAP2 = 0, $hFamily = 0, $hFont = 0, $tLayout = "", $hFormat = 0, $hBrush = 0
#endregion Global Vars
TCPStartup()
Global $iSocket = TCPConnect($iIPAddress, $iPort)
If @error Then
MsgBox(16, $sProgramTitle, "Could not connect !")
Exit -1
EndIf
TCPSend($iSocket, _
"GET /videostream.cgi HTTP/1.1" & @CRLF & _
"Host: " & $iIPAddress & ":" & $iPort & @CRLF & _
"Connection: keep-alive" & @CRLF & _
"Authorization: Basic " & $shtauth & @CRLF & @CRLF)
#region GUI
Global $hGUI = 0, $pPic = 0, $hPic = 0, $btnRecord = 0
$hGUI = GUICreate($sProgramTitle, 640, 525)
$pPic = GUICtrlCreatePic("", 0, 0, 640, 480, $SS_BITMAP)
GUICtrlSetState($pPic, $GUI_DISABLE)
$hPic = GUICtrlGetHandle($pPic)
$btnRecord = GUICtrlCreateButton("Record", 10, 490, 80, 26)
GUIRegisterMsg($WM_SYSCOMMAND, "WM_SYSCOMMAND")
GUISetState(@SW_SHOW, $hGUI)
#endregion GUI
_GDIPlus_Startup()
$hFamily = _GDIPlus_FontFamilyCreate("Arial")
$hFont = _GDIPlus_FontCreate($hFamily, 17)
$tLayout = _GDIPlus_RectFCreate(10, 10, 100, 40)
$hFormat = _GDIPlus_StringFormatCreate()
$hBrush = _GDIPlus_BrushCreateSolid(0xAFFF0000)
While 1
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
ExitLoop
Case $btnRecord
If $blRecording Then
GUICtrlSetData($btnRecord, "Record")
Else
If Not FileExists($sRecordDir) Then DirCreate($sRecordDir)
GUICtrlSetData($btnRecord, "Stop recording")
EndIf
$blRecording = Not $blRecording
EndSwitch
$bRecvtmp = TCPRecv($iSocket, 4096, 1) ;4kb
If @error Then ExitLoop
If Not BinaryLen($bRecvtmp) Then ContinueLoop
$bStream &= $bRecvtmp
If $iImgLen = 0 Then
$sStream = BinaryToString($bStream)
$iContLenPos = StringInStr($sStream, "Content-Length: ", 2)
$iEOH = StringInStr($sStream, @CRLF & @CRLF, 2, 1, $iContLenPos)
If $iEOH = 0 Or $iContLenPos = 0 Then ContinueLoop
$sTrim2ContLen = StringTrimLeft($sStream, $iContLenPos + $iContLengthLen - 1)
$iImgLen = Number(StringLeft($sTrim2ContLen, StringInStr($sTrim2ContLen, @CR, 2) - 1))
$bStream = BinaryMid($bStream, $iEOH + 4)
EndIf
If $iImgLen = 0 Then ContinueLoop
$iStreamLen = BinaryLen($bStream)
If $iStreamLen < $iImgLen Then ContinueLoop
If Not $blGUIMinimized Then
$hBMP = Load_BMP_From_Mem($bStream)
If $blRecording Then
$hGraphics = _GDIPlus_ImageGetGraphicsContext($hBMP)
_GDIPlus_GraphicsDrawStringEx($hGraphics, "[•REC]", $hFont, $tLayout, $hFormat, $hBrush)
EndIf
$hHBITMAP2 = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBMP)
_WinAPI_DeleteObject(_SendMessage($hPic, $STM_SETIMAGE, 0, $hHBITMAP2))
_GDIPlus_ImageDispose($hBMP)
If $blRecording Then _GDIPlus_GraphicsDispose($hGraphics)
_WinAPI_DeleteObject($hHBITMAP2)
EndIf
If $blRecording Then
$pBuffer = DllStructCreate("byte[" & $iImgLen & "]")
If $iStreamLen > $iImgLen Then
DllStructSetData($pBuffer, 1, BinaryMid($bStream, 1, $iImgLen))
$bStream = BinaryMid($bStream, $iImgLen)
Else
DllStructSetData($pBuffer, 1, $bStream)
$bStream = Binary("")
EndIf
$hImgFile = _WinAPI_CreateFile($sRecordDir & "\snap_" & StringFormat("%.4d", $iImgCount) & ".jpg", 3, 4, 4)
_WinAPI_WriteFile($hImgFile, DllStructGetPtr($pBuffer), $iImgLen, $iWritten)
_WinAPI_CloseHandle($hImgFile)
$iImgCount += 1
EndIf
$iImgLen = 0
WEnd
_GDIPlus_FontDispose($hFont)
_GDIPlus_FontFamilyDispose($hFamily)
_GDIPlus_StringFormatDispose($hFormat)
_GDIPlus_BrushDispose($hBrush)
_GDIPlus_Shutdown()
TCPCloseSocket($iSocket)
TCPShutdown()
Func WM_SYSCOMMAND($hWnd, $iMsg, $wParam, $lParam)
Local Const $SC_MINIMIZE = 0xF020, $SC_RESTORE = 0xF120
Switch BitAND($wParam, 0xFFF0)
Case $SC_MINIMIZE, $SC_RESTORE
$blGUIMinimized = Not $blGUIMinimized
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc ;==>WM_SYSCOMMAND
Func Load_BMP_From_Mem($mem_image)
;author: UEZ
;Additional Code: thanks to progandy for the MemGlobalAlloc and tVARIANT lines
If Not IsBinary($mem_image) Then Return SetError(1, 0, 0)
Local Const $memBitmap = Binary($mem_image)
Local Const $len = BinaryLen($memBitmap)
Local Const $hData = _MemGlobalAlloc($len, $GMEM_MOVEABLE)
Local Const $pData = _MemGlobalLock($hData)
Local $tMem = DllStructCreate("byte[" & $len & "]", $pData)
DllStructSetData($tMem, 1, $memBitmap)
_MemGlobalUnlock($hData)
Local $hStream = DllCall("ole32.dll", "int", "CreateStreamOnHGlobal", "handle", $pData, "int", True, "ptr*", 0)
$hStream = $hStream[3]
Local $hBitmap = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromStream", "ptr", $hStream, "int*", 0)
$hBitmap = $hBitmap[2]
Local Const $tVARIANT = DllStructCreate("word vt;word r1;word r2;word r3;ptr data; ptr")
DllCall("oleaut32.dll", "long", "DispCallFunc", "ptr", $hStream, "dword", 8 + 8 * @AutoItX64, _
"dword", 4, "dword", 23, "dword", 0, "ptr", 0, "ptr", 0, "ptr", DllStructGetPtr($tVARIANT))
$tMem = 0
Return $hBitmap
EndFunc ;==>Load_BMP_From_Mem