finish roughing in ffmpeg_input

pull/3038/head
Isaac Connor 2017-06-26 16:55:49 -04:00
commit 62d6394923
15 changed files with 144 additions and 131 deletions

View File

@ -33,7 +33,7 @@
%global _hardened_build 1
Name: zoneminder
Version: 1.31.0
Version: 1.31.1
Release: 1%{?dist}
Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons

View File

@ -18,6 +18,8 @@ if [ "$1" = "configure" ]; then
fi
# Do this every time the package is installed or upgraded
# Ensure zoneminder is stopped
deb-systemd-invoke stop zoneminder.service || exit $?
if [ "$ZM_DB_HOST" = "localhost" ]; then
@ -41,13 +43,8 @@ if [ "$1" = "configure" ]; then
echo "grant lock tables,alter,select,insert,update,delete,create,index on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
fi
# Ensure zoneminder is stopped
deb-systemd-invoke stop zoneminder.service || exit $?
zmupdate.pl --nointeractive
zmupdate.pl --nointeractive -f
echo "Done Updating, starting ZoneMinder"
deb-systemd-invoke start zoneminder.service || exit $?
else
echo 'NOTE: mysql not running, please start mysql and run dpkg-reconfigure zoneminder when it is running.'
fi
@ -58,6 +55,8 @@ if [ "$1" = "configure" ]; then
else
echo "Not doing database upgrade due to remote db server ($ZM_DB_HOST)"
fi
echo "Done Updating, starting ZoneMinder"
deb-systemd-invoke restart zoneminder.service || exit $?
fi

View File

@ -77,7 +77,7 @@ Source Path
Use this field to enter the full URL of the stream or file your camera supports. This is usually an RTSP url. There are several methods to learn this:
* Check the documentation that came with your camera
* Look for your camera in the hardware compatibilty list in the wiki http://wiki.zoneminder.com/Hardware_Compatibilty_List
* Look for your camera in the hardware compatibilty list in the wiki http://wiki.zoneminder.com/Hardware_Compatibility_List
* Try ZoneMinder's new ONVIF probe feature
* Download and install the ONVIF Device Manager onto a Windows machine https://sourceforge.net/projects/onvifdm/
* Use Google to find third party sites, such as ispy, which document this information

View File

@ -31,7 +31,6 @@
#include "zm.h"
#include "zm_db.h"
#include "zm_time.h"
#include "zm_mpeg.h"
#include "zm_signal.h"
#include "zm_event.h"
#include "zm_monitor.h"
@ -591,4 +590,3 @@ void Event::AddFrame( Image *image, struct timeval timestamp, int score, Image *
}
*/
}

View File

@ -35,12 +35,11 @@
#include "zm_signal.h"
#include "zm_event.h"
#include "zm_eventstream.h"
#include "zm_ffmpeg_input.h"
#include "zm_storage.h"
#include "zm_monitor.h"
#include "zm_sendfile.h"
//#define USE_PREPARED_SQL 1
bool EventStream::loadInitialEventData( int monitor_id, time_t event_time ) {
static char sql[ZM_SQL_SML_BUFSIZ];
@ -132,9 +131,13 @@ bool EventStream::loadEventData( int event_id ) {
event_data = new EventData;
event_data->event_id = event_id;
event_data->monitor_id = atoi( dbrow[0] );
event_data->start_time = atoi(dbrow[3]);
event_data->storage_id = dbrow[1] ? atoi( dbrow[1] ) : 0;
event_data->frame_count = dbrow[2] == NULL ? 0 : atoi(dbrow[2]);
event_data->start_time = atoi(dbrow[3]);
event_data->duration = atof(dbrow[4]);
strncpy( event_data->video_file, dbrow[5], sizeof( event_data->video_file )-1 );
mysql_free_result( result );
Storage * storage = new Storage( event_data->storage_id );
const char *storage_path = storage->Path();
@ -150,13 +153,9 @@ bool EventStream::loadEventData( int event_id ) {
else
snprintf( event_data->path, sizeof(event_data->path), "%s/%s/%ld/%ld", staticConfig.PATH_WEB.c_str(), storage_path, event_data->monitor_id, event_data->event_id );
}
event_data->frame_count = dbrow[2] == NULL ? 0 : atoi(dbrow[3]);
event_data->duration = atof(dbrow[4]);
strncpy( event_data->video_file, dbrow[5], sizeof( event_data->video_file )-1 );
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 ) ) {
@ -209,10 +208,10 @@ bool EventStream::loadEventData( int event_id ) {
//}
if ( event_data->video_file[0] ) {
char *filepath[MAX_PATH];
snprintf( filepath, sizeof(filepath), "%s/%s", event_data->path, event_data->video_file[0] );
char filepath[PATH_MAX];
snprintf( filepath, sizeof(filepath), "%s/%s", event_data->path, event_data->video_file );
ffmpeg_input = new FFmpeg_Input();
if ( ! ffmpeg->Open() ) {
if ( ! ffmpeg_input->Open( filepath ) ) {
delete ffmpeg_input;
ffmpeg_input = NULL;
}
@ -248,15 +247,18 @@ void EventStream::processCommand( const CmdMsg *msg ) {
case CMD_PLAY :
{
Debug( 1, "Got PLAY command" );
if ( paused )
{
if ( paused ) {
// Clear paused flag
paused = false;
}
// If we are in single event mode and at the last frame, replay the current event
if ( (mode == MODE_SINGLE) && ((unsigned int)curr_frame_id == event_data->frame_count) )
if ( (mode == MODE_SINGLE) && ((unsigned int)curr_frame_id == event_data->frame_count) ) {
Debug(1, "Was in single_mode, and last frame, so jumping to 1st frame");
curr_frame_id = 1;
} else {
Debug(1, "mode is %s, current frame is %d, frame count is %d", (mode == MODE_SINGLE ? "single" : "not single" ), curr_frame_id, event_data->frame_count );
}
replay_rate = ZM_RATE_BASE;
break;
@ -381,7 +383,9 @@ void EventStream::processCommand( const CmdMsg *msg ) {
zoom = 500;
break;
}
send_frame = true;
break;
}
case CMD_ZOOMOUT :
{
@ -404,6 +408,7 @@ void EventStream::processCommand( const CmdMsg *msg ) {
zoom = 100;
break;
}
send_frame = true;
break;
}
case CMD_PAN :
@ -446,6 +451,7 @@ void EventStream::processCommand( const CmdMsg *msg ) {
int offset = ((unsigned char)msg->msg_data[1]<<24)|((unsigned char)msg->msg_data[2]<<16)|((unsigned char)msg->msg_data[3]<<8)|(unsigned char)msg->msg_data[4];
curr_frame_id = (int)(event_data->frame_count*offset/event_data->duration);
Debug( 1, "Got SEEK command, to %d (new cfid: %d)", offset, curr_frame_id );
send_frame = true;
break;
}
case CMD_QUERY :
@ -476,7 +482,7 @@ void EventStream::processCommand( const CmdMsg *msg ) {
status_data.rate = replay_rate;
status_data.zoom = zoom;
status_data.paused = paused;
Debug( 2, "E:%d, P:%d, p:%d R:%d, Z:%d",
Debug( 2, "Event:%d, Paused:%d, progress:%d Rate:%d, Zoom:%d",
status_data.event,
status_data.paused,
status_data.progress,
@ -734,10 +740,13 @@ void EventStream::runStream() {
exit( 0 );
}
unsigned int delta_us = 0;
while( !zm_terminate ) {
gettimeofday( &now, NULL );
unsigned int delta_us = 0;
send_frame = false;
// commands may set send_frame to true
while(checkCommandQueue());
if ( step != 0 )
@ -779,11 +788,8 @@ void EventStream::runStream() {
//}
continue;
}
}
// Figure out if we should send this frame
bool send_frame = false;
if ( !paused ) {
// If we are streaming and this frame is due to be sent
if ( ((curr_frame_id-1)%frame_mod) == 0 ) {
delta_us = (unsigned int)(frame_data->delta * 1000000);
@ -819,6 +825,7 @@ void EventStream::runStream() {
curr_frame_id = 1;
if ( send_frame && type != STREAM_MPEG ) {
Debug( 3, "dUs: %d", delta_us );
if ( delta_us )
usleep( delta_us );
}
} else {

View File

@ -20,24 +20,13 @@
#ifndef ZM_EVENTSTREAM_H
#define ZM_EVENTSTREAM_H
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <time.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <mysql/mysql.h>
#include <set>
#include <map>
#include "zm.h"
#include "zm_image.h"
#include "zm_stream.h"
#include "zm_video.h"
#include "zm_ffmpeg_input.h"
#ifdef __cplusplus
extern "C" {
@ -80,15 +69,15 @@ class EventStream : public StreamBase {
static const StreamMode DEFAULT_MODE = MODE_SINGLE;
protected:
StreamMode mode;
bool forceEventChange;
protected:
int curr_frame_id;
double curr_stream_time;
bool send_frame;
EventData *event_data;
FFmpeg_Input *ffmpeg_input;
protected:
bool loadEventData( int event_id );
@ -114,6 +103,7 @@ class EventStream : public StreamBase {
input_codec_context = 0;
input_codec = 0;
ffmpeg_input = NULL;
}
void setStreamStart( int init_event_id, unsigned int init_frame_id=0 ) {

View File

@ -1,13 +1,17 @@
#include "zm_ffmpeg_input.h"
#include "zm_logger.h"
#include "zm_ffmpeg.h"
void FFmpeg_Input() {
FFmpeg_Input::FFmpeg_Input() {
input_format_context = NULL;
video_stream_id = -1;
audio_stream_id = -1;
}
FFmpeg_Input::~FFmpeg_Input() {
}
int Open( const char *filepath ) {
int FFmpeg_Input::Open( const char *filepath ) {
int error;
@ -54,18 +58,18 @@ int Open( const char *filepath ) {
#endif
/** Find a decoder for the audio stream. */
if (!(streams[i].codec = avcodec_find_decoder((*input_format_context)->streams[i]->codecpar->codec_id))) {
if (!(streams[i].codec = avcodec_find_decoder(input_format_context->streams[i]->codecpar->codec_id))) {
Error( "Could not find input codec\n");
avformat_close_input(input_format_context);
avformat_close_input(&input_format_context);
return AVERROR_EXIT;
}
/** Open the decoder for the audio stream to use it later. */
if ((error = avcodec_open2( streams[i].context, streams[i].codec, NULL)) < 0) {
Errror( "Could not open input codec (error '%s')\n",
Error( "Could not open input codec (error '%s')\n",
av_make_error_string(error).c_str() );
avcodec_free_context( streams[i].context );
avformat_close_input(input_format_context);
avcodec_free_context( &streams[i].context );
avformat_close_input(&input_format_context);
return error;
}
@ -76,5 +80,5 @@ int Open( const char *filepath ) {
Debug( 3, "Unable to locate audio stream in %s", filepath );
return 0;
} // end int Open( const char * filepath )
} // end int FFmpeg::Open( const char * filepath )

View File

@ -32,6 +32,6 @@ class FFmpeg_Input {
int video_stream_id;
int audio_stream_id;
AVFormatContext *input_format_context;
}
};
#endif

View File

@ -112,6 +112,8 @@ int main( int argc, const char *argv[] ) {
char *value = strtok( NULL, "=" );
if ( !value )
value = (char *)"";
Debug(4, "Query string parameter (%s)=(%s)", name, value );
if ( !strcmp( name, "source" ) ) {
source = !strcmp( value, "event" )?ZMS_EVENT:ZMS_MONITOR;
} else if ( !strcmp( name, "mode" ) ) {
@ -187,7 +189,7 @@ int main( int argc, const char *argv[] ) {
if ( *auth ) {
user = zmLoadAuthUser( auth, config.auth_hash_ips );
} else {
Debug( 1, "Need both username and password" );
Debug( 1, "Need both username and password if auth not specified" );
}
}
//else if ( strcmp( config.auth_relay, "plain" ) == 0 )

View File

@ -72,6 +72,9 @@ public $defaults = array(
if ( ! isset( $this->{'terms'} ) ) {
if ( array_key_exists( 'Query', $this ) and $this->{'Query'} ) {
$this->{'terms'} = jsonDecode( $this->{'Query'} );
if ( isset( $this->{'terms'}['terms'] ) )
$this->{'terms'} = $this->{'terms'}['terms'];
} else {
$this->{'terms'} = array();
}

View File

@ -138,7 +138,7 @@ if ( !empty($action) ) {
} else {
$sql .= ' Name = '.dbEscape($_REQUEST['filter']['Name']);
}
$sql .= ', Query = '.dbEscape(jsonEncode($_REQUEST['filter']['terms']));
$sql .= ', Query = '.dbEscape(jsonEncode($_REQUEST['filter']));
$sql .= ', AutoArchive = '.(!empty($_REQUEST['filter']['AutoArchive']) ? 1 : 0);
$sql .= ', AutoVideo = '. ( !empty($_REQUEST['filter']['AutoVideo']) ? 1 : 0);
$sql .= ', AutoUpload = '. ( !empty($_REQUEST['filter']['AutoUpload']) ? 1 : 0);

View File

@ -50,6 +50,7 @@ if ( isset( $_REQUEST['scale'] ) ) {
}
$replayModes = array(
'none' => translate('None'),
'single' => translate('ReplaySingle'),
'all' => translate('ReplayAll'),
'gapless' => translate('ReplayGapless'),
@ -64,9 +65,9 @@ if ( isset( $_REQUEST['replayMode'] ) )
$replayMode = validHtmlStr($_REQUEST['replayMode']);
if ( isset( $_COOKIE['replayMode']) && preg_match('#^[a-z]+$#', $_COOKIE['replayMode']) )
$replayMode = validHtmlStr($_COOKIE['replayMode']);
else {
$keys = array_keys( $replayModes );
$replayMode = array_shift( $keys );
if ( ( ! $replayMode ) or ( ! $replayModes[$replayMode] ) ) {
$replayMode = 'none';
}
// videojs zoomrotate only when direct recording
@ -188,8 +189,8 @@ if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
<input type="button" value="&lt;+" id="prevBtn" title="<?php echo translate('Prev') ?>" class="inactive" onclick="streamPrev( true );"/>
<input type="button" value="&lt;&lt;" id="fastRevBtn" title="<?php echo translate('Rewind') ?>" class="inactive" disabled="disabled" onclick="streamFastRev( true );"/>
<input type="button" value="&lt;" id="slowRevBtn" title="<?php echo translate('StepBack') ?>" class="unavail" disabled="disabled" onclick="streamSlowRev( true );"/>
<input type="button" value="||" id="pauseBtn" title="<?php echo translate('Pause') ?>" class="inactive" onclick="streamPause( true );"/>
<input type="button" value="|>" id="playBtn" title="<?php echo translate('Play') ?>" class="active" disabled="disabled" onclick="streamPlay( true );"/>
<input type="button" value="||" id="pauseBtn" title="<?php echo translate('Pause') ?>" class="inactive" onclick="pauseClicked();"/>
<input type="button" value="|>" id="playBtn" title="<?php echo translate('Play') ?>" class="active" disabled="disabled" onclick="playClicked();"/>
<input type="button" value="&gt;" id="slowFwdBtn" title="<?php echo translate('StepForward') ?>" class="unavail" disabled="disabled" onclick="streamSlowFwd( true );"/>
<input type="button" value="&gt;&gt;" id="fastFwdBtn" title="<?php echo translate('FastForward') ?>" class="inactive" disabled="disabled" onclick="streamFastFwd( true );"/>
<input type="button" value="&ndash;" id="zoomOutBtn" title="<?php echo translate('ZoomOut') ?>" class="avail" onclick="streamZoomOut();"/>

View File

@ -168,6 +168,7 @@ if ( (null !== $filter->Concurrent()) and $filter->Concurrent() )
<table id="fieldsTable" class="filterTable">
<tbody>
<?php
var_dump($terms);
for ( $i = 0; $i < count($terms); $i++ ) {
$term = $terms[$i];
if ( ! isset( $term['op'] ) )

View File

@ -4,6 +4,8 @@ function setButtonState( element, butClass ) {
if ( element ) {
element.className = butClass;
element.disabled = (butClass != 'inactive');
} else {
console.log("Element was null in setButtonState");
}
}
@ -58,16 +60,15 @@ function getCmdResponse( respObj, respText ) {
lastEventId = eventId;
}
if ( streamStatus.paused == true ) {
console.log('paused');
$('modeValue').set( 'text', "Paused" );
$('modeValue').set( 'text', 'Paused' );
$('rate').addClass( 'hidden' );
streamPause( false );
streamPause( );
} else {
console.log('playing');
$('modeValue').set( 'text', "Replay" );
$('rateValue').set( 'text', streamStatus.rate );
$('rate').removeClass( 'hidden' );
streamPlay( false );
streamPlay( );
}
$('progressValue').set( 'text', secsToTime( parseInt(streamStatus.progress) ) );
$('zoomValue').set( 'text', streamStatus.zoom );
@ -90,17 +91,25 @@ function getCmdResponse( respObj, respText ) {
var streamReq = new Request.JSON( { url: thisUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'chain', onSuccess: getCmdResponse } );
function streamPause( action ) {
function pauseClicked( ) {
streamReq.send( streamParms+"&command="+CMD_PAUSE );
}
// Called when stream becomes paused, just updates the button status
function streamPause( ) {
setButtonState( $('pauseBtn'), 'active' );
setButtonState( $('playBtn'), 'inactive' );
setButtonState( $('fastFwdBtn'), 'unavail' );
setButtonState( $('slowFwdBtn'), 'inactive' );
setButtonState( $('slowRevBtn'), 'inactive' );
setButtonState( $('fastRevBtn'), 'unavail' );
streamReq.send( streamParms+"&command="+CMD_PAUSE );
}
function streamPlay( action ) {
function playClicked( ) {
streamReq.send( streamParms+"&command="+CMD_PLAY );
}
function streamPlay( ) {
setButtonState( $('pauseBtn'), 'inactive' );
if (streamStatus)
setButtonState( $('playBtn'), streamStatus.rate==1?'active':'inactive' );
@ -108,7 +117,6 @@ function streamPlay( action ) {
setButtonState( $('slowFwdBtn'), 'unavail' );
setButtonState( $('slowRevBtn'), 'unavail' );
setButtonState( $('fastRevBtn'), 'inactive' );
streamReq.send( streamParms+"&command="+CMD_PLAY );
}
function streamFastFwd( action ) {