Merge remote-tracking branch 'origin/master' into video

Conflicts:
	configure.ac
	src/CMakeLists.txt
This commit is contained in:
Kfir Itzhak 2013-12-26 21:03:45 +02:00
commit e652441996
31 changed files with 368 additions and 257 deletions

View File

@ -62,6 +62,7 @@ set(ZM_EXTRA_LIBS "" CACHE STRING "A list of optional libraries, separated by se
set(ZM_MYSQL_ENGINE "InnoDB" CACHE STRING "MySQL engine to use with database, default: InnoDB")
set(ZM_NO_MMAP "OFF" CACHE BOOL "Set to ON to not use mmap shared memory. Shouldn't be enabled unless you experience problems with the shared memory. default: OFF")
set(ZM_NO_FFMPEG "OFF" CACHE BOOL "Set to ON to skip ffmpeg checks and force building ZM without ffmpeg. default: OFF")
set(ZM_NO_LIBVLC "OFF" CACHE BOOL "Set to ON to skip libvlc checks and force building ZM without libvlc. default: OFF")
set(ZM_NO_X10 "OFF" CACHE BOOL "Set to ON to build ZoneMinder without X10 support. default: OFF")
set(ZM_PERL_SUBPREFIX "${CMAKE_INSTALL_LIBDIR}/perl5" CACHE PATH "Use a different directory for the zm perl modules. NOTE: This is a subprefix, e.g. lib will be turned into <prefix>/lib, default: <libdir>/perl5")
set(ZM_PERL_USE_PATH "${CMAKE_INSTALL_PREFIX}/${ZM_PERL_SUBPREFIX}" CACHE PATH "Override the include path for zm perl modules. Useful if you are moving the perl modules without using the ZM_PERL_SUBPREFIX option. default: <prefix>/<zmperlsubprefix>")
@ -377,6 +378,26 @@ if(NOT ZM_NO_FFMPEG)
endif(NOT ZM_NO_FFMPEG)
# Do not check for libvlc if ZM_NO_LIBVLC is on
if(NOT ZM_NO_LIBVLC)
# libvlc (using find_library and find_path)
find_library(LIBVLC_LIBRARIES vlc)
if(LIBVLC_LIBRARIES)
set(HAVE_LIBVLC 1)
list(APPEND ZM_BIN_LIBS "${LIBVLC_LIBRARIES}")
find_path(LIBVLC_INCLUDE_DIR "vlc/vlc.h")
if(LIBVLC_INCLUDE_DIR)
include_directories("${LIBVLC_INCLUDE_DIR}")
set(CMAKE_REQUIRED_INCLUDES "${LIBVLC_INCLUDE_DIR}")
endif(LIBVLC_INCLUDE_DIR)
mark_as_advanced(FORCE LIBVLC_LIBRARIES LIBVLC_INCLUDE_DIR)
check_include_file("vlc/vlc.h" HAVE_VLC_VLC_H)
set(optlibsfound "${optlibsfound} libVLC")
else(LIBVLC_LIBRARIES)
set(optlibsnotfound "${optlibsnotfound} libVLC")
endif(LIBVLC_LIBRARIES)
endif(NOT ZM_NO_LIBVLC)
# *** END OF LIBRARY CHECKS ***
# Check for gnutls or crypto

View File

@ -276,6 +276,7 @@ AC_CHECK_LIB(avformat,avformat_version,,AC_MSG_WARN(libavformat.a is required fo
#AC_CHECK_LIB(avformat,av_new_stream,,AC_MSG_WARN(libavformat.a is required for MPEG streaming))
AC_CHECK_LIB(avdevice,avdevice_register_all,,AC_MSG_WARN(libavdevice.a may be required for MPEG streaming))
AC_CHECK_LIB(swscale,sws_scale,,,-lswscale)
AC_CHECK_LIB(vlc,libvlc_new,,AC_MSG_WARN(libvlc.a may be required for streaming))
AC_CHECK_LIB(bz2,BZ2_bzCompress,,AC_MSG_WARN(zm requires libbz2.a for recent versions of ffmpeg))
AC_CHECK_LIB(z,compress,,)
@ -316,6 +317,7 @@ fi
AC_CHECK_HEADERS(zlib.h,,,)
AC_CHECK_HEADERS(x264.h,,,)
AC_CHECK_HEADERS([mp4v2/mp4v2.h mp4v2.h mp4.h],,,)
AC_CHECK_HEADERS(vlc/vlc.h,,,)
if test "$ZM_SSL_LIB" == "openssl"; then
AC_CHECK_DECLS(MD5,,AC_MSG_ERROR([zm requires openssl/md5.h - use ZM_SSL_LIB option to select gnutls instead]),[#include <stdlib.h>

View File

@ -1,4 +1,4 @@
AUTOMAKE_OPTIONS = gnu
AUTOMAKE_OPTIONS = foreign
zmdbdatadir = $(pkgdatadir)/db

View File

@ -63,7 +63,7 @@ DROP TABLE IF EXISTS `Controls`;
CREATE TABLE `Controls` (
`Id` int(10) unsigned NOT NULL auto_increment,
`Name` varchar(64) NOT NULL default '',
`Type` enum('Local','Remote','Ffmpeg') NOT NULL default 'Local',
`Type` enum('Local','Remote','Ffmpeg','Libvlc') NOT NULL default 'Local',
`Protocol` varchar(64) default NULL,
`CanWake` tinyint(3) unsigned NOT NULL default '0',
`CanSleep` tinyint(3) unsigned NOT NULL default '0',
@ -282,7 +282,7 @@ DROP TABLE IF EXISTS `MonitorPresets`;
CREATE TABLE `MonitorPresets` (
`Id` int(10) unsigned NOT NULL auto_increment,
`Name` varchar(64) NOT NULL default '',
`Type` enum('Local','Remote','File','Ffmpeg') NOT NULL default 'Local',
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc') NOT NULL default 'Local',
`Device` tinytext,
`Channel` tinytext,
`Format` int(10) unsigned default NULL,
@ -313,7 +313,7 @@ DROP TABLE IF EXISTS `Monitors`;
CREATE TABLE `Monitors` (
`Id` int(10) unsigned NOT NULL auto_increment,
`Name` varchar(64) NOT NULL default '',
`Type` enum('Local','Remote','File','Ffmpeg') NOT NULL default 'Local',
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc') NOT NULL default 'Local',
`Function` enum('None','Monitor','Modect','Record','Mocord','Nodect') NOT NULL default 'Monitor',
`Enabled` tinyint(3) unsigned NOT NULL default '1',
`LinkedMonitors` varchar(255) NOT NULL default '',

11
db/zm_update-1.26.6.sql Normal file
View File

@ -0,0 +1,11 @@
--
-- This updates a 1.26.5 database to 1.26.6
--
--
-- Add Libvlc monitor type
--
ALTER TABLE Controls modify column Type enum('Local','Remote','Ffmpeg','Libvlc') NOT NULL default 'Local';
ALTER TABLE MonitorPresets modify column Type enum('Local','Remote','File','Ffmpeg','Libvlc') NOT NULL default 'Local';
ALTER TABLE Monitors modify column Type enum('Local','Remote','File','Ffmpeg','Libvlc') NOT NULL default 'Local';

View File

@ -25,7 +25,6 @@ start() {
echo -n "Starting $prog: "
mkdir -p $RUNDIR && chown www-data:www-data $RUNDIR
mkdir -p $TMPDIR && chown www-data:www-data $TMPDIR
zmfix -a
$command start
RETVAL=$?
[ $RETVAL = 0 ] && echo success

View File

@ -25,7 +25,7 @@ New installs
introduce an obvious security issue. The following should set this up:
mysql -u root -p
grant select,insert,update,delete,alter on zm.* to
grant select,insert,update,delete,lock tables,alter on zm.* to
'zmuser'@localhost identified by 'zmpass';
Obviously, change at least zmpass to an actual, secure password or

View File

@ -126,7 +126,6 @@ fi
%{_bindir}/zmdc.pl
%{_bindir}/zmf
%{_bindir}/zmfilter.pl
%attr(4755,root,root) %{_bindir}/zmfix
%{_bindir}/zmpkg.pl
%{_bindir}/zmstreamer
%{_bindir}/zmtrack.pl

View File

@ -228,7 +228,6 @@ fi
%{_bindir}/zmdc.pl
%{_bindir}/zmf
%{_bindir}/zmfilter.pl
%attr(4755,root,root) %{_bindir}/zmfix
%{_bindir}/zmpkg.pl
%{_bindir}/zmstreamer
%{_bindir}/zmtrack.pl

View File

@ -15,7 +15,7 @@
mysql -uroot -p
mysql> create database zm;
mysql> grant select,insert,update,delete,alter on zm.* to
mysql> grant select,insert,update,delete,lock tables,alter on zm.* to
'zmuser'@localhost identified by 'zmpass';
mysql> exit;
mysql -uroot -p < /usr/share/zoneminder/db/zm_create.sql

View File

@ -124,7 +124,6 @@ rm -rf %{_docdir}/%{name}-%{version}
%{_bindir}/zmdc.pl
%{_bindir}/zmf
%{_bindir}/zmfilter.pl
%attr(4755,root,root) %{_bindir}/zmfix
%{_bindir}/zmpkg.pl
%{_bindir}/zmstreamer
%{_bindir}/zmtrack.pl

View File

@ -233,7 +233,6 @@ fi
%{_bindir}/zmdc.pl
%{_bindir}/zmf
%{_bindir}/zmfilter.pl
%attr(4755,root,root) %{_bindir}/zmfix
%{_bindir}/zmpkg.pl
%{_bindir}/zmstreamer
%{_bindir}/zmtrack.pl

View File

@ -25,7 +25,6 @@ start() {
echo -n "Starting $prog: "
mkdir -p $RUNDIR && chown www-data:www-data $RUNDIR
mkdir -p $TMPDIR && chown www-data:www-data $TMPDIR
zmfix -a
$command start
RETVAL=$?
[ $RETVAL = 0 ] && echo success

View File

@ -362,7 +362,7 @@ our @options =
name => "ZM_HTTP_VERSION",
default => "1.0",
description => "The version of HTTP that ZoneMinder will use to connect",
help => "ZoneMinder can communicate with network cameras using either of the HTTP/1.1 or HTTP/1.0 standard. A server will normally fall back to the version it supports iwht no problem so this should usually by left at the default. However it can be changed to HTTP/1.0 if necessary to resolve particular issues.",
help => "ZoneMinder can communicate with network cameras using either of the HTTP/1.1 or HTTP/1.0 standard. A server will normally fall back to the version it supports with no problem so this should usually by left at the default. However it can be changed to HTTP/1.0 if necessary to resolve particular issues.",
type => { db_type=>"string", hint=>"1.1|1.0", pattern=>qr|^(1\.[01])$|, format=>q( $1?$1:"" ) },
category => "network",
},

View File

@ -110,7 +110,7 @@ sub open
$self->loadMonitor();
use LWP::UserAgent;
$self->{ua} = LWP::UserAgent->new;
$self->{ua}->agent( "ZoneMinder Control Agent/".ZOneMinder::Base::ZM_VERSION );
$self->{ua}->agent( "ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION );
$self->{state} = 'open';
}

View File

@ -51,7 +51,7 @@ use Date::Manip;
use Getopt::Long;
use Data::Dumper;
use constant EVENT_PATH => (ZM_DIR_EVENTS=~m|/|)?ZM_DIR_EVENTS:(ZM_PATH_WEB.'/'.ZM_DIR_EVENTS);
use constant EVENT_PATH => ($Config{ZM_DIR_EVENTS}=~m|/|)?$Config{ZM_DIR_EVENTS}:($Config{ZM_PATH_WEB}.'/'.$Config{ZM_DIR_EVENTS});
logInit();
logSetSignal();
@ -163,7 +163,12 @@ if ( !GetOptions( 'filter=s'=>\$filter_parm ) )
Usage();
}
chdir( $Config{EVENT_PATH} );
if ( ! EVENT_PATH ) {
Error( "No event path defined. Config was $Config{ZM_DIR_EVENTS}\n" );
die;
}
chdir( EVENT_PATH );
my $dbh = zmDbConnect();
@ -178,7 +183,7 @@ else
if ( !$filter_parm )
{
sleep( $Config{START_DELAY} );
sleep( START_DELAY );
}
my $filters;
@ -876,7 +881,7 @@ sub substituteTags
$sth->finish();
}
my $url = ZM_URL;
my $url = $Config{ZM_URL};
$text =~ s/%ZP%/$url/g;
$text =~ s/%MN%/$event->{MonitorName}/g;
$text =~ s/%MET%/$monitor->{EventCount}/g;

View File

@ -166,7 +166,6 @@ if ( $command =~ /^(?:start|restart)$/ )
}
}
zmMemTidy();
runCommand( "zmfix" );
runCommand( "zmdc.pl startup" );
my $sql = "select * from Monitors";

View File

@ -4,7 +4,7 @@
configure_file(zm_config.h.in "${CMAKE_CURRENT_BINARY_DIR}/zm_config.h" @ONLY)
# Group together all the source files that are used by all the binaries (zmc, zma, zmu, zms etc)
set(ZM_BIN_SRC_FILES zm_box.cpp zm_buffer.cpp zm_camera.cpp zm_comms.cpp zm_config.cpp zm_coord.cpp zm.cpp zm_db.cpp zm_logger.cpp zm_event.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_camera.cpp zm_image.cpp zm_jpeg.cpp zm_local_camera.cpp zm_monitor.cpp zm_ffmpeg.cpp zm_mpeg.cpp zm_poly.cpp zm_regexp.cpp zm_remote_camera.cpp zm_remote_camera_http.cpp zm_remote_camera_rtsp.cpp zm_rtp.cpp zm_rtp_ctrl.cpp zm_rtp_data.cpp zm_rtp_source.cpp zm_rtsp.cpp zm_sdp.cpp zm_signal.cpp zm_stream.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_video.cpp zm_zone.cpp)
set(ZM_BIN_SRC_FILES zm_box.cpp zm_buffer.cpp zm_camera.cpp zm_comms.cpp zm_config.cpp zm_coord.cpp zm.cpp zm_db.cpp zm_logger.cpp zm_event.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_camera.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_ffmpeg.cpp zm_mpeg.cpp zm_poly.cpp zm_regexp.cpp zm_remote_camera.cpp zm_remote_camera_http.cpp zm_remote_camera_rtsp.cpp zm_rtp.cpp zm_rtp_ctrl.cpp zm_rtp_data.cpp zm_rtp_source.cpp zm_rtsp.cpp zm_sdp.cpp zm_signal.cpp zm_stream.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_video.cpp zm_zone.cpp)
# A fix for cmake recompiling the source files for every target.
add_library(zm STATIC ${ZM_BIN_SRC_FILES})
@ -16,7 +16,6 @@ add_executable(zmf zmf.cpp)
add_executable(zms zms.cpp)
add_executable(nph-zms zms.cpp)
add_executable(zmstreamer zmstreamer.cpp)
add_executable(zmfix zmfix.cpp zm_config.cpp zm_regexp.cpp zm_logger.cpp zm_utils.cpp zm_db.cpp zm.cpp)
target_link_libraries(zmc zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
target_link_libraries(zma zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
@ -25,9 +24,8 @@ target_link_libraries(zmf zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
target_link_libraries(zms zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
target_link_libraries(nph-zms zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
target_link_libraries(zmstreamer zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
target_link_libraries(zmfix ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
install(TARGETS zmc zma zmu zmf zmstreamer zmfix RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
install(TARGETS zmc zma zmu zmf zmstreamer RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
install(TARGETS zms nph-zms RUNTIME DESTINATION "${ZM_CGIDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)

View File

@ -17,8 +17,7 @@ bin_PROGRAMS = \
zmu \
zms \
zmf \
zmstreamer \
zmfix
zmstreamer
zm_SOURCES = \
zm_box.cpp \
@ -36,6 +35,7 @@ zm_SOURCES = \
zm_ffmpeg_camera.cpp \
zm_image.cpp \
zm_jpeg.cpp \
zm_libvlc_camera.cpp \
zm_local_camera.cpp \
zm_monitor.cpp \
zm_ffmpeg.cpp \
@ -67,7 +67,6 @@ zms_SOURCES = zms.cpp $(zm_SOURCES)
zmu_SOURCES = zmu.cpp $(zm_SOURCES)
zmf_SOURCES = zmf.cpp $(zm_SOURCES)
zmstreamer_SOURCES = zmstreamer.cpp $(zm_SOURCES)
zmfix_SOURCES = zmfix.cpp zm_config.cpp zm_regexp.cpp zm_logger.cpp zm_utils.cpp zm_db.cpp zm.cpp
noinst_HEADERS = \
jinclude.h \
@ -90,6 +89,7 @@ noinst_HEADERS = \
zm.h \
zm_image.h \
zm_jpeg.h \
zm_libvlc_camera.h \
zm_local_camera.h \
zm_mem_utils.h \
zm_monitor.h \
@ -128,7 +128,6 @@ dist-hook:
install-exec-hook:
( cd $(DESTDIR)@bindir@; mkdir -p $(DESTDIR)$(cgidir); mv zms $(DESTDIR)$(cgidir) )
( cd $(DESTDIR)$(cgidir); chown $(webuser):$(webgroup) zms; ln -f zms nph-zms )
( cd $(DESTDIR)@bindir@; chmod u+s zmfix )
uninstall-hook:
( cd $(DESTDIR)$(cgidir); rm -f zms nph-zms )

View File

@ -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, LIBVLC_SRC } SourceType;
int id;
SourceType type;
@ -58,6 +58,7 @@ public:
bool IsRemote() const { return( type == REMOTE_SRC ); }
bool IsFile() const { return( type == FILE_SRC ); }
bool IsFfmpeg() const { return( type == FFMPEG_SRC ); }
bool IsLibvlc() const { return( type == LIBVLC_SRC ); }
unsigned int Width() const { return( width ); }
unsigned int Height() const { return( height ); }
unsigned int Colours() const { return( colours ); }

192
src/zm_libvlc_camera.cpp Normal file
View File

@ -0,0 +1,192 @@
/*
* ZoneMinder Libvlc Camera Class Implementation, $Date$, $Revision$
* 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"
#include "zm_libvlc_camera.h"
#if HAVE_LIBVLC
// Do all the buffer checking work here to avoid unnecessary locking
void* LibvlcLockBuffer(void* opaque, void** planes)
{
LibvlcPrivateData* data = (LibvlcPrivateData*)opaque;
data->mutex.lock();
uint8_t* buffer = data->buffer;
data->buffer = data->prevBuffer;
data->prevBuffer = buffer;
*planes = data->buffer;
return NULL;
}
void LibvlcUnlockBuffer(void* opaque, void* picture, void *const *planes)
{
LibvlcPrivateData* data = (LibvlcPrivateData*)opaque;
bool newFrame = false;
for(uint32_t i = 0; i < data->bufferSize; i++)
{
if(data->buffer[i] != data->prevBuffer[i])
{
newFrame = true;
break;
}
}
data->mutex.unlock();
time_t now;
time(&now);
// Return frames slightly faster than 1fps (if time() supports greater than one second resolution)
if(newFrame || difftime(now, data->prevTime) >= 0.8)
{
data->prevTime = now;
data->newImage.updateValueSignal(true);
}
}
LibvlcCamera::LibvlcCamera( int p_id, 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 ) :
Camera( p_id, LIBVLC_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 )
{
mLibvlcInstance = NULL;
mLibvlcMedia = NULL;
mLibvlcMediaPlayer = NULL;
mLibvlcData.buffer = NULL;
mLibvlcData.prevBuffer = NULL;
/* Has to be located inside the constructor so other components such as zma will receive correct colours and subpixel order */
if(colours == ZM_COLOUR_RGB32) {
subpixelorder = ZM_SUBPIX_ORDER_BGRA;
mTargetChroma = "RV32";
mBpp = 4;
} else if(colours == ZM_COLOUR_RGB24) {
subpixelorder = ZM_SUBPIX_ORDER_BGR;
mTargetChroma = "RV24";
mBpp = 3;
} else if(colours == ZM_COLOUR_GRAY8) {
subpixelorder = ZM_SUBPIX_ORDER_NONE;
mTargetChroma = "GREY";
mBpp = 1;
} else {
Panic("Unexpected colours: %d",colours);
}
if ( capture )
{
Initialise();
}
}
LibvlcCamera::~LibvlcCamera()
{
if ( capture )
{
Terminate();
}
if(mLibvlcMediaPlayer != NULL)
{
libvlc_media_player_release(mLibvlcMediaPlayer);
mLibvlcMediaPlayer = NULL;
}
if(mLibvlcMedia != NULL)
{
libvlc_media_release(mLibvlcMedia);
mLibvlcMedia = NULL;
}
if(mLibvlcInstance != NULL)
{
libvlc_release(mLibvlcInstance);
mLibvlcInstance = NULL;
}
}
void LibvlcCamera::Initialise()
{
}
void LibvlcCamera::Terminate()
{
libvlc_media_player_stop(mLibvlcMediaPlayer);
if(mLibvlcData.buffer != NULL)
{
zm_freealigned(mLibvlcData.buffer);
}
if(mLibvlcData.prevBuffer != NULL)
{
zm_freealigned(mLibvlcData.prevBuffer);
}
}
int LibvlcCamera::PrimeCapture()
{
Info("Priming capture from %s", mPath.c_str());
mLibvlcInstance = libvlc_new (0, NULL);
if(mLibvlcInstance == NULL)
Fatal("Unable to create libvlc instance due to: %s", libvlc_errmsg());
mLibvlcMedia = libvlc_media_new_location(mLibvlcInstance, mPath.c_str());
if(mLibvlcMedia == NULL)
Fatal("Unable to open input %s due to: %s", mPath.c_str(), libvlc_errmsg());
mLibvlcMediaPlayer = libvlc_media_player_new_from_media(mLibvlcMedia);
if(mLibvlcMediaPlayer == NULL)
Fatal("Unable to create player for %s due to: %s", mPath.c_str(), libvlc_errmsg());
libvlc_video_set_format(mLibvlcMediaPlayer, mTargetChroma.c_str(), width, height, width * mBpp);
libvlc_video_set_callbacks(mLibvlcMediaPlayer, &LibvlcLockBuffer, &LibvlcUnlockBuffer, NULL, &mLibvlcData);
mLibvlcData.bufferSize = width * height * mBpp;
// Libvlc wants 32 byte alignment for images (should in theory do this for all image lines)
mLibvlcData.buffer = (uint8_t*)zm_mallocaligned(32, mLibvlcData.bufferSize);
mLibvlcData.prevBuffer = (uint8_t*)zm_mallocaligned(32, mLibvlcData.bufferSize);
mLibvlcData.newImage.setValueImmediate(false);
libvlc_media_player_play(mLibvlcMediaPlayer);
return(0);
}
int LibvlcCamera::PreCapture()
{
return(0);
}
// Should not return -1 as cancels capture. Always wait for image if available.
int LibvlcCamera::Capture( Image &image )
{
while(!mLibvlcData.newImage.getValueImmediate())
mLibvlcData.newImage.getUpdatedValue(1);
mLibvlcData.mutex.lock();
image.Assign(width, height, colours, subpixelorder, mLibvlcData.buffer, width * height * mBpp);
mLibvlcData.newImage.setValueImmediate(false);
mLibvlcData.mutex.unlock();
return (0);
}
int LibvlcCamera::PostCapture()
{
return(0);
}
#endif // HAVE_LIBVLC

73
src/zm_libvlc_camera.h Normal file
View File

@ -0,0 +1,73 @@
/*
* ZoneMinder Libvlc Camera Class Interface, $Date$, $Revision$
* 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_LIBVLC_CAMERA_H
#define ZM_LIBVLC_CAMERA_H
#include "zm_buffer.h"
#include "zm_camera.h"
#include "zm_thread.h"
#if HAVE_LIBVLC
#if HAVE_VLC_VLC_H
#include "vlc/vlc.h"
#endif
// Used by libvlc callbacks
struct LibvlcPrivateData
{
uint8_t* buffer;
uint8_t* prevBuffer;
time_t prevTime;
uint32_t bufferSize;
Mutex mutex;
ThreadData<bool> newImage;
};
class LibvlcCamera : public Camera
{
protected:
std::string mPath;
LibvlcPrivateData mLibvlcData;
std::string mTargetChroma;
uint8_t mBpp;
libvlc_instance_t *mLibvlcInstance;
libvlc_media_t *mLibvlcMedia;
libvlc_media_player_t *mLibvlcMediaPlayer;
public:
LibvlcCamera( int p_id, 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 );
~LibvlcCamera();
const std::string &Path() const { return( mPath ); }
void Initialise();
void Terminate();
int PrimeCapture();
int PreCapture();
int Capture( Image &image );
int PostCapture();
};
#endif // HAVE_LIBVLC
#endif // ZM_LIBVLC_CAMERA_H

View File

@ -41,6 +41,9 @@
#if HAVE_LIBAVFORMAT
#include "zm_ffmpeg_camera.h"
#endif // HAVE_LIBAVFORMAT
#if HAVE_LIBVLC
#include "zm_libvlc_camera.h"
#endif // HAVE_LIBVLC
#if ZM_MEM_MAPPED
#include <sys/mman.h>
@ -2651,6 +2654,25 @@ 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 == "Libvlc")
{
#if HAVE_LIBVLC
camera = new LibvlcCamera(
id,
path.c_str(),
cam_width,
cam_height,
colours,
brightness,
contrast,
hue,
colour,
purpose==CAPTURE
);
#else // HAVE_LIBVLC
Fatal( "You must have vlc libraries installed to use vlc cameras for monitor %d", id );
#endif // HAVE_LIBVLC
}
else
{

View File

@ -1,207 +0,0 @@
//
// ZoneMinder Video Device Fixer, $Date$, $Revision$
// 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <mysql/mysql.h>
#include "zm.h"
#include "zm_db.h"
// Determine if we are a member of the group
int inGroup( gid_t gid )
{
// Get how many groups we are in
int n_gids = getgroups( 0, NULL );
if ( n_gids < 0 )
{
Error( "getgroups:%s", strerror(errno) );
return( -1 );
}
// Not in any groups
if ( !n_gids )
{
return( 0 );
}
// Allocate space to hold groups
gid_t *gids = new gid_t[n_gids * sizeof(gid_t)];
if ( !gids )
{
Error( "Unable to allocate groups: %s", strerror(errno) );
return( -1 );
}
// Get list of groups
if ( getgroups( n_gids, gids ) != n_gids )
{
Error( "getgroups:%s", strerror(errno) );
delete[] gids;
return( -1 );
}
// See if gid in list of groups we belong to
int in_gid = 0;
for ( int i = 0; i < n_gids; i++ )
{
if ( gids[i] == gid )
{
in_gid = 1;
}
}
delete[] gids;
return( in_gid );
}
bool fixDevice( const char *device_path )
{
struct stat stat_buf;
if ( stat( device_path, &stat_buf ) < 0 )
{
Error( "Can't stat %s: %s", device_path, strerror(errno));
return( false );
}
uid_t uid = getuid();
gid_t gid = getgid();
int in_gid;
if ( (in_gid = inGroup( stat_buf.st_gid )) < 0 )
{
return( false );
}
mode_t mask = 0;
if ( uid == stat_buf.st_uid )
{
// If we are the owner
mask = 00600;
}
else if ( gid == stat_buf.st_gid || in_gid )
{
// If we are in the owner group
mask = 00060;
}
else
{
// We are neither the owner nor in the group
mask = 00006;
}
mode_t mode = stat_buf.st_mode;
if ( (mode & mask) == mask )
{
Debug( 1, "Permissions on %s are ok at %o", device_path, mode );
return( true );
}
mode |= mask;
Info( "Resetting permissions on %s to %o", device_path, mode );
if ( chmod( device_path, mode ) < 0 )
{
Error( "Can't chmod %s to %o: %s", device_path, mode, strerror(errno));
return( false );
}
return( true );
}
int main( int argc, char *argv[] )
{
self = argv[0];
zmLoadConfig();
logInit( "zmfix" );
logCapLevel( Logger::ERROR );
// Only do registered devices
static char sql[ZM_SQL_SML_BUFSIZ];
snprintf( sql, sizeof(sql), "select distinct Device from Monitors where not isnull(Device) and Type = 'Local'" );
if ( mysql_query( &dbconn, sql ) )
{
Error( "Can't run query: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
MYSQL_RES *result = mysql_store_result( &dbconn );
if ( !result )
{
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ )
{
fixDevice( dbrow[0] );
}
if ( mysql_errno( &dbconn ) )
{
Error( "Can't fetch row: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
// Yadda yadda
mysql_free_result( result );
snprintf( sql, sizeof(sql), "select distinct ControlDevice from Monitors where not isEmpty(ControlDevice)" );
if ( mysql_query( &dbconn, sql ) )
{
Error( "Can't run query: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
result = mysql_store_result( &dbconn );
if ( !result )
{
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ )
{
fixDevice( dbrow[0] );
}
if ( mysql_errno( &dbconn ) )
{
Error( "Can't fetch row: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
// Yadda yadda
mysql_free_result( result );
if ( config.opt_x10 )
{
if ( config.x10_device )
{
fixDevice( config.x10_device );
}
}
return( 0 );
}

View File

@ -554,7 +554,6 @@ if ( !empty($action) )
if ( $restart )
{
$monitor = dbFetchOne( "select * from Monitors where Id = '".dbEscape($mid)."'" );
fixDevices();
//if ( $cookies )
//session_write_close();
if ( daemonCheck() )

View File

@ -256,9 +256,9 @@ classid="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95"
codebase="http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=6,0,02,902"
standby="Loading Microsoft Windows Media Player components..."
type="<?= $mimeType ?>">
<param name="FileName" value="<?= $src ?>">
<param name="autoStart" value="1">
<param name="showControls" value="0">
<param name="FileName" value="<?= $src ?>"/>
<param name="autoStart" value="1"/>
<param name="showControls" value="0"/>
<embed type="<?= $mimeType ?>"
pluginspage="http://www.microsoft.com/Windows/MediaPlayer/"
src="<?= $src ?>"
@ -281,9 +281,9 @@ showcontrols="0">
classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
codebase="http://www.apple.com/qtactivex/qtplugin.cab"
type="<?= $mimeType ?>">
<param name="src" value="<?= $src ?>">
<param name="autoplay" VALUE="true">
<param name="controller" VALUE="false">
<param name="src" value="<?= $src ?>"/>
<param name="autoplay" VALUE="true"/>
<param name="controller" VALUE="false"/>
<embed type="<?= $mimeType ?>"
src="<?= $src ?>"
pluginspage="http://www.apple.com/quicktime/download/"
@ -291,7 +291,7 @@ name="<?= validHtmlStr($title) ?>"
width="<?= validInt($width) ?>"
height="<?= validInt($height) ?>"
autoplay="true"
controller="true"
controller="true">
</embed>
</object>
<?php
@ -305,9 +305,9 @@ controller="true"
classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"
type="<?= $mimeType ?>">
<param name="movie" value="<?= $src ?>">
<param name=quality value="high">
<param name=bgcolor value="#ffffff">
<param name="movie" value="<?= $src ?>"/>
<param name="quality" value="high"/>
<param name="bgcolor" value="#ffffff"/>
<embed type="<?= $mimeType ?>"
pluginspage="http://www.macromedia.com/go/getflashplayer"
src="<?= $src ?>"
@ -315,7 +315,7 @@ name="<?= validHtmlStr($title) ?>"
width="<?= validInt($width) ?>"
height="<?= validInt($height) ?>"
quality="high"
bgcolor="#ffffff"
bgcolor="#ffffff">
</embed>
</object>
<?php
@ -919,13 +919,6 @@ function canStream()
return( canStreamNative() | canStreamApplet() );
}
function fixDevices()
{
$string = ZM_PATH_BIN."/zmfix";
$string .= " 2>/dev/null >&- <&- >/dev/null";
exec( $string );
}
function packageControl( $command )
{
$string = ZM_PATH_BIN.'/zmpkg.pl '.escapeshellarg( $command );

View File

@ -376,6 +376,7 @@ $SLANG = array(
'Language' => 'Language',
'Last' => 'Last',
'Layout' => 'Layout',
'Libvlc' => 'Libvlc',
'LimitResultsPost' => 'results only', // This is used at the end of the phrase 'Limit to first N results only'
'LimitResultsPre' => 'Limit to first', // This is used at the beginning of the phrase 'Limit to first N results only'
'LinkedMonitors' => 'Linked Monitors',

View File

@ -308,6 +308,11 @@ foreach( $displayMonitors as $monitor )
<td class="colSource"><?= makePopupLink( '?view=monitor&amp;mid='.$monitor['Id'], 'zmMonitor'.$monitor['Id'], 'monitor', '<span class="'.$dclass.'">'.preg_replace( '/^.*\//', '', $monitor['Path'] ).'</span>', canEdit( 'Monitors' ) ) ?></td>
<?php } elseif ( $monitor['Type'] == "Ffmpeg" ) { ?>
<td class="colSource"><?= makePopupLink( '?view=monitor&amp;mid='.$monitor['Id'], 'zmMonitor'.$monitor['Id'], 'monitor', '<span class="'.$dclass.'">'.preg_replace( '/^.*\//', '', $monitor['Path'] ).'</span>', canEdit( 'Monitors' ) ) ?></td>
<?php } elseif ( $monitor['Type'] == "Libvlc" ) {
$domain = parse_url( $monitor['Path'], PHP_URL_HOST );
$shortpath = $domain ? $domain : preg_replace( '/^.*\//', '', $monitor['Path'] );
?>
<td class="colSource"><?= makePopupLink( '?view=monitor&amp;mid='.$monitor['Id'], 'zmMonitor'.$monitor['Id'], 'monitor', '<span class="'.$dclass.'">'.$shortpath.'</span>', canEdit( 'Monitors' ) ) ?></td>
<?php } else { ?>
<td class="colSource">&nbsp;</td>
<?php } ?>

View File

@ -345,7 +345,7 @@ switch ( $tab )
?>
<tr><th scope="row"><?= $SLANG['Name'] ?></th><td><input type="text" name="newControl[Name]" value="<?= validHtmlStr($newControl['Name']) ?>" size="24"/></td></tr>
<?php
$types = array( 'Local'=>$SLANG['Local'], 'Remote'=>$SLANG['Remote'], 'Ffmpeg'=>$SLANG['Ffmpeg'] );
$types = array( 'Local'=>$SLANG['Local'], 'Remote'=>$SLANG['Remote'], 'Ffmpeg'=>$SLANG['Ffmpeg'], 'Libvlc'=>$SLANG['Libvlc'] );
?>
<tr><th scope="row"><?= $SLANG['Type'] ?></th><td><?= buildSelect( "newControl[Type]", $types ); ?></td></tr>
<tr><th scope="row"><?= $SLANG['Protocol'] ?></th><td><input type="text" name="newControl[Protocol]" value="<?= validHtmlStr($newControl['Protocol']) ?>" size="24"/></td></tr>

View File

@ -179,6 +179,7 @@ $sourceTypes = array(
'Remote' => $SLANG['Remote'],
'File' => $SLANG['File'],
'Ffmpeg' => $SLANG['Ffmpeg'],
'Libvlc' => $SLANG['Libvlc'],
);
if ( !ZM_HAS_V4L )
unset($sourceTypes['Local']);
@ -519,7 +520,7 @@ if ( $tab != 'source' || ($newMonitor['Type'] != 'Local' && $newMonitor['Type']
<input type="hidden" name="newMonitor[Method]" value="<?= validHtmlStr($newMonitor['Method']) ?>"/>
<?php
}
if ( $tab != 'source' || ($newMonitor['Type'] != 'Remote' && $newMonitor['Type'] != 'File' && $newMonitor['Type'] != 'Ffmpeg') )
if ( $tab != 'source' || ($newMonitor['Type'] != 'Remote' && $newMonitor['Type'] != 'File' && $newMonitor['Type'] != 'Ffmpeg' && $newMonitor['Type'] != 'Libvlc') )
{
?>
<input type="hidden" name="newMonitor[Path]" value="<?= validHtmlStr($newMonitor['Path']) ?>"/>
@ -740,7 +741,7 @@ switch ( $tab )
<tr><td><?= $SLANG['RemoteHostPath'] ?></td><td><input type="text" name="newMonitor[Path]" value="<?= validHtmlStr($newMonitor['Path']) ?>" size="36"/></td></tr>
<?php
}
elseif ( $newMonitor['Type'] == "File" || $newMonitor['Type'] == "Ffmpeg" )
elseif ( $newMonitor['Type'] == "File" || $newMonitor['Type'] == "Ffmpeg" || $newMonitor['Type'] == "Libvlc" )
{
?>
<tr><td><?= $SLANG['SourcePath'] ?></td><td><input type="text" name="newMonitor[Path]" value="<?= validHtmlStr($newMonitor['Path']) ?>" size="36"/></td></tr>

View File

@ -54,6 +54,8 @@
#cmakedefine HAVE_LIBAVUTIL_MATHEMATICS_H 1
#cmakedefine HAVE_LIBSWSCALE 1
#cmakedefine HAVE_LIBSWSCALE_SWSCALE_H 1
#cmakedefine HAVE_LIBVLC 1
#cmakedefine HAVE_VLC_VLC_H 1
/* Authenication checks */
#cmakedefine HAVE_MD5_OPENSSL 1