This commit is contained in:
Isaac Connor 2019-02-25 10:21:43 -05:00
parent 279e0d8bcf
commit 448294f593
11 changed files with 193 additions and 135 deletions

View File

@ -241,7 +241,7 @@ int FfmpegCamera::OpenFfmpeg() {
}
if ( ret < 0 ) {
Warning("Could not set rtsp_transport method '%s'\n", method.c_str());
Warning("Could not set rtsp_transport method '%s'", method.c_str());
}
Debug(1, "Calling avformat_open_input for %s", mPath.c_str());

View File

@ -2082,6 +2082,10 @@ int LocalCamera::Capture( ZMPacket &zm_packet ) {
} /* prime capture */
if ( ! zm_packet.image ) {
zm_packet.image = new Image(width, height, colours, subpixelorder);
}
if ( conversion_type != 0 ) {
Debug(3, "Performing format conversion");

View File

@ -1630,6 +1630,7 @@ bool Monitor::Analyse() {
ZMPacket *snap;
// Is it possible for snap->score to be ! -1?
// get_analysis_packet will lock the packet
while ( ( snap = packetqueue->get_analysis_packet() ) && ( snap->score == -1 ) ) {
unsigned int index = snap->image_index;
Debug(2, "Analysis index (%d), last_Write(%d)", index, shared_data->last_write_index);
@ -1638,7 +1639,6 @@ bool Monitor::Analyse() {
return 0;
}
snap->lock();
packets_processed += 1;
if ( snap->image_index == -1 ) {
@ -2069,7 +2069,6 @@ void Monitor::ReloadLinkedMonitors(const char *p_linked_monitors) {
db_mutex.lock();
static char sql[ZM_SQL_SML_BUFSIZ];
db_mutex.lock();
snprintf(sql, sizeof(sql), "SELECT Id, Name FROM Monitors WHERE Id = %d AND Function != 'None' AND Function != 'Monitor' AND Enabled = 1", link_ids[i] );
if ( mysql_query(&dbconn, sql) ) {
db_mutex.unlock();
@ -2177,25 +2176,27 @@ int Monitor::LoadFfmpegMonitors(const char *file, Monitor **&monitors, Purpose p
int Monitor::Capture() {
static int FirstCapture = 1; // Used in de-interlacing to indicate whether this is the even or odd image
unsigned int index = image_count % image_buffer_count;
unsigned int index = 0;
//image_count % image_buffer_count;
if ( (index == shared_data->last_read_index) && (function > MONITOR) ) {
Warning( "Buffer overrun at index %d, image %d, slow down capture, speed up analysis or increase ring buffer size", index, image_count );
Warning("Buffer overrun at index %d, image %d, slow down capture, speed up analysis or increase ring buffer size", index, image_count);
time_t now = time(0);
double approxFps = double(image_buffer_count)/double(now-image_buffer[index].timestamp->tv_sec);
time_t last_read_delta = now - shared_data->last_read_time;
if ( last_read_delta > (image_buffer_count/approxFps) ) {
Warning( "Last image read from shared memory %ld seconds ago, zma may have gone away", last_read_delta )
Warning("Last image read from shared memory %ld seconds ago, zma may have gone away", last_read_delta)
shared_data->last_read_index = image_buffer_count;
}
} else {
Debug(2,"Capture: Current write index %d, last read index %d, current (%d)", shared_data->last_write_index, shared_data->last_read_index, index );
Debug(2,"Capture: Last write(capture) index %d, last read(analysis) index %d, current (%d)",
shared_data->last_write_index, shared_data->last_read_index, index );
}
ZMPacket *packet = &image_buffer[index];
Debug(2,"before lock");
ZMPacket *packet = new ZMPacket();
//&image_buffer[index];
Debug(2,"before packet lock");
packet->lock();
Debug(2,"before reset");
packet->reset();
Image* capture_image = packet->image;
int captureResult = 0;
@ -2243,23 +2244,23 @@ int Monitor::Capture() {
if ( packet->packet.stream_index != video_stream_id ) {
Debug(2, "Have audio packet (%d) != videostream_id:(%d) q.vpktcount(%d) event?(%d) ",
packet->packet.stream_index, video_stream_id, packetqueue->video_packet_count, ( event ? 1 : 0 ) );
// Only queue if we have some video packets in there.
mutex.lock();
// Only queue if we have some video packets in there. Should push this logic into packetqueue
//mutex.lock();
if ( packetqueue->video_packet_count || event ) {
// Need to copy it into another ZMPacket.
ZMPacket *audio_packet = new ZMPacket(*packet);
//ZMPacket *audio_packet = new ZMPacket(*packet);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
audio_packet->codec_type = camera->get_AudioStream()->codecpar->codec_type;
packet->codec_type = camera->get_AudioStream()->codecpar->codec_type;
#else
audio_packet->codec_type = camera->get_AudioStream()->codec->codec_type;
packet->codec_type = camera->get_AudioStream()->codec->codec_type;
#endif
Debug(2, "Queueing packet");
packetqueue->queuePacket(audio_packet);
packetqueue->queuePacket(packet);
}
// Don't update last_write_index because that is used for live streaming
//shared_data->last_write_time = image_buffer[index].timestamp->tv_sec;
mutex.unlock();
//mutex.unlock();
packet->unlock();
return 1;
}
@ -2274,20 +2275,21 @@ int Monitor::Capture() {
//Debug(2,"About to decode");
if ( packet->decode(camera->get_VideoCodecContext()) ) {
//Debug(2,"Getimage");
packet->get_image();
packet->get_image( image_buffer[index].image );
}
// Have an av_packet,
}
Debug(2,"Before mutex lock");
mutex.lock();
//Debug(2,"Before mutex lock");
// FIXME this mutex is useless, packetqueue has it's own
//mutex.lock();
if ( packetqueue->video_packet_count || packet->keyframe || event ) {
Debug(2, "Have video packet for index (%d)", index);
packetqueue->queuePacket(packet);
} else {
Debug(2, "Not queuing video packet for index (%d)", index);
}
mutex.unlock();
//mutex.unlock();
/* Deinterlacing */
if ( deinterlacing_value ) {
@ -2355,7 +2357,7 @@ int Monitor::Capture() {
// assume that we are connected
snprintf(sql, sizeof(sql),
"INSERT INTO Monitor_Status (MonitorId,CaptureFPS,CaptureBandwidth,Status) "
"VALUES (%d, %.2lf,%u) ON DUPLICATE KEY UPDATE "
"VALUES (%d, %.2lf, %u, 'Connected') ON DUPLICATE KEY UPDATE "
"CaptureFPS = %.2lf, CaptureBandwidth=%u, Status='Connected'",
id, capture_fps, new_capture_bandwidth, capture_fps, new_capture_bandwidth);
if ( mysql_query(&dbconn, sql) ) {
@ -2701,24 +2703,18 @@ Monitor::Orientation Monitor::getOrientation() const { return orientation; }
// Wait for camera to get an image, and then assign it as the base reference image. So this should be done as the first task in the analysis thread startup.
void Monitor::get_ref_image() {
while (
( shared_data->last_write_index == (unsigned int)image_buffer_count )
&&
( shared_data->last_write_time == 0 )
&& ! zm_terminate
) {
Info("Waiting for capture daemon lastwriteindex(%d) lastwritetime(%d)",
ZMPacket * snap;
while ( ((!( snap = packetqueue->get_analysis_packet())) || ( snap->image_index == -1 )) && !zm_terminate) {
Debug(1, "Waiting for capture daemon lastwriteindex(%d) lastwritetime(%d)",
shared_data->last_write_index, shared_data->last_write_time);
usleep(10000);
//usleep(10000);
}
if ( zm_terminate )
return;
int last_write_index = shared_data->last_write_index ;
Debug(2,"Waiting for capture daemon unlock");
image_buffer[last_write_index].mutex.lock();
ref_image.Assign(width, height, camera->Colours(), camera->SubpixelOrder(), image_buffer[last_write_index].image->Buffer(), camera->ImageSize());
image_buffer[last_write_index].mutex.unlock();
ref_image.Assign(width, height, camera->Colours(), camera->SubpixelOrder(), snap->image->Buffer(), camera->ImageSize());
Debug(2,"Have image about to unlock");
snap->unlock();
}
std::vector<Group *> Monitor::Groups() {

View File

@ -74,9 +74,9 @@ bool MonitorStream::checkSwapPath(const char *path, bool create_path) {
} // end bool MonitorStream::checkSwapPath( const char *path, bool create_path )
void MonitorStream::processCommand(const CmdMsg *msg) {
Debug( 2, "Got message, type %d, msg %d", msg->msg_type, msg->msg_data[0] );
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] ) {
switch ( (MsgCommand)msg->msg_data[0] ) {
case CMD_PAUSE :
Debug(1, "Got PAUSE command");
paused = true;
@ -414,19 +414,19 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) {
return false;
}
fputs("\r\n\r\n",stdout);
fflush( stdout );
fflush(stdout);
struct timeval frameEndTime;
gettimeofday( &frameEndTime, NULL );
gettimeofday(&frameEndTime, NULL);
int frameSendTime = tvDiffMsec( frameStartTime, frameEndTime );
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 );
Error("Frame send time %d msec too slow, throttling maxfps to %.2f", frameSendTime, maxfps);
}
}
last_frame_sent = TV_2_FLOAT( now );
return( true );
last_frame_sent = TV_2_FLOAT(now);
return true;
} // end bool MonitorStream::sendFrame( Image *image, struct timeval *timestamp )
void MonitorStream::runStream() {
@ -483,7 +483,7 @@ void MonitorStream::runStream() {
} else {
swap_path = staticConfig.PATH_SWAP;
Debug( 3, "Checking swap path folder: %s", swap_path.c_str() );
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());
@ -503,8 +503,8 @@ void MonitorStream::runStream() {
} 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" );
memset(temp_image_buffer, 0, sizeof(*temp_image_buffer)*temp_image_buffer_count);
Debug(2, "Assigned temporary buffer");
}
}
} else {

View File

@ -31,7 +31,7 @@ ZMPacket::ZMPacket( ) {
out_frame = NULL;
image = NULL;
buffer = NULL;
av_init_packet( &packet );
av_init_packet(&packet);
packet.size = 0; // So we can detect whether it has been filled.
timestamp = NULL;
analysis_image = NULL;
@ -47,8 +47,8 @@ ZMPacket::ZMPacket( ZMPacket &p ) {
out_frame = NULL;
image = NULL;
buffer = NULL;
av_init_packet( &packet );
if ( zm_av_packet_ref( &packet, &p.packet ) < 0 ) {
av_init_packet(&packet);
if ( zm_av_packet_ref(&packet, &p.packet) < 0 ) {
Error("error refing packet");
}
timestamp = new struct timeval;
@ -59,17 +59,17 @@ ZMPacket::ZMPacket( ZMPacket &p ) {
}
ZMPacket::~ZMPacket() {
zm_av_packet_unref( &packet );
zm_av_packet_unref(&packet);
if ( in_frame ) {
//av_free(frame->data);
av_frame_free( &in_frame );
av_frame_free(&in_frame);
}
if ( out_frame ) {
//av_free(frame->data);
av_frame_free( &out_frame );
av_frame_free(&out_frame);
}
if ( buffer ) {
av_freep( &buffer );
av_freep(&buffer);
}
if ( analysis_image ) {
delete analysis_image;
@ -82,19 +82,19 @@ ZMPacket::~ZMPacket() {
void ZMPacket::reset() {
//Debug(2,"reset");
zm_av_packet_unref( &packet );
zm_av_packet_unref(&packet);
packet.size = 0;
if ( in_frame ) {
//Debug(4,"reset frame");
av_frame_free( &in_frame );
av_frame_free(&in_frame);
}
if ( out_frame ) {
//Debug(4,"reset frame");
av_frame_free( &out_frame );
av_frame_free(&out_frame);
}
if ( buffer ) {
//Debug(4,"freeing buffer");
av_freep( &buffer );
av_freep(&buffer);
}
if ( analysis_image ) {
delete analysis_image;
@ -111,42 +111,44 @@ void ZMPacket::reset() {
}
int ZMPacket::decode( AVCodecContext *ctx ) {
Debug(4, "about to decode video, image_index is (%d)", image_index );
Debug(4, "about to decode video, image_index is (%d)", image_index);
if ( in_frame ) {
Error("Already have a frame?");
Error("Already have a frame?");
} else {
in_frame = zm_av_frame_alloc();
in_frame = zm_av_frame_alloc();
}
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
int ret = avcodec_send_packet( ctx, &packet );
Debug(4,"send_packet");
int ret = avcodec_send_packet(ctx, &packet);
if ( ret < 0 ) {
Error( "Unable to send packet: %s", av_make_error_string(ret).c_str() );
av_frame_free( &in_frame );
Error("Unable to send packet: %s", av_make_error_string(ret).c_str());
av_frame_free(&in_frame);
return 0;
}
#if HAVE_AVUTIL_HWCONTEXT_H
if ( hwaccel ) {
ret = avcodec_receive_frame( ctx, hwFrame );
ret = avcodec_receive_frame(ctx, hwFrame);
if ( ret < 0 ) {
Error( "Unable to receive frame: %s", av_make_error_string(ret).c_str() );
av_frame_free( &in_frame );
Error("Unable to receive frame: %s", av_make_error_string(ret).c_str());
av_frame_free(&in_frame);
return 0;
}
ret = av_hwframe_transfer_data(frame, hwFrame, 0);
if ( ret < 0 ) {
Error( "Unable to transfer frame: %s", av_make_error_string(ret).c_str() );
av_frame_free( &in_frame );
Error("Unable to transfer frame: %s", av_make_error_string(ret).c_str());
av_frame_free(&in_frame);
return 0;
}
} else {
#endif
ret = avcodec_receive_frame( ctx, in_frame );
Debug(4,"receive_frame");
ret = avcodec_receive_frame(ctx, in_frame);
if ( ret < 0 ) {
Error( "Unable to receive frame: %s", av_make_error_string(ret).c_str() );
av_frame_free( &in_frame );
Error("Unable to receive frame: %s", av_make_error_string(ret).c_str());
av_frame_free(&in_frame);
return 0;
}
@ -156,38 +158,38 @@ int ZMPacket::decode( AVCodecContext *ctx ) {
# else
int frameComplete = 0;
int ret = zm_avcodec_decode_video( ctx, in_frame, &frameComplete, &packet );
int ret = zm_avcodec_decode_video(ctx, in_frame, &frameComplete, &packet);
if ( ret < 0 ) {
Error( "Unable to decode frame at frame %s", av_make_error_string(ret).c_str() );
av_frame_free( &in_frame );
Error("Unable to decode frame at frame %s", av_make_error_string(ret).c_str());
av_frame_free(&in_frame);
return 0;
}
if ( ! frameComplete ) {
if ( !frameComplete ) {
Debug(1, "incomplete frame?");
av_frame_free( &in_frame );
av_frame_free(&in_frame);
return 0;
}
#endif
return 1;
} // end ZMPacket::decode
Image * ZMPacket::get_image( Image *i ) {
if ( ! in_frame ) {
Image *ZMPacket::get_image(Image *i) {
if ( !in_frame ) {
Error("Can't get image without frame.. maybe need to decode first");
return NULL;
}
if ( ! image ) {
if ( ! i ) {
if ( !image ) {
if ( !i ) {
Error("Need a pre-allocated image buffer");
return NULL;
}
image = i;
}
image->Assign( in_frame );
image->Assign(in_frame);
return image;
}
Image *ZMPacket::set_image( Image *i ) {
Image *ZMPacket::set_image(Image *i) {
image = i;
return image;
}

View File

@ -62,8 +62,12 @@ class ZMPacket {
explicit ZMPacket( ZMPacket &packet );
ZMPacket();
~ZMPacket();
void lock() { mutex.lock(); };
void unlock() { mutex.unlock(); };
void lock() {
Debug(2,"Locking packet %d", this->image_index);
mutex.lock();
Debug(2,"packet %d locked", this->image_index);
};
void unlock() { Debug(2,"packet %d unlocked", this->image_index);mutex.unlock(); };
AVFrame *get_out_frame( const AVCodecContext *ctx );
int get_codec_imgsize() { return codec_imgsize; };
};

View File

@ -33,12 +33,15 @@ zm_packetqueue::zm_packetqueue( int video_image_count, int p_video_stream_id, in
packet_counts = new int[max_stream_id+1];
for ( int i=0; i <= max_stream_id; ++i )
packet_counts[i] = 0;
condition = new Condition(mutex);
}
zm_packetqueue::~zm_packetqueue() {
clearQueue();
delete[] packet_counts;
packet_counts = NULL;
delete condition;
condition = NULL;
}
/* Enqueues the given packet. Will maintain the analysis_it pointer and image packet counts.
@ -48,6 +51,7 @@ zm_packetqueue::~zm_packetqueue() {
bool zm_packetqueue::queuePacket( ZMPacket* zm_packet ) {
Debug(4, "packetqueue queuepacket, first_video_packet_index is %d", first_video_packet_index);
mutex.lock();
if ( zm_packet->image_index != -1 ) {
// It's a video packet
@ -55,51 +59,33 @@ bool zm_packetqueue::queuePacket( ZMPacket* zm_packet ) {
// If we can never queue the same packet, then they can never go past
if ( zm_packet->image_index == first_video_packet_index ) {
Debug(2, "queuing packet that is already on the queue(%d)", zm_packet->image_index);
ZMPacket *p = NULL;;
while ( pktQueue.size() && (p = pktQueue.front()) && ( p->image_index != zm_packet->image_index ) ) {
if ( ( analysis_it != pktQueue.end() ) && ( *analysis_it == p ) ) {
Debug(2, "Increasing analysis_it, meaning analysis is not keeping up");
++analysis_it;
}
while ( pktQueue.size() ) {
mutex.unlock();
ZMPacket *p = popPacket();
Debug(2,"Front packet index: %d", p->image_index);
mutex.lock();
pktQueue.pop_front();
if ( p->codec_type == AVMEDIA_TYPE_VIDEO ) {
Debug(2, "Decreasing video_packet_count (%d), popped (%d)",
video_packet_count, p->image_index);
video_packet_count -= 1;
first_video_packet_index += 1;
first_video_packet_index %= max_video_packet_count;
} else {
Debug(2, "Deleteing audio frame(%d)", p->image_index);
if ( p->codec_type != AVMEDIA_TYPE_VIDEO ) {
Debug(2, "Deleting audio frame(%d)", p->image_index);
delete p;
p = NULL;
}
Debug(2,"pktQueue.size(%d)", pktQueue.size() );
Debug(2,"pktQueue.size(%d)", pktQueue.size());
if ( p->image_index == zm_packet->image_index )
break;
} // end while there are packets at the head of the queue that are not this one
if ( p && ( p->image_index == zm_packet->image_index ) ) {
// it should
video_packet_count -= 1;
pktQueue.pop_front();
first_video_packet_index += 1;
first_video_packet_index %= max_video_packet_count;
} else {
Error("SHould have found the packet! front packet index was %d, new packet index is %d ",
p->image_index, zm_packet->image_index
);
}
if ( analysis_it == pktQueue.end() ) {
// Analsys_it should only point to end when queue is empty
Debug(2,"pointing analysis_it to begining");
analysis_it = pktQueue.begin();
}
} else if ( first_video_packet_index == -1 ) {
}
if ( first_video_packet_index == -1 ) {
// Initialize the first_video_packet indicator
first_video_packet_index = zm_packet->image_index;
video_packet_count += 1;
} // end if
video_packet_count += 1;
} // end if queuing a video packet
pktQueue.push_back(zm_packet);
@ -114,6 +100,10 @@ bool zm_packetqueue::queuePacket( ZMPacket* zm_packet ) {
}
#endif
// We signal on every packet because someday we may analyze sound
Debug(2,"Signalling");
condition->signal();
mutex.unlock();
return true;
} // end bool zm_packetqueue::queuePacket(ZMPacket* zm_packet)
@ -122,6 +112,9 @@ ZMPacket* zm_packetqueue::popPacket( ) {
if ( pktQueue.empty() ) {
return NULL;
}
Debug(2,"Mutex locking");
mutex.lock();
Debug(2,"Have Mutex lock");
ZMPacket *packet = pktQueue.front();
if ( *analysis_it == packet )
@ -140,7 +133,9 @@ ZMPacket* zm_packetqueue::popPacket( ) {
}
}
packet_counts[packet->packet.stream_index] -= 1;
mutex.unlock();
// Should we lock the packet?
return packet;
}
@ -155,6 +150,7 @@ unsigned int zm_packetqueue::clearQueue(unsigned int frames_to_keep, int stream_
if ( pktQueue.size() <= frames_to_keep ) {
return 0;
}
mutex.lock();
int packets_to_delete = pktQueue.size();
std::list<ZMPacket *>::reverse_iterator it;
@ -241,6 +237,7 @@ unsigned int zm_packetqueue::clearQueue(unsigned int frames_to_keep, int stream_
#endif
Debug(3, "Deleted packets, resulting size is %d", pktQueue.size());
mutex.unlock();
return delete_count;
} // end unsigned int zm_packetqueue::clearQueue( unsigned int frames_to_keep, int stream_id )
@ -278,15 +275,22 @@ int zm_packetqueue::packet_count( int stream_id ) {
// Returns a packet to analyse or NULL
ZMPacket *zm_packetqueue::get_analysis_packet() {
if ( ! pktQueue.size() )
return NULL;
if ( analysis_it == pktQueue.end() )
return NULL;
mutex.lock();
while ( (! pktQueue.size()) || ( analysis_it == pktQueue.end() ) ) {
Debug(2,"waiting. Queue size %d analysis_it == end? %d", pktQueue.size(), ( analysis_it == pktQueue.end() ) );
condition->wait();
}
//Debug(2, "Distance from head: (%d)", std::distance( pktQueue.begin(), analysis_it ) );
//Debug(2, "Distance from end: (%d)", std::distance( analysis_it, pktQueue.end() ) );
ZMPacket *p = *analysis_it;
Debug(2,"analysis_packet image_index: %d, about to lock packet", p->image_index);
p->lock();
Debug(2, "Locked packet, unlocking mutex");
mutex.unlock();
return *analysis_it;
return p;
} // end ZMPacket *zm_packetqueue::get_analysis_packet()
// The idea is that analsys_it will only be == end() if the queue is empty
@ -301,3 +305,44 @@ bool zm_packetqueue::increment_analysis_it( ) {
analysis_it = next_it;
return true;
} // end bool zm_packetqueue::increment_analysis_it( )
// Locks the packet, but also removes it from the queue including analysis_it
void zm_packetqueue::lock_packet( ZMPacket &packet ) {
mutex.lock();
if ( packet.image_index != -1 ) {
// It's a video packet
// If we can never queue the same packet, then they can never go past
if ( packet.image_index == first_video_packet_index ) {
Debug(2, "queuing packet that is already on the queue(%d)", packet.image_index);
while ( pktQueue.size() ) {
mutex.unlock();
ZMPacket *p = popPacket();
Debug(2,"Front packet index: %d", p->image_index);
mutex.lock();
if ( p->codec_type != AVMEDIA_TYPE_VIDEO ) {
Debug(2, "Deleting audio frame(%d)", p->image_index);
delete p;
p = NULL;
}
Debug(2,"pktQueue.size(%d)", pktQueue.size());
if ( p->image_index == packet.image_index )
break;
} // end while there are packets at the head of the queue that are not this one
if ( analysis_it == pktQueue.end() ) {
// Analsys_it should only point to end when queue is empty
Debug(2,"pointing analysis_it to begining");
analysis_it = pktQueue.begin();
}
}
if ( first_video_packet_index == -1 ) {
// Initialize the first_video_packet indicator
first_video_packet_index = packet.image_index;
} // end if
video_packet_count += 1;
} // end if queuing a video packet
packet.lock();
mutex.unlock();
}

View File

@ -42,7 +42,8 @@ class zm_packetqueue {
int max_stream_id;
int *packet_counts; /* packet count for each stream_id, to keep track of how many video vs audio packets are in the queue */
Mutex mutex;
RecursiveMutex mutex;
Condition *condition;
public:
zm_packetqueue(int p_max_video_packet_count, int p_video_stream_id, int p_audio_stream_id);
@ -60,6 +61,7 @@ class zm_packetqueue {
// Functions to manage the analysis frame logic
bool increment_analysis_it();
ZMPacket *get_analysis_packet();
void lock_packet( ZMPacket &packet );
};
#endif /* ZM_PACKETQUEUE_H */

View File

@ -215,8 +215,9 @@ if ( $action ) {
# If I put this here, it protects all views and popups, but it has to go after actions.php because actions.php does the actual logging in.
if ( ZM_OPT_USE_AUTH and !isset($user) and ($view != 'login') ) {
Logger::Debug('Redirecting to login');
$view = 'none';
$redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=login';
# We adjust the view instead of redirecting so that we can store the original url and just to it after logging in
$view = 'login';
#$redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=login';
$request = null;
} else if ( ZM_SHOW_PRIVACY && ($view != 'privacy') && ($view != 'options') && (!$request) && canEdit('System') ) {
$view = 'none';

View File

@ -36,7 +36,7 @@ if ( $user['MonitorIds'] ) {
}
$Monitor = $Event->Monitor();
if (isset($_REQUEST['rate'])) {
if ( isset($_REQUEST['rate']) ) {
$rate = validInt($_REQUEST['rate']);
} else if ( isset($_COOKIE['zmEventRate']) ) {
$rate = $_COOKIE['zmEventRate'];
@ -44,7 +44,7 @@ if (isset($_REQUEST['rate'])) {
$rate = reScale(RATE_BASE, $Monitor->DefaultRate(), ZM_WEB_DEFAULT_RATE);
}
if (isset($_REQUEST['scale'])) {
if ( isset($_REQUEST['scale']) ) {
$scale = validInt($_REQUEST['scale']);
} else if ( isset( $_COOKIE['zmEventScaleAuto'] ) ) {
// If we're using scale to fit use it on all monitors
@ -56,12 +56,12 @@ if (isset($_REQUEST['scale'])) {
}
$codec = 'auto';
if (isset($_REQUEST['codec'])) {
if ( isset($_REQUEST['codec']) ) {
$codec = $_REQUEST['codec'];
session_start();
$_SESSION['zmEventCodec'.$Event->MonitorId()] = $codec;
session_write_close();
} else if ( isset( $_SESSION['zmEventCodec'.$Event->MonitorId()] ) ) {
} else if ( isset($_SESSION['zmEventCodec'.$Event->MonitorId()]) ) {
$codec = $_SESSION['zmEventCodec'.$Event->MonitorId()];
} else {
$codec = $Monitor->DefaultCodec();
@ -91,7 +91,7 @@ if ( isset( $_REQUEST['replayMode'] ) )
if ( isset( $_COOKIE['replayMode']) && preg_match('#^[a-z]+$#', $_COOKIE['replayMode']) )
$replayMode = validHtmlStr($_COOKIE['replayMode']);
if ( ( ! $replayMode ) or ( ! $replayModes[$replayMode] ) ) {
if ( ( !$replayMode ) or ( !$replayModes[$replayMode] ) ) {
$replayMode = 'none';
}
@ -145,7 +145,7 @@ if ( ! $Event->Id() ) {
<div id="nameControl">
<input type="text" id="eventName" name="eventName" value="<?php echo validHtmlStr($Event->Name()) ?>" />
<button value="Rename" type="button" data-on-click="renameEvent"<?php if ( !canEdit('Events') ) { ?> disabled="disabled"<?php } ?>>
<?php echo translate('Rename') ?></button>
<?php echo translate('Rename') ?></button>
</div>
<?php
if ( canEdit('Events') ) {
@ -172,8 +172,8 @@ if ( canEdit('Events') ) {
} // end if Event->DefaultVideo
?>
<div id="exportEvent"><button type="button" data-on-click="exportEvent"><?php echo translate('Export') ?></button></div>
<div id="replayControl"><label for="replayMode"><?php echo translate('Replay') ?></label><?php echo buildSelect( "replayMode", $replayModes, "changeReplayMode();" ); ?></div>
<div id="scaleControl"><label for="scale"><?php echo translate('Scale') ?></label><?php echo buildSelect( "scale", $scales, "changeScale();" ); ?></div>
<div id="replayControl"><label for="replayMode"><?php echo translate('Replay') ?></label><?php echo buildSelect('replayMode', $replayModes, 'changeReplayMode();'); ?></div>
<div id="scaleControl"><label for="scale"><?php echo translate('Scale') ?></label><?php echo buildSelect('scale', $scales, 'changeScale();'); ?></div>
<div id="codecControl"><label for="codec"><?php echo translate('Codec') ?></label><?php echo htmlSelect('codec', $codecs, $codec, array('onchange'=>'changeCodec(this);') ); ?></div>
</div>
</div>
@ -192,7 +192,6 @@ if ( $video_tag ) {
<?php
} else {
?>
<?php if ( !$video_tag ) { ?>
<div id="imageFeed">
<?php
if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
@ -212,7 +211,9 @@ if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
<div class="progressBox" id="progressBox" title="" style="width: 0%;"></div>
</div><!--progressBar-->
</div><!--imageFeed-->
<?php } /*end if !DefaultVideo*/ ?>
<?php
} /*end if !DefaultVideo*/
?>
<p id="dvrControls">
<input type="button" value="&lt;+" id="prevBtn" title="<?php echo translate('Prev') ?>" class="inactive" data-on-click-true="streamPrev"/>
<input type="button" value="&lt;&lt;" id="fastRevBtn" title="<?php echo translate('Rewind') ?>" class="inactive" data-on-click-true="streamFastRev"/>

View File

@ -18,8 +18,11 @@
}
?>";
//var newUrl = thisUrl + querySuffix;
var newUrl = '<?php echo $_SERVER['PHP_SELF'] ?>' + querySuffix;
if ( querySuffix == '?view=login' ) {
querySuffix = '?view=console';
}
var newUrl = querySuffix;
console.log("Redirecting to" + newUrl + ' ' + thisUrl);
window.location.replace(newUrl);
}
).delay( 500 );