Decipher Posted April 14, 2013 Share Posted April 14, 2013 (edited) I have a directory containg images which is updated at 4 second intervals these images are snapshots from 9 different cameras. 9 Images every 4 seconds with the exception being that when each camera's limit is reached that is 15 images per camera then those images are deleted - sorta like emptying a buffer. The file naming scheme is as follows (seconds since epoch & "." & last octet of the ip address & ".jpg") I need to get the most recent frame and display it in my GUI. It must be as fast as possible because there is already a 4 second delay. This an IP Camera Viewer. I've tried the code below but its not smooth and it freezes constantly. expandcollapse popup#NoTrayIcon #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Outfile=..\..\Documents and Settings\root\Desktop\CamViewer.exe #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <GUIConstantsEx.au3> #include <Date.au3> HotKeySet("{ESC}", "_Exit") Global $hCamViewer, $hPic, $sCameraDir = "H:\Cam\Images" Global $aCamera[8][3] = [[171, "", 0], [172, "", 0], [173, "", 0], [174, "", 0], [175, "", 0], [176, "", 0], [177, "", 0], [178, "", 0]] Global Enum $iDev, $iCtrl , $iFrame Global Enum $iGS , $iPL FileChangeDir($sCameraDir) _SpawnViewer() Sleep(1000) AdlibRegister("_UpdateViewer", 4000) While 1 If GUIGetMsg() == $GUI_EVENT_CLOSE Then Exit EndIf Sleep(50) WEnd Func _UpdateDisplay($iCamera) Local $sImage = _SetImage($iCamera) If $sImage <> "" Then GUICtrlSetImage($aCamera[$iCamera][$iCtrl], $sImage, 0, 0) EndIf EndFunc Func _UpdateViewer() Local $bDelay = False If WinGetTitle($hCamViewer, "") == "Updating..." Then AdlibUnRegister("_UpdateViewer") $bDelay = True While WinGetTitle($hCamViewer, "") == "Updating..." Sleep(500) WEnd EndIf WinSetTitle($hCamViewer, "", "Updating...") For $iCamera = 0 To 7 Step 1 _UpdateDisplay($iCamera) Next WinSetTitle($hCamViewer, "", _Now()) If $bDelay == True Then AdlibRegister("_UpdateViewer", 3000) EndIf EndFunc Func _SpawnViewer() Local $sFrame = "" $hCamViewer = GUICreate("Updating...", @DesktopWidth, @DesktopHeight, -1, -1) Local $iLeft = 0, $iTop = 0, $iWidth = @DesktopWidth / 4, $iHeight = @DesktopHeight / 2 For $iCamera = 0 To 7 Step 1 $sFrame = _SetImage($iCamera) While Not FileExists($sFrame) $sFrame = _SetImage($iCamera) Sleep(500) WEnd $aCamera[$iCamera][$iCtrl] = GUICtrlCreatePic($sFrame, $iLeft, $iTop, $iWidth, $iHeight) $iLeft += $iWidth If $iLeft >= @DesktopWidth Then $iLeft = 0 $iTop += $iHeight EndIf Next GUISetState(@SW_SHOW) WinSetTitle($hCamViewer, "", _Now()) EndFunc Func _RequestImage($iCamera) Local $hImages = FileFindFirstFile("*." & $aCamera[$iCamera][$iDev] & ".jpg") Local $aJPG[30], $iCount = 0 While 1 $aJPG[$iCount] = FileFindNextFile($hImages) $iCount += 1 If @error Or $iCount == 49 Then ExitLoop WEnd Return _MostRecentFrame($aJPG) EndFunc Func _SetImage($iCamera) $aCamera[$iCamera][$iFrame] += 4 Local $sFrame = $aCamera[$iCamera][$iFrame] & "." & $aCamera[$iCamera][$iDev] & ".jpg" If FileExists($sFrame) Then If FileExists(($aCamera[$iCamera][$iFrame] + 4) & "." & $aCamera[$iCamera][$iDev] & ".jpg") Then $aCamera[$iCamera][$iFrame] += 4 $sFrame = $aCamera[$iCamera][$iFrame] & "." & $aCamera[$iCamera][$iDev] & ".jpg" ConsoleWrite("Camera #" & $aCamera[$iCamera][$iDev] & " Computed Frame: " & $sFrame & @CRLF) Return $sFrame EndIf ConsoleWrite("Camera #" & $aCamera[$iCamera][$iDev] & " Computed Frame: " & $sFrame & @CRLF) Return $sFrame EndIf $sFrame = _RequestImage($iCamera) Local $aFrame = StringSplit($sFrame, ".", 2) $aCamera[$iCamera][$iFrame] = $aFrame[0] ConsoleWrite("Camera #" & $aCamera[$iCamera][$iDev] & " Recent Frame: " & $aCamera[$iCamera][$iFrame] & @CRLF) Return $sFrame EndFunc Func _MostRecentFrame($aJPG) Local $iMax = 0 For $i = 0 To UBound($aJPG, 1) -1 If $aJPG[$i] = "" Then Return $aJPG[$iMax] EndIf If Int($aJPG[$i]) >= Int($aJPG[$iMax]) Then $iMax = $i EndIf Next Return $aJPG[$iMax] EndFunc Func _Exit() Exit EndFunc It freezes after so many seconds and not all the images will display intially. If they don't display when I run the script then they are not updated. I'm stumbed on this. Any and all help appreciated thanks. Edited April 16, 2013 by Decipher Spoiler Link to comment Share on other sites More sharing options...
Decipher Posted April 16, 2013 Author Share Posted April 16, 2013 Bump, This could be a useful script for others as well. I'm using a script on the remote computer that has access to the IP Cameras taking snapshot at a specified interval along with WinScp synchronizing the remote and local directory that contains the images. The CamViewer just takes the most recent images and displays them in a GUI. The problem is that viewer script is way to buggy. Spoiler Link to comment Share on other sites More sharing options...
Decipher Posted April 16, 2013 Author Share Posted April 16, 2013 I just commented almost every line of code in hope of recieving some help with this issue. I believe there to be a problem when using GUICtrlSetImage that is causing it to freeze. expandcollapse popup#NoTrayIcon #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Outfile=..\..\Documents and Settings\root\Desktop\CamViewer.exe #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <GUIConstantsEx.au3> #include <Date.au3> #include <Misc.au3> ; - Only allow one instance of this script to run. If _Singleton("CameraViewer", 1) = 0 Then Exit EndIf ; - Exit upon user pressing the ESC key HotKeySet("{ESC}", "_Exit") ; - Define the handle to the GUI and the directory that contains the images as Global variables Global $hCamViewer, $sCameraDir = "H:\Cam\Images" ; - Global two dimensional array where the second dimension indexes are defined directly below Global $aCamera[8][3] = [[171, "", 0], [172, "", 0], [173, "", 0], [174, "", 0], [175, "", 0], [176, "", 0], [177, "", 0], [178, "", 0]] ; - $iDev == the last octet of the IP address i. e. 171 Global Enum $iDev, _ ; - $iCtrl == the handle to the image control $iCtrl , _ ; - $iFrame == the first part of the image's filename the exact time in seconds that the image was created. $iFrame ; - Change the script's working directory to the directory containing images FileChangeDir($sCameraDir) ; - Create the GUI and register an Adlib Function to run periodically _SpawnViewer() ; - Idle when other functions aren't being processed While 1 Sleep(50) WEnd Func _SpawnViewer() Local $sFrame = "" ; - Will contain the image's filename $hCamViewer = GUICreate("Updating...", @DesktopWidth, 240*2, -1, -1) ; Create a default GUI as wide as the desktop and the height is equal to the image size * 2 this allows for two rows containing 4 images ; - $iWidth is the desktop width divided by 4 so that when creating the picture controls, 4 images will fit evenly Local $iLeft = 0, $iTop = 0, $iWidth = @DesktopWidth/4, $iHeight = 240 ; $iHeight == Height of JPEG ; - Populate the GUI with 8 images, two rows of 4 For $iCamera = 0 To 7 Step 1 ; - I'm passing the number index of the $aCamera arrays first dimension to _SetImage ; - $sFrame == i.e. 1366122997.172.jpg $sFrame = _SetImage($iCamera) While Not FileExists($sFrame) ; As the images are being sychronized the remote script will delete the images periodically so ensure it exist before populating the pic control Sleep(500) ; If it dosen't exist wait half a second and check the new image $sFrame = _SetImage($iCamera) WEnd ; - I think this is self explanatory $aCamera[$iCamera][$iCtrl] = GUICtrlCreatePic($sFrame, $iLeft, $iTop, $iWidth, $iHeight) ; - Adjust $iLeft by the size of each control that is created $iLeft += $iWidth ; - When the first row is complete then reset $iLeft and $iTop == the height of the first row so that the second row is directly beneath the first If $iLeft >= @DesktopWidth Then $iLeft = 0 $iTop += $iHeight EndIf Next ;- Show the GUI GUISetState(@SW_SHOW) WinSetTitle($hCamViewer, "", _Now()) ;- Give the GUI the Always on Top attribute WinSetOnTop($hCamViewer, "", 1) ; - Wait 4 seconds just because it seems to help make the images intially appear, if they don't show here then they won't be updated..... Sleep(4000) _UpdateViewer() ;- Call the update function and then register it to be called every 4 seconds from this point AdlibRegister("_UpdateViewer", 4000) EndFunc Func _UpdateViewer() ; - $bDelay is a switch that is being used to determine wether or not this function is registered to run periodically Local $bDelay = False ; - Initally it is False because we know that it is registered or will be after this function is called initally above ; - If the title shows "Updating..." then we know that this function is already being executed If WinGetTitle($hCamViewer, "") == "Updating..." Then ; - Log the fact that if this check wasn't being performed then two instances would be running simultaneouly which unneccessary and is what I originally thought was causing the problem ConsoleWrite("Encountered a delay..." & @CRLF) ;- Unregister this function while we wait for the other instance to finish AdlibUnRegister("_UpdateViewer") ; - Trigger the switch so we can check if it has been unregistered later $bDelay = True ;- Wait for the title to be updated indicating that the function has finished While WinGetTitle($hCamViewer, "") == "Updating..." Sleep(500) WEnd EndIf ; - So at this point there won't be any other instances of this function running we can update the display ; - Update the title which also ensures that this function won't overlap with another instance WinSetTitle($hCamViewer, "", "Updating...") ; - Update the pic controls For $iCamera = 0 To 7 Step 1 _UpdateDisplay($iCamera) Next ; - Reset the window title to the current date and time WinSetTitle($hCamViewer, "", _Now()) ; - If we unregisted this function then we reregister it here If $bDelay == True Then ConsoleWrite("Resuming from delay..." & @CRLF) AdlibRegister("_UpdateViewer", 4000) EndIf EndFunc Func _UpdateDisplay($iCamera) ; $iCamera may be 0-7 ; $sImage contains the filename Local $sImage = _SetImage($iCamera) ; If $sImage is void or the filename dosen't exist then we won't call GUICtrlSetImage which I assume is the source of the problem. If $sImage <> "" And FileExists($sImage) Then GUICtrlSetImage($aCamera[$iCamera][$iCtrl], $sImage, 0, 0) ;FileDelete($sImage) EndIf EndFunc Func _SetImage($iCamera) ; - first I try to guess the filename of the next image that's being download to the image directory ;- $aCamera[$iCamera][$iFrame] == the time the picture was taken in seconds + 4 $aCamera[$iCamera][$iFrame] += 4 ; - this is concatenating i.e. ("1366122997" & "." & "171" & ".jpg") == 1366122997.171.jpg Local $sFrame = $aCamera[$iCamera][$iFrame] & "." & $aCamera[$iCamera][$iDev] & ".jpg" ; - If the file exists which is usually does because the images are being taken at 4 second intervals If FileExists($sFrame) Then ;- Log that information to the console and return the image's filename ConsoleWrite("Camera #" & $aCamera[$iCamera][$iDev] & " Computed Frame: " & $sFrame & @CRLF) Return $sFrame EndIf ; - If the file didn't exist didn't we need to scan the image directory and get the most recent image and return that instead $sFrame = _RequestImage($iCamera) ; $iCamera may be the values from 0 to 7 which is specifying the index of $aCamera's first dimension i.e. evaluates to 171 ; I split the file name into three parts, index 0 contains the time in seconds of which the image was taken Local $aFrame = StringSplit($sFrame, ".", 2) ; - Record the time in seconds that the image was taken $aCamera[$iCamera][$iFrame] = $aFrame[0] ; - Log the information to the console ConsoleWrite("Camera #" & $aCamera[$iCamera][$iDev] & " Recent Frame: " & $sFrame & @CRLF) ; - Return the image's filename Return $sFrame EndFunc Func _RequestImage($iCamera) #cs We are searching: FileFindFirstFile("*." & "171" & ".jpg") or FileFindFirstFile("*.171.jpg") #ce Local $hImages = FileFindFirstFile("*." & $aCamera[$iCamera][$iDev] & ".jpg") ; Define an array to hold the images that are found using FileFindNextFile and store them, $iCount is the $aJPG index Local $aJPG[100], $iCount = 0 ; - Loop until we've found all the images that have i.e. the 171 suffix While 1 $aJPG[$iCount] = FileFindNextFile($hImages) $iCount += 1 If @error Or $iCount == 49 Then ExitLoop WEnd ; Return the most recent frame...du Return _MostRecentFrame($aJPG) EndFunc ; This is just doing an numerical compersion on the filenames in $aJPG where the highest value aka the most recently taken image is returned. Func _MostRecentFrame($aJPG) Local $iMax = 0 For $i = 0 To UBound($aJPG, 1) -1 If $aJPG[$i] = "" Then Return $aJPG[$iMax] EndIf If Int($aJPG[$i]) >= Int($aJPG[$iMax]) Then $iMax = $i EndIf Next Return $aJPG[$iMax] EndFunc ; Exit upon pressing the ESC key Func _Exit() Exit EndFunc Spoiler Link to comment Share on other sites More sharing options...
BrewManNH Posted April 16, 2013 Share Posted April 16, 2013 Couple of things I see right off the bat, one is that the variable $bDelay in the function _UpdateViewer is always going to be false when the function is called. Another thing, don't use "==" for comparisons unless you plan on using strings and not booleans, "==" is a case sensitive string comparison operator. If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag GudeHow to ask questions the smart way! I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from. Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays. - ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script. - Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label. - _FileGetProperty - Retrieve the properties of a file - SciTE Toolbar - A toolbar demo for use with the SciTE editor - GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI. - Latin Square password generator Link to comment Share on other sites More sharing options...
Decipher Posted April 16, 2013 Author Share Posted April 16, 2013 (edited) Oops, I use javascript and other scripting languages alot so the comparison operators can get confusing... I'll make the changes and report back. Thanks *Edit - I set $bDelay = False as a Global variable and switched all the equality comparison operators to just "=" because I don't need to do any case sensitive comparisons. It still freezes but something also worth noting is that when the script is compiled it will persist longer before it hangs. I also have used ConsoleWrite(@ScriptLineNumber) after every line of code checking to see where it freezes, the last line logged is before GUICtrlSetImage... I took your word for the $bDelay variable but after taking a second glance there is nothing wrong with it being set to false when the function is executed because when the function is called that means that it was registered to begin with... Edited April 16, 2013 by Decipher Spoiler Link to comment Share on other sites More sharing options...
Decipher Posted April 18, 2013 Author Share Posted April 18, 2013 Bump, Is there something besides GUICtrlSetImage that I can use? Could GDI+ or something like it be used to display the images as a stream/video? Spoiler Link to comment Share on other sites More sharing options...
Decipher Posted April 19, 2013 Author Share Posted April 19, 2013 Last Bump? Spoiler Link to comment Share on other sites More sharing options...
Decipher Posted April 20, 2013 Author Share Posted April 20, 2013 I quess not. Spoiler Link to comment Share on other sites More sharing options...
FireFox Posted April 21, 2013 Share Posted April 21, 2013 (edited) Hi, Take a look at my IP Camera example. Br, FireFox. Edited April 21, 2013 by FireFox Link to comment Share on other sites More sharing options...
Decipher Posted April 21, 2013 Author Share Posted April 21, 2013 FireFox, First, thanks for replying. The these IP cameras have a web interface but I can't access them remotely. No access to the router's configuration and I think there is two of them or maybe just a switch with some fancy firmware and a core router. I keep trying to hack it with no freakin success. So I wrote a script to download the snapshot like the multi-view web interface(I had a peek at the Javascript) at specific intervals and use WinSCP to forward those images using the SSH server I setup. Long story short is I don't have a video stream to access. If you know of a way to somehow forward the stream using SSH or some other hack that'd be cool otherwise I'd like to just find a way to stablize the code I have now. Is there anything I can use besides GUICtrlSetImage on JPEG images? Anonymous Spoiler Link to comment Share on other sites More sharing options...
FireFox Posted April 21, 2013 Share Posted April 21, 2013 As you can see I use GDIPlus to display the stream, you can do the same thing. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now