diff --git a/CMakeLists.txt b/CMakeLists.txt index c7bf19162..e3e3779f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ # cmake_minimum_required (VERSION 2.6) project (zoneminder) -set(zoneminder_VERSION "1.28.105") +set(zoneminder_VERSION "1.28.106") # make API version a minor of ZM version set(zoneminder_API_VERSION "${zoneminder_VERSION}.1") diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index dbe6f3f66..6f9e514a1 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -341,6 +341,7 @@ CREATE TABLE `Monitors` ( `Palette` int(10) unsigned NOT NULL default '0', `Orientation` enum('0','90','180','270','hori','vert') NOT NULL default '0', `Deinterlacing` int(10) unsigned NOT NULL default '0', + `RTSPDescribe` tinyint(1) unsigned NOT NULL default '0', `Brightness` mediumint(7) NOT NULL default '-1', `Contrast` mediumint(7) NOT NULL default '-1', `Hue` mediumint(7) NOT NULL default '-1', diff --git a/db/zm_update-1.28.106.sql b/db/zm_update-1.28.106.sql new file mode 100644 index 000000000..894022d22 --- /dev/null +++ b/db/zm_update-1.28.106.sql @@ -0,0 +1,21 @@ +-- +-- This updates a 1.28.105 database to 1.28.106 +-- + +-- +-- Add Monitor RTSPDescribe field +-- Used to enable or disable processing of the remote camera RTSP DESCRIBE response header +-- +SET @s = (SELECT IF( + (SELECT COUNT(*) + FROM INFORMATION_SCHEMA.COLUMNS + WHERE table_name = 'Monitors' + AND table_schema = DATABASE() + AND column_name = 'RTSPDescribe' + ) > 0, +"SELECT 'Column RTSPDescribe already exists in Monitors'", +"ALTER TABLE `Monitors` ADD `RTSPDescribe` tinyint(1) unsigned NOT NULL default '0' AFTER `Deinterlacing`" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 3638707c6..4455917e6 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -2224,11 +2224,11 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c static char sql[ZM_SQL_MED_BUFSIZ]; if ( !protocol ) { - strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Remote'", sizeof(sql) ); + strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Remote'", sizeof(sql) ); } else { - snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Remote' and Protocol = '%s' and Host = '%s' and Port = '%s' and Path = '%s'", protocol, host, port, path ); + snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Remote' and Protocol = '%s' and Host = '%s' and Port = '%s' and Path = '%s'", protocol, host, port, path ); } if ( mysql_query( &dbconn, sql ) ) { @@ -2267,7 +2267,8 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c int colours = atoi(dbrow[col]); col++; /* int palette = atoi(dbrow[col]); */ col++; Orientation orientation = (Orientation)atoi(dbrow[col]); col++; - unsigned int deinterlacing = atoi(dbrow[col]); col++; + unsigned int deinterlacing = atoi(dbrow[col]); col++; + bool rtsp_describe = (*dbrow[col] != '0'); col++; int brightness = atoi(dbrow[col]); col++; int contrast = atoi(dbrow[col]); col++; int hue = atoi(dbrow[col]); col++; @@ -2332,6 +2333,7 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c path, // Path cam_width, cam_height, + rtsp_describe, colours, brightness, contrast, @@ -2699,7 +2701,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, V4LMultiBuffer, V4LCapturesPerFrame, Protocol, Method, Host, Port, Path, Options, User, Pass, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Id = %d", id ); + snprintf( sql, sizeof(sql), "select Id, Name, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Protocol, Method, Host, Port, Path, Options, User, Pass, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Id = %d", id ); if ( mysql_query( &dbconn, sql ) ) { Error( "Can't run query: %s", mysql_error( &dbconn ) ); @@ -2766,6 +2768,7 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame ); int palette = atoi(dbrow[col]); col++; Orientation orientation = (Orientation)atoi(dbrow[col]); col++; unsigned int deinterlacing = atoi(dbrow[col]); col++; + bool rtsp_describe = (*dbrow[col] != '0'); col++; int brightness = atoi(dbrow[col]); col++; int contrast = atoi(dbrow[col]); col++; int hue = atoi(dbrow[col]); col++; @@ -2867,6 +2870,7 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame ); path.c_str(), cam_width, cam_height, + rtsp_describe, colours, brightness, contrast, diff --git a/src/zm_remote_camera_rtsp.cpp b/src/zm_remote_camera_rtsp.cpp index 9f7b39227..b7b976996 100644 --- a/src/zm_remote_camera_rtsp.cpp +++ b/src/zm_remote_camera_rtsp.cpp @@ -28,9 +28,10 @@ #include #include -RemoteCameraRtsp::RemoteCameraRtsp( int p_id, const std::string &p_method, const std::string &p_host, const std::string &p_port, const std::string &p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) : +RemoteCameraRtsp::RemoteCameraRtsp( int p_id, const std::string &p_method, const std::string &p_host, const std::string &p_port, const std::string &p_path, int p_width, int p_height, bool p_rtsp_describe, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) : RemoteCamera( p_id, "rtsp", p_host, p_port, p_path, p_width, p_height, p_colours, p_brightness, p_contrast, p_hue, p_colour, p_capture ), - rtspThread( 0 ) + rtspThread( 0 ), + rtsp_describe( p_rtsp_describe ) { if ( p_method == "rtpUni" ) method = RtspThread::RTP_UNICAST; @@ -125,7 +126,7 @@ void RemoteCameraRtsp::Terminate() int RemoteCameraRtsp::Connect() { - rtspThread = new RtspThread( id, method, protocol, host, port, path, auth ); + rtspThread = new RtspThread( id, method, protocol, host, port, path, auth, rtsp_describe ); rtspThread->start(); diff --git a/src/zm_remote_camera_rtsp.h b/src/zm_remote_camera_rtsp.h index b5a1e3c89..71debf40b 100644 --- a/src/zm_remote_camera_rtsp.h +++ b/src/zm_remote_camera_rtsp.h @@ -40,10 +40,11 @@ protected: int rtsp_sd; int rtp_sd; int rtcp_sd; + bool rtsp_describe; Buffer buffer; - Buffer lastSps; - Buffer lastPps; + Buffer lastSps; + Buffer lastPps; RtspThread::RtspMethod method; @@ -66,18 +67,19 @@ protected: #endif public: - RemoteCameraRtsp( int p_id, const std::string &method, const std::string &host, const std::string &port, const std::string &path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); + RemoteCameraRtsp( int p_id, const std::string &method, const std::string &host, const std::string &port, const std::string &path, int p_width, int p_height, bool p_rtsp_describe, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); ~RemoteCameraRtsp(); void Initialise(); void Terminate(); - int Connect(); - int Disconnect(); + int Connect(); + int Disconnect(); int PrimeCapture(); int PreCapture(); int Capture( Image &image ); int PostCapture(); + }; #endif // ZM_REMOTE_CAMERA_RTSP_H diff --git a/src/zm_rtsp.cpp b/src/zm_rtsp.cpp index 556174291..0dbcb7329 100644 --- a/src/zm_rtsp.cpp +++ b/src/zm_rtsp.cpp @@ -167,13 +167,14 @@ void RtspThread::releasePorts( int port ) smAssignedPorts.erase( port ); } -RtspThread::RtspThread( int id, RtspMethod method, const std::string &protocol, const std::string &host, const std::string &port, const std::string &path, const std::string &auth) : +RtspThread::RtspThread( int id, RtspMethod method, const std::string &protocol, const std::string &host, const std::string &port, const std::string &path, const std::string &auth, bool rtsp_describe) : mId( id ), mMethod( method ), mProtocol( protocol ), mHost( host ), mPort( port ), mPath( path ), + mRtspDescribe( rtsp_describe ), mSessDesc( 0 ), mFormatContext( 0 ), mSeq( 0 ), @@ -382,20 +383,23 @@ int RtspThread::run() if( sdpStart == std::string::npos ) return( -1 ); - std::string DescHeader = response.substr( 0,sdpStart ); - Debug( 1, "Processing DESCRIBE response header '%s'", DescHeader.c_str() ); + if ( mRtspDescribe ) + { + std::string DescHeader = response.substr( 0,sdpStart ); + Debug( 1, "Processing DESCRIBE response header '%s'", DescHeader.c_str() ); - lines = split( DescHeader, "\r\n" ); - for ( size_t i = 0; i < lines.size(); i++ ) - { - // If the device sends us a url value for Content-Base in the response header, we should use that instead - if ( ( lines[i].size() > 13 ) && ( lines[i].substr( 0, 13 ) == "Content-Base:" ) ) - { - mUrl = trimSpaces( lines[i].substr( 13 ) ); - Info("Received new Content-Base in DESCRIBE response header. Updated device Url to: '%s'", mUrl.c_str() ); - break; - } - } + lines = split( DescHeader, "\r\n" ); + for ( size_t i = 0; i < lines.size(); i++ ) + { + // If the device sends us a url value for Content-Base in the response header, we should use that instead + if ( ( lines[i].size() > 13 ) && ( lines[i].substr( 0, 13 ) == "Content-Base:" ) ) + { + mUrl = trimSpaces( lines[i].substr( 13 ) ); + Info("Received new Content-Base in DESCRIBE response header. Updated device Url to: '%s'", mUrl.c_str() ); + break; + } + } + } sdpStart += endOfHeaders.length(); diff --git a/src/zm_rtsp.h b/src/zm_rtsp.h index 937646b6d..f5dcb9552 100644 --- a/src/zm_rtsp.h +++ b/src/zm_rtsp.h @@ -50,6 +50,7 @@ private: private: int mId; + bool mRtspDescribe; RtspMethod mMethod; std::string mProtocol; std::string mHost; @@ -95,7 +96,7 @@ private: void checkAuthResponse(std::string &response); public: - RtspThread( int id, RtspMethod method, const std::string &protocol, const std::string &host, const std::string &port, const std::string &path, const std::string &auth); + RtspThread( int id, RtspMethod method, const std::string &protocol, const std::string &host, const std::string &port, const std::string &path, const std::string &auth, bool rtsp_describe ); ~RtspThread(); public: diff --git a/version b/version index 8424efb95..71864bd8d 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.28.105 +1.28.106 diff --git a/web/includes/actions.php b/web/includes/actions.php index 3ddf1bb40..53d9c8a6e 100644 --- a/web/includes/actions.php +++ b/web/includes/actions.php @@ -445,7 +445,8 @@ if ( !empty($action) ) 'TrackMotion' => 'toggle', 'Enabled' => 'toggle', 'DoNativeMotDet' => 'toggle', - 'Exif' => 'toggle' + 'Exif' => 'toggle', + 'RTSPDescribe' => 'toggle', ); $columns = getTableColumns( 'Monitors' ); diff --git a/web/lang/en_gb.php b/web/lang/en_gb.php index bf0258caf..76a71e301 100644 --- a/web/lang/en_gb.php +++ b/web/lang/en_gb.php @@ -256,6 +256,7 @@ $SLANG = array( 'DefaultScale' => 'Default Scale', 'DefaultView' => 'Default View', 'Deinterlacing' => 'Deinterlacing', + 'RTSPDescribe' => 'Use RTSP Response Media URL', 'Delay' => 'Delay', 'DeleteAndNext' => 'Delete & Next', 'DeleteAndPrev' => 'Delete & Prev', @@ -903,7 +904,13 @@ $OLANG = array( 'OPTIONS_EXIF' => array( 'Help' => "Enable this option to embed EXIF data into each jpeg frame." ), - + 'OPTIONS_RTSPDESCRIBE' => array( + 'Help' => "Sometimes, during the intial RTSP handshake, the camera will send an updated media URL. ". + "Enable this option to tell ZoneMinder to use this URL. Disable this option to ignore the ". + "value from the camera and use the value as entered in the monitor configuration~~~~". + "Generally this should be enabled. However, there are cases where the camera can get its". + "own URL incorrect, such as when the camera is streaming through a firewall" + ), // 'LANG_DEFAULT' => array( // 'Prompt' => "This is a new prompt for this option", diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index 5920409ad..369319608 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -78,6 +78,7 @@ if ( ! empty($_REQUEST['mid']) ) { 'Height' => "240", 'Orientation' => "0", 'Deinterlacing' => 0, + 'RTSPDescribe' => 0, 'LabelFormat' => '%N - %d/%m/%y %H:%M:%S', 'LabelX' => 0, 'LabelY' => 0, @@ -563,6 +564,12 @@ if ( $tab != 'source' ) + + @@ -823,6 +830,14 @@ switch ( $tab ) + +  () checked="checked"/> +