2003-03-26 19:57:29 +08:00
//
2003-04-22 22:15:01 +08:00
// ZoneMinder Event Class Implementation, $Date$, $Revision$
2006-01-17 18:56:30 +08:00
// Copyright (C) 2003, 2004, 2005, 2006 Philip Coombes
2003-03-26 19:57:29 +08:00
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
2003-04-22 22:15:01 +08:00
# include <fcntl.h>
# include <sys/socket.h>
# include <sys/un.h>
# include <sys/uio.h>
# include <getopt.h>
2004-01-28 01:03:45 +08:00
# include <glob.h>
2003-04-22 22:15:01 +08:00
2003-03-26 19:57:29 +08:00
# include "zm.h"
# include "zm_db.h"
2004-03-04 23:05:54 +08:00
# include "zm_mpeg.h"
2003-03-26 19:57:29 +08:00
# include "zm_event.h"
# include "zm_monitor.h"
2003-04-22 22:15:01 +08:00
# include "zmf.h"
2004-02-16 04:07:16 +08:00
bool Event : : initialised = false ;
2004-03-22 18:33:40 +08:00
char Event : : capture_file_format [ PATH_MAX ] ;
char Event : : analyse_file_format [ PATH_MAX ] ;
char Event : : general_file_format [ PATH_MAX ] ;
2004-02-16 04:07:16 +08:00
2004-09-25 20:37:45 +08:00
int Event : : pre_alarm_count = 0 ;
Event : : PreAlarmData Event : : pre_alarm_data [ MAX_PRE_ALARM_FRAMES ] = { 0 } ;
2006-01-15 06:47:02 +08:00
Event : : Event ( Monitor * p_monitor , struct timeval p_start_time , const char * p_cause , const char * p_text ) : monitor ( p_monitor ) , start_time ( p_start_time )
2003-03-26 19:57:29 +08:00
{
2004-02-16 04:07:16 +08:00
if ( ! initialised )
Initialise ( ) ;
2006-01-15 06:47:02 +08:00
strncpy ( cause , p_cause , sizeof ( cause ) ) ;
strncpy ( text , p_text , sizeof ( text ) ) ;
2003-07-04 04:39:47 +08:00
static char sql [ BUFSIZ ] ;
2003-03-26 19:57:29 +08:00
static char start_time_str [ 32 ] ;
strftime ( start_time_str , sizeof ( start_time_str ) , " %Y-%m-%d %H:%M:%S " , localtime ( & start_time . tv_sec ) ) ;
2006-01-15 06:47:02 +08:00
snprintf ( sql , sizeof ( sql ) , " insert into Events ( MonitorId, Name, StartTime, Width, Height, Cause, Notes ) values ( %d, 'New Event', '%s', %d, %d, '%s', '%s' ) " , monitor - > Id ( ) , start_time_str , monitor - > Width ( ) , monitor - > Height ( ) , cause , text ) ;
2003-03-26 19:57:29 +08:00
if ( mysql_query ( & dbconn , sql ) )
{
2003-04-15 17:04:38 +08:00
Error ( ( " Can't insert event: %s " , mysql_error ( & dbconn ) ) ) ;
2003-03-26 19:57:29 +08:00
exit ( mysql_errno ( & dbconn ) ) ;
}
id = mysql_insert_id ( & dbconn ) ;
2003-09-23 17:52:45 +08:00
end_time . tv_sec = 0 ;
2003-03-26 19:57:29 +08:00
frames = 0 ;
alarm_frames = 0 ;
tot_score = 0 ;
max_score = 0 ;
2005-05-16 17:27:06 +08:00
snprintf ( path , sizeof ( path ) , " %s/%d/%d " , config . dir_events , monitor - > Id ( ) , id ) ;
2003-03-26 19:57:29 +08:00
struct stat statbuf ;
errno = 0 ;
stat ( path , & statbuf ) ;
if ( errno = = ENOENT | | errno = = ENOTDIR )
{
if ( mkdir ( path , 0755 ) )
{
2003-04-15 17:04:38 +08:00
Error ( ( " Can't make %s: %s " , path , strerror ( errno ) ) ) ;
2003-03-26 19:57:29 +08:00
}
}
2004-05-05 17:19:07 +08:00
last_db_frame = 0 ;
2003-03-26 19:57:29 +08:00
}
Event : : ~ Event ( )
{
2004-05-05 17:19:07 +08:00
if ( frames > last_db_frame )
{
struct DeltaTimeval delta_time ;
DELTA_TIMEVAL ( delta_time , end_time , start_time , DT_PREC_2 ) ;
Debug ( 1 , ( " Adding closing frame %d to DB " , frames ) ) ;
static char sql [ BUFSIZ ] ;
2004-09-25 20:37:45 +08:00
snprintf ( sql , sizeof ( sql ) , " insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ( %d, %d, from_unixtime( %d ), %s%ld.%02ld ) " , id , frames , end_time . tv_sec , delta_time . positive ? " " : " - " , delta_time . sec , delta_time . fsec ) ;
2004-05-05 17:19:07 +08:00
if ( mysql_query ( & dbconn , sql ) )
{
Error ( ( " Can't insert frame: %s " , mysql_error ( & dbconn ) ) ) ;
exit ( mysql_errno ( & dbconn ) ) ;
}
}
2003-07-04 04:39:47 +08:00
static char sql [ BUFSIZ ] ;
2003-03-26 19:57:29 +08:00
static char end_time_str [ 32 ] ;
struct DeltaTimeval delta_time ;
2003-05-16 18:17:05 +08:00
DELTA_TIMEVAL ( delta_time , end_time , start_time , DT_PREC_2 ) ;
2003-03-26 19:57:29 +08:00
strftime ( end_time_str , sizeof ( end_time_str ) , " %Y-%m-%d %H:%M:%S " , localtime ( & end_time . tv_sec ) ) ;
2004-09-23 21:43:10 +08:00
snprintf ( sql , sizeof ( sql ) , " update Events set Name='%s%d', EndTime = '%s', Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d where Id = %d " , monitor - > EventPrefix ( ) , id , end_time_str , delta_time . positive ? " " : " - " , delta_time . sec , delta_time . fsec , frames , alarm_frames , tot_score , ( int ) ( alarm_frames ? ( tot_score / alarm_frames ) : 0 ) , max_score , id ) ;
2003-03-26 19:57:29 +08:00
if ( mysql_query ( & dbconn , sql ) )
{
2003-04-15 17:04:38 +08:00
Error ( ( " Can't update event: %s " , mysql_error ( & dbconn ) ) ) ;
2003-03-26 19:57:29 +08:00
exit ( mysql_errno ( & dbconn ) ) ;
}
}
2003-04-22 22:15:01 +08:00
int Event : : sd = - 1 ;
bool Event : : OpenFrameSocket ( int monitor_id )
{
if ( sd > 0 )
{
close ( sd ) ;
}
sd = socket ( AF_UNIX , SOCK_STREAM , 0 ) ;
if ( sd < 0 )
{
Error ( ( " Can't create socket: %s " , strerror ( errno ) ) ) ;
return ( false ) ;
}
2005-05-16 17:27:06 +08:00
int socket_buffer_size = config . frame_socket_size ;
2004-03-04 20:50:42 +08:00
if ( socket_buffer_size > 0 )
{
if ( setsockopt ( sd , SOL_SOCKET , SO_SNDBUF , & socket_buffer_size , sizeof ( socket_buffer_size ) ) < 0 )
{
Error ( ( " Can't get socket buffer size to %d, error = %s " , socket_buffer_size , strerror ( errno ) ) ) ;
close ( sd ) ;
sd = - 1 ;
return ( false ) ;
}
}
2003-04-22 22:15:01 +08:00
int flags ;
if ( ( flags = fcntl ( sd , F_GETFL ) ) < 0 )
{
Error ( ( " Can't get socket flags, error = %s " , strerror ( errno ) ) ) ;
close ( sd ) ;
sd = - 1 ;
return ( false ) ;
}
flags | = O_NONBLOCK ;
if ( fcntl ( sd , F_SETFL , flags ) < 0 )
{
Error ( ( " Can't set socket flags, error = %s " , strerror ( errno ) ) ) ;
close ( sd ) ;
sd = - 1 ;
return ( false ) ;
}
char sock_path [ PATH_MAX ] = " " ;
2005-05-16 17:27:06 +08:00
snprintf ( sock_path , sizeof ( sock_path ) , " %s/zmf-%d.sock " , config . path_socks , monitor_id ) ;
2003-04-22 22:15:01 +08:00
struct sockaddr_un addr ;
2004-04-20 00:02:17 +08:00
strncpy ( addr . sun_path , sock_path , sizeof ( addr . sun_path ) ) ;
2003-04-22 22:15:01 +08:00
addr . sun_family = AF_UNIX ;
if ( connect ( sd , ( struct sockaddr * ) & addr , strlen ( addr . sun_path ) + sizeof ( addr . sun_family ) ) < 0 )
{
2004-03-17 18:28:07 +08:00
Warning ( ( " Can't connect to frame server: %s " , strerror ( errno ) ) ) ;
2003-04-22 22:15:01 +08:00
close ( sd ) ;
sd = - 1 ;
return ( false ) ;
}
2004-03-17 18:28:07 +08:00
Debug ( 1 , ( " Opened connection to frame server " ) ) ;
2003-04-22 22:15:01 +08:00
return ( true ) ;
}
bool Event : : ValidateFrameSocket ( int monitor_id )
{
if ( sd < 0 )
{
return ( OpenFrameSocket ( monitor_id ) ) ;
}
return ( true ) ;
}
bool Event : : SendFrameImage ( const Image * image , bool alarm_frame )
{
if ( ! ValidateFrameSocket ( monitor - > Id ( ) ) )
{
return ( false ) ;
}
static int jpg_buffer_size = 0 ;
2003-05-02 23:03:16 +08:00
static unsigned char jpg_buffer [ ZM_MAX_IMAGE_SIZE ] ;
2003-04-22 22:15:01 +08:00
2005-11-19 01:26:12 +08:00
image - > EncodeJpeg ( jpg_buffer , & jpg_buffer_size , config . jpeg_file_quality ) ;
2003-04-22 22:15:01 +08:00
static FrameHeader frame_header ;
frame_header . event_id = id ;
frame_header . frame_id = frames ;
frame_header . alarm_frame = alarm_frame ;
frame_header . image_length = jpg_buffer_size ;
struct iovec iovecs [ 2 ] ;
iovecs [ 0 ] . iov_base = & frame_header ;
iovecs [ 0 ] . iov_len = sizeof ( frame_header ) ;
iovecs [ 1 ] . iov_base = jpg_buffer ;
iovecs [ 1 ] . iov_len = jpg_buffer_size ;
2004-01-15 05:26:47 +08:00
ssize_t writev_size = sizeof ( frame_header ) + jpg_buffer_size ;
ssize_t writev_result = writev ( sd , iovecs , sizeof ( iovecs ) / sizeof ( * iovecs ) ) ;
if ( writev_result ! = writev_size )
2003-04-22 22:15:01 +08:00
{
2004-01-15 05:26:47 +08:00
if ( writev_result < 0 )
2003-04-22 22:15:01 +08:00
{
2004-01-15 05:26:47 +08:00
if ( errno = = EAGAIN )
{
Warning ( ( " Blocking write detected " ) ) ;
}
else
{
Error ( ( " Can't write frame: %s " , strerror ( errno ) ) ) ;
close ( sd ) ;
sd = - 1 ;
}
2003-04-22 22:15:01 +08:00
}
else
{
2004-01-15 05:26:47 +08:00
Error ( ( " Incomplete frame write: %d of %d bytes written " , writev_result , writev_size ) ) ;
2003-04-22 22:15:01 +08:00
close ( sd ) ;
sd = - 1 ;
}
return ( false ) ;
}
2003-10-19 17:48:10 +08:00
Debug ( 1 , ( " Wrote frame image, %d bytes " , jpg_buffer_size ) ) ;
2003-04-22 22:15:01 +08:00
return ( true ) ;
}
2004-02-16 04:07:16 +08:00
bool Event : : WriteFrameImage ( Image * image , struct timeval timestamp , const char * event_file , bool alarm_frame )
2003-04-22 22:15:01 +08:00
{
2005-05-16 17:27:06 +08:00
if ( config . timestamp_on_capture )
2004-02-16 04:07:16 +08:00
{
2005-05-16 17:27:06 +08:00
if ( ! config . opt_frame_server | | ! SendFrameImage ( image , alarm_frame ) )
2004-02-16 19:12:28 +08:00
{
image - > WriteJpeg ( event_file ) ;
}
2004-02-16 04:07:16 +08:00
}
2004-02-16 19:12:28 +08:00
else
2003-04-22 22:15:01 +08:00
{
2004-02-16 19:12:28 +08:00
Image ts_image ( * image ) ;
monitor - > TimestampImage ( & ts_image , timestamp . tv_sec ) ;
2005-05-16 17:27:06 +08:00
if ( ! config . opt_frame_server | | ! SendFrameImage ( & ts_image , alarm_frame ) )
2004-02-16 19:12:28 +08:00
{
ts_image . WriteJpeg ( event_file ) ;
}
2003-04-22 22:15:01 +08:00
}
return ( true ) ;
}
2004-02-16 04:07:16 +08:00
void Event : : AddFrames ( int n_frames , Image * * images , struct timeval * * timestamps )
2003-04-17 23:38:21 +08:00
{
2003-11-05 22:49:55 +08:00
static char sql [ BUFSIZ ] ;
2004-09-25 20:37:45 +08:00
strncpy ( sql , " insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values " , BUFSIZ ) ;
2003-04-17 23:38:21 +08:00
for ( int i = 0 ; i < n_frames ; i + + )
{
frames + + ;
2003-04-22 22:15:01 +08:00
2003-04-17 23:38:21 +08:00
static char event_file [ PATH_MAX ] ;
2004-04-20 00:02:17 +08:00
snprintf ( event_file , sizeof ( event_file ) , capture_file_format , path , frames ) ;
2003-04-22 22:15:01 +08:00
Debug ( 1 , ( " Writing pre-capture frame %d " , frames ) ) ;
2004-02-16 04:07:16 +08:00
WriteFrameImage ( images [ i ] , * ( timestamps [ i ] ) , event_file ) ;
2003-04-17 23:38:21 +08:00
struct DeltaTimeval delta_time ;
2003-05-16 18:17:05 +08:00
DELTA_TIMEVAL ( delta_time , * ( timestamps [ i ] ) , start_time , DT_PREC_2 ) ;
2003-04-17 23:38:21 +08:00
2004-04-20 00:02:17 +08:00
int sql_len = strlen ( sql ) ;
2004-09-25 20:37:45 +08:00
snprintf ( sql + sql_len , sizeof ( sql ) - sql_len , " ( %d, %d, from_unixtime(%d), %s%ld.%02ld ), " , id , frames , timestamps [ i ] - > tv_sec , delta_time . positive ? " " : " - " , delta_time . sec , delta_time . fsec ) ;
2003-04-17 23:38:21 +08:00
}
Debug ( 1 , ( " Adding %d frames to DB " , n_frames ) ) ;
* ( sql + strlen ( sql ) - 2 ) = ' \0 ' ;
if ( mysql_query ( & dbconn , sql ) )
{
Error ( ( " Can't insert frames: %s " , mysql_error ( & dbconn ) ) ) ;
exit ( mysql_errno ( & dbconn ) ) ;
}
2004-05-05 17:19:07 +08:00
last_db_frame = frames ;
2003-04-17 23:38:21 +08:00
}
2004-03-04 23:13:10 +08:00
void Event : : AddFrame ( Image * image , struct timeval timestamp , int score , Image * alarm_image )
2003-03-26 19:57:29 +08:00
{
frames + + ;
static char event_file [ PATH_MAX ] ;
2004-04-20 00:02:17 +08:00
snprintf ( event_file , sizeof ( event_file ) , capture_file_format , path , frames ) ;
2003-04-22 22:15:01 +08:00
Debug ( 1 , ( " Writing capture frame %d " , frames ) ) ;
2004-02-16 04:07:16 +08:00
WriteFrameImage ( image , timestamp , event_file ) ;
2003-03-26 19:57:29 +08:00
struct DeltaTimeval delta_time ;
2003-05-16 18:17:05 +08:00
DELTA_TIMEVAL ( delta_time , timestamp , start_time , DT_PREC_2 ) ;
2003-03-26 19:57:29 +08:00
2005-05-16 17:27:06 +08:00
bool db_frame = ( score > = 0 ) | | ( ( frames % config . bulk_frame_interval ) = = 0 ) | | ! frames ;
2004-03-04 23:13:10 +08:00
if ( db_frame )
2003-03-26 19:57:29 +08:00
{
2004-03-05 18:31:39 +08:00
const char * frame_type = score > 0 ? " Alarm " : ( score < 0 ? " Bulk " : " Normal " ) ;
2004-03-04 23:13:10 +08:00
Debug ( 1 , ( " Adding frame %d to DB " , frames ) ) ;
static char sql [ BUFSIZ ] ;
2004-09-25 20:37:45 +08:00
snprintf ( sql , sizeof ( sql ) , " insert into Frames ( EventId, FrameId, Type, TimeStamp, Delta, Score ) values ( %d, %d, '%s', from_unixtime( %d ), %s%ld.%02ld, %d ) " , id , frames , frame_type , timestamp . tv_sec , delta_time . positive ? " " : " - " , delta_time . sec , delta_time . fsec , score ) ;
2004-03-04 23:13:10 +08:00
if ( mysql_query ( & dbconn , sql ) )
{
Error ( ( " Can't insert frame: %s " , mysql_error ( & dbconn ) ) ) ;
exit ( mysql_errno ( & dbconn ) ) ;
}
2004-05-05 17:19:07 +08:00
last_db_frame = frames ;
2003-03-26 19:57:29 +08:00
}
2004-03-04 23:13:10 +08:00
if ( score > 0 )
2003-03-26 19:57:29 +08:00
{
end_time = timestamp ;
alarm_frames + + ;
2003-04-22 22:15:01 +08:00
2003-03-26 19:57:29 +08:00
tot_score + = score ;
if ( score > max_score )
max_score = score ;
2003-11-21 18:38:41 +08:00
if ( alarm_image )
{
2004-04-20 00:02:17 +08:00
snprintf ( event_file , sizeof ( event_file ) , analyse_file_format , path , frames ) ;
2003-11-21 18:38:41 +08:00
Debug ( 1 , ( " Writing analysis frame %d " , frames ) ) ;
2004-02-16 04:07:16 +08:00
WriteFrameImage ( alarm_image , timestamp , event_file , true ) ;
2003-11-21 18:38:41 +08:00
}
2003-03-26 19:57:29 +08:00
}
2004-01-28 01:03:45 +08:00
2005-05-16 17:27:06 +08:00
if ( config . record_diag_images )
2004-01-28 01:03:45 +08:00
{
char diag_glob [ PATH_MAX ] = " " ;
2005-05-16 17:27:06 +08:00
snprintf ( diag_glob , sizeof ( diag_glob ) , " %s/%d/diag-*.jpg " , config . dir_events , monitor - > Id ( ) ) ;
2004-01-28 01:03:45 +08:00
glob_t pglob ;
int glob_status = glob ( diag_glob , 0 , 0 , & pglob ) ;
if ( glob_status ! = 0 )
{
if ( glob_status < 0 )
{
Error ( ( " Can't glob '%s': %s " , diag_glob , strerror ( errno ) ) ) ;
}
else
{
2004-03-17 18:28:07 +08:00
Debug ( 1 , ( " Can't glob '%s': %d " , diag_glob , glob_status ) ) ;
2004-01-28 01:03:45 +08:00
}
}
else
{
char new_diag_path [ PATH_MAX ] = " " ;
for ( int i = 0 ; i < pglob . gl_pathc ; i + + )
{
char * diag_path = pglob . gl_pathv [ i ] ;
char * diag_file = strstr ( diag_path , " diag- " ) ;
if ( diag_file )
{
2004-04-20 00:02:17 +08:00
snprintf ( new_diag_path , sizeof ( new_diag_path ) , general_file_format , path , frames , diag_file ) ;
2004-01-28 01:03:45 +08:00
if ( rename ( diag_path , new_diag_path ) < 0 )
{
Error ( ( " Can't rename '%s' to '%s': %s " , diag_path , new_diag_path , strerror ( errno ) ) ) ;
}
}
}
}
globfree ( & pglob ) ;
}
2003-03-26 19:57:29 +08:00
}
2006-01-12 23:41:39 +08:00
void Event : : StreamEvent ( int event_id , int frame_id , int scale , int rate , int maxfps )
2003-03-26 19:57:29 +08:00
{
2003-07-04 04:39:47 +08:00
static char sql [ BUFSIZ ] ;
2004-02-06 05:58:44 +08:00
static char eventpath [ PATH_MAX ] ;
2004-01-28 01:03:45 +08:00
2004-03-23 19:43:36 +08:00
if ( ! initialised )
Initialise ( ) ;
2004-04-20 00:02:17 +08:00
snprintf ( sql , sizeof ( sql ) , " select M.Id, M.Name, E.Frames, max(F.Delta)-min(F.Delta) as Duration from Events as E inner join Monitors as M on E.MonitorId = M.Id inner join Frames as F on E.Id = F.EventId where E.Id = %d group by E.Id " , event_id ) ;
2003-03-26 19:57:29 +08:00
if ( mysql_query ( & dbconn , sql ) )
{
2003-04-15 17:04:38 +08:00
Error ( ( " Can't run query: %s " , mysql_error ( & dbconn ) ) ) ;
2003-03-26 19:57:29 +08:00
exit ( mysql_errno ( & dbconn ) ) ;
}
MYSQL_RES * result = mysql_store_result ( & dbconn ) ;
if ( ! result )
{
2003-04-15 17:04:38 +08:00
Error ( ( " Can't use query result: %s " , mysql_error ( & dbconn ) ) ) ;
2003-03-26 19:57:29 +08:00
exit ( mysql_errno ( & dbconn ) ) ;
}
2004-02-06 05:58:44 +08:00
MYSQL_ROW dbrow = mysql_fetch_row ( result ) ;
if ( mysql_errno ( & dbconn ) )
{
Error ( ( " Can't fetch row: %s " , mysql_error ( & dbconn ) ) ) ;
exit ( mysql_errno ( & dbconn ) ) ;
}
2005-05-16 17:27:06 +08:00
snprintf ( eventpath , sizeof ( eventpath ) , " %s/%s/%d/%d " , ZM_PATH_WEB , config . dir_events , atoi ( dbrow [ 0 ] ) , event_id ) ;
2004-03-23 19:43:36 +08:00
int frames = atoi ( dbrow [ 2 ] ) ;
2005-01-17 01:49:04 +08:00
double duration = atof ( dbrow [ 3 ] ) ;
2004-03-15 16:48:52 +08:00
int min_fps = 1 ;
int max_fps = maxfps ;
2005-01-17 01:49:04 +08:00
int base_fps = ( int ) ( ( double ) frames / duration ) ;
2004-03-15 16:48:52 +08:00
int effective_fps = ( base_fps * rate ) / ZM_RATE_SCALE ;
int frame_mod = 1 ;
// Min frame repeat?
while ( effective_fps > max_fps )
{
effective_fps / = 2 ;
frame_mod * = 2 ;
}
2005-01-17 01:49:04 +08:00
Debug ( 1 , ( " Frames:%d, Duration: %.2f, BFPS:%d, EFPS:%d, FM:%d " , frames , duration , base_fps , effective_fps , frame_mod ) ) ;
2004-02-06 05:58:44 +08:00
mysql_free_result ( result ) ;
2006-01-12 23:41:39 +08:00
snprintf ( sql , sizeof ( sql ) , " select FrameId, EventId, Delta from Frames where EventId = %d and FrameId >= %d order by FrameId " , event_id , frame_id ) ;
2004-02-06 05:58:44 +08:00
if ( mysql_query ( & dbconn , sql ) )
{
Error ( ( " Can't run query: %s " , mysql_error ( & dbconn ) ) ) ;
exit ( mysql_errno ( & dbconn ) ) ;
}
result = mysql_store_result ( & dbconn ) ;
if ( ! result )
{
Error ( ( " Can't use query result: %s " , mysql_error ( & dbconn ) ) ) ;
exit ( mysql_errno ( & dbconn ) ) ;
}
2003-03-26 19:57:29 +08:00
2004-03-04 23:05:54 +08:00
fprintf ( stdout , " Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame \r \n \r \n " ) ;
2003-03-26 19:57:29 +08:00
FILE * fdj = NULL ;
int n_bytes = 0 ;
2006-01-12 23:41:39 +08:00
int id = frame_id , db_id , last_db_id = 0 ;
2004-03-15 16:48:52 +08:00
double base_delta , last_delta = 0.0 L ;
double db_delta , last_db_delta = 0.0 L ;
unsigned int delta_us = 0 ;
2003-10-16 17:00:53 +08:00
static unsigned char buffer [ ZM_MAX_IMAGE_SIZE ] ;
2004-03-15 16:48:52 +08:00
while ( ( id < = frames ) & & ( dbrow = mysql_fetch_row ( result ) ) )
2003-03-26 19:57:29 +08:00
{
2006-01-12 23:41:39 +08:00
if ( id = = frame_id )
2003-05-23 00:34:22 +08:00
{
2004-03-15 16:48:52 +08:00
base_delta = atof ( dbrow [ 2 ] ) ;
2003-05-23 00:34:22 +08:00
}
2003-10-16 17:00:53 +08:00
2004-03-15 16:48:52 +08:00
db_id = atoi ( dbrow [ 0 ] ) ;
db_delta = atof ( dbrow [ 2 ] ) - base_delta ;
bool db_written = false ;
while ( db_id > = id )
2003-03-26 19:57:29 +08:00
{
2004-03-15 16:48:52 +08:00
if ( ( frame_mod = = 1 ) | | ( ( ( id - 1 ) % frame_mod ) = = 0 ) )
2003-10-16 17:00:53 +08:00
{
2004-03-15 16:48:52 +08:00
double this_delta = last_db_delta + ( ( ( id - last_db_id ) * ( db_delta - last_db_delta ) ) / ( db_id - last_db_id ) ) ;
2006-01-13 01:07:26 +08:00
if ( this_delta > last_delta )
delta_us = ( unsigned int ) ( ( this_delta - last_delta ) * 1000000 ) ;
else
delta_us = 0 ;
2004-03-15 16:48:52 +08:00
if ( rate ! = ZM_RATE_SCALE )
delta_us = ( delta_us * ZM_RATE_SCALE ) / rate ;
Debug ( 2 , ( " I:%d, DI:%d, LDBI:%d, DD:%lf, LD:%lf, LDBD:%lf, TD:%lf, DU:%d " , id , db_id , last_db_id , db_delta , last_delta , last_db_delta , this_delta , delta_us ) ) ;
static char filepath [ PATH_MAX ] ;
2004-04-20 00:02:17 +08:00
snprintf ( filepath , sizeof ( filepath ) , capture_file_format , eventpath , id ) ;
2004-03-15 16:48:52 +08:00
if ( scale = = 100 )
{
if ( ( fdj = fopen ( filepath , " r " ) ) )
{
2004-03-23 19:43:36 +08:00
n_bytes = fread ( buffer , 1 , sizeof ( buffer ) , fdj ) ;
2004-03-15 16:48:52 +08:00
fclose ( fdj ) ;
}
else
{
Error ( ( " Can't open %s: %s " , filepath , strerror ( errno ) ) ) ;
}
}
else
2003-10-16 17:00:53 +08:00
{
2004-03-15 16:48:52 +08:00
Image image ( filepath ) ;
image . Scale ( scale ) ;
image . EncodeJpeg ( buffer , & n_bytes ) ;
2003-10-16 17:00:53 +08:00
}
2005-06-23 16:40:43 +08:00
fprintf ( stdout , " --ZoneMinderFrame \r \n " ) ;
2004-03-23 19:43:36 +08:00
fprintf ( stdout , " Content-Length: %d \r \n " , n_bytes ) ;
fprintf ( stdout , " Content-Type: image/jpeg \r \n \r \n " ) ;
2005-06-23 16:40:43 +08:00
fwrite ( buffer , n_bytes , 1 , stdout ) ;
fprintf ( stdout , " \r \n \r \n " ) ;
2004-03-15 16:48:52 +08:00
fflush ( stdout ) ;
last_delta = this_delta ;
db_written = true ;
usleep ( delta_us ) ;
2003-03-26 19:57:29 +08:00
}
2004-03-15 16:48:52 +08:00
id + + ;
2003-03-26 19:57:29 +08:00
}
2004-03-15 16:48:52 +08:00
if ( db_written )
2003-03-26 19:57:29 +08:00
{
2004-03-15 16:48:52 +08:00
last_db_id = db_id ;
last_db_delta = db_delta ;
2004-03-04 23:05:54 +08:00
}
}
if ( mysql_errno ( & dbconn ) )
{
Error ( ( " Can't fetch row: %s " , mysql_error ( & dbconn ) ) ) ;
exit ( mysql_errno ( & dbconn ) ) ;
}
// Yadda yadda
mysql_free_result ( result ) ;
}
# if HAVE_LIBAVCODEC
2006-01-12 23:41:39 +08:00
void Event : : StreamMpeg ( int event_id , int frame_id , const char * format , int scale , int rate , int maxfps , int bitrate )
2004-03-04 23:05:54 +08:00
{
static char sql [ BUFSIZ ] ;
static char eventpath [ PATH_MAX ] ;
2004-03-23 19:43:36 +08:00
if ( ! initialised )
Initialise ( ) ;
2004-04-20 00:02:17 +08:00
snprintf ( sql , sizeof ( sql ) , " select M.Id, M.Name, E.Frames, max(F.Delta)-min(F.Delta) as Duration from Events as E inner join Monitors as M on E.MonitorId = M.Id inner join Frames as F on E.Id = F.EventId where E.Id = %d group by E.Id " , event_id ) ;
2004-03-04 23:05:54 +08:00
if ( mysql_query ( & dbconn , sql ) )
{
Error ( ( " Can't run query: %s " , mysql_error ( & dbconn ) ) ) ;
exit ( mysql_errno ( & dbconn ) ) ;
}
MYSQL_RES * result = mysql_store_result ( & dbconn ) ;
if ( ! result )
{
Error ( ( " Can't use query result: %s " , mysql_error ( & dbconn ) ) ) ;
exit ( mysql_errno ( & dbconn ) ) ;
}
MYSQL_ROW dbrow = mysql_fetch_row ( result ) ;
if ( mysql_errno ( & dbconn ) )
{
Error ( ( " Can't fetch row: %s " , mysql_error ( & dbconn ) ) ) ;
exit ( mysql_errno ( & dbconn ) ) ;
}
2005-05-16 17:27:06 +08:00
snprintf ( eventpath , sizeof ( eventpath ) , " %s/%s/%d/%d " , ZM_PATH_WEB , config . dir_events , atoi ( dbrow [ 0 ] ) , event_id ) ;
2004-03-23 19:43:36 +08:00
int frames = atoi ( dbrow [ 2 ] ) ;
2005-01-17 01:49:04 +08:00
double duration = atof ( dbrow [ 3 ] ) ;
2004-03-08 18:33:19 +08:00
int min_fps = 1 ;
2004-03-11 19:18:14 +08:00
int max_fps = maxfps ;
2005-01-17 01:49:04 +08:00
int base_fps = ( int ) ( ( double ) frames / duration ) ;
2004-03-08 18:33:19 +08:00
int effective_fps = ( base_fps * rate ) / ZM_RATE_SCALE ;
int frame_mod = 1 ;
// Min frame repeat?
while ( effective_fps > max_fps )
2004-03-04 23:05:54 +08:00
{
2004-03-08 18:33:19 +08:00
effective_fps / = 2 ;
frame_mod * = 2 ;
2004-03-04 23:05:54 +08:00
}
2004-03-08 18:33:19 +08:00
2005-01-17 01:49:04 +08:00
Debug ( 1 , ( " Frames:%d, Duration: %.2f, BFPS:%d, EFPS:%d, FM:%d " , frames , duration , base_fps , effective_fps , frame_mod ) ) ;
2004-03-04 23:05:54 +08:00
mysql_free_result ( result ) ;
2006-01-12 23:41:39 +08:00
snprintf ( sql , sizeof ( sql ) , " select FrameId, EventId, Delta from Frames where EventId = %d and FrameId >= %d order by FrameId " , event_id , frame_id ) ;
2004-03-04 23:05:54 +08:00
if ( mysql_query ( & dbconn , sql ) )
{
Error ( ( " Can't run query: %s " , mysql_error ( & dbconn ) ) ) ;
exit ( mysql_errno ( & dbconn ) ) ;
}
result = mysql_store_result ( & dbconn ) ;
if ( ! result )
{
Error ( ( " Can't use query result: %s " , mysql_error ( & dbconn ) ) ) ;
exit ( mysql_errno ( & dbconn ) ) ;
}
VideoStream * vid_stream = 0 ;
2006-01-12 23:41:39 +08:00
int id = frame_id , last_id = 0 ;
2004-03-08 18:33:19 +08:00
double base_delta , last_delta = 0.0 L ;
unsigned int delta_ms = 0 ;
while ( ( id < = frames ) & & ( dbrow = mysql_fetch_row ( result ) ) )
2004-03-04 23:05:54 +08:00
{
2006-01-12 23:41:39 +08:00
if ( id = = frame_id )
2004-03-04 23:05:54 +08:00
{
2004-03-08 18:33:19 +08:00
base_delta = last_delta = atof ( dbrow [ 2 ] ) ;
2003-03-26 19:57:29 +08:00
}
2004-03-04 23:05:54 +08:00
2004-03-08 18:33:19 +08:00
int db_id = atoi ( dbrow [ 0 ] ) ;
double db_delta = atof ( dbrow [ 2 ] ) - base_delta ;
2004-03-15 16:48:52 +08:00
bool db_written = false ;
2004-03-08 18:33:19 +08:00
while ( db_id > = id )
2004-03-04 23:05:54 +08:00
{
2004-03-08 18:33:19 +08:00
if ( ( frame_mod = = 1 ) | | ( ( ( id - 1 ) % frame_mod ) = = 0 ) )
{
static char filepath [ PATH_MAX ] ;
2004-04-20 00:02:17 +08:00
snprintf ( filepath , sizeof ( filepath ) , capture_file_format , eventpath , id ) ;
2004-03-08 18:33:19 +08:00
Image image ( filepath ) ;
if ( ! vid_stream )
{
vid_stream = new VideoStream ( " pipe: " , format , bitrate , effective_fps , image . Colours ( ) , ( image . Width ( ) * scale ) / ZM_SCALE_SCALE , ( image . Height ( ) * scale ) / ZM_SCALE_SCALE ) ;
2005-12-07 21:42:25 +08:00
fprintf ( stdout , " Content-type: %s \r \n \r \n " , vid_stream - > MimeType ( ) ) ;
vid_stream - > OpenStream ( ) ;
2004-03-08 18:33:19 +08:00
}
if ( scale ! = 100 )
{
image . Scale ( scale ) ;
}
double temp_delta = ( ( id - last_id ) * ( db_delta - last_delta ) ) / ( db_id - last_id ) ;
delta_ms = ( unsigned int ) ( ( last_delta + temp_delta ) * 1000 ) ;
if ( rate ! = ZM_RATE_SCALE )
delta_ms = ( delta_ms * ZM_RATE_SCALE ) / rate ;
2006-01-15 06:47:02 +08:00
double pts = vid_stream - > EncodeFrame ( image . Buffer ( ) , image . Size ( ) , config . mpeg_timed_frames , delta_ms ) ;
2004-03-08 18:33:19 +08:00
2004-03-15 16:48:52 +08:00
Debug ( 2 , ( " I:%d, DI:%d, LI:%d, DD:%lf, LD:%lf, TD:%lf, DM:%d, PTS:%lf " , id , db_id , last_id , db_delta , last_delta , temp_delta , delta_ms , pts ) ) ;
db_written = true ;
2004-03-08 18:33:19 +08:00
}
id + + ;
2004-03-04 23:05:54 +08:00
}
2004-03-15 16:48:52 +08:00
if ( db_written )
{
last_id = db_id ;
last_delta = db_delta ;
2004-03-15 17:37:21 +08:00
}
2003-03-26 19:57:29 +08:00
}
if ( mysql_errno ( & dbconn ) )
{
2003-04-15 17:04:38 +08:00
Error ( ( " Can't fetch row: %s " , mysql_error ( & dbconn ) ) ) ;
2003-03-26 19:57:29 +08:00
exit ( mysql_errno ( & dbconn ) ) ;
}
// Yadda yadda
mysql_free_result ( result ) ;
2004-03-04 23:05:54 +08:00
delete vid_stream ;
2003-03-26 19:57:29 +08:00
}
2004-03-04 23:05:54 +08:00
# endif // HAVE_LIBAVCODEC