Compare commits
4 Commits
1.36.12_he
...
fix_zms_pa
Author | SHA1 | Date |
---|---|---|
Isaac Connor | fcc507b93e | |
Isaac Connor | d63df84c98 | |
Isaac Connor | f23ee8441f | |
Isaac Connor | 2901043bc9 |
2378
src/zm_event.cpp
2378
src/zm_event.cpp
File diff suppressed because it is too large
Load Diff
293
src/zm_event.h
293
src/zm_event.h
|
@ -41,194 +41,193 @@
|
||||||
class Zone;
|
class Zone;
|
||||||
class Monitor;
|
class Monitor;
|
||||||
|
|
||||||
#define MAX_PRE_ALARM_FRAMES 16 // Maximum number of prealarm frames that can be stored
|
#define MAX_PRE_ALARM_FRAMES 16 // Maximum number of prealarm frames that can be stored
|
||||||
|
|
||||||
//
|
//
|
||||||
// Class describing events, i.e. captured periods of activity.
|
// Class describing events, i.e. captured periods of activity.
|
||||||
//
|
//
|
||||||
class Event
|
class Event
|
||||||
{
|
{
|
||||||
friend class EventStream;
|
friend class EventStream;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static bool initialised;
|
static bool initialised;
|
||||||
static char capture_file_format[PATH_MAX];
|
static char capture_file_format[PATH_MAX];
|
||||||
static char analyse_file_format[PATH_MAX];
|
static char analyse_file_format[PATH_MAX];
|
||||||
static char general_file_format[PATH_MAX];
|
static char general_file_format[PATH_MAX];
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static int sd;
|
static int sd;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::set<std::string> StringSet;
|
typedef std::set<std::string> StringSet;
|
||||||
typedef std::map<std::string,StringSet> StringSetMap;
|
typedef std::map<std::string,StringSet> StringSetMap;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef enum { NORMAL, BULK, ALARM } FrameType;
|
typedef enum { NORMAL, BULK, ALARM } FrameType;
|
||||||
|
|
||||||
struct PreAlarmData
|
struct PreAlarmData
|
||||||
{
|
{
|
||||||
Image *image;
|
Image *image;
|
||||||
struct timeval timestamp;
|
struct timeval timestamp;
|
||||||
unsigned int score;
|
unsigned int score;
|
||||||
Image *alarm_frame;
|
Image *alarm_frame;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int pre_alarm_count;
|
static int pre_alarm_count;
|
||||||
static PreAlarmData pre_alarm_data[MAX_PRE_ALARM_FRAMES];
|
static PreAlarmData pre_alarm_data[MAX_PRE_ALARM_FRAMES];
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
unsigned int id;
|
unsigned int id;
|
||||||
Monitor *monitor;
|
Monitor *monitor;
|
||||||
struct timeval start_time;
|
struct timeval start_time;
|
||||||
struct timeval end_time;
|
struct timeval end_time;
|
||||||
std::string cause;
|
std::string cause;
|
||||||
StringSetMap noteSetMap;
|
StringSetMap noteSetMap;
|
||||||
int frames;
|
int frames;
|
||||||
int alarm_frames;
|
int alarm_frames;
|
||||||
unsigned int tot_score;
|
unsigned int tot_score;
|
||||||
unsigned int max_score;
|
unsigned int max_score;
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int last_db_frame;
|
int last_db_frame;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void Initialise()
|
static void Initialise()
|
||||||
{
|
{
|
||||||
if ( initialised )
|
if ( initialised )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
snprintf( capture_file_format, sizeof(capture_file_format), "%%s/%%0%dd-capture.jpg", config.event_image_digits );
|
snprintf( capture_file_format, sizeof(capture_file_format), "%%s/%%0%dd-capture.jpg", config.event_image_digits );
|
||||||
snprintf( analyse_file_format, sizeof(analyse_file_format), "%%s/%%0%dd-analyse.jpg", config.event_image_digits );
|
snprintf( analyse_file_format, sizeof(analyse_file_format), "%%s/%%0%dd-analyse.jpg", config.event_image_digits );
|
||||||
snprintf( general_file_format, sizeof(general_file_format), "%%s/%%0%dd-%%s", config.event_image_digits );
|
snprintf( general_file_format, sizeof(general_file_format), "%%s/%%0%dd-%%s", config.event_image_digits );
|
||||||
|
|
||||||
initialised = true;
|
initialised = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void createNotes( std::string ¬es );
|
void createNotes( std::string ¬es );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static bool OpenFrameSocket( int );
|
static bool OpenFrameSocket( int );
|
||||||
static bool ValidateFrameSocket( int );
|
static bool ValidateFrameSocket( int );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Event( Monitor *p_monitor, struct timeval p_start_time, const std::string &p_cause, const StringSetMap &p_noteSetMap );
|
Event( Monitor *p_monitor, struct timeval p_start_time, const std::string &p_cause, const StringSetMap &p_noteSetMap );
|
||||||
~Event();
|
~Event();
|
||||||
|
|
||||||
int Id() const { return( id ); }
|
int Id() const { return( id ); }
|
||||||
const std::string &Cause() { return( cause ); }
|
const std::string &Cause() { return( cause ); }
|
||||||
int Frames() const { return( frames ); }
|
int Frames() const { return( frames ); }
|
||||||
int AlarmFrames() const { return( alarm_frames ); }
|
int AlarmFrames() const { return( alarm_frames ); }
|
||||||
|
|
||||||
const struct timeval &StartTime() const { return( start_time ); }
|
const struct timeval &StartTime() const { return( start_time ); }
|
||||||
const struct timeval &EndTime() const { return( end_time ); }
|
const struct timeval &EndTime() const { return( end_time ); }
|
||||||
struct timeval &EndTime() { return( end_time ); }
|
struct timeval &EndTime() { return( end_time ); }
|
||||||
|
|
||||||
bool SendFrameImage( const Image *image, bool alarm_frame=false );
|
bool SendFrameImage( const Image *image, bool alarm_frame=false );
|
||||||
bool WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame=false );
|
bool WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame=false );
|
||||||
|
|
||||||
void updateNotes( const StringSetMap &stringSetMap );
|
void updateNotes( const StringSetMap &stringSetMap );
|
||||||
|
|
||||||
void AddFrames( int n_frames, Image **images, struct timeval **timestamps );
|
void AddFrames( int n_frames, Image **images, struct timeval **timestamps );
|
||||||
void AddFrame( Image *image, struct timeval timestamp, int score=0, Image *alarm_frame=NULL );
|
void AddFrame( Image *image, struct timeval timestamp, int score=0, Image *alarm_frame=NULL );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void AddFramesInternal( int n_frames, int start_frame, Image **images, struct timeval **timestamps );
|
void AddFramesInternal( int n_frames, int start_frame, Image **images, struct timeval **timestamps );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const char *getSubPath( struct tm *time )
|
static const char *getSubPath( struct tm *time )
|
||||||
|
{
|
||||||
|
static char subpath[PATH_MAX] = "";
|
||||||
|
snprintf( subpath, sizeof(subpath), "%02d/%02d/%02d/%02d/%02d/%02d", time->tm_year-100, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec );
|
||||||
|
return( subpath );
|
||||||
|
}
|
||||||
|
static const char *getSubPath( time_t *time )
|
||||||
|
{
|
||||||
|
return( Event::getSubPath( localtime( time ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static int PreAlarmCount()
|
||||||
|
{
|
||||||
|
return( pre_alarm_count );
|
||||||
|
}
|
||||||
|
static void EmptyPreAlarmFrames()
|
||||||
|
{
|
||||||
|
if ( pre_alarm_count > 0 )
|
||||||
{
|
{
|
||||||
static char subpath[PATH_MAX] = "";
|
for ( int i = 0; i < MAX_PRE_ALARM_FRAMES; i++ )
|
||||||
snprintf( subpath, sizeof(subpath), "%02d/%02d/%02d/%02d/%02d/%02d", time->tm_year-100, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec );
|
{
|
||||||
return( subpath );
|
delete pre_alarm_data[i].image;
|
||||||
|
delete pre_alarm_data[i].alarm_frame;
|
||||||
|
}
|
||||||
|
memset( pre_alarm_data, 0, sizeof(pre_alarm_data) );
|
||||||
}
|
}
|
||||||
static const char *getSubPath( time_t *time )
|
pre_alarm_count = 0;
|
||||||
|
}
|
||||||
|
static void AddPreAlarmFrame( Image *image, struct timeval timestamp, int score=0, Image *alarm_frame=NULL )
|
||||||
|
{
|
||||||
|
pre_alarm_data[pre_alarm_count].image = new Image( *image );
|
||||||
|
pre_alarm_data[pre_alarm_count].timestamp = timestamp;
|
||||||
|
pre_alarm_data[pre_alarm_count].score = score;
|
||||||
|
if ( alarm_frame )
|
||||||
{
|
{
|
||||||
return( Event::getSubPath( localtime( time ) ) );
|
pre_alarm_data[pre_alarm_count].alarm_frame = new Image( *alarm_frame );
|
||||||
}
|
}
|
||||||
|
pre_alarm_count++;
|
||||||
public:
|
}
|
||||||
static int PreAlarmCount()
|
void SavePreAlarmFrames()
|
||||||
{
|
{
|
||||||
return( pre_alarm_count );
|
for ( int i = 0; i < pre_alarm_count; i++ )
|
||||||
}
|
{
|
||||||
static void EmptyPreAlarmFrames()
|
AddFrame( pre_alarm_data[i].image, pre_alarm_data[i].timestamp, pre_alarm_data[i].score, pre_alarm_data[i].alarm_frame );
|
||||||
{
|
}
|
||||||
if ( pre_alarm_count > 0 )
|
EmptyPreAlarmFrames();
|
||||||
{
|
}
|
||||||
for ( int i = 0; i < MAX_PRE_ALARM_FRAMES; i++ )
|
|
||||||
{
|
|
||||||
delete pre_alarm_data[i].image;
|
|
||||||
delete pre_alarm_data[i].alarm_frame;
|
|
||||||
}
|
|
||||||
memset( pre_alarm_data, 0, sizeof(pre_alarm_data) );
|
|
||||||
}
|
|
||||||
pre_alarm_count = 0;
|
|
||||||
}
|
|
||||||
static void AddPreAlarmFrame( Image *image, struct timeval timestamp, int score=0, Image *alarm_frame=NULL )
|
|
||||||
{
|
|
||||||
pre_alarm_data[pre_alarm_count].image = new Image( *image );
|
|
||||||
pre_alarm_data[pre_alarm_count].timestamp = timestamp;
|
|
||||||
pre_alarm_data[pre_alarm_count].score = score;
|
|
||||||
if ( alarm_frame )
|
|
||||||
{
|
|
||||||
pre_alarm_data[pre_alarm_count].alarm_frame = new Image( *alarm_frame );
|
|
||||||
}
|
|
||||||
pre_alarm_count++;
|
|
||||||
}
|
|
||||||
void SavePreAlarmFrames()
|
|
||||||
{
|
|
||||||
for ( int i = 0; i < pre_alarm_count; i++ )
|
|
||||||
{
|
|
||||||
AddFrame( pre_alarm_data[i].image, pre_alarm_data[i].timestamp, pre_alarm_data[i].score, pre_alarm_data[i].alarm_frame );
|
|
||||||
}
|
|
||||||
EmptyPreAlarmFrames();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class EventStream : public StreamBase
|
class EventStream : public StreamBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef enum { MODE_SINGLE, MODE_ALL, MODE_ALL_GAPLESS } StreamMode;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct FrameData {
|
struct FrameData {
|
||||||
//unsigned long id;
|
//unsigned long id;
|
||||||
time_t timestamp;
|
time_t timestamp;
|
||||||
time_t offset;
|
time_t offset;
|
||||||
double delta;
|
double delta;
|
||||||
bool in_db;
|
bool in_db;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EventData
|
struct EventData
|
||||||
{
|
{
|
||||||
unsigned long event_id;
|
unsigned long event_id;
|
||||||
unsigned long monitor_id;
|
unsigned long monitor_id;
|
||||||
unsigned long frame_count;
|
unsigned long frame_count;
|
||||||
time_t start_time;
|
time_t start_time;
|
||||||
double duration;
|
double duration;
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
int n_frames;
|
int n_frames;
|
||||||
FrameData *frames;
|
FrameData *frames;
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static const int STREAM_PAUSE_WAIT = 250000; // Microseconds
|
static const int STREAM_PAUSE_WAIT = 250000; // Microseconds
|
||||||
|
|
||||||
static const StreamMode DEFAULT_MODE = MODE_SINGLE;
|
static const StreamMode DEFAULT_MODE = SINGLE;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
StreamMode mode;
|
StreamMode mode;
|
||||||
bool forceEventChange;
|
bool forceEventChange;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int curr_frame_id;
|
int curr_frame_id;
|
||||||
double curr_stream_time;
|
double curr_stream_time;
|
||||||
|
|
||||||
EventData *event_data;
|
EventData *event_data;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool loadEventData( int event_id );
|
bool loadEventData( int event_id );
|
||||||
bool loadInitialEventData( int init_event_id, int init_frame_id );
|
bool loadInitialEventData( int init_event_id, int init_frame_id );
|
||||||
bool loadInitialEventData( int monitor_id, time_t event_time );
|
bool loadInitialEventData( int monitor_id, time_t event_time );
|
||||||
|
@ -237,31 +236,31 @@ protected:
|
||||||
void processCommand( const CmdMsg *msg );
|
void processCommand( const CmdMsg *msg );
|
||||||
bool sendFrame( int delta_us );
|
bool sendFrame( int delta_us );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EventStream()
|
EventStream()
|
||||||
{
|
{
|
||||||
mode = DEFAULT_MODE;
|
mode = DEFAULT_MODE;
|
||||||
|
|
||||||
forceEventChange = false;
|
forceEventChange = false;
|
||||||
|
|
||||||
curr_frame_id = 0;
|
curr_frame_id = 0;
|
||||||
curr_stream_time = 0.0;
|
curr_stream_time = 0.0;
|
||||||
|
|
||||||
event_data = 0;
|
event_data = 0;
|
||||||
}
|
}
|
||||||
void setStreamStart( int init_event_id, int init_frame_id=0 )
|
void setStreamStart( int init_event_id, int init_frame_id=0 )
|
||||||
{
|
{
|
||||||
loadInitialEventData( init_event_id, init_frame_id );
|
loadInitialEventData( init_event_id, init_frame_id );
|
||||||
loadMonitor( event_data->monitor_id );
|
loadMonitor( event_data->monitor_id );
|
||||||
}
|
}
|
||||||
void setStreamStart( int monitor_id, time_t event_time )
|
void setStreamStart( int monitor_id, time_t event_time )
|
||||||
{
|
{
|
||||||
loadInitialEventData( monitor_id, event_time );
|
loadInitialEventData( monitor_id, event_time );
|
||||||
loadMonitor( monitor_id );
|
loadMonitor( monitor_id );
|
||||||
}
|
}
|
||||||
void setStreamMode( StreamMode p_mode )
|
void setStreamMode( StreamMode p_mode )
|
||||||
{
|
{
|
||||||
mode = p_mode;
|
mode = p_mode;
|
||||||
}
|
}
|
||||||
void runStream();
|
void runStream();
|
||||||
};
|
};
|
||||||
|
|
7124
src/zm_monitor.cpp
7124
src/zm_monitor.cpp
File diff suppressed because it is too large
Load Diff
|
@ -28,299 +28,299 @@
|
||||||
StreamBase::~StreamBase()
|
StreamBase::~StreamBase()
|
||||||
{
|
{
|
||||||
#if HAVE_LIBAVCODEC
|
#if HAVE_LIBAVCODEC
|
||||||
if ( vid_stream )
|
if ( vid_stream )
|
||||||
{
|
{
|
||||||
delete vid_stream;
|
delete vid_stream;
|
||||||
vid_stream = NULL;
|
vid_stream = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
closeComms();
|
closeComms();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StreamBase::loadMonitor( int monitor_id )
|
bool StreamBase::loadMonitor( int monitor_id )
|
||||||
{
|
{
|
||||||
if ( !(monitor = Monitor::Load( monitor_id, false, Monitor::QUERY )) )
|
if ( !(monitor = Monitor::Load( monitor_id, false, Monitor::QUERY )) )
|
||||||
{
|
{
|
||||||
Fatal( "Unable to load monitor id %d for streaming", monitor_id );
|
Fatal( "Unable to load monitor id %d for streaming", monitor_id );
|
||||||
return( false );
|
return( false );
|
||||||
}
|
}
|
||||||
monitor->connect();
|
monitor->connect();
|
||||||
return( true );
|
return( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StreamBase::checkInitialised()
|
bool StreamBase::checkInitialised()
|
||||||
{
|
{
|
||||||
if ( !monitor )
|
if ( !monitor )
|
||||||
{
|
{
|
||||||
Fatal( "Cannot stream, not initialised" );
|
Fatal( "Cannot stream, not initialised" );
|
||||||
return( false );
|
return( false );
|
||||||
}
|
}
|
||||||
return( true );
|
return( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamBase::updateFrameRate( double fps )
|
void StreamBase::updateFrameRate( double fps )
|
||||||
{
|
{
|
||||||
base_fps = fps;
|
base_fps = fps;
|
||||||
effective_fps = (base_fps*abs(replay_rate))/ZM_RATE_BASE;
|
effective_fps = (base_fps*abs(replay_rate))/ZM_RATE_BASE;
|
||||||
frame_mod = 1;
|
frame_mod = 1;
|
||||||
Debug( 3, "FPS:%.2f, MXFPS:%.2f, BFPS:%.2f, EFPS:%.2f, FM:%d", fps, maxfps, base_fps, effective_fps, frame_mod );
|
Debug( 3, "FPS:%.2f, MXFPS:%.2f, BFPS:%.2f, EFPS:%.2f, FM:%d", fps, maxfps, base_fps, effective_fps, frame_mod );
|
||||||
// Min frame repeat?
|
// Min frame repeat?
|
||||||
while( effective_fps > maxfps )
|
while( effective_fps > maxfps )
|
||||||
{
|
{
|
||||||
effective_fps /= 2.0;
|
effective_fps /= 2.0;
|
||||||
frame_mod *= 2;
|
frame_mod *= 2;
|
||||||
}
|
}
|
||||||
Debug( 3, "aEFPS:%.2f, aFM:%d", effective_fps, frame_mod );
|
Debug( 3, "aEFPS:%.2f, aFM:%d", effective_fps, frame_mod );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StreamBase::checkCommandQueue()
|
bool StreamBase::checkCommandQueue()
|
||||||
{
|
{
|
||||||
if ( sd >= 0 )
|
if ( sd >= 0 )
|
||||||
|
{
|
||||||
|
CmdMsg msg;
|
||||||
|
memset( &msg, 0, sizeof(msg) );
|
||||||
|
int nbytes = recvfrom( sd, &msg, sizeof(msg), MSG_DONTWAIT, 0, 0 );
|
||||||
|
if ( nbytes < 0 )
|
||||||
{
|
{
|
||||||
CmdMsg msg;
|
if ( errno != EAGAIN )
|
||||||
memset( &msg, 0, sizeof(msg) );
|
{
|
||||||
int nbytes = recvfrom( sd, &msg, sizeof(msg), MSG_DONTWAIT, 0, 0 );
|
Fatal( "recvfrom(), errno = %d, error = %s", errno, strerror(errno) );
|
||||||
if ( nbytes < 0 )
|
}
|
||||||
{
|
|
||||||
if ( errno != EAGAIN )
|
|
||||||
{
|
|
||||||
Fatal( "recvfrom(), errno = %d, error = %s", errno, strerror(errno) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//else if ( (nbytes != sizeof(msg)) )
|
|
||||||
//{
|
|
||||||
//Error( "Partial message received, expected %d bytes, got %d", sizeof(msg), nbytes );
|
|
||||||
//}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
processCommand( &msg );
|
|
||||||
return( true );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return( false );
|
//else if ( (nbytes != sizeof(msg)) )
|
||||||
|
//{
|
||||||
|
//Error( "Partial message received, expected %d bytes, got %d", sizeof(msg), nbytes );
|
||||||
|
//}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
processCommand( &msg );
|
||||||
|
return( true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
Image *StreamBase::prepareImage( Image *image )
|
Image *StreamBase::prepareImage( Image *image )
|
||||||
{
|
{
|
||||||
static int last_scale = 0;
|
static int last_scale = 0;
|
||||||
static int last_zoom = 0;
|
static int last_zoom = 0;
|
||||||
static int last_x = 0;
|
static int last_x = 0;
|
||||||
static int last_y = 0;
|
static int last_y = 0;
|
||||||
|
|
||||||
if ( !last_scale )
|
if ( !last_scale )
|
||||||
last_scale = scale;
|
|
||||||
if ( !last_zoom )
|
|
||||||
last_zoom = zoom;
|
|
||||||
|
|
||||||
// Do not bother to scale zoomed in images, just crop them and let the browser scale
|
|
||||||
// Works in FF2 but breaks FF3 which doesn't like image sizes changing in mid stream.
|
|
||||||
bool optimisedScaling = false;
|
|
||||||
|
|
||||||
bool image_copied = false;
|
|
||||||
|
|
||||||
int mag = (scale * zoom) / ZM_SCALE_BASE;
|
|
||||||
int act_mag = optimisedScaling?(mag > ZM_SCALE_BASE?ZM_SCALE_BASE:mag):mag;
|
|
||||||
Debug( 3, "Scaling by %d, zooming by %d = magnifying by %d(%d)", scale, zoom, mag, act_mag );
|
|
||||||
|
|
||||||
int last_mag = (last_scale * last_zoom) / ZM_SCALE_BASE;
|
|
||||||
int last_act_mag = last_mag > ZM_SCALE_BASE?ZM_SCALE_BASE:last_mag;
|
|
||||||
Debug( 3, "Last scaling by %d, zooming by %d = magnifying by %d(%d)", last_scale, last_zoom, last_mag, last_act_mag );
|
|
||||||
|
|
||||||
int base_image_width = image->Width(), base_image_height = image->Height();
|
|
||||||
Debug( 3, "Base image width = %d, height = %d", base_image_width, base_image_height );
|
|
||||||
|
|
||||||
int virt_image_width = (base_image_width * mag) / ZM_SCALE_BASE, virt_image_height = (base_image_height * mag) / ZM_SCALE_BASE;
|
|
||||||
Debug( 3, "Virtual image width = %d, height = %d", virt_image_width, virt_image_height );
|
|
||||||
|
|
||||||
int last_virt_image_width = (base_image_width * last_mag) / ZM_SCALE_BASE, last_virt_image_height = (base_image_height * last_mag) / ZM_SCALE_BASE;
|
|
||||||
Debug( 3, "Last virtual image width = %d, height = %d", last_virt_image_width, last_virt_image_height );
|
|
||||||
|
|
||||||
int act_image_width = (base_image_width * act_mag ) / ZM_SCALE_BASE, act_image_height = (base_image_height * act_mag ) / ZM_SCALE_BASE;
|
|
||||||
Debug( 3, "Actual image width = %d, height = %d", act_image_width, act_image_height );
|
|
||||||
|
|
||||||
int last_act_image_width = (base_image_width * last_act_mag ) / ZM_SCALE_BASE, last_act_image_height = (base_image_height * last_act_mag ) / ZM_SCALE_BASE;
|
|
||||||
Debug( 3, "Last actual image width = %d, height = %d", last_act_image_width, last_act_image_height );
|
|
||||||
|
|
||||||
int disp_image_width = (image->Width() * scale) / ZM_SCALE_BASE, disp_image_height = (image->Height() * scale) / ZM_SCALE_BASE;
|
|
||||||
Debug( 3, "Display image width = %d, height = %d", disp_image_width, disp_image_height );
|
|
||||||
|
|
||||||
int last_disp_image_width = (image->Width() * last_scale) / ZM_SCALE_BASE, last_disp_image_height = (image->Height() * last_scale) / ZM_SCALE_BASE;
|
|
||||||
Debug( 3, "Last display image width = %d, height = %d", last_disp_image_width, last_disp_image_height );
|
|
||||||
|
|
||||||
int send_image_width = (disp_image_width * act_mag ) / mag, send_image_height = (disp_image_height * act_mag ) / mag;
|
|
||||||
Debug( 3, "Send image width = %d, height = %d", send_image_width, send_image_height );
|
|
||||||
|
|
||||||
int last_send_image_width = (last_disp_image_width * last_act_mag ) / last_mag, last_send_image_height = (last_disp_image_height * last_act_mag ) / last_mag;
|
|
||||||
Debug( 3, "Last send image width = %d, height = %d", last_send_image_width, last_send_image_height );
|
|
||||||
|
|
||||||
if ( mag != ZM_SCALE_BASE )
|
|
||||||
{
|
|
||||||
if ( act_mag != ZM_SCALE_BASE )
|
|
||||||
{
|
|
||||||
Debug( 3, "Magnifying by %d", mag );
|
|
||||||
if ( !image_copied )
|
|
||||||
{
|
|
||||||
static Image copy_image;
|
|
||||||
copy_image.Assign( *image );
|
|
||||||
image = ©_image;
|
|
||||||
image_copied = true;
|
|
||||||
}
|
|
||||||
image->Scale( mag );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug( 3, "Real image width = %d, height = %d", image->Width(), image->Height() );
|
|
||||||
|
|
||||||
if ( disp_image_width < virt_image_width || disp_image_height < virt_image_height )
|
|
||||||
{
|
|
||||||
static Box last_crop;
|
|
||||||
|
|
||||||
if ( mag != last_mag || x != last_x || y != last_y )
|
|
||||||
{
|
|
||||||
Debug( 3, "Got click at %d,%d x %d", x, y, mag );
|
|
||||||
|
|
||||||
//if ( !last_mag )
|
|
||||||
//last_mag = mag;
|
|
||||||
|
|
||||||
if ( !(last_disp_image_width < last_virt_image_width || last_disp_image_height < last_virt_image_height) )
|
|
||||||
last_crop = Box();
|
|
||||||
|
|
||||||
Debug( 3, "Recalculating crop" );
|
|
||||||
// Recalculate crop parameters, as %ges
|
|
||||||
int click_x = (last_crop.LoX() * 100 ) / last_act_image_width; // Initial crop offset from last image
|
|
||||||
click_x += ( x * 100 ) / last_virt_image_width;
|
|
||||||
int click_y = (last_crop.LoY() * 100 ) / last_act_image_height; // Initial crop offset from last image
|
|
||||||
click_y += ( y * 100 ) / last_virt_image_height;
|
|
||||||
Debug( 3, "Got adjusted click at %d%%,%d%%", click_x, click_y );
|
|
||||||
|
|
||||||
// Convert the click locations to the current image pixels
|
|
||||||
click_x = ( click_x * act_image_width ) / 100;
|
|
||||||
click_y = ( click_y * act_image_height ) / 100;
|
|
||||||
Debug( 3, "Got readjusted click at %d,%d", click_x, click_y );
|
|
||||||
|
|
||||||
int lo_x = click_x - (send_image_width/2);
|
|
||||||
if ( lo_x < 0 )
|
|
||||||
lo_x = 0;
|
|
||||||
int hi_x = lo_x + (send_image_width-1);
|
|
||||||
if ( hi_x >= act_image_width )
|
|
||||||
{
|
|
||||||
hi_x = act_image_width - 1;
|
|
||||||
lo_x = hi_x - (send_image_width - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int lo_y = click_y - (send_image_height/2);
|
|
||||||
if ( lo_y < 0 )
|
|
||||||
lo_y = 0;
|
|
||||||
int hi_y = lo_y + (send_image_height-1);
|
|
||||||
if ( hi_y >= act_image_height )
|
|
||||||
{
|
|
||||||
hi_y = act_image_height - 1;
|
|
||||||
lo_y = hi_y - (send_image_height - 1);
|
|
||||||
}
|
|
||||||
last_crop = Box( lo_x, lo_y, hi_x, hi_y );
|
|
||||||
}
|
|
||||||
Debug( 3, "Cropping to %d,%d -> %d,%d", last_crop.LoX(), last_crop.LoY(), last_crop.HiX(), last_crop.HiY() );
|
|
||||||
if ( !image_copied )
|
|
||||||
{
|
|
||||||
static Image copy_image;
|
|
||||||
copy_image.Assign( *image );
|
|
||||||
image = ©_image;
|
|
||||||
image_copied = true;
|
|
||||||
}
|
|
||||||
image->Crop( last_crop );
|
|
||||||
}
|
|
||||||
last_scale = scale;
|
last_scale = scale;
|
||||||
|
if ( !last_zoom )
|
||||||
last_zoom = zoom;
|
last_zoom = zoom;
|
||||||
last_x = x;
|
|
||||||
last_y = y;
|
|
||||||
|
|
||||||
return( image );
|
// Do not bother to scale zoomed in images, just crop them and let the browser scale
|
||||||
|
// Works in FF2 but breaks FF3 which doesn't like image sizes changing in mid stream.
|
||||||
|
bool optimisedScaling = false;
|
||||||
|
|
||||||
|
bool image_copied = false;
|
||||||
|
|
||||||
|
int mag = (scale * zoom) / ZM_SCALE_BASE;
|
||||||
|
int act_mag = optimisedScaling?(mag > ZM_SCALE_BASE?ZM_SCALE_BASE:mag):mag;
|
||||||
|
Debug( 3, "Scaling by %d, zooming by %d = magnifying by %d(%d)", scale, zoom, mag, act_mag );
|
||||||
|
|
||||||
|
int last_mag = (last_scale * last_zoom) / ZM_SCALE_BASE;
|
||||||
|
int last_act_mag = last_mag > ZM_SCALE_BASE?ZM_SCALE_BASE:last_mag;
|
||||||
|
Debug( 3, "Last scaling by %d, zooming by %d = magnifying by %d(%d)", last_scale, last_zoom, last_mag, last_act_mag );
|
||||||
|
|
||||||
|
int base_image_width = image->Width(), base_image_height = image->Height();
|
||||||
|
Debug( 3, "Base image width = %d, height = %d", base_image_width, base_image_height );
|
||||||
|
|
||||||
|
int virt_image_width = (base_image_width * mag) / ZM_SCALE_BASE, virt_image_height = (base_image_height * mag) / ZM_SCALE_BASE;
|
||||||
|
Debug( 3, "Virtual image width = %d, height = %d", virt_image_width, virt_image_height );
|
||||||
|
|
||||||
|
int last_virt_image_width = (base_image_width * last_mag) / ZM_SCALE_BASE, last_virt_image_height = (base_image_height * last_mag) / ZM_SCALE_BASE;
|
||||||
|
Debug( 3, "Last virtual image width = %d, height = %d", last_virt_image_width, last_virt_image_height );
|
||||||
|
|
||||||
|
int act_image_width = (base_image_width * act_mag ) / ZM_SCALE_BASE, act_image_height = (base_image_height * act_mag ) / ZM_SCALE_BASE;
|
||||||
|
Debug( 3, "Actual image width = %d, height = %d", act_image_width, act_image_height );
|
||||||
|
|
||||||
|
int last_act_image_width = (base_image_width * last_act_mag ) / ZM_SCALE_BASE, last_act_image_height = (base_image_height * last_act_mag ) / ZM_SCALE_BASE;
|
||||||
|
Debug( 3, "Last actual image width = %d, height = %d", last_act_image_width, last_act_image_height );
|
||||||
|
|
||||||
|
int disp_image_width = (image->Width() * scale) / ZM_SCALE_BASE, disp_image_height = (image->Height() * scale) / ZM_SCALE_BASE;
|
||||||
|
Debug( 3, "Display image width = %d, height = %d", disp_image_width, disp_image_height );
|
||||||
|
|
||||||
|
int last_disp_image_width = (image->Width() * last_scale) / ZM_SCALE_BASE, last_disp_image_height = (image->Height() * last_scale) / ZM_SCALE_BASE;
|
||||||
|
Debug( 3, "Last display image width = %d, height = %d", last_disp_image_width, last_disp_image_height );
|
||||||
|
|
||||||
|
int send_image_width = (disp_image_width * act_mag ) / mag, send_image_height = (disp_image_height * act_mag ) / mag;
|
||||||
|
Debug( 3, "Send image width = %d, height = %d", send_image_width, send_image_height );
|
||||||
|
|
||||||
|
int last_send_image_width = (last_disp_image_width * last_act_mag ) / last_mag, last_send_image_height = (last_disp_image_height * last_act_mag ) / last_mag;
|
||||||
|
Debug( 3, "Last send image width = %d, height = %d", last_send_image_width, last_send_image_height );
|
||||||
|
|
||||||
|
if ( mag != ZM_SCALE_BASE )
|
||||||
|
{
|
||||||
|
if ( act_mag != ZM_SCALE_BASE )
|
||||||
|
{
|
||||||
|
Debug( 3, "Magnifying by %d", mag );
|
||||||
|
if ( !image_copied )
|
||||||
|
{
|
||||||
|
static Image copy_image;
|
||||||
|
copy_image.Assign( *image );
|
||||||
|
image = ©_image;
|
||||||
|
image_copied = true;
|
||||||
|
}
|
||||||
|
image->Scale( mag );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug( 3, "Real image width = %d, height = %d", image->Width(), image->Height() );
|
||||||
|
|
||||||
|
if ( disp_image_width < virt_image_width || disp_image_height < virt_image_height )
|
||||||
|
{
|
||||||
|
static Box last_crop;
|
||||||
|
|
||||||
|
if ( mag != last_mag || x != last_x || y != last_y )
|
||||||
|
{
|
||||||
|
Debug( 3, "Got click at %d,%d x %d", x, y, mag );
|
||||||
|
|
||||||
|
//if ( !last_mag )
|
||||||
|
//last_mag = mag;
|
||||||
|
|
||||||
|
if ( !(last_disp_image_width < last_virt_image_width || last_disp_image_height < last_virt_image_height) )
|
||||||
|
last_crop = Box();
|
||||||
|
|
||||||
|
Debug( 3, "Recalculating crop" );
|
||||||
|
// Recalculate crop parameters, as %ges
|
||||||
|
int click_x = (last_crop.LoX() * 100 ) / last_act_image_width; // Initial crop offset from last image
|
||||||
|
click_x += ( x * 100 ) / last_virt_image_width;
|
||||||
|
int click_y = (last_crop.LoY() * 100 ) / last_act_image_height; // Initial crop offset from last image
|
||||||
|
click_y += ( y * 100 ) / last_virt_image_height;
|
||||||
|
Debug( 3, "Got adjusted click at %d%%,%d%%", click_x, click_y );
|
||||||
|
|
||||||
|
// Convert the click locations to the current image pixels
|
||||||
|
click_x = ( click_x * act_image_width ) / 100;
|
||||||
|
click_y = ( click_y * act_image_height ) / 100;
|
||||||
|
Debug( 3, "Got readjusted click at %d,%d", click_x, click_y );
|
||||||
|
|
||||||
|
int lo_x = click_x - (send_image_width/2);
|
||||||
|
if ( lo_x < 0 )
|
||||||
|
lo_x = 0;
|
||||||
|
int hi_x = lo_x + (send_image_width-1);
|
||||||
|
if ( hi_x >= act_image_width )
|
||||||
|
{
|
||||||
|
hi_x = act_image_width - 1;
|
||||||
|
lo_x = hi_x - (send_image_width - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int lo_y = click_y - (send_image_height/2);
|
||||||
|
if ( lo_y < 0 )
|
||||||
|
lo_y = 0;
|
||||||
|
int hi_y = lo_y + (send_image_height-1);
|
||||||
|
if ( hi_y >= act_image_height )
|
||||||
|
{
|
||||||
|
hi_y = act_image_height - 1;
|
||||||
|
lo_y = hi_y - (send_image_height - 1);
|
||||||
|
}
|
||||||
|
last_crop = Box( lo_x, lo_y, hi_x, hi_y );
|
||||||
|
}
|
||||||
|
Debug( 3, "Cropping to %d,%d -> %d,%d", last_crop.LoX(), last_crop.LoY(), last_crop.HiX(), last_crop.HiY() );
|
||||||
|
if ( !image_copied )
|
||||||
|
{
|
||||||
|
static Image copy_image;
|
||||||
|
copy_image.Assign( *image );
|
||||||
|
image = ©_image;
|
||||||
|
image_copied = true;
|
||||||
|
}
|
||||||
|
image->Crop( last_crop );
|
||||||
|
}
|
||||||
|
last_scale = scale;
|
||||||
|
last_zoom = zoom;
|
||||||
|
last_x = x;
|
||||||
|
last_y = y;
|
||||||
|
|
||||||
|
return( image );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StreamBase::sendTextFrame( const char *frame_text )
|
bool StreamBase::sendTextFrame( const char *frame_text )
|
||||||
{
|
{
|
||||||
Debug( 2, "Sending text frame '%s'", frame_text );
|
Debug( 2, "Sending text frame '%s'", frame_text );
|
||||||
|
|
||||||
Image image( monitor->Width(), monitor->Height(), monitor->Colours(), monitor->SubpixelOrder() );
|
Image image( monitor->Width(), monitor->Height(), monitor->Colours(), monitor->SubpixelOrder() );
|
||||||
image.Annotate( frame_text, image.centreCoord( frame_text ) );
|
image.Annotate( frame_text, image.centreCoord( frame_text ) );
|
||||||
|
|
||||||
if ( scale != 100 )
|
if ( scale != 100 )
|
||||||
{
|
{
|
||||||
image.Scale( scale );
|
image.Scale( scale );
|
||||||
}
|
}
|
||||||
#if HAVE_LIBAVCODEC
|
#if HAVE_LIBAVCODEC
|
||||||
if ( type == STREAM_MPEG )
|
if ( type == MPEG )
|
||||||
|
{
|
||||||
|
if ( !vid_stream )
|
||||||
{
|
{
|
||||||
if ( !vid_stream )
|
vid_stream = new VideoStream( "pipe:", format, bitrate, effective_fps, image.Colours(), image.SubpixelOrder(), image.Width(), image.Height() );
|
||||||
{
|
fprintf( stdout, "Content-type: %s\r\n\r\n", vid_stream->MimeType() );
|
||||||
vid_stream = new VideoStream( "pipe:", format, bitrate, effective_fps, image.Colours(), image.SubpixelOrder(), image.Width(), image.Height() );
|
vid_stream->OpenStream();
|
||||||
fprintf( stdout, "Content-type: %s\r\n\r\n", vid_stream->MimeType() );
|
|
||||||
vid_stream->OpenStream();
|
|
||||||
}
|
|
||||||
/* double pts = */ vid_stream->EncodeFrame( image.Buffer(), image.Size() );
|
|
||||||
}
|
}
|
||||||
else
|
/* double pts = */ vid_stream->EncodeFrame( image.Buffer(), image.Size() );
|
||||||
|
}
|
||||||
|
else
|
||||||
#endif // HAVE_LIBAVCODEC
|
#endif // HAVE_LIBAVCODEC
|
||||||
|
{
|
||||||
|
static unsigned char buffer[ZM_MAX_IMAGE_SIZE];
|
||||||
|
int n_bytes = 0;
|
||||||
|
|
||||||
|
image.EncodeJpeg( buffer, &n_bytes );
|
||||||
|
|
||||||
|
fprintf( stdout, "--ZoneMinderFrame\r\n" );
|
||||||
|
fprintf( stdout, "Content-Length: %d\r\n", n_bytes );
|
||||||
|
fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" );
|
||||||
|
if ( fwrite( buffer, n_bytes, 1, stdout ) != 1 )
|
||||||
{
|
{
|
||||||
static unsigned char buffer[ZM_MAX_IMAGE_SIZE];
|
Error( "Unable to send stream text frame: %s", strerror(errno) );
|
||||||
int n_bytes = 0;
|
return( false );
|
||||||
|
|
||||||
image.EncodeJpeg( buffer, &n_bytes );
|
|
||||||
|
|
||||||
fprintf( stdout, "--ZoneMinderFrame\r\n" );
|
|
||||||
fprintf( stdout, "Content-Length: %d\r\n", n_bytes );
|
|
||||||
fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" );
|
|
||||||
if ( fwrite( buffer, n_bytes, 1, stdout ) != 1 )
|
|
||||||
{
|
|
||||||
Error( "Unable to send stream text frame: %s", strerror(errno) );
|
|
||||||
return( false );
|
|
||||||
}
|
|
||||||
fprintf( stdout, "\r\n\r\n" );
|
|
||||||
fflush( stdout );
|
|
||||||
}
|
}
|
||||||
last_frame_sent = TV_2_FLOAT( now );
|
fprintf( stdout, "\r\n\r\n" );
|
||||||
return( true );
|
fflush( stdout );
|
||||||
|
}
|
||||||
|
last_frame_sent = TV_2_FLOAT( now );
|
||||||
|
return( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamBase::openComms()
|
void StreamBase::openComms()
|
||||||
{
|
{
|
||||||
if ( connkey > 0 )
|
if ( connkey > 0 )
|
||||||
|
{
|
||||||
|
sd = socket( AF_UNIX, SOCK_DGRAM, 0 );
|
||||||
|
if ( sd < 0 )
|
||||||
{
|
{
|
||||||
sd = socket( AF_UNIX, SOCK_DGRAM, 0 );
|
Fatal( "Can't create socket: %s", strerror(errno) );
|
||||||
if ( sd < 0 )
|
|
||||||
{
|
|
||||||
Fatal( "Can't create socket: %s", strerror(errno) );
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf( loc_sock_path, sizeof(loc_sock_path), "%s/zms-%06ds.sock", config.path_socks, connkey );
|
|
||||||
unlink( loc_sock_path );
|
|
||||||
|
|
||||||
strncpy( loc_addr.sun_path, loc_sock_path, sizeof(loc_addr.sun_path) );
|
|
||||||
loc_addr.sun_family = AF_UNIX;
|
|
||||||
if ( bind( sd, (struct sockaddr *)&loc_addr, strlen(loc_addr.sun_path)+sizeof(loc_addr.sun_family)) < 0 )
|
|
||||||
{
|
|
||||||
Fatal( "Can't bind: %s", strerror(errno) );
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf( rem_sock_path, sizeof(rem_sock_path), "%s/zms-%06dw.sock", config.path_socks, connkey );
|
|
||||||
strncpy( rem_addr.sun_path, rem_sock_path, sizeof(rem_addr.sun_path) );
|
|
||||||
rem_addr.sun_family = AF_UNIX;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snprintf( loc_sock_path, sizeof(loc_sock_path), "%s/zms-%06ds.sock", config.path_socks, connkey );
|
||||||
|
unlink( loc_sock_path );
|
||||||
|
|
||||||
|
strncpy( loc_addr.sun_path, loc_sock_path, sizeof(loc_addr.sun_path) );
|
||||||
|
loc_addr.sun_family = AF_UNIX;
|
||||||
|
if ( bind( sd, (struct sockaddr *)&loc_addr, strlen(loc_addr.sun_path)+sizeof(loc_addr.sun_family)) < 0 )
|
||||||
|
{
|
||||||
|
Fatal( "Can't bind: %s", strerror(errno) );
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf( rem_sock_path, sizeof(rem_sock_path), "%s/zms-%06dw.sock", config.path_socks, connkey );
|
||||||
|
strncpy( rem_addr.sun_path, rem_sock_path, sizeof(rem_addr.sun_path) );
|
||||||
|
rem_addr.sun_family = AF_UNIX;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamBase::closeComms()
|
void StreamBase::closeComms()
|
||||||
{
|
{
|
||||||
if ( connkey > 0 )
|
if ( connkey > 0 )
|
||||||
|
{
|
||||||
|
if ( sd >= 0 )
|
||||||
{
|
{
|
||||||
if ( sd >= 0 )
|
close( sd );
|
||||||
{
|
sd = -1;
|
||||||
close( sd );
|
|
||||||
sd = -1;
|
|
||||||
}
|
|
||||||
if ( loc_sock_path[0] )
|
|
||||||
{
|
|
||||||
unlink( loc_sock_path );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if ( loc_sock_path[0] )
|
||||||
|
{
|
||||||
|
unlink( loc_sock_path );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
113
src/zm_stream.h
113
src/zm_stream.h
|
@ -32,38 +32,40 @@ class Monitor;
|
||||||
|
|
||||||
class StreamBase
|
class StreamBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef enum { STREAM_JPEG, STREAM_RAW, STREAM_ZIP, STREAM_SINGLE, STREAM_MPEG } StreamType;
|
typedef enum { JPEG, RAW, ZIP, MPEG } StreamType;
|
||||||
|
typedef enum { SINGLE, STREAM, ALL, ALL_GAPLESS } StreamMode;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static const int MAX_STREAM_DELAY = 5; // Seconds
|
static const int MAX_STREAM_DELAY = 5; // Seconds
|
||||||
|
|
||||||
static const StreamType DEFAULT_TYPE = STREAM_JPEG;
|
static const StreamType DEFAULT_TYPE = JPEG;
|
||||||
enum { DEFAULT_RATE=ZM_RATE_BASE };
|
enum { DEFAULT_RATE=ZM_RATE_BASE };
|
||||||
enum { DEFAULT_SCALE=ZM_SCALE_BASE };
|
enum { DEFAULT_SCALE=ZM_SCALE_BASE };
|
||||||
enum { DEFAULT_ZOOM=ZM_SCALE_BASE };
|
enum { DEFAULT_ZOOM=ZM_SCALE_BASE };
|
||||||
enum { DEFAULT_MAXFPS=10 };
|
enum { DEFAULT_MAXFPS=10 };
|
||||||
enum { DEFAULT_BITRATE=100000 };
|
enum { DEFAULT_BITRATE=100000 };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int msg_type;
|
int msg_type;
|
||||||
char msg_data[16];
|
char msg_data[16];
|
||||||
} CmdMsg;
|
} CmdMsg;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int msg_type;
|
int msg_type;
|
||||||
char msg_data[256];
|
char msg_data[256];
|
||||||
} DataMsg;
|
} DataMsg;
|
||||||
|
|
||||||
typedef enum { MSG_CMD=1, MSG_DATA_WATCH, MSG_DATA_EVENT } MsgType;
|
typedef enum { MSG_CMD=1, MSG_DATA_WATCH, MSG_DATA_EVENT } MsgType;
|
||||||
typedef enum { CMD_NONE=0, CMD_PAUSE, CMD_PLAY, CMD_STOP, CMD_FASTFWD, CMD_SLOWFWD, CMD_SLOWREV, CMD_FASTREV, CMD_ZOOMIN, CMD_ZOOMOUT, CMD_PAN, CMD_SCALE, CMD_PREV, CMD_NEXT, CMD_SEEK, CMD_VARPLAY, CMD_GET_IMAGE, CMD_QUERY=99 } MsgCommand;
|
typedef enum { CMD_NONE=0, CMD_PAUSE, CMD_PLAY, CMD_STOP, CMD_FASTFWD, CMD_SLOWFWD, CMD_SLOWREV, CMD_FASTREV, CMD_ZOOMIN, CMD_ZOOMOUT, CMD_PAN, CMD_SCALE, CMD_PREV, CMD_NEXT, CMD_SEEK, CMD_VARPLAY, CMD_GET_IMAGE, CMD_QUERY=99 } MsgCommand;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Monitor *monitor;
|
Monitor *monitor;
|
||||||
|
|
||||||
StreamType type;
|
StreamType type;
|
||||||
const char *format;
|
StreamMode mode;
|
||||||
|
const char *format; // used to pass to ffmpeg libs
|
||||||
int replay_rate;
|
int replay_rate;
|
||||||
int scale;
|
int scale;
|
||||||
int zoom;
|
int zoom;
|
||||||
|
@ -71,15 +73,15 @@ protected:
|
||||||
int bitrate;
|
int bitrate;
|
||||||
unsigned short x, y;
|
unsigned short x, y;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int connkey;
|
int connkey;
|
||||||
int sd;
|
int sd;
|
||||||
char loc_sock_path[PATH_MAX];
|
char loc_sock_path[PATH_MAX];
|
||||||
struct sockaddr_un loc_addr;
|
struct sockaddr_un loc_addr;
|
||||||
char rem_sock_path[PATH_MAX];
|
char rem_sock_path[PATH_MAX];
|
||||||
struct sockaddr_un rem_addr;
|
struct sockaddr_un rem_addr;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool paused;
|
bool paused;
|
||||||
int step;
|
int step;
|
||||||
|
|
||||||
|
@ -98,7 +100,7 @@ protected:
|
||||||
|
|
||||||
CmdMsg msg;
|
CmdMsg msg;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool loadMonitor( int monitor_id );
|
bool loadMonitor( int monitor_id );
|
||||||
bool checkInitialised();
|
bool checkInitialised();
|
||||||
void updateFrameRate( double fps );
|
void updateFrameRate( double fps );
|
||||||
|
@ -107,68 +109,73 @@ protected:
|
||||||
bool checkCommandQueue();
|
bool checkCommandQueue();
|
||||||
virtual void processCommand( const CmdMsg *msg )=0;
|
virtual void processCommand( const CmdMsg *msg )=0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StreamBase()
|
StreamBase()
|
||||||
{
|
{
|
||||||
monitor = 0;
|
monitor = 0;
|
||||||
|
|
||||||
type = DEFAULT_TYPE;
|
type = DEFAULT_TYPE;
|
||||||
format = "";
|
mode = STREAM;
|
||||||
replay_rate = DEFAULT_RATE;
|
format = "";
|
||||||
scale = DEFAULT_SCALE;
|
replay_rate = DEFAULT_RATE;
|
||||||
zoom = DEFAULT_ZOOM;
|
scale = DEFAULT_SCALE;
|
||||||
maxfps = DEFAULT_MAXFPS;
|
zoom = DEFAULT_ZOOM;
|
||||||
bitrate = DEFAULT_BITRATE;
|
maxfps = DEFAULT_MAXFPS;
|
||||||
|
bitrate = DEFAULT_BITRATE;
|
||||||
|
|
||||||
paused = false;
|
paused = false;
|
||||||
step = 0;
|
step = 0;
|
||||||
x = 0;
|
x = 0;
|
||||||
y = 0;
|
y = 0;
|
||||||
|
|
||||||
connkey = 0;
|
connkey = 0;
|
||||||
sd = -1;
|
sd = -1;
|
||||||
memset( &loc_sock_path, 0, sizeof(loc_sock_path) );
|
memset( &loc_sock_path, 0, sizeof(loc_sock_path) );
|
||||||
memset( &loc_addr, 0, sizeof(loc_addr) );
|
memset( &loc_addr, 0, sizeof(loc_addr) );
|
||||||
memset( &rem_sock_path, 0, sizeof(rem_sock_path) );
|
memset( &rem_sock_path, 0, sizeof(rem_sock_path) );
|
||||||
memset( &rem_addr, 0, sizeof(rem_addr) );
|
memset( &rem_addr, 0, sizeof(rem_addr) );
|
||||||
|
|
||||||
base_fps = 0.0;
|
base_fps = 0.0;
|
||||||
effective_fps = 0.0;
|
effective_fps = 0.0;
|
||||||
frame_mod = 1;
|
frame_mod = 1;
|
||||||
|
|
||||||
#if HAVE_LIBAVCODEC
|
#if HAVE_LIBAVCODEC
|
||||||
vid_stream = 0;
|
vid_stream = 0;
|
||||||
#endif // HAVE_LIBAVCODEC
|
#endif // HAVE_LIBAVCODEC
|
||||||
}
|
}
|
||||||
virtual ~StreamBase();
|
virtual ~StreamBase();
|
||||||
|
|
||||||
void setStreamType( StreamType p_type )
|
void setStreamType( StreamType p_type )
|
||||||
{
|
{
|
||||||
type = p_type;
|
type = p_type;
|
||||||
}
|
}
|
||||||
void setStreamFormat( const char *p_format )
|
void setStreamMode( StreamMode p_mode )
|
||||||
{
|
{
|
||||||
format = p_format;
|
mode = p_mode;
|
||||||
}
|
}
|
||||||
void setStreamScale( int p_scale )
|
void setStreamFormat( const char *p_format )
|
||||||
{
|
{
|
||||||
scale = p_scale;
|
format = p_format;
|
||||||
}
|
}
|
||||||
void setStreamReplayRate( int p_rate )
|
void setStreamScale( int p_scale )
|
||||||
{
|
{
|
||||||
replay_rate = p_rate;
|
scale = p_scale;
|
||||||
}
|
}
|
||||||
void setStreamMaxFPS( double p_maxfps )
|
void setStreamReplayRate( int p_rate )
|
||||||
{
|
{
|
||||||
maxfps = p_maxfps;
|
replay_rate = p_rate;
|
||||||
}
|
}
|
||||||
void setStreamBitrate( int p_bitrate )
|
void setStreamMaxFPS( double p_maxfps )
|
||||||
{
|
{
|
||||||
bitrate = p_bitrate;
|
maxfps = p_maxfps;
|
||||||
}
|
}
|
||||||
void setStreamQueue( int p_connkey )
|
void setStreamBitrate( int p_bitrate )
|
||||||
{
|
{
|
||||||
connkey = p_connkey;
|
bitrate = p_bitrate;
|
||||||
|
}
|
||||||
|
void setStreamQueue( int p_connkey )
|
||||||
|
{
|
||||||
|
connkey = p_connkey;
|
||||||
}
|
}
|
||||||
virtual void openComms();
|
virtual void openComms();
|
||||||
virtual void closeComms();
|
virtual void closeComms();
|
||||||
|
|
613
src/zms.cpp
613
src/zms.cpp
|
@ -28,318 +28,339 @@
|
||||||
|
|
||||||
bool ValidateAccess( User *user, int mon_id )
|
bool ValidateAccess( User *user, int mon_id )
|
||||||
{
|
{
|
||||||
bool allowed = true;
|
bool allowed = true;
|
||||||
|
|
||||||
if ( mon_id > 0 )
|
if ( mon_id > 0 )
|
||||||
{
|
{
|
||||||
if ( user->getStream() < User::PERM_VIEW )
|
if ( user->getStream() < User::PERM_VIEW )
|
||||||
allowed = false;
|
allowed = false;
|
||||||
if ( !user->canAccess( mon_id ) )
|
if ( !user->canAccess( mon_id ) )
|
||||||
allowed = false;
|
allowed = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( user->getEvents() < User::PERM_VIEW )
|
if ( user->getEvents() < User::PERM_VIEW )
|
||||||
allowed = false;
|
allowed = false;
|
||||||
}
|
}
|
||||||
if ( !allowed )
|
if ( !allowed )
|
||||||
{
|
{
|
||||||
Error( "Error, insufficient privileges for requested action" );
|
Error( "Error, insufficient privileges for requested action" );
|
||||||
exit( -1 );
|
exit( -1 );
|
||||||
}
|
}
|
||||||
return( allowed );
|
return( allowed );
|
||||||
}
|
}
|
||||||
|
|
||||||
int main( int argc, const char *argv[] )
|
int main( int argc, const char *argv[] )
|
||||||
{
|
{
|
||||||
self = argv[0];
|
self = argv[0];
|
||||||
|
|
||||||
srand( getpid() * time( 0 ) );
|
srand( getpid() * time( 0 ) );
|
||||||
|
|
||||||
enum { ZMS_MONITOR, ZMS_EVENT } source = ZMS_MONITOR;
|
enum { ZMS_MONITOR, ZMS_EVENT } source = ZMS_MONITOR;
|
||||||
enum { ZMS_JPEG, ZMS_MPEG, ZMS_RAW, ZMS_ZIP, ZMS_SINGLE } mode = ZMS_JPEG;
|
StreamBase::StreamMode mode; // When streaming a live view or event, default to STREAM. If a frame is specified then default to SINGLE>
|
||||||
char format[32] = "";
|
StreamBase::StreamType type = StreamBase::JPEG;
|
||||||
int monitor_id = 0;
|
char format[32] = ""; //used to specify format to ffmpeg libs
|
||||||
time_t event_time = 0;
|
int monitor_id = 0;
|
||||||
int event_id = 0;
|
time_t event_time = 0;
|
||||||
int frame_id = 1;
|
int event_id = 0;
|
||||||
unsigned int scale = 100;
|
int frame_id = 1;
|
||||||
unsigned int rate = 100;
|
unsigned int scale = 100;
|
||||||
double maxfps = 10.0;
|
unsigned int rate = 100;
|
||||||
unsigned int bitrate = 100000;
|
double maxfps = 10.0;
|
||||||
unsigned int ttl = 0;
|
unsigned int bitrate = 100000;
|
||||||
EventStream::StreamMode replay = EventStream::MODE_SINGLE;
|
unsigned int ttl = 0;
|
||||||
char username[64] = "";
|
EventStream::StreamMode replay = EventStream::SINGLE;
|
||||||
char password[64] = "";
|
char username[64] = "";
|
||||||
char auth[64] = "";
|
char password[64] = "";
|
||||||
unsigned int connkey = 0;
|
char auth[64] = "";
|
||||||
unsigned int playback_buffer = 0;
|
unsigned int connkey = 0;
|
||||||
|
unsigned int playback_buffer = 0;
|
||||||
|
|
||||||
bool nph = false;
|
bool nph = false;
|
||||||
const char *basename = strrchr( argv[0], '/' );
|
const char *basename = strrchr( argv[0], '/' );
|
||||||
if (basename) //if we found a / lets skip past it
|
if (basename) //if we found a / lets skip past it
|
||||||
basename++;
|
basename++;
|
||||||
else //argv[0] will not always contain the full path, but rather just the script name
|
else //argv[0] will not always contain the full path, but rather just the script name
|
||||||
basename = argv[0];
|
basename = argv[0];
|
||||||
const char *nph_prefix = "nph-";
|
const char *nph_prefix = "nph-";
|
||||||
if ( basename && !strncmp( basename, nph_prefix, strlen(nph_prefix) ) )
|
if ( basename && !strncmp( basename, nph_prefix, strlen(nph_prefix) ) )
|
||||||
{
|
{
|
||||||
nph = true;
|
nph = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
zmLoadConfig();
|
zmLoadConfig();
|
||||||
|
|
||||||
logInit( "zms" );
|
logInit( "zms" );
|
||||||
|
|
||||||
ssedetect();
|
ssedetect();
|
||||||
|
|
||||||
zmSetDefaultTermHandler();
|
zmSetDefaultTermHandler();
|
||||||
zmSetDefaultDieHandler();
|
zmSetDefaultDieHandler();
|
||||||
|
|
||||||
const char *query = getenv( "QUERY_STRING" );
|
const char *query = getenv( "QUERY_STRING" );
|
||||||
if ( query )
|
if ( query )
|
||||||
{
|
{
|
||||||
Debug( 1, "Query: %s", query );
|
Debug( 1, "Query: %s", query );
|
||||||
|
|
||||||
char temp_query[1024];
|
char temp_query[1024];
|
||||||
strncpy( temp_query, query, sizeof(temp_query) );
|
strncpy( temp_query, query, sizeof(temp_query) );
|
||||||
char *q_ptr = temp_query;
|
char *q_ptr = temp_query;
|
||||||
char *parms[16]; // Shouldn't be more than this
|
char *parms[16]; // Shouldn't be more than this
|
||||||
int parm_no = 0;
|
int parm_no = 0;
|
||||||
while( (parm_no < 16) && (parms[parm_no] = strtok( q_ptr, "&" )) )
|
while( (parm_no < 16) && (parms[parm_no] = strtok( q_ptr, "&" )) )
|
||||||
{
|
|
||||||
parm_no++;
|
|
||||||
q_ptr = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( int p = 0; p < parm_no; p++ )
|
|
||||||
{
|
|
||||||
char *name = strtok( parms[p], "=" );
|
|
||||||
char *value = strtok( NULL, "=" );
|
|
||||||
if ( !value )
|
|
||||||
value = (char *)"";
|
|
||||||
if ( !strcmp( name, "source" ) )
|
|
||||||
{
|
|
||||||
source = !strcmp( value, "event" )?ZMS_EVENT:ZMS_MONITOR;
|
|
||||||
}
|
|
||||||
else if ( !strcmp( name, "mode" ) )
|
|
||||||
{
|
|
||||||
mode = !strcmp( value, "jpeg" )?ZMS_JPEG:ZMS_MPEG;
|
|
||||||
mode = !strcmp( value, "raw" )?ZMS_RAW:mode;
|
|
||||||
mode = !strcmp( value, "zip" )?ZMS_ZIP:mode;
|
|
||||||
mode = !strcmp( value, "single" )?ZMS_SINGLE:mode;
|
|
||||||
}
|
|
||||||
else if ( !strcmp( name, "format" ) )
|
|
||||||
strncpy( format, value, sizeof(format) );
|
|
||||||
else if ( !strcmp( name, "monitor" ) )
|
|
||||||
monitor_id = atoi( value );
|
|
||||||
else if ( !strcmp( name, "time" ) )
|
|
||||||
event_time = atoi( value );
|
|
||||||
else if ( !strcmp( name, "event" ) )
|
|
||||||
event_id = strtoull( value, (char **)NULL, 10 );
|
|
||||||
else if ( !strcmp( name, "frame" ) )
|
|
||||||
frame_id = strtoull( value, (char **)NULL, 10 );
|
|
||||||
else if ( !strcmp( name, "scale" ) )
|
|
||||||
scale = atoi( value );
|
|
||||||
else if ( !strcmp( name, "rate" ) )
|
|
||||||
rate = atoi( value );
|
|
||||||
else if ( !strcmp( name, "maxfps" ) )
|
|
||||||
maxfps = atof( value );
|
|
||||||
else if ( !strcmp( name, "bitrate" ) )
|
|
||||||
bitrate = atoi( value );
|
|
||||||
else if ( !strcmp( name, "ttl" ) )
|
|
||||||
ttl = atoi(value);
|
|
||||||
else if ( !strcmp( name, "replay" ) )
|
|
||||||
{
|
|
||||||
replay = !strcmp( value, "gapless" )?EventStream::MODE_ALL_GAPLESS:EventStream::MODE_SINGLE;
|
|
||||||
replay = !strcmp( value, "all" )?EventStream::MODE_ALL:replay;
|
|
||||||
}
|
|
||||||
else if ( !strcmp( name, "connkey" ) )
|
|
||||||
connkey = atoi(value);
|
|
||||||
else if ( !strcmp( name, "buffer" ) )
|
|
||||||
playback_buffer = atoi(value);
|
|
||||||
else if ( config.opt_use_auth )
|
|
||||||
{
|
|
||||||
if ( strcmp( config.auth_relay, "none" ) == 0 )
|
|
||||||
{
|
|
||||||
if ( !strcmp( name, "user" ) )
|
|
||||||
{
|
|
||||||
strncpy( username, value, sizeof(username) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//if ( strcmp( config.auth_relay, "hashed" ) == 0 )
|
|
||||||
{
|
|
||||||
if ( !strcmp( name, "auth" ) )
|
|
||||||
{
|
|
||||||
strncpy( auth, value, sizeof(auth) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//else if ( strcmp( config.auth_relay, "plain" ) == 0 )
|
|
||||||
{
|
|
||||||
if ( !strcmp( name, "user" ) )
|
|
||||||
{
|
|
||||||
strncpy( username, value, sizeof(username) );
|
|
||||||
}
|
|
||||||
if ( !strcmp( name, "pass" ) )
|
|
||||||
{
|
|
||||||
strncpy( password, value, sizeof(password) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( config.opt_use_auth )
|
|
||||||
{
|
|
||||||
User *user = 0;
|
|
||||||
|
|
||||||
if ( strcmp( config.auth_relay, "none" ) == 0 )
|
|
||||||
{
|
|
||||||
if ( *username )
|
|
||||||
{
|
|
||||||
user = zmLoadUser( username );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//if ( strcmp( config.auth_relay, "hashed" ) == 0 )
|
|
||||||
{
|
|
||||||
if ( *auth )
|
|
||||||
{
|
|
||||||
user = zmLoadAuthUser( auth, config.auth_hash_ips );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//else if ( strcmp( config.auth_relay, "plain" ) == 0 )
|
|
||||||
{
|
|
||||||
if ( *username && *password )
|
|
||||||
{
|
|
||||||
user = zmLoadUser( username, password );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( !user )
|
|
||||||
{
|
|
||||||
Error( "Unable to authenticate user" );
|
|
||||||
logTerm();
|
|
||||||
zmDbClose();
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
ValidateAccess( user, monitor_id );
|
|
||||||
}
|
|
||||||
|
|
||||||
setbuf( stdout, 0 );
|
|
||||||
if ( nph )
|
|
||||||
{
|
|
||||||
fprintf( stdout, "HTTP/1.0 200 OK\r\n" );
|
|
||||||
}
|
|
||||||
fprintf( stdout, "Server: ZoneMinder Video Server/%s\r\n", ZM_VERSION );
|
|
||||||
|
|
||||||
time_t now = time( 0 );
|
|
||||||
char date_string[64];
|
|
||||||
strftime( date_string, sizeof(date_string)-1, "%a, %d %b %Y %H:%M:%S GMT", gmtime( &now ) );
|
|
||||||
|
|
||||||
fprintf( stdout, "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n" );
|
|
||||||
fprintf( stdout, "Last-Modified: %s\r\n", date_string );
|
|
||||||
fprintf( stdout, "Cache-Control: no-store, no-cache, must-revalidate\r\n" );
|
|
||||||
fprintf( stdout, "Cache-Control: post-check=0, pre-check=0\r\n" );
|
|
||||||
fprintf( stdout, "Pragma: no-cache\r\n");
|
|
||||||
// Removed as causing more problems than it fixed.
|
|
||||||
//if ( !nph )
|
|
||||||
//{
|
|
||||||
//fprintf( stdout, "Content-Length: 0\r\n");
|
|
||||||
//}
|
|
||||||
|
|
||||||
if ( source == ZMS_MONITOR )
|
|
||||||
{
|
|
||||||
MonitorStream stream;
|
|
||||||
stream.setStreamScale( scale );
|
|
||||||
stream.setStreamReplayRate( rate );
|
|
||||||
stream.setStreamMaxFPS( maxfps );
|
|
||||||
stream.setStreamTTL( ttl );
|
|
||||||
stream.setStreamQueue( connkey );
|
|
||||||
stream.setStreamBuffer( playback_buffer );
|
|
||||||
if ( ! stream.setStreamStart( monitor_id ) ) {
|
|
||||||
Error( "Unable to connect to zmc process for monitor %d", monitor_id );
|
|
||||||
fprintf( stderr, "Unable to connect to zmc process. Please ensure that it is running." );
|
|
||||||
logTerm();
|
|
||||||
zmDbClose();
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( mode == ZMS_JPEG )
|
|
||||||
{
|
|
||||||
stream.setStreamType( MonitorStream::STREAM_JPEG );
|
|
||||||
}
|
|
||||||
else if ( mode == ZMS_RAW )
|
|
||||||
{
|
|
||||||
stream.setStreamType( MonitorStream::STREAM_RAW );
|
|
||||||
}
|
|
||||||
else if ( mode == ZMS_ZIP )
|
|
||||||
{
|
|
||||||
stream.setStreamType( MonitorStream::STREAM_ZIP );
|
|
||||||
}
|
|
||||||
else if ( mode == ZMS_SINGLE )
|
|
||||||
{
|
|
||||||
stream.setStreamType( MonitorStream::STREAM_SINGLE );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#if HAVE_LIBAVCODEC
|
|
||||||
stream.setStreamFormat( format );
|
|
||||||
stream.setStreamBitrate( bitrate );
|
|
||||||
stream.setStreamType( MonitorStream::STREAM_MPEG );
|
|
||||||
#else // HAVE_LIBAVCODEC
|
|
||||||
Error( "MPEG streaming of '%s' attempted while disabled", query );
|
|
||||||
fprintf( stderr, "MPEG streaming is disabled.\nYou should configure with the --with-ffmpeg option and rebuild to use this functionality.\n" );
|
|
||||||
logTerm();
|
|
||||||
zmDbClose();
|
|
||||||
return( -1 );
|
|
||||||
#endif // HAVE_LIBAVCODEC
|
|
||||||
}
|
|
||||||
stream.runStream();
|
|
||||||
}
|
|
||||||
else if ( source == ZMS_EVENT )
|
|
||||||
{
|
{
|
||||||
EventStream stream;
|
parm_no++;
|
||||||
stream.setStreamScale( scale );
|
q_ptr = NULL;
|
||||||
stream.setStreamReplayRate( rate );
|
|
||||||
stream.setStreamMaxFPS( maxfps );
|
|
||||||
stream.setStreamMode( replay );
|
|
||||||
stream.setStreamQueue( connkey );
|
|
||||||
if ( monitor_id && event_time )
|
|
||||||
{
|
|
||||||
stream.setStreamStart( monitor_id, event_time );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stream.setStreamStart( event_id, frame_id );
|
|
||||||
}
|
|
||||||
if ( mode == ZMS_JPEG )
|
|
||||||
{
|
|
||||||
stream.setStreamType( EventStream::STREAM_JPEG );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#if HAVE_LIBAVCODEC
|
|
||||||
stream.setStreamFormat( format );
|
|
||||||
stream.setStreamBitrate( bitrate );
|
|
||||||
stream.setStreamType( EventStream::STREAM_MPEG );
|
|
||||||
#else // HAVE_LIBAVCODEC
|
|
||||||
Error( "MPEG streaming of '%s' attempted while disabled", query );
|
|
||||||
fprintf( stderr, "MPEG streaming is disabled.\nYou should ensure the ffmpeg libraries are installed and detected and rebuild to use this functionality.\n" );
|
|
||||||
logTerm();
|
|
||||||
zmDbClose();
|
|
||||||
return( -1 );
|
|
||||||
#endif // HAVE_LIBAVCODEC
|
|
||||||
}
|
|
||||||
stream.runStream();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logTerm();
|
for ( int p = 0; p < parm_no; p++ )
|
||||||
zmDbClose();
|
{
|
||||||
|
char *name = strtok( parms[p], "=" );
|
||||||
|
char *value = strtok( NULL, "=" );
|
||||||
|
if ( !value )
|
||||||
|
value = (char *)"";
|
||||||
|
if ( !strcmp( name, "source" ) )
|
||||||
|
{
|
||||||
|
source = !strcmp( value, "event" )?ZMS_EVENT:ZMS_MONITOR;
|
||||||
|
}
|
||||||
|
else if ( !strcmp( name, "mode" ) )
|
||||||
|
{
|
||||||
|
if ( !strcmp( value, "single" ) ) {
|
||||||
|
mode = StreamBase::SINGLE;
|
||||||
|
} else if ( !strcmp( value, "stream" ) ) {
|
||||||
|
mode = StreamBase::STREAM;
|
||||||
|
} else if ( !strcmp( value, "jpeg" ) ) {
|
||||||
|
type = StreamBase::JPEG;
|
||||||
|
// code for STREAM/SINGLE comes later.
|
||||||
|
} else if ( !strcmp( value, "raw" ) ) {
|
||||||
|
type = StreamBase::RAW;
|
||||||
|
|
||||||
return( 0 );
|
} else if ( !strcmp( value, "zip" ) ) {
|
||||||
|
type = StreamBase::ZIP;
|
||||||
|
} else {
|
||||||
|
Warning( "Unsupported mode: (%s) defaulting to ", value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( !strcmp( name, "format" ) )
|
||||||
|
if ( !strcmp( value, "jpeg" ) ) {
|
||||||
|
type = StreamBase::JPEG;
|
||||||
|
} else if ( !strcmp( value, "raw" ) ) {
|
||||||
|
type = StreamBase::RAW;
|
||||||
|
} else if ( !strcmp( value, "zip" ) ) {
|
||||||
|
type = StreamBase::ZIP;
|
||||||
|
} else if ( !strcmp( value, "mpeg" ) ) {
|
||||||
|
type = StreamBase::MPEG;
|
||||||
|
strncpy( format, value, sizeof(format) );
|
||||||
|
} else {
|
||||||
|
Warning( "Unsupported format: (%s) defaulting to ", value );
|
||||||
|
strncpy( format, value, sizeof(format) );
|
||||||
|
}
|
||||||
|
else if ( !strcmp( name, "monitor" ) )
|
||||||
|
monitor_id = atoi( value );
|
||||||
|
else if ( !strcmp( name, "time" ) )
|
||||||
|
event_time = atoi( value );
|
||||||
|
else if ( !strcmp( name, "event" ) )
|
||||||
|
event_id = strtoull( value, (char **)NULL, 10 );
|
||||||
|
else if ( !strcmp( name, "frame" ) )
|
||||||
|
frame_id = strtoull( value, (char **)NULL, 10 );
|
||||||
|
else if ( !strcmp( name, "scale" ) )
|
||||||
|
scale = atoi( value );
|
||||||
|
else if ( !strcmp( name, "rate" ) )
|
||||||
|
rate = atoi( value );
|
||||||
|
else if ( !strcmp( name, "maxfps" ) )
|
||||||
|
maxfps = atof( value );
|
||||||
|
else if ( !strcmp( name, "bitrate" ) )
|
||||||
|
bitrate = atoi( value );
|
||||||
|
else if ( !strcmp( name, "ttl" ) )
|
||||||
|
ttl = atoi(value);
|
||||||
|
else if ( !strcmp( name, "replay" ) )
|
||||||
|
{
|
||||||
|
replay = !strcmp( value, "gapless" )?StreamBase::ALL_GAPLESS:StreamBase::SINGLE;
|
||||||
|
replay = !strcmp( value, "all" )?StreamBase::ALL:replay;
|
||||||
|
}
|
||||||
|
else if ( !strcmp( name, "connkey" ) )
|
||||||
|
connkey = atoi(value);
|
||||||
|
else if ( !strcmp( name, "buffer" ) )
|
||||||
|
playback_buffer = atoi(value);
|
||||||
|
else if ( config.opt_use_auth )
|
||||||
|
{
|
||||||
|
if ( strcmp( config.auth_relay, "none" ) == 0 )
|
||||||
|
{
|
||||||
|
if ( !strcmp( name, "user" ) )
|
||||||
|
{
|
||||||
|
strncpy( username, value, sizeof(username) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//if ( strcmp( config.auth_relay, "hashed" ) == 0 )
|
||||||
|
{
|
||||||
|
if ( !strcmp( name, "auth" ) )
|
||||||
|
{
|
||||||
|
strncpy( auth, value, sizeof(auth) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//else if ( strcmp( config.auth_relay, "plain" ) == 0 )
|
||||||
|
{
|
||||||
|
if ( !strcmp( name, "user" ) )
|
||||||
|
{
|
||||||
|
strncpy( username, value, sizeof(username) );
|
||||||
|
}
|
||||||
|
if ( !strcmp( name, "pass" ) )
|
||||||
|
{
|
||||||
|
strncpy( password, value, sizeof(password) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( config.opt_use_auth )
|
||||||
|
{
|
||||||
|
User *user = 0;
|
||||||
|
|
||||||
|
if ( strcmp( config.auth_relay, "none" ) == 0 )
|
||||||
|
{
|
||||||
|
if ( *username )
|
||||||
|
{
|
||||||
|
user = zmLoadUser( username );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//if ( strcmp( config.auth_relay, "hashed" ) == 0 )
|
||||||
|
{
|
||||||
|
if ( *auth )
|
||||||
|
{
|
||||||
|
user = zmLoadAuthUser( auth, config.auth_hash_ips );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//else if ( strcmp( config.auth_relay, "plain" ) == 0 )
|
||||||
|
{
|
||||||
|
if ( *username && *password )
|
||||||
|
{
|
||||||
|
user = zmLoadUser( username, password );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !user )
|
||||||
|
{
|
||||||
|
Error( "Unable to authenticate user" );
|
||||||
|
logTerm();
|
||||||
|
zmDbClose();
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
ValidateAccess( user, monitor_id );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! mode ) {
|
||||||
|
if ( source == ZMS_MONITOR ) {
|
||||||
|
mode = StreamBase::STREAM;
|
||||||
|
} else {
|
||||||
|
// when getting from an event, if a frame_id is specified, then default to single, otherwise stream
|
||||||
|
if ( frame_id ) {
|
||||||
|
mode = StreamBase::SINGLE;
|
||||||
|
} else {
|
||||||
|
mode = StreamBase::STREAM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setbuf( stdout, 0 );
|
||||||
|
if ( nph )
|
||||||
|
{
|
||||||
|
fprintf( stdout, "HTTP/1.0 200 OK\r\n" );
|
||||||
|
}
|
||||||
|
fprintf( stdout, "Server: ZoneMinder Video Server/%s\r\n", ZM_VERSION );
|
||||||
|
|
||||||
|
time_t now = time( 0 );
|
||||||
|
char date_string[64];
|
||||||
|
strftime( date_string, sizeof(date_string)-1, "%a, %d %b %Y %H:%M:%S GMT", gmtime( &now ) );
|
||||||
|
|
||||||
|
fprintf( stdout, "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n" );
|
||||||
|
fprintf( stdout, "Last-Modified: %s\r\n", date_string );
|
||||||
|
fprintf( stdout, "Cache-Control: no-store, no-cache, must-revalidate\r\n" );
|
||||||
|
fprintf( stdout, "Cache-Control: post-check=0, pre-check=0\r\n" );
|
||||||
|
fprintf( stdout, "Pragma: no-cache\r\n");
|
||||||
|
// Removed as causing more problems than it fixed.
|
||||||
|
//if ( !nph )
|
||||||
|
//{
|
||||||
|
//fprintf( stdout, "Content-Length: 0\r\n");
|
||||||
|
//}
|
||||||
|
|
||||||
|
if ( source == ZMS_MONITOR )
|
||||||
|
{
|
||||||
|
MonitorStream stream;
|
||||||
|
stream.setStreamScale( scale );
|
||||||
|
stream.setStreamReplayRate( rate );
|
||||||
|
stream.setStreamMaxFPS( maxfps );
|
||||||
|
stream.setStreamTTL( ttl );
|
||||||
|
stream.setStreamQueue( connkey );
|
||||||
|
stream.setStreamBuffer( playback_buffer );
|
||||||
|
if ( ! stream.setStreamStart( monitor_id ) ) {
|
||||||
|
Error( "Unable to connect to zmc process for monitor %d", monitor_id );
|
||||||
|
fprintf( stderr, "Unable to connect to zmc process. Please ensure that it is running." );
|
||||||
|
logTerm();
|
||||||
|
zmDbClose();
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.setStreamMode( mode );
|
||||||
|
stream.setStreamType( type );
|
||||||
|
|
||||||
|
if ( type == StreamBase::MPEG )
|
||||||
|
{
|
||||||
|
#if HAVE_LIBAVCODEC
|
||||||
|
stream.setStreamFormat( format );
|
||||||
|
stream.setStreamBitrate( bitrate );
|
||||||
|
stream.setStreamType( type );
|
||||||
|
#else // HAVE_LIBAVCODEC
|
||||||
|
Error( "MPEG streaming of '%s' attempted while disabled", query );
|
||||||
|
fprintf( stderr, "MPEG streaming is disabled.\nYou should configure with the --with-ffmpeg option and rebuild to use this functionality.\n" );
|
||||||
|
logTerm();
|
||||||
|
zmDbClose();
|
||||||
|
return( -1 );
|
||||||
|
#endif // HAVE_LIBAVCODEC
|
||||||
|
}
|
||||||
|
stream.runStream();
|
||||||
|
}
|
||||||
|
else if ( source == ZMS_EVENT )
|
||||||
|
{
|
||||||
|
EventStream stream;
|
||||||
|
stream.setStreamScale( scale );
|
||||||
|
stream.setStreamReplayRate( rate );
|
||||||
|
stream.setStreamMaxFPS( maxfps );
|
||||||
|
stream.setStreamMode( replay );
|
||||||
|
stream.setStreamQueue( connkey );
|
||||||
|
if ( monitor_id && event_time )
|
||||||
|
{
|
||||||
|
stream.setStreamStart( monitor_id, event_time );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stream.setStreamStart( event_id, frame_id );
|
||||||
|
}
|
||||||
|
stream.setStreamMode( mode );
|
||||||
|
stream.setStreamType( type );
|
||||||
|
if ( type == StreamBase::MPEG )
|
||||||
|
{
|
||||||
|
#if HAVE_LIBAVCODEC
|
||||||
|
stream.setStreamFormat( format );
|
||||||
|
stream.setStreamBitrate( bitrate );
|
||||||
|
#else // HAVE_LIBAVCODEC
|
||||||
|
Error( "MPEG streaming of '%s' attempted while disabled", query );
|
||||||
|
fprintf( stderr, "MPEG streaming is disabled.\nYou should ensure the ffmpeg libraries are installed and detected and rebuild to use this functionality.\n" );
|
||||||
|
logTerm();
|
||||||
|
zmDbClose();
|
||||||
|
return( -1 );
|
||||||
|
#endif // HAVE_LIBAVCODEC
|
||||||
|
}
|
||||||
|
stream.runStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
logTerm();
|
||||||
|
zmDbClose();
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,34 +21,34 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
zmstreamer - eyeZM video streamer
|
zmstreamer - eyeZM video streamer
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
zmstreamer -e <mode>
|
zmstreamer -e <mode>
|
||||||
zmstreamer -o <format>
|
zmstreamer -o <format>
|
||||||
zmstreamer -u <buffer size>
|
zmstreamer -u <buffer size>
|
||||||
zmstreamer -f <maximum fps>
|
zmstreamer -f <maximum fps>
|
||||||
zmstreamer -s <scale>
|
zmstreamer -s <scale>
|
||||||
zmstreamer -b <bitrate in bps>
|
zmstreamer -b <bitrate in bps>
|
||||||
zmstreamer -m <monitor id>
|
zmstreamer -m <monitor id>
|
||||||
zmstreamer -d <debug mode>
|
zmstreamer -d <debug mode>
|
||||||
zmstreamer -i
|
zmstreamer -i
|
||||||
zmstreamer -?
|
zmstreamer -?
|
||||||
zmstreamer -h
|
zmstreamer -h
|
||||||
zmstreamer -v
|
zmstreamer -v
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
*DEPRECIATED* The xml skin and all files associated with the xml skin are now
|
*DEPRECIATED* The xml skin and all files associated with the xml skin are now
|
||||||
depreciated. Please use the ZoneMinder API instead.
|
depreciated. Please use the ZoneMinder API instead.
|
||||||
|
|
||||||
This binary works in conjunction with the XML skin to stream video to iPhones
|
This binary works in conjunction with the XML skin to stream video to iPhones
|
||||||
running the eyeZm app.
|
running the eyeZm app.
|
||||||
|
|
||||||
=head1 OPTIONS
|
=head1 OPTIONS
|
||||||
|
|
||||||
-e <mode> - Specify output mode: mpeg/jpg/zip/single/raw.
|
-e <mode> - Specify output mode: mpeg/jpg/zip/single/raw.
|
||||||
-o <format> - Specify output format.
|
-o <format> - Specify output format.
|
||||||
|
@ -61,9 +61,9 @@ running the eyeZm app.
|
||||||
-i, -?, -h - Display usage information
|
-i, -?, -h - Display usage information
|
||||||
-v - Print the installed version of ZoneMinder
|
-v - Print the installed version of ZoneMinder
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -92,161 +92,165 @@ running the eyeZm app.
|
||||||
#define ZMS_DEFAULT_BUFFER 1000
|
#define ZMS_DEFAULT_BUFFER 1000
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
self = argv[0];
|
self = argv[0];
|
||||||
// Set initial values to the default values
|
// Set initial values to the default values
|
||||||
int debug = ZMS_DEFAULT_DEBUG;
|
int debug = ZMS_DEFAULT_DEBUG;
|
||||||
int id = ZMS_DEFAULT_ID;
|
int id = ZMS_DEFAULT_ID;
|
||||||
int bitrate = ZMS_DEFAULT_BITRATE;
|
int bitrate = ZMS_DEFAULT_BITRATE;
|
||||||
int scale = ZMS_DEFAULT_SCALE;
|
int scale = ZMS_DEFAULT_SCALE;
|
||||||
char mode[32];
|
char mode[32];
|
||||||
sprintf(mode, "%s", ZMS_DEFAULT_MODE);
|
sprintf(mode, "%s", ZMS_DEFAULT_MODE);
|
||||||
char format[32];
|
char format[32];
|
||||||
sprintf(format, "%s", ZMS_DEFAULT_FORMAT);
|
sprintf(format, "%s", ZMS_DEFAULT_FORMAT);
|
||||||
double maxfps = ZMS_DEFAULT_FPS;
|
double maxfps = ZMS_DEFAULT_FPS;
|
||||||
int buffer = ZMS_DEFAULT_BUFFER;
|
int buffer = ZMS_DEFAULT_BUFFER;
|
||||||
|
|
||||||
// Parse command-line options
|
// Parse command-line options
|
||||||
int arg;
|
int arg;
|
||||||
while ((arg = getopt(argc, argv, OPTIONS)) != -1) {
|
while ((arg = getopt(argc, argv, OPTIONS)) != -1) {
|
||||||
switch (arg) {
|
switch (arg) {
|
||||||
case 'e':
|
case 'e':
|
||||||
sprintf(mode, "%s", optarg);
|
sprintf(mode, "%s", optarg);
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
sprintf(format, "%s", optarg);
|
sprintf(format, "%s", optarg);
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
buffer = atoi(optarg);
|
buffer = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
maxfps = atof(optarg);
|
maxfps = atof(optarg);
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
scale = atoi(optarg);
|
scale = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
bitrate = atoi(optarg);
|
bitrate = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
id = atoi(optarg);
|
id = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
debug = atoi(optarg);
|
debug = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
case 'i':
|
case 'i':
|
||||||
case '?':
|
case '?':
|
||||||
printf("-e <mode> : Specify output mode: mpeg/jpg/zip/single/raw. Default = %s\n", ZMS_DEFAULT_MODE);
|
printf("-e <mode> : Specify output mode: mpeg/jpg/zip/single/raw. Default = %s\n", ZMS_DEFAULT_MODE);
|
||||||
printf("-o <format> : Specify output format. Default = %s\n", ZMS_DEFAULT_FORMAT);
|
printf("-o <format> : Specify output format. Default = %s\n", ZMS_DEFAULT_FORMAT);
|
||||||
printf("-u <buffer size> : Specify buffer size in ms. Default = %d\n", ZMS_DEFAULT_BUFFER);
|
printf("-u <buffer size> : Specify buffer size in ms. Default = %d\n", ZMS_DEFAULT_BUFFER);
|
||||||
printf("-f <maximum fps> : Specify maximum framerate. Default = %lf\n", ZMS_DEFAULT_FPS);
|
printf("-f <maximum fps> : Specify maximum framerate. Default = %lf\n", ZMS_DEFAULT_FPS);
|
||||||
printf("-s <scale> : Specify scale. Default = %d\n", ZMS_DEFAULT_SCALE);
|
printf("-s <scale> : Specify scale. Default = %d\n", ZMS_DEFAULT_SCALE);
|
||||||
printf("-b <bitrate in bps> : Specify bitrate. Default = %d\n", ZMS_DEFAULT_BITRATE);
|
printf("-b <bitrate in bps> : Specify bitrate. Default = %d\n", ZMS_DEFAULT_BITRATE);
|
||||||
printf("-m <monitor id> : Specify monitor id. Default = %d\n", ZMS_DEFAULT_ID);
|
printf("-m <monitor id> : Specify monitor id. Default = %d\n", ZMS_DEFAULT_ID);
|
||||||
printf("-d <debug mode> : 0 = off, 1 = no streaming, 2 = with streaming. Default = 0\n");
|
printf("-d <debug mode> : 0 = off, 1 = no streaming, 2 = with streaming. Default = 0\n");
|
||||||
printf("-i or -? or -h: This information\n");
|
printf("-i or -? or -h: This information\n");
|
||||||
printf("-v : This installed version of ZoneMinder\n");
|
printf("-v : This installed version of ZoneMinder\n");
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
case 'v':
|
case 'v':
|
||||||
std::cout << ZM_VERSION << "\n";
|
std::cout << ZM_VERSION << "\n";
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set stream type
|
// Set stream type
|
||||||
StreamBase::StreamType streamtype;
|
StreamBase::StreamType streamtype;
|
||||||
if (!strcasecmp("raw", mode))
|
StreamBase::StreamMode streammode = StreamBase::STREAM;
|
||||||
streamtype = MonitorStream::STREAM_RAW;
|
|
||||||
else if (!strcasecmp("mpeg", mode))
|
|
||||||
streamtype = MonitorStream::STREAM_MPEG;
|
|
||||||
else if (!strcasecmp("jpg", mode))
|
|
||||||
streamtype = MonitorStream::STREAM_JPEG;
|
|
||||||
else if (!strcasecmp("single", mode))
|
|
||||||
streamtype = MonitorStream::STREAM_SINGLE;
|
|
||||||
else if (!strcasecmp("zip", mode))
|
|
||||||
streamtype = MonitorStream::STREAM_ZIP;
|
|
||||||
else
|
|
||||||
streamtype = MonitorStream::STREAM_MPEG;
|
|
||||||
|
|
||||||
if (debug) {
|
if (!strcasecmp("raw", mode))
|
||||||
// Show stream parameters
|
streamtype = StreamBase::RAW;
|
||||||
printf("Stream parameters:\n");
|
else if (!strcasecmp("mpeg", mode))
|
||||||
switch (streamtype) {
|
streamtype = StreamBase::MPEG;
|
||||||
case MonitorStream::STREAM_MPEG:
|
else if (!strcasecmp("jpg", mode))
|
||||||
printf("Output mode (-e) = %s\n", "mpeg");
|
streamtype = StreamBase::JPEG;
|
||||||
printf("Output format (-o) = %s\n", format);
|
else if (!strcasecmp("single", mode))
|
||||||
break;
|
streammode = StreamBase::SINGLE;
|
||||||
default:
|
else if (!strcasecmp("zip", mode))
|
||||||
printf("Output mode (-e) = %s\n", mode);
|
streamtype = StreamBase::ZIP;
|
||||||
}
|
else if (!strcasecmp("mpeg", mode))
|
||||||
printf("Buffer size (-u) = %d ms\n", buffer);
|
streamtype = StreamBase::MPEG;
|
||||||
printf("Maximum FPS (-f) = %lf FPS\n", maxfps);
|
else
|
||||||
printf("Scale (-s) = %d%%\n", scale);
|
streamtype = StreamBase::MPEG;
|
||||||
printf("Bitrate (-b) = %d bps\n", bitrate);
|
|
||||||
printf("Monitor Id (-m) = %d\n", id);
|
if (debug) {
|
||||||
|
// Show stream parameters
|
||||||
|
printf("Stream parameters:\n");
|
||||||
|
switch (streamtype) {
|
||||||
|
case StreamBase::MPEG:
|
||||||
|
printf("Output mode (-e) = %s\n", "mpeg");
|
||||||
|
printf("Output format (-o) = %s\n", format);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Output mode (-e) = %s\n", mode);
|
||||||
}
|
}
|
||||||
|
printf("Buffer size (-u) = %d ms\n", buffer);
|
||||||
|
printf("Maximum FPS (-f) = %lf FPS\n", maxfps);
|
||||||
|
printf("Scale (-s) = %d%%\n", scale);
|
||||||
|
printf("Bitrate (-b) = %d bps\n", bitrate);
|
||||||
|
printf("Monitor Id (-m) = %d\n", id);
|
||||||
|
}
|
||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
// Set ZM debugger to print to stdout
|
// Set ZM debugger to print to stdout
|
||||||
printf("Setting up ZoneMinder debugger to print to stdout...");
|
printf("Setting up ZoneMinder debugger to print to stdout...");
|
||||||
setenv("ZM_DBG_PRINT", "1", 1);
|
setenv("ZM_DBG_PRINT", "1", 1);
|
||||||
printf("Done.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loading ZM configurations
|
|
||||||
printf("Loading ZoneMinder configurations...");
|
|
||||||
zmLoadConfig();
|
|
||||||
printf("Done.\n");
|
printf("Done.\n");
|
||||||
|
}
|
||||||
|
|
||||||
logInit("zmstreamer");
|
// Loading ZM configurations
|
||||||
|
printf("Loading ZoneMinder configurations...");
|
||||||
|
zmLoadConfig();
|
||||||
|
printf("Done.\n");
|
||||||
|
|
||||||
ssedetect();
|
logInit("zmstreamer");
|
||||||
|
|
||||||
// Setting stream parameters
|
ssedetect();
|
||||||
MonitorStream stream;
|
|
||||||
stream.setStreamScale(scale); // default = 100 (scale)
|
// Setting stream parameters
|
||||||
stream.setStreamReplayRate(100); // default = 100 (rate)
|
MonitorStream stream;
|
||||||
stream.setStreamMaxFPS(maxfps); // default = 10 (maxfps)
|
stream.setStreamScale(scale); // default = 100 (scale)
|
||||||
if (debug) stream.setStreamTTL(1);
|
stream.setStreamReplayRate(100); // default = 100 (rate)
|
||||||
else stream.setStreamTTL(0); // default = 0 (ttl)
|
stream.setStreamMaxFPS(maxfps); // default = 10 (maxfps)
|
||||||
stream.setStreamQueue(0); // default = 0 (connkey)
|
if (debug) stream.setStreamTTL(1);
|
||||||
stream.setStreamBuffer(buffer); // default = 0 (buffer)
|
else stream.setStreamTTL(0); // default = 0 (ttl)
|
||||||
stream.setStreamStart(id); // default = 0 (monitor_id)
|
stream.setStreamQueue(0); // default = 0 (connkey)
|
||||||
stream.setStreamType(streamtype);
|
stream.setStreamBuffer(buffer); // default = 0 (buffer)
|
||||||
if (streamtype == MonitorStream::STREAM_MPEG) {
|
stream.setStreamStart(id); // default = 0 (monitor_id)
|
||||||
|
stream.setStreamType(streamtype);
|
||||||
|
if (streamtype == StreamBase::MPEG) {
|
||||||
#if HAVE_LIBAVCODEC
|
#if HAVE_LIBAVCODEC
|
||||||
if (debug) printf("HAVE_LIBAVCODEC is set\n");
|
if (debug) printf("HAVE_LIBAVCODEC is set\n");
|
||||||
stream.setStreamFormat(format); // default = "" (format)
|
stream.setStreamFormat(format); // default = "" (format)
|
||||||
stream.setStreamBitrate(bitrate); // default = 100000 (bitrate)
|
stream.setStreamBitrate(bitrate); // default = 100000 (bitrate)
|
||||||
#else
|
#else
|
||||||
fprintf(stderr, "MPEG streaming is disabled.\nYou should configure with the --with-ffmpeg option and rebuild to use this functionality.\n");
|
fprintf(stderr, "MPEG streaming is disabled.\nYou should configure with the --with-ffmpeg option and rebuild to use this functionality.\n");
|
||||||
logTerm();
|
|
||||||
zmDbClose();
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debug != 1) {
|
|
||||||
if (debug) printf("Running stream...");
|
|
||||||
|
|
||||||
// Output headers
|
|
||||||
fprintf(stdout, "Server: ZoneMinder Video Server/%s\r\n", ZM_VERSION);
|
|
||||||
time_t now = time(0);
|
|
||||||
char date_string[64];
|
|
||||||
strftime(date_string, sizeof (date_string) - 1, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now));
|
|
||||||
fprintf(stdout, "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n");
|
|
||||||
fprintf(stdout, "Last-Modified: %s\r\n", date_string);
|
|
||||||
fprintf(stdout, "Cache-Control: no-store, no-cache, must-revalidate\r\n");
|
|
||||||
fprintf(stdout, "Cache-Control: post-check=0, pre-check=0\r\n");
|
|
||||||
fprintf(stdout, "Pragma: no-cache\r\n");
|
|
||||||
|
|
||||||
// Run stream
|
|
||||||
stream.runStream();
|
|
||||||
}
|
|
||||||
if (debug) printf("Done.\n");
|
|
||||||
|
|
||||||
logTerm();
|
logTerm();
|
||||||
zmDbClose();
|
zmDbClose();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
return (EXIT_SUCCESS);
|
if (debug != 1) {
|
||||||
|
if (debug) printf("Running stream...");
|
||||||
|
|
||||||
|
// Output headers
|
||||||
|
fprintf(stdout, "Server: ZoneMinder Video Server/%s\r\n", ZM_VERSION);
|
||||||
|
time_t now = time(0);
|
||||||
|
char date_string[64];
|
||||||
|
strftime(date_string, sizeof (date_string) - 1, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now));
|
||||||
|
fprintf(stdout, "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n");
|
||||||
|
fprintf(stdout, "Last-Modified: %s\r\n", date_string);
|
||||||
|
fprintf(stdout, "Cache-Control: no-store, no-cache, must-revalidate\r\n");
|
||||||
|
fprintf(stdout, "Cache-Control: post-check=0, pre-check=0\r\n");
|
||||||
|
fprintf(stdout, "Pragma: no-cache\r\n");
|
||||||
|
|
||||||
|
// Run stream
|
||||||
|
stream.runStream();
|
||||||
|
}
|
||||||
|
if (debug) printf("Done.\n");
|
||||||
|
|
||||||
|
logTerm();
|
||||||
|
zmDbClose();
|
||||||
|
|
||||||
|
return (EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,12 +222,12 @@
|
||||||
/**
|
/**
|
||||||
* A random string used in security hashing methods.
|
* A random string used in security hashing methods.
|
||||||
*/
|
*/
|
||||||
Configure::write('Security.salt', 'Q0MjGG2xRQEhJVQR85WhFJKI7f2St8RYMlVR7GNQ');
|
Configure::write('Security.salt', 'dhvuDdqOdgzivhu3Cr1pTAzt0z27NygqxSu7NiYw');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A random numeric string (digits only) used to encrypt/decrypt strings.
|
* A random numeric string (digits only) used to encrypt/decrypt strings.
|
||||||
*/
|
*/
|
||||||
Configure::write('Security.cipherSeed', '02670120062639232092038865362');
|
Configure::write('Security.cipherSeed', '38170258349803886784814175156');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply timestamps with the last modified time to static assets (js, css, images).
|
* Apply timestamps with the last modified time to static assets (js, css, images).
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit e22c1563a51d86aac0d5054beee28b4afb60c802
|
Subproject commit c3976f1478c681b0bbc132ec3a3e82c3984eeed5
|
Loading…
Reference in New Issue