void WebViewGraphicsBased::enableFrameRateMeasurement() { m_measureFps = true; m_lastConsultTime = m_startTime = QTime::currentTime(); QTimer* updateTimer = new QTimer(this); updateTimer->setInterval(1000); connect(updateTimer, SIGNAL(timeout()), this, SLOT(updateFrameRate())); updateTimer->start(); }
void CMainFrame::OnTimer(UINT_PTR nIDEvent) { const CFlyCapDoc* pDoc = (CFlyCapDoc*)GetActiveDocument(); if( pDoc != NULL ) { updateFrameRate(); updateImageInfo(); } CFrameWnd::OnTimer(nIDEvent); }
WebViewGraphicsBased::WebViewGraphicsBased(QWidget* parent) : QGraphicsView(parent) , m_item(new GraphicsWebView) , m_numPaintsTotal(0) , m_numPaintsSinceLastMeasure(0) , m_measureFps(false) , m_resizesToContents(false) , m_machine(0) { setScene(new QGraphicsScene(this)); scene()->addItem(m_item); setFrameShape(QFrame::NoFrame); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_updateTimer = new QTimer(this); m_updateTimer->setInterval(1000); connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(updateFrameRate())); }
void Simulation::doSimulationStep() { ++simulationStep; simulatedTime += scene->stepLength; scene->updateActuators(); collisions = contactPoints = 0; dSpaceCollide2((dGeomID)staticSpace, (dGeomID)movableSpace, this, (dNearCallback*)&staticCollisionWithSpaceCallback); if(scene->detectBodyCollisions) dSpaceCollide(movableSpace, this, (dNearCallback*)&staticCollisionSpaceWithSpaceCallback); if(scene->useQuickSolver && (simulationStep % scene->quickSolverSkip) == 0) dWorldQuickStep(physicalWorld, scene->stepLength); else dWorldStep(physicalWorld, scene->stepLength); dJointGroupEmpty(contactGroup); updateFrameRate(); }
CameraPub::CameraPub() : Display() , camera_trigger_name_("camera_trigger") , nh_() , new_caminfo_(false) , force_render_(false) , trigger_activated_(false) , last_image_publication_time_(0) , caminfo_ok_(false) , video_publisher_(0) { topic_property_ = new RosTopicProperty("Image Topic", "", QString::fromStdString(ros::message_traits::datatype<sensor_msgs::Image>()), "sensor_msgs::Image topic to publish to.", this, SLOT(updateTopic())); namespace_property_ = new StringProperty("Display namespace", "", "Namespace for this display.", this, SLOT(updateDisplayNamespace())); camera_info_property_ = new RosTopicProperty("Camera Info Topic", "", QString::fromStdString(ros::message_traits::datatype<sensor_msgs::CameraInfo>()), "sensor_msgs::CameraInfo topic to subscribe to.", this, SLOT(updateTopic())); queue_size_property_ = new IntProperty( "Queue Size", 2, "Advanced: set the size of the incoming message queue. Increasing this " "is useful if your incoming TF data is delayed significantly from your" " image data, but it can greatly increase memory usage if the messages are big.", this, SLOT(updateQueueSize())); queue_size_property_->setMin(1); frame_rate_property_ = new FloatProperty("Frame Rate", -1, "Sets target frame rate. Set to < 0 for maximum speed, set to 0 to stop, you can " "trigger single images with the /rviz_camera_trigger service.", this, SLOT(updateFrameRate())); frame_rate_property_->setMin(-1); background_color_property_ = new ColorProperty("Background Color", Qt::black, "Sets background color, values from 0.0 to 1.0.", this, SLOT(updateBackgroundColor())); }
CameraView::CameraView(Camera * camera, QWidget *parent, int tabIdx): QWidget(parent), ui(new Ui::CameraView){ _cam = camera; _tabIdx = tabIdx; connect(_cam, SIGNAL(CTAFrameUpdatedSignal()), this, SLOT(showCTAFrame())); connect(_cam, SIGNAL(ATCFrameUpdatedSignal()), this, SLOT(showATCFrame())); connect(_cam, SIGNAL(ATCRecFrameUpdatedSignal()), this, SLOT(showATCRecFrame())); connect(_cam, SIGNAL(frameRateUpdatedSignal()), this, SLOT(updateFrameRate())); //***NBS***// connect(_cam, SIGNAL(residualEnergyUpdatedSignal()), this, SLOT(updateResidualEnergy())); //***NBS***// connect(_cam,SIGNAL(curBandwidthChangedSignal(int,double)),this,SLOT(updateBandwidthSlot(int,double))); connect (_cam,SIGNAL(recognitionCompletedSignal(QString,QString)),SLOT(updateRecognitionResultSlot(QString,QString))); ui->setupUi(this); ui->label_image->setText(""); }
bool EventStream::loadEventData( int event_id ) { static char sql[ZM_SQL_MED_BUFSIZ]; snprintf( sql, sizeof(sql), "select M.Id, M.Name, E.Frames, unix_timestamp( StartTime ) as StartTimestamp, 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 ); 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 ) ); } if ( !mysql_num_rows( result ) ) { Fatal( "Unable to load event %d, not found in DB", event_id ); } MYSQL_ROW dbrow = mysql_fetch_row( result ); if ( mysql_errno( &dbconn ) ) { Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); exit( mysql_errno( &dbconn ) ); } delete event_data; event_data = new EventData; event_data->event_id = event_id; event_data->monitor_id = atoi( dbrow[0] ); event_data->start_time = atoi(dbrow[3]); if ( config.use_deep_storage ) { struct tm *event_time = localtime( &event_data->start_time ); if ( config.dir_events[0] == '/' ) snprintf( event_data->path, sizeof(event_data->path), "%s/%ld/%02d/%02d/%02d/%02d/%02d/%02d", config.dir_events, event_data->monitor_id, event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday, event_time->tm_hour, event_time->tm_min, event_time->tm_sec ); else snprintf( event_data->path, sizeof(event_data->path), "%s/%s/%ld/%02d/%02d/%02d/%02d/%02d/%02d", staticConfig.PATH_WEB.c_str(), config.dir_events, event_data->monitor_id, event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday, event_time->tm_hour, event_time->tm_min, event_time->tm_sec ); } else { if ( config.dir_events[0] == '/' ) snprintf( event_data->path, sizeof(event_data->path), "%s/%ld/%ld", config.dir_events, event_data->monitor_id, event_data->event_id ); else snprintf( event_data->path, sizeof(event_data->path), "%s/%s/%ld/%ld", staticConfig.PATH_WEB.c_str(), config.dir_events, event_data->monitor_id, event_data->event_id ); } event_data->frame_count = dbrow[2] == NULL ? 0 : atoi(dbrow[2]); event_data->duration = atof(dbrow[4]); updateFrameRate( (double)event_data->frame_count/event_data->duration ); mysql_free_result( result ); snprintf( sql, sizeof(sql), "select FrameId, unix_timestamp( `TimeStamp` ), Delta from Frames where EventId = %d order by FrameId asc", event_id ); 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 ) ); } event_data->n_frames = mysql_num_rows( result ); event_data->frames = new FrameData[event_data->frame_count]; int id, last_id = 0; time_t timestamp, last_timestamp = event_data->start_time; double delta, last_delta = 0.0; while ( ( dbrow = mysql_fetch_row( result ) ) ) { id = atoi(dbrow[0]); timestamp = atoi(dbrow[1]); delta = atof(dbrow[2]); int id_diff = id - last_id; double frame_delta = (delta-last_delta)/id_diff; if ( id_diff > 1 ) { for ( int i = last_id+1; i < id; i++ ) { event_data->frames[i-1].timestamp = (time_t)(last_timestamp + ((i-last_id)*frame_delta)); event_data->frames[i-1].offset = (time_t)(event_data->frames[i-1].timestamp-event_data->start_time); event_data->frames[i-1].delta = frame_delta; event_data->frames[i-1].in_db = false; } } event_data->frames[id-1].timestamp = timestamp; event_data->frames[id-1].offset = (time_t)(event_data->frames[id-1].timestamp-event_data->start_time); event_data->frames[id-1].delta = id>1?frame_delta:0.0; event_data->frames[id-1].in_db = true; last_id = id; last_delta = delta; last_timestamp = timestamp; } if ( mysql_errno( &dbconn ) ) { Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); exit( mysql_errno( &dbconn ) ); } //for ( int i = 0; i < 250; i++ ) //{ //Info( "%d -> %d @ %f (%d)", i+1, event_data->frames[i].timestamp, event_data->frames[i].delta, event_data->frames[i].in_db ); //} mysql_free_result( result ); if ( forceEventChange || mode == MODE_ALL_GAPLESS ) { if ( replay_rate > 0 ) curr_stream_time = event_data->frames[0].timestamp; else curr_stream_time = event_data->frames[event_data->frame_count-1].timestamp; } Debug( 2, "Event:%ld, Frames:%ld, Duration: %.2f", event_data->event_id, event_data->frame_count, event_data->duration ); return( true ); }
void MonitorStream::processCommand(const CmdMsg *msg) { Debug( 2, "Got message, type %d, msg %d", msg->msg_type, msg->msg_data[0] ); // Check for incoming command switch( (MsgCommand)msg->msg_data[0] ) { case CMD_PAUSE : Debug(1, "Got PAUSE command"); paused = true; delayed = true; last_frame_sent = TV_2_FLOAT(now); break; case CMD_PLAY : Debug(1, "Got PLAY command"); if ( paused ) { paused = false; delayed = true; } replay_rate = ZM_RATE_BASE; break; case CMD_VARPLAY : Debug(1, "Got VARPLAY command"); if ( paused ) { paused = false; delayed = true; } replay_rate = ntohs(((unsigned char)msg->msg_data[2]<<8)|(unsigned char)msg->msg_data[1])-32768; break; case CMD_STOP : Debug(1, "Got STOP command"); paused = false; delayed = false; break; case CMD_FASTFWD : Debug(1, "Got FAST FWD command"); if ( paused ) { paused = false; delayed = true; } // Set play rate switch ( replay_rate ) { case 2 * ZM_RATE_BASE : replay_rate = 5 * ZM_RATE_BASE; break; case 5 * ZM_RATE_BASE : replay_rate = 10 * ZM_RATE_BASE; break; case 10 * ZM_RATE_BASE : replay_rate = 25 * ZM_RATE_BASE; break; case 25 * ZM_RATE_BASE : case 50 * ZM_RATE_BASE : replay_rate = 50 * ZM_RATE_BASE; break; default : replay_rate = 2 * ZM_RATE_BASE; break; } break; case CMD_SLOWFWD : Debug( 1, "Got SLOW FWD command" ); paused = true; delayed = true; replay_rate = ZM_RATE_BASE; step = 1; break; case CMD_SLOWREV : Debug( 1, "Got SLOW REV command" ); paused = true; delayed = true; replay_rate = ZM_RATE_BASE; step = -1; break; case CMD_FASTREV : Debug( 1, "Got FAST REV command" ); if ( paused ) { paused = false; delayed = true; } // Set play rate switch ( replay_rate ) { case -2 * ZM_RATE_BASE : replay_rate = -5 * ZM_RATE_BASE; break; case -5 * ZM_RATE_BASE : replay_rate = -10 * ZM_RATE_BASE; break; case -10 * ZM_RATE_BASE : replay_rate = -25 * ZM_RATE_BASE; break; case -25 * ZM_RATE_BASE : case -50 * ZM_RATE_BASE : replay_rate = -50 * ZM_RATE_BASE; break; default : replay_rate = -2 * ZM_RATE_BASE; break; } break; case CMD_ZOOMIN : x = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; y = ((unsigned char)msg->msg_data[3]<<8)|(unsigned char)msg->msg_data[4]; Debug( 1, "Got ZOOM IN command, to %d,%d", x, y ); switch ( zoom ) { case 100: zoom = 150; break; case 150: zoom = 200; break; case 200: zoom = 300; break; case 300: zoom = 400; break; case 400: default : zoom = 500; break; } break; case CMD_ZOOMOUT : Debug( 1, "Got ZOOM OUT command" ); switch ( zoom ) { case 500: zoom = 400; break; case 400: zoom = 300; break; case 300: zoom = 200; break; case 200: zoom = 150; break; case 150: default : zoom = 100; break; } break; case CMD_PAN : x = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; y = ((unsigned char)msg->msg_data[3]<<8)|(unsigned char)msg->msg_data[4]; Debug(1, "Got PAN command, to %d,%d", x, y); break; case CMD_SCALE : scale = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; Debug(1, "Got SCALE command, to %d", scale); break; case CMD_QUIT : Info("User initiated exit - CMD_QUIT"); break; case CMD_QUERY : Debug(1, "Got QUERY command, sending STATUS"); break; default : Error("Got unexpected command %d", msg->msg_data[0]); break; } // end switch command struct { int id; int state; double fps; int buffer_level; int rate; double delay; int zoom; bool delayed; bool paused; bool enabled; bool forced; } status_data; status_data.id = monitor->Id(); status_data.fps = monitor->GetFPS(); status_data.state = monitor->shared_data->state; if ( playback_buffer > 0 ) status_data.buffer_level = (MOD_ADD( (temp_write_index-temp_read_index), 0, temp_image_buffer_count )*100)/temp_image_buffer_count; else status_data.buffer_level = 0; status_data.delayed = delayed; status_data.paused = paused; status_data.rate = replay_rate; status_data.delay = TV_2_FLOAT( now ) - TV_2_FLOAT( last_frame_timestamp ); status_data.zoom = zoom; //status_data.enabled = monitor->shared_data->active; status_data.enabled = monitor->trigger_data->trigger_state!=Monitor::TRIGGER_OFF; status_data.forced = monitor->trigger_data->trigger_state==Monitor::TRIGGER_ON; Debug(2, "Buffer Level:%d, Delayed:%d, Paused:%d, Rate:%d, delay:%.3f, Zoom:%d, Enabled:%d Forced:%d", status_data.buffer_level, status_data.delayed, status_data.paused, status_data.rate, status_data.delay, status_data.zoom, status_data.enabled, status_data.forced ); DataMsg status_msg; status_msg.msg_type = MSG_DATA_WATCH; memcpy(&status_msg.msg_data, &status_data, sizeof(status_data)); int nbytes = 0; if ( (nbytes = sendto(sd, &status_msg, sizeof(status_msg), MSG_DONTWAIT, (sockaddr *)&rem_addr, sizeof(rem_addr))) < 0 ) { //if ( errno != EAGAIN ) { Error( "Can't sendto on sd %d: %s", sd, strerror(errno) ); //exit( -1 ); } } Debug(2, "Number of bytes sent to (%s): (%d)", rem_addr.sun_path, nbytes); // quit after sending a status, if this was a quit request if ( (MsgCommand)msg->msg_data[0]==CMD_QUIT ) { Debug(2,"Quitting"); exit(0); } Debug(2,"Updating framerate"); updateFrameRate(monitor->GetFPS()); } // end void MonitorStream::processCommand(const CmdMsg *msg)
void MonitorStream::runStream() { if ( type == STREAM_SINGLE ) { // Not yet migrated over to stream class SingleImage(scale); return; } openComms(); if ( !checkInitialised() ) { Error("Not initialized"); return; } updateFrameRate(monitor->GetFPS()); if ( type == STREAM_JPEG ) fputs("Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n", stdout); // point to end which is theoretically not a valid value because all indexes are % image_buffer_count unsigned int last_read_index = monitor->image_buffer_count; time_t stream_start_time; time(&stream_start_time); frame_count = 0; temp_image_buffer = 0; temp_image_buffer_count = playback_buffer; temp_read_index = temp_image_buffer_count; temp_write_index = temp_image_buffer_count; std::string swap_path; bool buffered_playback = false; // Last image and timestamp when paused, will be resent occasionally to prevent timeout Image *paused_image = NULL; struct timeval paused_timestamp; // 15 is the max length for the swap path suffix, /zmswap-whatever, assuming max 6 digits for monitor id const int max_swap_len_suffix = 15; int swap_path_length = staticConfig.PATH_SWAP.length() + 1; // +1 for NULL terminator int subfolder1_length = snprintf(NULL, 0, "/zmswap-m%d", monitor->Id()) + 1; int subfolder2_length = snprintf(NULL, 0, "/zmswap-q%06d", connkey) + 1; int total_swap_path_length = swap_path_length + subfolder1_length + subfolder2_length; if ( connkey && ( playback_buffer > 0 ) ) { if ( total_swap_path_length + max_swap_len_suffix > PATH_MAX ) { Error("Swap Path is too long. %d > %d ", total_swap_path_length+max_swap_len_suffix, PATH_MAX); } else { swap_path = staticConfig.PATH_SWAP; Debug( 3, "Checking swap path folder: %s", swap_path.c_str() ); if ( checkSwapPath(swap_path.c_str(), true) ) { swap_path += stringtf("/zmswap-m%d", monitor->Id()); Debug(4, "Checking swap path subfolder: %s", swap_path.c_str()); if ( checkSwapPath(swap_path.c_str(), true) ) { swap_path += stringtf("/zmswap-q%06d", connkey); Debug(4, "Checking swap path subfolder: %s", swap_path.c_str()); if ( checkSwapPath(swap_path.c_str(), true) ) { buffered_playback = true; } } } if ( !buffered_playback ) { Error("Unable to validate swap image path, disabling buffered playback"); } else { Debug(2, "Assigning temporary buffer"); temp_image_buffer = new SwapImage[temp_image_buffer_count]; memset( temp_image_buffer, 0, sizeof(*temp_image_buffer)*temp_image_buffer_count ); Debug( 2, "Assigned temporary buffer" ); } } } else { Debug(2, "Not using playback_buffer"); } // end if connkey & playback_buffer float max_secs_since_last_sent_frame = 10.0; //should be > keep alive amount (5 secs) while ( !zm_terminate ) { bool got_command = false; if ( feof(stdout) ) { Debug(2,"feof stdout"); break; } else if ( ferror(stdout) ) { Debug(2,"ferror stdout"); break; } else if ( !monitor->ShmValid() ) { Debug(2,"monitor not valid.... maybe we should wait until it comes back."); break; } gettimeofday(&now, NULL); bool was_paused = paused; if ( connkey ) { while(checkCommandQueue()) { Debug(2, "Have checking command Queue for connkey: %d", connkey ); got_command = true; } // Update modified time of the socket .lock file so that we can tell which ones are stale. if ( now.tv_sec - last_comm_update.tv_sec > 3600 ) { touch(sock_path_lock); last_comm_update = now; } } if ( paused ) { if ( !was_paused ) { int index = monitor->shared_data->last_write_index % monitor->image_buffer_count; Debug(1,"Saving paused image from index %d",index); paused_image = new Image( *monitor->image_buffer[index].image ); paused_timestamp = *(monitor->image_buffer[index].timestamp); } } else if ( paused_image ) { Debug(1,"Clearing paused_image"); delete paused_image; paused_image = NULL; } if ( buffered_playback && delayed ) { if ( temp_read_index == temp_write_index ) { // Go back to live viewing Debug( 1, "Exceeded temporary streaming buffer" ); // Clear paused flag paused = false; // Clear delayed_play flag delayed = false; replay_rate = ZM_RATE_BASE; } else { if ( !paused ) { int temp_index = MOD_ADD(temp_read_index, 0, temp_image_buffer_count); //Debug( 3, "tri: %d, ti: %d", temp_read_index, temp_index ); SwapImage *swap_image = &temp_image_buffer[temp_index]; if ( !swap_image->valid ) { paused = true; delayed = true; temp_read_index = MOD_ADD(temp_read_index, (replay_rate>=0?-1:1), temp_image_buffer_count); } else { //Debug( 3, "siT: %f, lfT: %f", TV_2_FLOAT( swap_image->timestamp ), TV_2_FLOAT( last_frame_timestamp ) ); double expected_delta_time = ((TV_2_FLOAT( swap_image->timestamp ) - TV_2_FLOAT( last_frame_timestamp )) * ZM_RATE_BASE)/replay_rate; double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent; //Debug( 3, "eDT: %.3lf, aDT: %.3f, lFS:%.3f, NOW:%.3f", expected_delta_time, actual_delta_time, last_frame_sent, TV_2_FLOAT( now ) ); // If the next frame is due if ( actual_delta_time > expected_delta_time ) { //Debug( 2, "eDT: %.3lf, aDT: %.3f", expected_delta_time, actual_delta_time ); if ( temp_index%frame_mod == 0 ) { Debug( 2, "Sending delayed frame %d", temp_index ); // Send the next frame if ( ! sendFrame(temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp) ) zm_terminate = true; memcpy(&last_frame_timestamp, &(swap_image->timestamp), sizeof(last_frame_timestamp)); //frame_sent = true; } temp_read_index = MOD_ADD(temp_read_index, (replay_rate>0?1:-1), temp_image_buffer_count); } } } else if ( step != 0 ) { temp_read_index = MOD_ADD( temp_read_index, (step>0?1:-1), temp_image_buffer_count ); SwapImage *swap_image = &temp_image_buffer[temp_read_index]; // Send the next frame if ( !sendFrame( temp_image_buffer[temp_read_index].file_name, &temp_image_buffer[temp_read_index].timestamp ) ) zm_terminate = true; memcpy( &last_frame_timestamp, &(swap_image->timestamp), sizeof(last_frame_timestamp) ); //frame_sent = true; step = 0; } else { //paused? int temp_index = MOD_ADD(temp_read_index, 0, temp_image_buffer_count); double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent; if ( got_command || actual_delta_time > 5 ) { // Send keepalive Debug( 2, "Sending keepalive frame %d", temp_index ); // Send the next frame if ( !sendFrame( temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp ) ) zm_terminate = true; //frame_sent = true; } } // end if (!paused) or step or paused } // end if have exceeded buffer or not if ( temp_read_index == temp_write_index ) { // Go back to live viewing Warning( "Rewound over write index, resuming live play" ); // Clear paused flag paused = false; // Clear delayed_play flag delayed = false; replay_rate = ZM_RATE_BASE; } } // end if ( buffered_playback && delayed ) if ( last_read_index != monitor->shared_data->last_write_index ) { // have a new image to send int index = monitor->shared_data->last_write_index % monitor->image_buffer_count; // % shouldn't be neccessary last_read_index = monitor->shared_data->last_write_index; Debug( 2, "index: %d: frame_mod: %d frame count: %d paused(%d) delayed(%d)", index, frame_mod, frame_count, paused, delayed ); if ( (frame_mod == 1) || ((frame_count%frame_mod) == 0) ) { if ( !paused && !delayed ) { // Send the next frame Monitor::Snapshot *snap = &monitor->image_buffer[index]; Debug(2, "sending Frame."); if ( !sendFrame(snap->image, snap->timestamp) ) { Debug(2, "sendFrame failed, quiting."); zm_terminate = true; } // Perhaps we should use NOW instead. memcpy(&last_frame_timestamp, snap->timestamp, sizeof(last_frame_timestamp)); //frame_sent = true; temp_read_index = temp_write_index; } else { double actual_delta_time = TV_2_FLOAT(now) - last_frame_sent; if ( actual_delta_time > 5 ) { if ( paused_image ) { // Send keepalive Debug(2, "Sending keepalive frame "); // Send the next frame if ( !sendFrame(paused_image, &paused_timestamp) ) zm_terminate = true; } else { Debug(2, "Would have sent keepalive frame, but had no paused_image "); } } } } // end if should send frame if ( buffered_playback && !paused ) { if ( monitor->shared_data->valid ) { if ( monitor->image_buffer[index].timestamp->tv_sec ) { int temp_index = temp_write_index%temp_image_buffer_count; Debug(2, "Storing frame %d", temp_index); if ( !temp_image_buffer[temp_index].valid ) { snprintf( temp_image_buffer[temp_index].file_name, sizeof(temp_image_buffer[0].file_name), "%s/zmswap-i%05d.jpg", swap_path.c_str(), temp_index ); temp_image_buffer[temp_index].valid = true; } memcpy( &(temp_image_buffer[temp_index].timestamp), monitor->image_buffer[index].timestamp, sizeof(temp_image_buffer[0].timestamp) ); monitor->image_buffer[index].image->WriteJpeg( temp_image_buffer[temp_index].file_name, config.jpeg_file_quality ); temp_write_index = MOD_ADD( temp_write_index, 1, temp_image_buffer_count ); if ( temp_write_index == temp_read_index ) { // Go back to live viewing Warning( "Exceeded temporary buffer, resuming live play" ); paused = false; delayed = false; replay_rate = ZM_RATE_BASE; } } else { Warning( "Unable to store frame as timestamp invalid" ); } } else { Warning( "Unable to store frame as shared memory invalid" ); } } // end if buffered playback frame_count++; } else { Debug(4,"Waiting for capture last_write_index=%u", monitor->shared_data->last_write_index); } // end if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index ) unsigned long sleep_time = (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2))); Debug(4, "Sleeping for (%d)", sleep_time); usleep(sleep_time); if ( ttl ) { if ( (now.tv_sec - stream_start_time) > ttl ) { Debug(2, "now(%d) - start(%d) > ttl(%d) break", now.tv_sec, stream_start_time, ttl); break; } } if ( ! last_frame_sent ) { // If we didn't capture above, because frame_mod was bad? Then last_frame_sent will not have a value. last_frame_sent = now.tv_sec; Warning( "no last_frame_sent. Shouldn't happen. frame_mod was (%d) frame_count (%d) ", frame_mod, frame_count ); } else if ( (!paused) && ( (TV_2_FLOAT( now ) - last_frame_sent) > max_secs_since_last_sent_frame ) ) { Error( "Terminating, last frame sent time %f secs more than maximum of %f", TV_2_FLOAT( now ) - last_frame_sent, max_secs_since_last_sent_frame ); break; } } // end while if ( buffered_playback ) { Debug(1, "Cleaning swap files from %s", swap_path.c_str()); struct stat stat_buf; if ( stat(swap_path.c_str(), &stat_buf) < 0 ) { if ( errno != ENOENT ) { Error("Can't stat '%s': %s", swap_path.c_str(), strerror(errno)); } } else if ( !S_ISDIR(stat_buf.st_mode) ) { Error("Swap image path '%s' is not a directory", swap_path.c_str()); } else { char glob_pattern[PATH_MAX] = ""; snprintf(glob_pattern, sizeof(glob_pattern), "%s/*.*", swap_path.c_str()); glob_t pglob; int glob_status = glob(glob_pattern, 0, 0, &pglob); if ( glob_status != 0 ) { if ( glob_status < 0 ) { Error("Can't glob '%s': %s", glob_pattern, strerror(errno)); } else { Debug(1, "Can't glob '%s': %d", glob_pattern, glob_status); } } else { for ( unsigned int i = 0; i < pglob.gl_pathc; i++ ) { if ( unlink(pglob.gl_pathv[i]) < 0 ) { Error("Can't unlink '%s': %s", pglob.gl_pathv[i], strerror(errno)); } } } globfree( &pglob ); if ( rmdir(swap_path.c_str()) < 0 ) { Error( "Can't rmdir '%s': %s", swap_path.c_str(), strerror(errno) ); } } // end if checking for swap_path } // end if buffered_playback closeComms(); } // end MonitorStream::runStream