From 8e96df76432bf0a808af27871cb746d8bf37bb18 Mon Sep 17 00:00:00 2001 From: Kfir Itzhak Date: Mon, 4 Nov 2013 16:52:21 +0200 Subject: [PATCH] Initial work on adding cURL to zoneminder --- db/zm_create.sql.in | 2 + src/zm_camera.h | 2 +- src/zm_curl_camera.cpp | 132 ++++++++++++++++++++++++++++ src/zm_curl_camera.h | 70 +++++++++++++++ src/zm_monitor.cpp | 25 +++++- web/skins/classic/views/monitor.php | 11 +++ 6 files changed, 240 insertions(+), 2 deletions(-) create mode 100644 src/zm_curl_camera.cpp create mode 100644 src/zm_curl_camera.h diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 20e28d591..d9fcab3ce 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -327,6 +327,8 @@ CREATE TABLE `Monitors` ( `Port` varchar(8) NOT NULL default '', `SubPath` varchar(64) NOT NULL default '', `Path` varchar(255) NOT NULL default '', + `User` varchar(64) NOT NULL default '', + `Pass` varchar(64) NOT NULL default '', `Width` smallint(5) unsigned NOT NULL default '0', `Height` smallint(5) unsigned NOT NULL default '0', `Colours` tinyint(3) unsigned NOT NULL default '1', diff --git a/src/zm_camera.h b/src/zm_camera.h index 8713d3956..48748b59e 100644 --- a/src/zm_camera.h +++ b/src/zm_camera.h @@ -32,7 +32,7 @@ class Camera { protected: - typedef enum { LOCAL_SRC, REMOTE_SRC, FILE_SRC, FFMPEG_SRC } SourceType; + typedef enum { LOCAL_SRC, REMOTE_SRC, FILE_SRC, FFMPEG_SRC, CURL_SRC } SourceType; int id; SourceType type; diff --git a/src/zm_curl_camera.cpp b/src/zm_curl_camera.cpp new file mode 100644 index 000000000..429848739 --- /dev/null +++ b/src/zm_curl_camera.cpp @@ -0,0 +1,132 @@ +// +// ZoneMinder cURL Camera Class Implementation, $Date: 2009-01-16 12:18:50 +0000 (Fri, 16 Jan 2009) $, $Revision: 2713 $ +// Copyright (C) 2001-2008 Philip Coombes +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// + +#include "zm.h" + +#if HAVE_LIBCURL + +static FILE* curldebugfile = NULL; // Remove later + +#include "zm_curl_camera.h" + +cURLCamera::cURLCamera( int p_id, const std::string &p_path, const std::string &p_username, const std::string &p_password, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) : + Camera( p_id, CURL_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ), + mPath( p_path ), mUsername +{ + if ( capture ) + { + Initialise(); + c = curl_easy_init(); + if(c == NULL) { + Fatal("Failed getting easy handle from libcurl"); + } + } +} + +cURLCamera::~cURLCamera() +{ + if ( capture ) + { + if(c != NULL) { + curl_easy_cleanup(c); + c = NULL; + } + Terminate(); + } +} + +void cURLCamera::Initialise() +{ + ret = curl_global_init(CURL_GLOBAL_ALL | CURL_GLOBAL_ACK_EINTR); + if(ret != CURLE_OK) { + Fatal("libcurl initialization failed. error %d: ", curl_easy_strerror(ret)); + } + + Debug(2,"libcurl version: %s",curl_version()); + + curldebugfile = fopen("/tmp/curl_debug.log","w"); // Remove later +} + +void cURLCamera::Terminate() +{ + curl_global_cleanup(); + + fclose(curldebugfile); // Remove later +} + +int cURLCamera::PrimeCapture() +{ + Info( "Priming capture from %s", mPath.c_str() ); + + /* Temporary */ + curl_easy_setopt(c, CURLOPT_VERBOSE, 1); + curl_easy_setopt(c, CURLOPT_STDERR, curldebugfile); + + ret = curl_easy_setopt(c, CURLOPT_URL, mPath.c_str()); + if(ret != CURLE_OK) + Fatal("Failed setting libcurl URL. error %d: ", curl_easy_strerror(ret)); + + ret = curl_easy_setopt(c, CURLOPT_HEADERFUNCTION, header_callback); + if(ret != CURLE_OK) + Fatal("Failed setting libcurl header callback function. error %d: ", curl_easy_strerror(ret)); + + ret = curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, data_callback); + if(ret != CURLE_OK) + Fatal("Failed setting libcurl header callback function. error %d: ", curl_easy_strerror(ret)); + + ret = curl_easy_setopt(c, CURLOPT_HTTPAUTH, CURLAUTH_ANY); + if(ret != CURLE_OK) + Warning("Failed setting libcurl acceptable http authenication methods. error %d: ", curl_easy_strerror(ret)); +} + +int cURLCamera::PreCapture() +{ + // Nothing to do here + return( 0 ); +} + +int cURLCamera::Capture( Image &image ) +{ + uint8_t* directbuffer; + bool frameComplete = false; + + /* Request a writeable buffer of the target image */ + directbuffer = image.WriteBuffer(width, height, colours, subpixelorder); + if(directbuffer == NULL) { + Error("Failed requesting writeable buffer for the captured image."); + return (-1); + } + + success = curl_easy_perform(easyhandle); + + + } + return (0); +} + +int cURLCamera::PostCapture() +{ + // Nothing to do here + return( 0 ); +} + +size_t cURLCamera::data_callback(void *buffer, size_t size, size_t nmemb, void *userdata); +size_t cURLCamera::header_callback( void *buffer, size_t size, size_t nmemb, void *userdata);. + +#endif // HAVE_LIBCURL diff --git a/src/zm_curl_camera.h b/src/zm_curl_camera.h new file mode 100644 index 000000000..8d987b48b --- /dev/null +++ b/src/zm_curl_camera.h @@ -0,0 +1,70 @@ +// +// ZoneMinder cURL Class Interface, $Date: 2008-07-25 10:33:23 +0100 (Fri, 25 Jul 2008) $, $Revision: 2611 $ +// Copyright (C) 2001-2008 Philip Coombes +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// + +#ifndef ZM_CURL_CAMERA_H +#define ZM_CURL_CAMERA_H + +#include "zm_camera.h" +#include "zm_ffmpeg.h" +#include "zm_buffer.h" +#include "zm_regexp.h" +#include "zm_utils.h" + +#if HAVE_CURL_CURL_H +#include +#endif + +// +// Class representing 'remote' cameras, i.e. those which are +// accessed over a network connection. +// +class cURLCamera : public Camera +{ +protected: + std::string mPath; + std::string mUser; + std::string mPass; + curl* c = NULL; + +public: + cURLCamera( int p_id, const std::string &path, const std::string &username, const std::string &password, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); + ~cURLCamera(); + + const std::string &Path() const { return( mPath ); } + const std::string &Username() const { return( mUser ); } + const std::string &Password() const { return( mPass ); } + + void Initialise(); + void Terminate(); + + int PrimeCapture(); + int PreCapture(); + int Capture( Image &image ); + int PostCapture(); + + size_t data_callback(void *buffer, size_t size, size_t nmemb, void *userdata); + size_t header_callback( void *buffer, size_t size, size_t nmemb, void *userdata);. + int debug_callback(CURL* handle, curl_infotype type, char* str, size_t strsize, void* data); + +private: + int ret; + +}; + +#endif // ZM_CURL_CAMERA_H diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 463cf2b07..6a88af804 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -2404,7 +2404,7 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose ) { static char sql[ZM_SQL_MED_BUFSIZ]; - snprintf( sql, sizeof(sql), "select Id, Name, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Id = %d", id ); + snprintf( sql, sizeof(sql), "select Id, Name, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Protocol, Method, Host, Port, Path, User, Pass, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Id = %d", id ); if ( mysql_query( &dbconn, sql ) ) { Error( "Can't run query: %s", mysql_error( &dbconn ) ); @@ -2440,6 +2440,8 @@ Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose ) std::string host = dbrow[col]; col++; std::string port = dbrow[col]; col++; std::string path = dbrow[col]; col++; + std::string user = dbrow[col]; col++; + std::string pass = dbrow[col]; col++; int width = atoi(dbrow[col]); col++; int height = atoi(dbrow[col]); col++; @@ -2588,6 +2590,27 @@ Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose ) #else // HAVE_LIBAVFORMAT Fatal( "You must have ffmpeg libraries installed to use ffmpeg cameras for monitor %d", id ); #endif // HAVE_LIBAVFORMAT + } + else if ( type == "cURL" ) + { +#if HAVE_LIBCURL + camera = new cURLCamera( + id, + path.c_str(), + user.c_str(), + pass.c_str(), + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); +#else // HAVE_LIBCURL + Fatal( "You must have libcurl installed to use ffmpeg cameras for monitor %d", id ); +#endif // HAVE_LIBCURL } else { diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index 0170a308f..4a00e9ece 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -64,6 +64,8 @@ else 'Host' => "", 'Path' => "", 'Port' => "80", + 'User' => "", + 'Pass' => "", 'Colours' => 3, 'Palette' => 0, 'Width' => "320", @@ -174,6 +176,7 @@ $sourceTypes = array( 'Remote' => $SLANG['Remote'], 'File' => $SLANG['File'], 'Ffmpeg' => $SLANG['Ffmpeg'], + 'cURL' => $SLANG['cURL'], ); if ( !ZM_HAS_V4L ) unset($sourceTypes['Local']); @@ -684,6 +687,14 @@ switch ( $tab ) { ?> + + + +