add generic Option field to ffmpeg and libvlc cameras

pull/421/head
m-bene 2014-05-05 13:29:12 +02:00
parent 9fb794f4d0
commit ceff5a98ea
11 changed files with 114 additions and 31 deletions

View File

@ -157,7 +157,7 @@ PREPARE stmt FROM @s;
EXECUTE stmt;
--
-- Add Monitor Options field; used for specifying Ffmpeg AVoptions like rtsp_transport tcp
-- Add Monitor Options field; used for specifying Ffmpeg AVoptions like rtsp_transport http or libVLC options
--
SET @s = (SELECT IF(
(SELECT COUNT(*)

View File

@ -23,9 +23,10 @@
#include "zm_ffmpeg_camera.h"
FfmpegCamera::FfmpegCamera( 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 ) :
FfmpegCamera::FfmpegCamera( int p_id, const std::string &p_path, const std::string &p_options, 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, FFMPEG_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 )
mPath( p_path ),
mOptions( p_options )
{
if ( capture )
{
@ -110,12 +111,23 @@ void FfmpegCamera::Terminate()
int FfmpegCamera::PrimeCapture()
{
Info( "Priming capture from %s", mPath.c_str() );
// Open the input, not necessarily a file
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 4, 0)
if ( av_open_input_file( &mFormatContext, mPath.c_str(), NULL, 0, NULL ) !=0 )
#else
if ( avformat_open_input( &mFormatContext, mPath.c_str(), NULL, NULL ) !=0 )
// Handle options
AVDictionary *opts = 0;
StringVector opVect = split(Options(), ",");
for (int i=0; i<opVect.size(), i++)
{
StringVector parts = split(opVect[i],"=");
if (parts.size() > 1)
av_dict_set(&opts, trimSpaces(parts[0]), trimSpaces(parts[1]));
}
if ( avformat_open_input( &mFormatContext, mPath.c_str(), NULL, &opts ) !=0 )
#endif
Fatal( "Unable to open input %s due to: %s", mPath.c_str(), strerror(errno) );

View File

@ -34,6 +34,7 @@ class FfmpegCamera : public Camera
{
protected:
std::string mPath;
std::string mOptions;
int frameCount;
@ -52,10 +53,11 @@ protected:
#endif
public:
FfmpegCamera( 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 );
FfmpegCamera( int p_id, const std::string &path, const std::string &p_options, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture );
~FfmpegCamera();
const std::string &Path() const { return( mPath ); }
const std::string &Options() const { return( mOptions ); }
void Initialise();
void Terminate();

View File

@ -61,9 +61,10 @@ void LibvlcUnlockBuffer(void* opaque, void* picture, void *const *planes)
}
}
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 ) :
LibvlcCamera::LibvlcCamera( int p_id, const std::string &p_path, const std::string &p_options, 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 )
mPath( p_path ),
mOptions( p_options )
{
mLibvlcInstance = NULL;
mLibvlcMedia = NULL;
@ -115,6 +116,10 @@ LibvlcCamera::~LibvlcCamera()
libvlc_release(mLibvlcInstance);
mLibvlcInstance = NULL;
}
if (mOptArgV != NULL)
{
delete[] mOptArgV;
}
}
void LibvlcCamera::Initialise()
@ -137,8 +142,17 @@ void LibvlcCamera::Terminate()
int LibvlcCamera::PrimeCapture()
{
Info("Priming capture from %s", mPath.c_str());
mLibvlcInstance = libvlc_new (0, NULL);
StringVector opVect = split(Options(), ",");
if (opVect.size() > 0)
{
mOptArgV = new char*[opVect.size()];cmd
for (int i=0; i< opVect.size(); i++)
mOptArgV[i] = opVect[i].c_str();
}
mLibvlcInstance = libvlc_new (opVect.size(), optArgV);
if(mLibvlcInstance == NULL)
Fatal("Unable to create libvlc instance due to: %s", libvlc_errmsg());

View File

@ -45,7 +45,8 @@ class LibvlcCamera : public Camera
{
protected:
std::string mPath;
std::string mOptions;
unisgned char **mOptArgV;
LibvlcPrivateData mLibvlcData;
std::string mTargetChroma;
uint8_t mBpp;
@ -55,10 +56,11 @@ protected:
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( int p_id, const std::string &path, const std::string &p_options, 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 ); }
const std::string &Options() const { return( mOptions ); }
void Initialise();
void Terminate();

View File

@ -56,21 +56,6 @@
#endif // ZM_MEM_MAPPED
//=============================================================================
std::string trimSpaces(std::string str)
{
// Trim Both leading and trailing spaces
size_t startpos = str.find_first_not_of(" \t"); // Find the first character position after excluding leading blank spaces
size_t endpos = str.find_last_not_of(" \t"); // Find the first character position from reverse af
// if all spaces or empty return an empty string
if(( std::string::npos == startpos ) || ( std::string::npos == endpos))
{
return std::string("");
}
else
return str.substr( startpos, endpos-startpos+1 );
}
std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
std::stringstream ss(s);
@ -2306,11 +2291,11 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
static char sql[ZM_SQL_MED_BUFSIZ];
if ( !file[0] )
{
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Ffmpeg'", sizeof(sql) );
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Options, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Ffmpeg'", sizeof(sql) );
}
else
{
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Ffmpeg' and Path = '%s'", file );
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Options, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Ffmpeg' and Path = '%s'", file );
}
if ( mysql_query( &dbconn, sql ) )
{
@ -2339,6 +2324,7 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
const char *linked_monitors = dbrow[col]; col++;
const char *path = dbrow[col]; col++;
const char *options = dbrow[col]; col++;
int width = atoi(dbrow[col]); col++;
int height = atoi(dbrow[col]); col++;
@ -2379,6 +2365,7 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
Camera *camera = new FfmpegCamera(
id,
path, // File
options,
cam_width,
cam_height,
colours,
@ -2441,7 +2428,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, 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, MotionFrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, 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, Options, 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, MotionFrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Id = %d", id );
if ( mysql_query( &dbconn, sql ) )
{
Error( "Can't run query: %s", mysql_error( &dbconn ) );
@ -2477,6 +2464,7 @@ 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 options = dbrow[col]; col++;
std::string user = dbrow[col]; col++;
std::string pass = dbrow[col]; col++;
@ -2617,6 +2605,7 @@ Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose )
camera = new FfmpegCamera(
id,
path.c_str(),
options,
cam_width,
cam_height,
colours,
@ -2636,6 +2625,7 @@ Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose )
camera = new LibvlcCamera(
id,
path.c_str(),
options,
cam_width,
cam_height,
colours,

View File

@ -30,6 +30,7 @@
#include "zm_zone.h"
#include "zm_event.h"
#include "zm_camera.h"
#include "zm_utils.h"
#include "zm_image_analyser.h"

View File

@ -27,6 +27,36 @@
unsigned int sseversion = 0;
std::string trimSet(std::string str, std::string trimset) {
// Trim Both leading and trailing sets
size_t startpos = str.find_first_not_of(trimset); // Find the first character position after excluding leading blank spaces
size_t endpos = str.find_last_not_of(trimset); // Find the first character position from reverse af
// if all spaces or empty return an empty string
if(( std::string::npos == startpos ) || ( std::string::npos == endpos))
{
return std::string("");
}
else
return str.substr( startpos, endpos-startpos+1 );
}
std::string trimSpaces(std::string str)
{
return trimSet(str, " \t");
}
std::string replaceAll(std::string str, std::string from, std::string to) {
if(from.empty())
return str;
size_t start_pos = 0;
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
str.replace(start_pos, from.length(), to);
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
}
return str;
}
const std::string stringtf( const char *format, ... )
{
va_list ap;

View File

@ -27,6 +27,10 @@
typedef std::vector<std::string> StringVector;
std::string trimSpaces(std::string str);
std::string trimSet(std::string str, std::string trimset);
std::string replaceAll(std::string str, std::string from, std::string to);
const std::string stringtf( const char *format, ... );
const std::string stringtf( const std::string &format, ... );

View File

@ -63,6 +63,7 @@ else
'Method' => "",
'Host' => "",
'Path' => "",
'Options' => "",
'Port' => "80",
'User' => "",
'Pass' => "",
@ -506,6 +507,12 @@ if ( $tab != 'source' || ($newMonitor['Type'] != 'Local' && $newMonitor['Type']
<input type="hidden" name="newMonitor[Method]" value="<?= validHtmlStr($newMonitor['Method']) ?>"/>
<?php
}
if ( $tab != 'source' || ($newMonitor['Type'] != 'Ffmpeg' && $newMonitor['Type'] != 'Libvlc' ))
{
?>
<input type="hidden" name="newMonitor[Options]" value="<?= validHtmlStr($newMonitor['Options']) ?>"/>
<?php
}
if ( $tab != 'source' || ($newMonitor['Type'] != 'Remote' && $newMonitor['Type'] != 'File' && $newMonitor['Type'] != 'Ffmpeg' && $newMonitor['Type'] != 'Libvlc' && $newMonitor['Type'] != 'cURL') )
{
?>
@ -722,7 +729,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" || $newMonitor['Type'] == "Libvlc" )
elseif ( $newMonitor['Type'] == "File" )
{
?>
<tr><td><?= $SLANG['SourcePath'] ?></td><td><input type="text" name="newMonitor[Path]" value="<?= validHtmlStr($newMonitor['Path']) ?>" size="36"/></td></tr>
@ -734,6 +741,13 @@ switch ( $tab )
<tr><td><?= "URL" ?></td><td><input type="text" name="newMonitor[Path]" value="<?= validHtmlStr($newMonitor['Path']) ?>" size="36"/></td></tr>
<tr><td><?= "Username" ?></td><td><input type="text" name="newMonitor[User]" value="<?= validHtmlStr($newMonitor['User']) ?>" size="12"/></td></tr>
<tr><td><?= "Password" ?></td><td><input type="text" name="newMonitor[Pass]" value="<?= validHtmlStr($newMonitor['Pass']) ?>" size="12"/></td></tr>
<?php
}
elseif ( $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>
<tr><td><?= "Options" ?></td><td><input type="text" name="newMonitor[Options]" value="<?= validHtmlStr($newMonitor['Options']) ?>" size="36"/></td></tr>
<?php
}
?>

View File

@ -63,6 +63,7 @@ else
'Method' => "",
'Host' => "",
'Path' => "",
'Options' => "",
'Port' => "80",
'User' => "",
'Pass' => "",
@ -507,6 +508,12 @@ if ( $tab != 'source' || ($newMonitor['Type'] != 'Local' && $newMonitor['Type']
<input type="hidden" name="newMonitor[Method]" value="<?= validHtmlStr($newMonitor['Method']) ?>"/>
<?php
}
if ( $tab != 'source' || ($newMonitor['Type'] != 'Ffmpeg' && $newMonitor['Type'] != 'Libvlc' ))
{
?>
<input type="hidden" name="newMonitor[Options]" value="<?= validHtmlStr($newMonitor['Options']) ?>"/>
<?php
}
if ( $tab != 'source' || ($newMonitor['Type'] != 'Remote' && $newMonitor['Type'] != 'File' && $newMonitor['Type'] != 'Ffmpeg' && $newMonitor['Type'] != 'Libvlc' && $newMonitor['Type'] != 'cURL') )
{
?>
@ -723,7 +730,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" || $newMonitor['Type'] == "Libvlc" )
elseif ( $newMonitor['Type'] == "File" )
{
?>
<tr><td><?= $SLANG['SourcePath'] ?></td><td><input type="text" name="newMonitor[Path]" value="<?= validHtmlStr($newMonitor['Path']) ?>" size="36"/></td></tr>
@ -735,6 +742,13 @@ switch ( $tab )
<tr><td><?= "URL" ?></td><td><input type="text" name="newMonitor[Path]" value="<?= validHtmlStr($newMonitor['Path']) ?>" size="36"/></td></tr>
<tr><td><?= "Username" ?></td><td><input type="text" name="newMonitor[User]" value="<?= validHtmlStr($newMonitor['User']) ?>" size="12"/></td></tr>
<tr><td><?= "Password" ?></td><td><input type="text" name="newMonitor[Pass]" value="<?= validHtmlStr($newMonitor['Pass']) ?>" size="12"/></td></tr>
<?php
}
elseif ( $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>
<tr><td><?= "Options" ?></td><td><input type="text" name="newMonitor[Options]" value="<?= validHtmlStr($newMonitor['Options']) ?>" size="36"/></td></tr>
<?php
}
?>