Beispiel #1
0
Event::~Event()
{
    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[ZM_SQL_SML_BUFSIZ];
        snprintf( sql, sizeof(sql), "insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ( %d, %d, from_unixtime( %ld ), %s%ld.%02ld )", id, frames, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec );
        if ( mysql_query( &dbconn, sql ) )
        {
            Error( "Can't insert frame: %s", mysql_error( &dbconn ) );
            exit( mysql_errno( &dbconn ) );
        }
    }

    static char sql[ZM_SQL_MED_BUFSIZ];

    struct DeltaTimeval delta_time;
    DELTA_TIMEVAL( delta_time, end_time, start_time, DT_PREC_2 );

    snprintf( sql, sizeof(sql), "update Events set Name='%s%d', EndTime = from_unixtime( %ld ), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d where Id = %d", monitor->EventPrefix(), id, end_time.tv_sec, 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 );
    if ( mysql_query( &dbconn, sql ) )
    {
        Error( "Can't update event: %s", mysql_error( &dbconn ) );
        exit( mysql_errno( &dbconn ) );
    }
}
Beispiel #2
0
void Event::AddFrames( int n_frames, Image **images, struct timeval **timestamps )
{
    static char sql[BUFSIZ];
    strncpy( sql, "insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ", BUFSIZ );
    for ( int i = 0; i < n_frames; i++ )
    {
        frames++;

        static char event_file[PATH_MAX];
        snprintf( event_file, sizeof(event_file), capture_file_format, path, frames );

        Debug( 1, "Writing pre-capture frame %d", frames );
        WriteFrameImage( images[i], *(timestamps[i]), event_file );

        struct DeltaTimeval delta_time;
        DELTA_TIMEVAL( delta_time, *(timestamps[i]), start_time, DT_PREC_2 );

        int sql_len = strlen(sql);
        snprintf( sql+sql_len, sizeof(sql)-sql_len, "( %d, %d, from_unixtime(%ld), %s%ld.%02ld ), ", id, frames, timestamps[i]->tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec );
    }

    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 ) );
    }

    last_db_frame = frames;
}
Beispiel #3
0
void Event::AddFramesInternal( int n_frames, int start_frame, Image **images, struct timeval **timestamps ) {
  static char sql[ZM_SQL_LGE_BUFSIZ];
  strncpy(sql, "insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ", sizeof(sql));
  int frameCount = 0;
  for ( int i = start_frame; i < n_frames && i - start_frame < ZM_SQL_BATCH_SIZE; i++ ) {
    if ( timestamps[i]->tv_sec <= 0 ) {
      Debug(1, "Not adding pre-capture frame %d, zero or less than 0 timestamp", i);
      continue;
    }

    frames++;

    static char event_file[PATH_MAX];
    snprintf(event_file, sizeof(event_file), staticConfig.capture_file_format, path, frames);
    if ( monitor->GetOptSaveJPEGs() & 1 ) {
      Debug(1, "Writing pre-capture frame %d", frames);
      WriteFrameImage(images[i], *(timestamps[i]), event_file);
    } else {
      //If this is the first frame, we should add a thumbnail to the event directory
      // ICON: We are working through the pre-event frames so this snapshot won't 
      // neccessarily be of the motion.  But some events are less than 10 frames, 
      // so I am changing this to 1, but we should overwrite it later with a better snapshot.
      if ( frames == 1 ) {
        char snapshot_file[PATH_MAX];
        snprintf(snapshot_file, sizeof(snapshot_file), "%s/snapshot.jpg", path);
        WriteFrameImage(images[i], *(timestamps[i]), snapshot_file);
      }
    }
    if ( videowriter != NULL ) {
      WriteFrameVideo(images[i], *(timestamps[i]), videowriter);
    }

    struct DeltaTimeval delta_time;
    DELTA_TIMEVAL( delta_time, *(timestamps[i]), start_time, DT_PREC_2 );
    // Delta is Decimal(8,2) so 6 integer digits and 2 decimal digits
    if ( delta_time.sec > 999999 ) {
      Warning("Invalid delta_time from_unixtime(%ld), %s%ld.%02ld", 
           timestamps[i]->tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec );
        delta_time.sec = 0;
    }

    int sql_len = strlen(sql);
    snprintf(sql+sql_len, sizeof(sql)-sql_len, "( %" PRIu64 ", %d, from_unixtime(%ld), %s%ld.%02ld ), ", id, frames, timestamps[i]->tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec);

    frameCount++;
  } // end foreach frame

  if ( frameCount ) {
    Debug(1, "Adding %d/%d frames to DB", frameCount, n_frames);
    *(sql+strlen(sql)-2) = '\0';
    db_mutex.lock();
    if ( mysql_query( &dbconn, sql ) ) {
      Error("Can't insert frames: %s, sql was (%s)", mysql_error(&dbconn), sql);
    }
    db_mutex.unlock();
    last_db_frame = frames;
  } else {
    Debug(1, "No valid pre-capture frames to add");
  }
}
Beispiel #4
0
bool Event::WriteFrameVideo( const Image *image, const struct timeval timestamp, VideoWriter* videow ) {
  const Image* frameimg = image;
  Image ts_image;

  /* Checking for invalid parameters */
  if ( videow == NULL ) {
    Error("NULL Video object");
    return false;
  }

  /* If the image does not contain a timestamp, add the timestamp */
  if ( !config.timestamp_on_capture ) {
    ts_image = *image;
    monitor->TimestampImage( &ts_image, &timestamp );
    frameimg = &ts_image;
  }

  /* Calculate delta time */
  struct DeltaTimeval delta_time3;
  DELTA_TIMEVAL( delta_time3, timestamp, start_time, DT_PREC_3 );
  unsigned int timeMS = (delta_time3.sec * delta_time3.prec) + delta_time3.fsec;

  /* Encode and write the frame */
  if ( videowriter->Encode(frameimg, timeMS) != 0 ) {
    Error("Failed encoding video frame");
  }

  return true;
}
Beispiel #5
0
Event::~Event() {

  // We close the videowriter first, because if we finish the event, we might try to view the file, but we aren't done writing it yet.

  /* Close the video file */
  if ( videowriter != NULL ) {
    int nRet = videowriter->Close();
    if ( nRet != 0 ) {
      Error("Failed closing video stream");
    }
    delete videowriter;
    videowriter = NULL;
  }

  // Should not be static because we are multi-threaded
  char sql[ZM_SQL_MED_BUFSIZ];
  struct DeltaTimeval delta_time;
  DELTA_TIMEVAL(delta_time, end_time, start_time, DT_PREC_2);
  Debug(2, "start_time:%d.%d end_time%d.%d", start_time.tv_sec, start_time.tv_usec, end_time.tv_sec, end_time.tv_usec);

  if ( frames > last_db_frame ) {
    Debug(1, "Adding closing frame %d to DB", frames);
    snprintf(sql, sizeof(sql), 
        "INSERT INTO Frames ( EventId, FrameId, TimeStamp, Delta ) VALUES ( %" PRIu64 ", %d, from_unixtime( %ld ), %s%ld.%02ld )",
        id, frames, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec);
    db_mutex.lock();
    if ( mysql_query(&dbconn, sql) ) {
      db_mutex.unlock();
      Error("Can't insert frame: %s", mysql_error(&dbconn));
    } else {
      db_mutex.unlock();
      Debug(1,"Success writing last frame");
    }
  }

  snprintf(sql, sizeof(sql), 
      "UPDATE Events SET Name='%s %" PRIu64 "', EndTime = from_unixtime( %ld ), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d, DefaultVideo = '%s' WHERE Id = %" PRIu64,
      monitor->EventPrefix(), id, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, frames, alarm_frames, tot_score, (int)(alarm_frames?(tot_score/alarm_frames):0), max_score, video_name, id );
  db_mutex.lock();
  while ( mysql_query(&dbconn, sql) && !zm_terminate ) {
    db_mutex.unlock();
    Error("Can't update event: %s reason: %s", sql, mysql_error(&dbconn));
    sleep(1);
    db_mutex.lock();
  }
  db_mutex.unlock();

} // Event::~Event()
Beispiel #6
0
void Event::AddFramesInternal( int n_frames, int start_frame, Image **images, struct timeval **timestamps )
{
    static char sql[ZM_SQL_LGE_BUFSIZ];
    strncpy( sql, "insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ", sizeof(sql) );
    int frameCount = 0;
    for ( int i = start_frame; i < n_frames && i - start_frame < ZM_SQL_BATCH_SIZE; i++ )
    {
        if ( !timestamps[i]->tv_sec )
        {
            Debug( 1, "Not adding pre-capture frame %d, zero timestamp", i );
            continue;
        }

        frames++;

        static char event_file[PATH_MAX];
        snprintf( event_file, sizeof(event_file), capture_file_format, path, frames );

        Debug( 1, "Writing pre-capture frame %d", frames );
        WriteFrameImage( images[i], *(timestamps[i]), event_file );

        struct DeltaTimeval delta_time;
        DELTA_TIMEVAL( delta_time, *(timestamps[i]), start_time, DT_PREC_2 );

        int sql_len = strlen(sql);
        snprintf( sql+sql_len, sizeof(sql)-sql_len, "( %d, %d, from_unixtime(%ld), %s%ld.%02ld ), ", id, frames, timestamps[i]->tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec );

        frameCount++;
    }

    if ( frameCount )
    {
        Debug( 1, "Adding %d/%d frames to DB", frameCount, 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 ) );
        }
        last_db_frame = frames;
    }
    else
    {
        Debug( 1, "No valid pre-capture frames to add" );
    }
}
Beispiel #7
0
int main( int argc, char *argv[] )
{
	self = argv[0];

	srand( getpid() * time( 0 ) );

	const char *device = "";
	const char *protocol = "";
	const char *host = "";
	const char *port = "";
	const char *path = "";
	const char *file = "";
	int monitor_id = -1;

	static struct option long_options[] = {
		{"device", 1, 0, 'd'},
		{"protocol", 1, 0, 'r'},
		{"host", 1, 0, 'H'},
		{"port", 1, 0, 'P'},
	 	{"path", 1, 0, 'p'},
	 	{"file", 1, 0, 'f'},
		{"monitor", 1, 0, 'm'},
		{"help", 0, 0, 'h'},
		{"version", 0, 0, 'v'},
		{0, 0, 0, 0}
	};

	while (1)
	{
		int option_index = 0;

		int c = getopt_long (argc, argv, "d:H:P:p:f:m:h:v", long_options, &option_index);
		if (c == -1)
		{
			break;
		}

		switch (c)
		{
			case 'd':
				device = optarg;
				break;
			case 'H':
				host = optarg;
				break;
			case 'P':
				port = optarg;
				break;
			case 'p':
				path = optarg;
				break;
			case 'f':
				file = optarg;
				break;
			case 'm':
				monitor_id = atoi(optarg);
				break;
			case 'h':
			case '?':
				Usage();
				break;
			case 'v':
				std::cout << ZM_VERSION << "\n";
				exit(0);
			default:
				//fprintf( stderr, "?? getopt returned character code 0%o ??\n", c );
				break;
		}
	}

	if (optind < argc)
	{
		fprintf( stderr, "Extraneous options, " );
		while (optind < argc)
			printf ("%s ", argv[optind++]);
		printf ("\n");
		Usage();
	}

	int modes = ( device[0]?1:0 + host[0]?1:0 + file[0]?1:0 + (monitor_id>0?1:0) );
	if ( modes > 1 )
	{
		fprintf( stderr, "Only one of device, host/port/path, file or monitor id allowed\n" );
		Usage();
		exit( 0 );
	}

	if ( modes < 1 )
	{
		fprintf( stderr, "One of device, host/port/path, file or monitor id must be specified\n" );
		Usage();
		exit( 0 );
	}

	char log_id_string[32] = "";
	if ( device[0] )
	{
		const char *slash_ptr = strrchr( device, '/' );
		snprintf( log_id_string, sizeof(log_id_string), "zmc_d%s", slash_ptr?slash_ptr+1:device );
	}
	else if ( host[0] )
	{
		snprintf( log_id_string, sizeof(log_id_string), "zmc_h%s", host );
	}
	else if ( file[0] )
	{
		const char *slash_ptr = strrchr( file, '/' );
		snprintf( log_id_string, sizeof(log_id_string), "zmc_f%s", slash_ptr?slash_ptr+1:file );
	}
	else
	{
		snprintf( log_id_string, sizeof(log_id_string), "zmc_m%d", monitor_id );
	}

	zmLoadConfig();

	logInit( log_id_string );
	
	ssedetect();

	Monitor **monitors = 0;
	int n_monitors = 0;
#if ZM_HAS_V4L
	if ( device[0] )
	{
		n_monitors = Monitor::LoadLocalMonitors( device, monitors, Monitor::CAPTURE );
	}
	else
#endif // ZM_HAS_V4L
    if ( host[0] )
	{
		if ( !port )
			port = "80";
		n_monitors = Monitor::LoadRemoteMonitors( protocol, host, port, path, monitors, Monitor::CAPTURE );
	}
	else if ( file[0] )
	{
		n_monitors = Monitor::LoadFileMonitors( file, monitors, Monitor::CAPTURE );
	}
	else
	{
		Monitor *monitor = Monitor::Load( monitor_id, true, Monitor::CAPTURE );
		if ( monitor )
		{
			monitors = new Monitor *[1];
			monitors[0] = monitor;
			n_monitors = 1;
		}
	}

	if ( !n_monitors )
	{
		Error( "No monitors found" );
		exit ( -1 );
	}

	Info( "Starting Capture version %s", ZM_VERSION );

	zmSetDefaultTermHandler();
	zmSetDefaultDieHandler();

	sigset_t block_set;
	sigemptyset( &block_set );

	sigaddset( &block_set, SIGUSR1 );
	sigaddset( &block_set, SIGUSR2 );

	if ( monitors[0]->PrimeCapture() < 0 )
	{
        Error( "Failed to prime capture of initial monitor" );
		exit( -1 );
	}

	long *capture_delays = new long[n_monitors];
	long *alarm_capture_delays = new long[n_monitors];
	long *next_delays = new long[n_monitors];
	struct timeval * last_capture_times = new struct timeval[n_monitors];
	for ( int i = 0; i < n_monitors; i++ )
	{
		last_capture_times[i].tv_sec = last_capture_times[i].tv_usec = 0;
		capture_delays[i] = monitors[i]->GetCaptureDelay();
		alarm_capture_delays[i] = monitors[i]->GetAlarmCaptureDelay();
	}

    int result = 0;
	struct timeval now;
	struct DeltaTimeval delta_time;
	while( !zm_terminate )
	{
		sigprocmask( SIG_BLOCK, &block_set, 0 );
		for ( int i = 0; i < n_monitors; i++ )
		{
			long min_delay = MAXINT;

			gettimeofday( &now, NULL );
			for ( int j = 0; j < n_monitors; j++ )
			{
				if ( last_capture_times[j].tv_sec )
				{
					DELTA_TIMEVAL( delta_time, now, last_capture_times[j], DT_PREC_3 );
					if ( monitors[i]->GetState() == Monitor::ALARM )
						next_delays[j] = alarm_capture_delays[j]-delta_time.delta;
					else
						next_delays[j] = capture_delays[j]-delta_time.delta;
					if ( next_delays[j] < 0 )
						next_delays[j] = 0;
				}
				else
				{
					next_delays[j] = 0;
				}
				if ( next_delays[j] <= min_delay )
				{
					min_delay = next_delays[j];
				}
			}

			if ( next_delays[i] <= min_delay || next_delays[i] <= 0 )
			{
				if ( monitors[i]->PreCapture() < 0 )
				{
                    Error( "Failed to pre-capture monitor %d %d (%d/%d)", monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors );
                    zm_terminate = true;
                    result = -1;
                    break;
				}
				if ( monitors[i]->Capture() < 0 )
				{
                    Error( "Failed to capture image from monitor %d %s (%d/%d)", monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors );
                    zm_terminate = true;
                    result = -1;
                    break;
				}
				if ( monitors[i]->PostCapture() < 0 )
				{
                    Error( "Failed to post-capture monitor %d %s (%d/%d)", monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors );
                    zm_terminate = true;
                    result = -1;
                    break;
				}

				if ( next_delays[i] > 0 )
				{
					gettimeofday( &now, NULL );
					DELTA_TIMEVAL( delta_time, now, last_capture_times[i], DT_PREC_3 );
					long sleep_time = next_delays[i]-delta_time.delta;
					if ( sleep_time > 0 )
					{
						usleep( sleep_time*(DT_MAXGRAN/DT_PREC_3) );
					}
				}
				gettimeofday( &(last_capture_times[i]), NULL );
			}
		}
		sigprocmask( SIG_UNBLOCK, &block_set, 0 );
	}
	for ( int i = 0; i < n_monitors; i++ )
	{
		delete monitors[i];
	}
	delete [] monitors;
	delete [] alarm_capture_delays;
	delete [] capture_delays;
	delete [] next_delays;
	delete [] last_capture_times;

	logTerm();
	zmDbClose();

	return( result );
}
Beispiel #8
0
void Event::AddFrame( Image *image, struct timeval timestamp, int score, Image *alarm_image )
{
    if ( !timestamp.tv_sec )
    {
        Debug( 1, "Not adding new frame, zero timestamp" );
        return;
    }

    frames++;

    static char event_file[PATH_MAX];
    snprintf( event_file, sizeof(event_file), capture_file_format, path, frames );

    Debug( 1, "Writing capture frame %d", frames );
    WriteFrameImage( image, timestamp, event_file );

    struct DeltaTimeval delta_time;
    DELTA_TIMEVAL( delta_time, timestamp, start_time, DT_PREC_2 );

    const char *frame_type = score>0?"Alarm":(score<0?"Bulk":"Normal");
    if ( score < 0 )
        score = 0;

    bool db_frame = (strcmp(frame_type,"Bulk") != 0) || ((frames%config.bulk_frame_interval)==0) || !frames;
    if ( db_frame )
    {

        Debug( 1, "Adding frame %d of type \"%s\" to DB", frames, frame_type );
        static char sql[ZM_SQL_MED_BUFSIZ];
        snprintf( sql, sizeof(sql), "insert into Frames ( EventId, FrameId, Type, TimeStamp, Delta, Score ) values ( %d, %d, '%s', from_unixtime( %ld ), %s%ld.%02ld, %d )", id, frames, frame_type, timestamp.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, score );
        if ( mysql_query( &dbconn, sql ) )
        {
            Error( "Can't insert frame: %s", mysql_error( &dbconn ) );
            exit( mysql_errno( &dbconn ) );
        }
        last_db_frame = frames;

        // We are writing a Bulk frame
        if ( !strcmp( frame_type,"Bulk") )
        {
            snprintf( sql, sizeof(sql), "update Events set Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d where Id = %d", 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 );
            if ( mysql_query( &dbconn, sql ) )
            {
                Error( "Can't update event: %s", mysql_error( &dbconn ) );
                exit( mysql_errno( &dbconn ) );
            }
        }
    }

    end_time = timestamp;

        // We are writing an Alarm frame
        if ( !strcmp( frame_type,"Alarm") )
    {
        alarm_frames++;

        tot_score += score;
        if ( score > (int)max_score )
            max_score = score;

        if ( alarm_image )
        {
            snprintf( event_file, sizeof(event_file), analyse_file_format, path, frames );

            Debug( 1, "Writing analysis frame %d", frames );
            WriteFrameImage( alarm_image, timestamp, event_file, true );
        }
    }
    
    /* This makes viewing the diagnostic images impossible because it keeps deleting them
    if ( config.record_diag_images )
    {
        char diag_glob[PATH_MAX] = "";

        snprintf( diag_glob, sizeof(diag_glob), "%s/%d/diag-*.jpg", config.dir_events, monitor->Id() );
        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
            {
                Debug( 1, "Can't glob '%s': %d", diag_glob, glob_status );
            }
        }
        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 )
                {
                    snprintf( new_diag_path, sizeof(new_diag_path), general_file_format, path, frames, diag_file );

                    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 );
    }
    */
}
Beispiel #9
0
void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *alarm_image) {
  if ( !timestamp.tv_sec ) {
    Debug(1, "Not adding new frame, zero timestamp");
    return;
  }

  frames++;

  static char event_file[PATH_MAX];
  snprintf(event_file, sizeof(event_file), staticConfig.capture_file_format, path, frames);

  if ( monitor->GetOptSaveJPEGs() & 1 ) {
    Debug(1, "Writing capture frame %d to %s", frames, event_file);
    if ( ! WriteFrameImage(image, timestamp, event_file) ) {
      Error("Failed to write frame image");
    }
  } else {
    //If this is the first frame, we should add a thumbnail to the event directory
    if ( frames == 1 || score > (int)max_score ) {
      char snapshot_file[PATH_MAX];
      snprintf(snapshot_file, sizeof(snapshot_file), "%s/snapshot.jpg", path);
      WriteFrameImage(image, timestamp, snapshot_file);
    }
    // The first frame with a score will be the frame that alarmed the event
    if (!alarm_frame_written && score > 0) {
      alarm_frame_written = true;
      char alarm_file[PATH_MAX];
      snprintf(alarm_file, sizeof(alarm_file), "%s/alarm.jpg", path);
      WriteFrameImage(image, timestamp, alarm_file);
    }
  }
  if ( videowriter != NULL ) {
Debug(3, "Writing video");
    WriteFrameVideo(image, timestamp, videowriter);
  }

  struct DeltaTimeval delta_time;
  DELTA_TIMEVAL(delta_time, timestamp, start_time, DT_PREC_2);

  FrameType frame_type = score>0?ALARM:(score<0?BULK:NORMAL);
  // < 0 means no motion detection is being done.
  if ( score < 0 )
    score = 0;

  bool db_frame = ( frame_type != BULK ) || (!frames) || ((frames%config.bulk_frame_interval)==0) ;
  if ( db_frame ) {

    Debug( 1, "Adding frame %d of type \"%s\" to DB", frames, Event::frame_type_names[frame_type] );
    static char sql[ZM_SQL_MED_BUFSIZ];
    snprintf(sql, sizeof(sql),
        "INSERT INTO Frames ( EventId, FrameId, Type, TimeStamp, Delta, Score )"
        " VALUES ( %" PRIu64 ", %d, '%s', from_unixtime( %ld ), %s%ld.%02ld, %d )",
        id, frames, frame_type_names[frame_type], timestamp.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, score);
    db_mutex.lock();
    if ( mysql_query(&dbconn, sql) ) {
      Error("Can't insert frame: %s", mysql_error(&dbconn));
      Error("SQL was %s", sql);
      db_mutex.unlock();
      return;
    }
    db_mutex.unlock();
    last_db_frame = frames;

    // We are writing a Bulk frame
    if ( frame_type == BULK ) {
      snprintf(sql, sizeof(sql), 
          "UPDATE Events SET Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d where Id = %" PRIu64, 
          ( 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
          );
      db_mutex.lock();
      while ( mysql_query(&dbconn, sql) && !zm_terminate ) {
        Error("Can't update event: %s", mysql_error(&dbconn));
        db_mutex.unlock();
        sleep(1);
        db_mutex.lock();
      }
      db_mutex.unlock();
    }
  } // end if db_frame

  end_time = timestamp;

  // We are writing an Alarm frame
  if ( frame_type == ALARM ) {
    alarm_frames++;

    tot_score += score;
    if ( score > (int)max_score )
      max_score = score;

    if ( alarm_image ) {
      if ( monitor->GetOptSaveJPEGs() & 2 ) {
        snprintf(event_file, sizeof(event_file), staticConfig.analyse_file_format, path, frames);
        Debug(1, "Writing analysis frame %d", frames);
        if ( ! WriteFrameImage(alarm_image, timestamp, event_file, true) ) {
          Error("Failed to write analysis frame image");
        }
      }
    }
  }

  /* This makes viewing the diagnostic images impossible because it keeps deleting them
  if ( config.record_diag_images ) {
    char diag_glob[PATH_MAX] = "";

    snprintf( diag_glob, sizeof(diag_glob), "%s/%d/diag-*.jpg", staticConfig.DIR_EVENTS.c_str(), monitor->Id() );
    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 {
        Debug( 1, "Can't glob '%s': %d", diag_glob, glob_status );
      }
    } 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 ) {
          snprintf( new_diag_path, sizeof(new_diag_path), general_file_format, path, frames, diag_file );

          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 );
  }
  */
}
Beispiel #10
0
bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) {
  Image *send_image = prepareImage(image);
  if ( !config.timestamp_on_capture && timestamp )
    monitor->TimestampImage(send_image, timestamp);

#if HAVE_LIBAVCODEC
  if ( type == STREAM_MPEG ) {
    if ( !vid_stream ) {
      vid_stream = new VideoStream("pipe:", format, bitrate, effective_fps, send_image->Colours(), send_image->SubpixelOrder(), send_image->Width(), send_image->Height());
      fprintf(stdout, "Content-type: %s\r\n\r\n", vid_stream->MimeType());
      vid_stream->OpenStream();
    }
    static struct timeval base_time;
    struct DeltaTimeval delta_time;
    if ( !frame_count )
      base_time = *timestamp;
    DELTA_TIMEVAL(delta_time, *timestamp, base_time, DT_PREC_3);
    /* double pts = */ vid_stream->EncodeFrame(send_image->Buffer(), send_image->Size(), config.mpeg_timed_frames, delta_time.delta);
  } else
#endif // HAVE_LIBAVCODEC
  {
    static unsigned char temp_img_buffer[ZM_MAX_IMAGE_SIZE];

    int img_buffer_size = 0;
    unsigned char *img_buffer = temp_img_buffer;

    // Calculate how long it takes to actually send the frame
    struct timeval frameStartTime;
    gettimeofday(&frameStartTime, NULL);
    
    fputs("--ZoneMinderFrame\r\n", stdout);
    switch( type ) {
      case STREAM_JPEG :
        send_image->EncodeJpeg(img_buffer, &img_buffer_size);
        fputs("Content-Type: image/jpeg\r\n", stdout);
        break;
      case STREAM_RAW :
        fputs("Content-Type: image/x-rgb\r\n", stdout);
        img_buffer = (uint8_t*)send_image->Buffer();
        img_buffer_size = send_image->Size();
        break;
      case STREAM_ZIP :
        fputs("Content-Type: image/x-rgbz\r\n",stdout);
        unsigned long zip_buffer_size;
        send_image->Zip(img_buffer, &zip_buffer_size);
        img_buffer_size = zip_buffer_size;
        break;
      default :
        Error("Unexpected frame type %d", type);
        return false;
    }
    fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size);
    if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
      if ( !zm_terminate ){ 
        // If the pipe was closed, we will get signalled SIGPIPE to exit, which will set zm_terminate
        Warning("Unable to send stream frame: %s", strerror(errno));
      }
      return false;
    }
    fputs("\r\n\r\n",stdout);
    fflush( stdout );

    struct timeval frameEndTime;
    gettimeofday( &frameEndTime, NULL );

    int frameSendTime = tvDiffMsec( frameStartTime, frameEndTime );
    if ( frameSendTime > 1000/maxfps ) {
      maxfps /= 1.5;
      Error( "Frame send time %d msec too slow, throttling maxfps to %.2f", frameSendTime, maxfps );
    }
  }
  last_frame_sent = TV_2_FLOAT( now );
  return( true );
} // end bool MonitorStream::sendFrame( Image *image, struct timeval *timestamp )