Compare commits

...

4 Commits

Author SHA1 Message Date
Isaac Connor fcc507b93e whitespace/tabs updates 2017-01-08 16:12:19 -05:00
Isaac Connor d63df84c98 fixup spaces/tabs 2017-01-08 16:09:04 -05:00
Isaac Connor f23ee8441f add defaults for mode and fix single mode on event 2015-08-07 18:41:07 -04:00
Isaac Connor 2901043bc9 re-organize streams to support source=event&mode=single from zms. 2015-07-30 14:16:04 -04:00
9 changed files with 5705 additions and 5674 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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 &notes ); void createNotes( std::string &notes );
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();
}; };

File diff suppressed because it is too large Load Diff

View File

@ -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 = &copy_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 = &copy_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 = &copy_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 = &copy_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 );
}
}
} }

View File

@ -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();

View File

@ -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();
logInit( "zms" ); zmLoadConfig();
ssedetect();
zmSetDefaultTermHandler(); logInit( "zms" );
zmSetDefaultDieHandler();
const char *query = getenv( "QUERY_STRING" ); ssedetect();
if ( query )
{
Debug( 1, "Query: %s", query );
char temp_query[1024];
strncpy( temp_query, query, sizeof(temp_query) );
char *q_ptr = temp_query;
char *parms[16]; // Shouldn't be more than this
int parm_no = 0;
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 ) zmSetDefaultTermHandler();
{ zmSetDefaultDieHandler();
User *user = 0;
if ( strcmp( config.auth_relay, "none" ) == 0 ) const char *query = getenv( "QUERY_STRING" );
{ if ( query )
if ( *username ) {
{ Debug( 1, "Query: %s", query );
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 ); char temp_query[1024];
if ( nph ) strncpy( temp_query, query, sizeof(temp_query) );
{ char *q_ptr = temp_query;
fprintf( stdout, "HTTP/1.0 200 OK\r\n" ); char *parms[16]; // Shouldn't be more than this
} int parm_no = 0;
fprintf( stdout, "Server: ZoneMinder Video Server/%s\r\n", ZM_VERSION ); while( (parm_no < 16) && (parms[parm_no] = strtok( q_ptr, "&" )) )
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 );
} }

View File

@ -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...");
ssedetect(); zmLoadConfig();
printf("Done.\n");
// Setting stream parameters logInit("zmstreamer");
MonitorStream stream;
stream.setStreamScale(scale); // default = 100 (scale) ssedetect();
stream.setStreamReplayRate(100); // default = 100 (rate)
stream.setStreamMaxFPS(maxfps); // default = 10 (maxfps) // Setting stream parameters
if (debug) stream.setStreamTTL(1); MonitorStream stream;
else stream.setStreamTTL(0); // default = 0 (ttl) stream.setStreamScale(scale); // default = 100 (scale)
stream.setStreamQueue(0); // default = 0 (connkey) stream.setStreamReplayRate(100); // default = 100 (rate)
stream.setStreamBuffer(buffer); // default = 0 (buffer) stream.setStreamMaxFPS(maxfps); // default = 10 (maxfps)
stream.setStreamStart(id); // default = 0 (monitor_id) if (debug) stream.setStreamTTL(1);
stream.setStreamType(streamtype); else stream.setStreamTTL(0); // default = 0 (ttl)
if (streamtype == MonitorStream::STREAM_MPEG) { stream.setStreamQueue(0); // default = 0 (connkey)
stream.setStreamBuffer(buffer); // default = 0 (buffer)
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);
} }

View File

@ -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