Merge branch 'storageareas' into valgrind

This commit is contained in:
Isaac Connor 2016-04-20 10:01:30 -04:00
commit 2fcdee87d9
19 changed files with 275 additions and 139 deletions

View File

@ -3,51 +3,51 @@
set -e
if [ "$1" = "configure" ]; then
if [ -e "/etc/init.d/mysql" ]; then
#
# Get mysql started if it isn't
#
if ! $(/etc/init.d/mysql status >/dev/null 2>&1); then
invoke-rc.d mysql start
fi
if $(/etc/init.d/mysql status >/dev/null 2>&1); then
mysqladmin --defaults-file=/etc/mysql/debian.cnf -f reload
# test if database if already present...
if ! $(echo quit | mysql --defaults-file=/etc/mysql/debian.cnf zm > /dev/null 2> /dev/null) ; then
cat /usr/share/zoneminder/db/zm_create.sql | mysql --defaults-file=/etc/mysql/debian.cnf
echo 'grant lock tables, alter,select,insert,update,delete on zm.* to 'zmuser'@localhost identified by "zmpass";' | mysql --defaults-file=/etc/mysql/debian.cnf mysql
fi
invoke-rc.d zoneminder stop || true
zmupdate.pl --nointeractive
. /etc/zm/zm.conf
else
echo 'NOTE: mysql not running, please start mysql and run dpkg-reconfigure zoneminder when it is running.'
fi
else
echo 'mysql not found, assuming remote server.'
fi
chown www-data:www-data /var/log/zm
chown www-data:www-data /var/lib/zm/
# The logs can contain passwords, etc... so by setting group root, only www-data can read them, not people in the www-data group.
chown www-data:root /var/log/zm
chown www-data:www-data /var/lib/zm
if [ -z "$2" ]; then
chown www-data:www-data -R /var/cache/zoneminder
chown www-data:www-data -R /var/cache/zoneminder
fi
fi
# Ensure zoneminder is stopped...
if [ -x "/etc/init.d/zoneminder" ]; then
if invoke-rc.d zoneminder status ; then
invoke-rc.d zoneminder stop || exit $?
# Do this every time the package is installed or upgraded
if [ "$ZM_DB_HOST" = "localhost" ]; then
if [ -e "/etc/init.d/mysql" ]; then
#
# Get mysql started if it isn't
#
if ! $(/etc/init.d/mysql status >/dev/null 2>&1); then
invoke-rc.d mysql start
fi
if $(/etc/init.d/mysql status >/dev/null 2>&1); then
mysqladmin --defaults-file=/etc/mysql/debian.cnf -f reload
# test if database if already present...
if ! $(echo quit | mysql --defaults-file=/etc/mysql/debian.cnf zm > /dev/null 2> /dev/null) ; then
cat /usr/share/zoneminder/db/zm_create.sql | mysql --defaults-file=/etc/mysql/debian.cnf
# This creates the user.
echo "grant lock tables, alter,select,insert,update,delete,create,index on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost identified by \"${ZM_DB_PASS}\";" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
else
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
invoke-rc.d zoneminder stop || true
zmupdate.pl --nointeractive
zmupdate.pl --nointeractive -f
invoke-rc.d zoneminder start || true
else
echo 'NOTE: mysql not running, please start mysql and run dpkg-reconfigure zoneminder when it is running.'
fi
else
echo 'mysql not found, assuming remote server.'
fi
fi
if [ "$1" = "configure" ]; then
if [ -z "$2" ]; then
chown www-data:www-data /var/log/zm
chown www-data:www-data /var/lib/zm/
chown www-data:www-data -R /var/cache/zoneminder
else
chown www-data:www-data /var/log/zm
zmupdate.pl
fi
echo "Not doing database upgrade due to remote db server ($ZM_DB_HOST)"
fi
fi
#DEBHELPER#

View File

@ -3,11 +3,51 @@
set -e
if [ "$1" = "configure" ]; then
chown www-data:root /var/log/zm
chown www-data:www-data /var/lib/zm
if [ -z "$2" ]; then
chown www-data:www-data -R /var/cache/zoneminder
fi
. /etc/zm/zm.conf
# The logs can contain passwords, etc... so by setting group root, only www-data can read them, not people in the www-data group
chown www-data:root /var/log/zm
chown www-data:www-data /var/lib/zm
if [ -z "$2" ]; then
chown www-data:www-data -R /var/cache/zoneminder
fi
# Do this every time the package is installed or upgraded
if [ "$ZM_DB_HOST" = "localhost" ]; then
if [ -e "/etc/init.d/mysql" ]; then
#
# Get mysql started if it isn't
#
if ! $(/etc/init.d/mysql status >/dev/null 2>&1); then
invoke-rc.d mysql start
fi
if $(/etc/init.d/mysql status >/dev/null 2>&1); then
mysqladmin --defaults-file=/etc/mysql/debian.cnf -f reload
# test if database if already present...
if ! $(echo quit | mysql --defaults-file=/etc/mysql/debian.cnf zm > /dev/null 2> /dev/null) ; then
cat /usr/share/zoneminder/db/zm_create.sql | mysql --defaults-file=/etc/mysql/debian.cnf
# This creates the user.
echo "grant lock tables, alter,select,insert,update,delete,create,index on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost identified by \"${ZM_DB_PASS}\";" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
else
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
invoke-rc.d zoneminder stop || true
zmupdate.pl --nointeractive
zmupdate.pl --nointeractive -f
invoke-rc.d zoneminder start || true
else
echo 'NOTE: mysql not running, please start mysql and run dpkg-reconfigure zoneminder when it is running.'
fi
else
echo 'mysql not found, assuming remote server.'
fi
else
echo "Not doing database upgrade due to remote db server ($ZM_DB_HOST)"
fi
fi
#DEBHELPER#

View File

@ -57,7 +57,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
,libsys-cpu-perl, libsys-meminfo-perl
,mysql-client | virtual-mysql-client
,perl-modules
,php5-mysql
,php5-mysql, php5-gd
,policykit-1
,rsyslog | system-log-daemon
,zip

View File

@ -2,28 +2,57 @@
set -e
. /etc/zm/zm.conf
if [ "$1" = "configure" ]; then
chown www-data:root /var/log/zm
chown www-data:www-data /var/lib/zm
if [ -z "$2" ]; then
chown www-data:www-data -R /var/cache/zoneminder
fi
. /etc/zm/zm.conf
# The logs can contain passwords, etc... so by setting group root, only www-data can read them, not people in the www-data group
chown www-data:root /var/log/zm
chown www-data:www-data /var/lib/zm
if [ -z "$2" ]; then
chown www-data:www-data -R /var/cache/zoneminder
fi
# Do this every time the package is installed or upgraded
# Test for database presence to avoid failure of zmupdate.pl
# Ensure zoneminder is stopped
deb-systemd-invoke stop zoneminder.service || exit $?
if [ "$ZM_DB_HOST" = "localhost" ]; then
echo 'grant lock tables, create, index, alter on zm.* to 'zmuser'@localhost identified by "zmpass";' | mysql --defaults-file=/etc/mysql/debian.cnf mysql
# Run the ZoneMinder update tool
zmupdate.pl --nointeractive
else
if [ -e "/etc/init.d/mysql" ]; then
#
# Get mysql started if it isn't
#
if ! $(/etc/init.d/mysql status >/dev/null 2>&1); then
deb-systemd-invoke start mysql.service || exit $?
fi
if $(/etc/init.d/mysql status >/dev/null 2>&1); then
mysqladmin --defaults-file=/etc/mysql/debian.cnf -f reload
# test if database if already present...
if ! $(echo quit | mysql --defaults-file=/etc/mysql/debian.cnf zm > /dev/null 2> /dev/null) ; then
cat /usr/share/zoneminder/db/zm_create.sql | mysql --defaults-file=/etc/mysql/debian.cnf
# This creates the user.
echo "grant lock tables,alter,select,insert,update,delete,create,index on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost identified by \"${ZM_DB_PASS}\";" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
else
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
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
else
echo 'mysql not found, assuming remote server.'
fi
else
echo "Not doing database upgrade due to remote db server ($ZM_DB_HOST)"
fi;
fi
fi

View File

@ -514,6 +514,8 @@ You do not need to rebuild ZM for X10 support. You will need to install the perl
Extending Zoneminder
------------------------
.. _runstate_cron_example:
How can I get ZM to do different things at different times of day or week?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -67,8 +67,14 @@ own empty screen.
* **D**: This is the core of ZoneMinder - recording events. It gives you a count of how many events were recorded over the hour, day, week, month.
* **E**: These are the "Zones". Zones are areas within the camera that you mark as 'hotspots' for motion detection. Simply put, when you first configure your monitors (cameras), by default Zoneminder uses the entire field of view of the camera to detect motion. You may not want this. You may want to create "zones" specifically for detecting motion and ignore others. For example, lets consider a room with a fan that spins. You surely don't want to consider the fan moving continuously a reason for triggering a record? Probably not - in that case, you'd leave the fan out while making your zones.
* **F**: This is the "source" column that tells you the type of the camera - if its an IP camera, a USB camera or more. In this example, they are all IP cameras. Note the color red on item F ? Well that means there is something wrong with that camera. No wonder the log also shows red. Good indication for you to tap on logs and investigate
* **G**: This defines how Zoneminder will record events. There are various modes. In brief Modect == record if a motion is detected,Record = always record 24x7, Mocord = always record PLUS detect motion, Monitor = just provide a live view but don't record anytime, Nodect = Don't record till an externa entity via zmtrigger tells Zoneminder to (this is advanced usage).
* **G**: This defines how Zoneminder will record events. There are various modes. In brief Modect == record if a motion is detected,Record = always record 24x7, Mocord = always record PLUS detect motion, Monitor = just provide a live view but don't record anytime, Nodect = Don't record till an external entity via zmtrigger tells Zoneminder to (this is advanced usage).
* **H**: If you click on these links you can view a "Montage" of all your configured monitors or cycle through each one
* **I**: One of the most often missed features is the ability of ZoneMinder to maintain "run states". If you click on the "Running" text, ZoneMinder brings up a popup that allows you to define additional "states" (referred to as runstates). A runstate is essentially a snapshot that records the state of each monitor and you can switch between states easily. For example, you might have a run state defined that switches all monitors to "monitor" mode in which they are not recording anything while another state that sets some of the monitors to "modect". Why would you want this? A great example is to disable recording when you are at home and enable when you are away, based on time of day or other triggers. You can switch states by selecting an appropriate state manually, or do it automatically via cron jobs, for example. An example of using cron to automatically switch is provided in the :ref:`FAQ <runstate_cron_example>`. More esoteric examples of switching run states based on phone location can be found `here <https://forums.zoneminder.com/viewtopic.php?f=9&t=23026>`__.
Here is an example of multiple run states that I've defined. Each one of these runstates changes the mode of specific monitors depending on time of day and other conditions. Use your imagination to decide which conditions require state changes.
.. image:: images/runstates.png
Adding Monitors

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 KiB

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@ -155,10 +155,12 @@ MAIN: while( $loop ) {
Fatal("ZM_AUDIT_MIN_AGE is not set in config.");
}
my %Monitors;
my $db_monitors;
my $monitorSelectSql = "select Id from Monitors order by Id";
my $monitorSelectSql = "select * from Monitors order by Id";
my $monitorSelectSth = $dbh->prepare_cached( $monitorSelectSql )
or Fatal( "Can't prepare '$monitorSelectSql': ".$dbh->errstr() );
my $eventSelectSql = "SELECT Id, (unix_timestamp() - unix_timestamp(StartTime)) as Age
FROM Events WHERE MonitorId = ? ORDER BY Id";
my $eventSelectSth = $dbh->prepare_cached( $eventSelectSql )
@ -169,6 +171,8 @@ MAIN: while( $loop ) {
or Fatal( "Can't execute: ".$monitorSelectSth->errstr() );
while( my $monitor = $monitorSelectSth->fetchrow_hashref() )
{
$Monitors{$$monitor{Id}} = $monitor;
Debug( "Found database monitor '$monitor->{Id}'" );
my $db_events = $db_monitors->{$monitor->{Id}} = {};
my $res = $eventSelectSth->execute( $monitor->{Id} )
@ -467,20 +471,30 @@ MAIN: while( $loop ) {
# New audit to close any events that were left open for longer than MIN_AGE seconds
my $selectUnclosedEventsSql =
"SELECT E.Id,
max(F.TimeStamp) as EndTime,
unix_timestamp(max(F.TimeStamp)) - unix_timestamp(E.StartTime) as Length,
max(F.FrameId) as Frames,
#"SELECT E.Id, ANY_VALUE(E.MonitorId),
#
#max(F.TimeStamp) as EndTime,
#unix_timestamp(max(F.TimeStamp)) - unix_timestamp(E.StartTime) as Length,
#max(F.FrameId) as Frames,
#count(if(F.Score>0,1,NULL)) as AlarmFrames,
#sum(F.Score) as TotScore,
#max(F.Score) as MaxScore
#FROM Events as E
#INNER JOIN Frames as F on E.Id = F.EventId
#WHERE isnull(E.Frames) or isnull(E.EndTime)
#GROUP BY E.Id HAVING EndTime < (now() - interval ".$Config{ZM_AUDIT_MIN_AGE}." second)"
#;
"SELECT *, unix_timestamp(StartTime) AS TimeStamp FROM Events WHERE EndTime IS NULL AND StartTime < (now() - interval ".$Config{ZM_AUDIT_MIN_AGE}." second)";
my $selectFrameDataSql = "SELECT max(TimeStamp) as EndTime, unix_timestamp(max(TimeStamp)) AS EndTimeStamp, max(FrameId) as Frames,
count(if(F.Score>0,1,NULL)) as AlarmFrames,
sum(F.Score) as TotScore,
max(F.Score) as MaxScore,
M.EventPrefix as Prefix
FROM Events as E
LEFT JOIN Monitors as M on E.MonitorId = M.Id
INNER JOIN Frames as F on E.Id = F.EventId
WHERE isnull(E.Frames) or isnull(E.EndTime)
GROUP BY E.Id HAVING EndTime < (now() - interval ".$Config{ZM_AUDIT_MIN_AGE}." second)"
;
max(F.Score) as MaxScore
FROM Frames WHERE EventId=?";
my $selectFrameDataSth = $dbh->prepare_cached($selectFrameDataSql)
or Fatal( "Can't prepare '$selectFrameDataSql': ".$dbh->errstr() );
my $selectUnclosedEventsSth = $dbh->prepare_cached( $selectUnclosedEventsSql )
or Fatal( "Can't prepare '$selectUnclosedEventsSql': ".$dbh->errstr() );
my $updateUnclosedEventsSql =
@ -505,26 +519,32 @@ MAIN: while( $loop ) {
aud_print( "Found open event '$event->{Id}'" );
if ( confirm( 'close', 'closing' ) )
{
$res = $updateUnclosedEventsSth->execute
(
sprintf("%s%d%s",
$event->{Prefix},
$event->{Id},
RECOVER_TAG
),
$event->{EndTime},
$event->{Length},
$event->{Frames},
$event->{AlarmFrames},
$event->{TotScore},
$event->{AlarmFrames}
? int($event->{TotScore} / $event->{AlarmFrames})
: 0
,
$event->{MaxScore},
RECOVER_TEXT,
$event->{Id}
) or Fatal( "Can't execute: ".$updateUnclosedEventsSth->errstr() );
$res = $selectFrameDataSth->execute( $event->{Id} );
my $frame = $selectFrameDataSth->fetchrow_hashref();
if ( $frame ) {
$res = $updateUnclosedEventsSth->execute
(
sprintf("%s%d%s",
$Monitors{$event->{MonitorId}}->{EventPrefix},
$event->{Id},
RECOVER_TAG
),
$frame->{EndTime},
$frame->{EndTimeStamp} - $event->{TimeStamp},
$frame->{Frames},
$frame->{AlarmFrames},
$frame->{TotScore},
$frame->{AlarmFrames}
? int($frame->{TotScore} / $frame->{AlarmFrames})
: 0
,
$frame->{MaxScore},
RECOVER_TEXT,
$event->{Id}
) or Fatal( "Can't execute: ".$updateUnclosedEventsSth->errstr() );
} else {
Error("SHOULD DELETE");
} # end if has frame data
}
}

View File

@ -862,7 +862,7 @@ sub killAll
my $killall;
if ( '@HOST_OS@' eq 'BSD' )
{
$killall = 'killall -';
$killall = 'killall -q -';
} elsif ( '@HOST_OS@' eq 'solaris' ) {
$killall = 'pkill -';
} else {

View File

@ -61,6 +61,7 @@ FfmpegCamera::FfmpegCamera( int p_id, const std::string &p_path, const std::stri
mOpenStart = 0;
mReopenThread = 0;
wasRecording = false;
videoStore = NULL;
#if HAVE_LIBSWSCALE
mConvertContext = NULL;
@ -99,6 +100,7 @@ void FfmpegCamera::Initialise()
av_log_set_level( AV_LOG_QUIET );
av_register_all();
avformat_network_init();
}
void FfmpegCamera::Terminate()
@ -356,7 +358,8 @@ int FfmpegCamera::OpenFfmpeg() {
if ( mAudioStreamId == -1 )
Debug( 2, "Unable to locate audio stream in %s", mPath.c_str() );
Debug ( 1, "Found video stream" );
Debug ( 3, "Found video stream at index %d", mVideoStreamId );
Debug ( 3, "Found audio stream at index %d", mAudioStreamId );
mCodecContext = mFormatContext->streams[mVideoStreamId]->codec;
@ -408,7 +411,7 @@ int FfmpegCamera::OpenFfmpeg() {
Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize);
}
Debug ( 1, "Validated imagesize" );
Debug ( 1, "Validated imagesize %d", pSize );
#if HAVE_LIBSWSCALE
Debug ( 1, "Calling sws_isSupportedInput" );
@ -590,9 +593,11 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height);
//Keep the last keyframe so we can establish immediate video
/*if(packet.flags & AV_PKT_FLAG_KEY)
av_copy_packet(&lastKeyframePkt, &packet);*/
//TODO I think we need to store the key frame location for seeking as part of the event
if(packet.flags & AV_PKT_FLAG_KEY) {
Debug(4, "Have keyframe");
av_copy_packet(&lastKeyframePkt, &packet);
//TODO I think we need to store the key frame location for seeking as part of the event
}
//Video recording
if ( recording && !wasRecording ) {
@ -603,6 +608,9 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
wasRecording = true;
strcpy(oldDirectory, event_file);
// Need to write out all the frames from the last keyframe?
} else if ( ( ! recording ) && wasRecording && videoStore ) {
Info("Deleting videoStore instance");
delete videoStore;
@ -660,9 +668,10 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
}
if ( videoStore && recording ) {
if ( record_audio ) {
Debug(3, "Recording audio packet" );
Debug(3, "Recording audio packet streamindex(%d) packetstreamindex(%d)", mAudioStreamId, packet.stream_index );
//Write the packet to our video store
int ret = videoStore->writeAudioFramePacket(&packet, mFormatContext->streams[packet.stream_index]); //FIXME no relevance of last key frame
//FIXME no relevance of last key frame
int ret = videoStore->writeAudioFramePacket( &packet, mFormatContext->streams[packet.stream_index] );
if ( ret < 0 ) {//Less than zero and we skipped a frame
av_free_packet( &packet );
return 0;

View File

@ -64,7 +64,9 @@ protected:
bool wasRecording;
VideoStore *videoStore;
char oldDirectory[4096];
//AVPacket lastKeyframePkt;
// Last Key frame
AVPacket lastKeyframePkt;
#if HAVE_LIBSWSCALE
struct SwsContext *mConvertContext;

View File

@ -33,7 +33,8 @@ extern "C"{
}
VideoStore::VideoStore(const char *filename_in, const char *format_in,
AVStream *input_st, AVStream *inpaud_st,
AVStream *input_st,
AVStream *inpaud_st,
int64_t nStartTime) {
AVDictionary *pmetadata = NULL;
@ -46,8 +47,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
keyframeMessage = false;
keyframeSkipNumber = 0;
Info("Opening video storage stream %s\n", filename);
Info("Opening video storage stream %s format: %d\n", filename, format);
//Init everything we need
int ret;
@ -96,12 +96,13 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
}
if (inpaud_st) {
audio_st = avformat_new_stream(oc, inpaud_st->codec->codec);
if (!audio_st) {
Error("Unable to create audio out stream\n");
audio_st = NULL;
} else {
ret=avcodec_copy_context(audio_st->codec, inpaud_st->codec);
ret = avcodec_copy_context(audio_st->codec, inpaud_st->codec);
if (ret < 0) {
Fatal("Unable to copy audio context %s\n", av_make_error_string(ret).c_str());
}
@ -111,6 +112,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
}
}
} else {
Debug(3, "No Audio output stream");
audio_st = NULL;
}
@ -146,7 +148,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
startTime=av_gettime()-nStartTime;//oc->start_time;
Info("VideoStore startTime=%d\n",startTime);
}
} // VideoStore::VideoStore
VideoStore::~VideoStore(){
@ -249,7 +251,7 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt, AVStream *input_st){//, AV
} else if ((prevDts > 0) && (prevDts >= opkt.dts)) {
Warning("%s:%d: DTS out of order: %lld \u226E %lld; discarding frame", __FILE__, __LINE__, prevDts, opkt.dts);
prevDts = opkt.dts;
dumpPacket(&opkt);
dumpPacket(&opkt);
} else {
int ret;
@ -272,34 +274,47 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt, AVStream *input_st){//, AV
int VideoStore::writeAudioFramePacket(AVPacket *ipkt, AVStream *input_st){
if(!audio_st)
if(!audio_st) {
Error("Called writeAudioFramePacket when no audio_st");
return -1;//FIXME -ve return codes do not free packet in ffmpeg_camera at the moment
}
/*if(!keyframeMessage)
return -1;*/
//zm_dump_stream_format( oc, ipkt->stream_index, 0, 1 );
int64_t ost_tb_start_time = av_rescale_q(startTime, AV_TIME_BASE_Q, video_st->time_base);
// What is this doing? Getting the time of the start of this video chunk? Does that actually make sense?
int64_t ost_tb_start_time = av_rescale_q(startTime, AV_TIME_BASE_Q, audio_st->time_base);
AVPacket opkt;
av_init_packet(&opkt);
Debug(3, "after init packet" );
//Scale the PTS of the outgoing packet to be the correct time base
if (ipkt->pts != AV_NOPTS_VALUE)
if (ipkt->pts != AV_NOPTS_VALUE) {
Debug(3, "Rescaling output pts");
opkt.pts = av_rescale_q(ipkt->pts-startPts, input_st->time_base, audio_st->time_base) - ost_tb_start_time;
else
} else {
Debug(3, "Setting output pts to AV_NOPTS_VALUE");
opkt.pts = AV_NOPTS_VALUE;
}
//Scale the DTS of the outgoing packet to be the correct time base
if(ipkt->dts == AV_NOPTS_VALUE) {
Debug(4, "ipkt->dts == AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts );
opkt.dts = av_rescale_q(input_st->cur_dts-startDts, AV_TIME_BASE_Q, audio_st->time_base);
Debug(3, "ipkt->dts == AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts );
} else
Debug(4, "ipkt->dts == AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts );
} else {
Debug(4, "ipkt->dts != AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts );
opkt.dts = av_rescale_q(ipkt->dts-startDts, input_st->time_base, audio_st->time_base);
Debug(4, "ipkt->dts != AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts );
}
opkt.dts -= ost_tb_start_time;
// Seems like it would be really weird for the codec type to NOT be audiu
if (audio_st->codec->codec_type == AVMEDIA_TYPE_AUDIO && ipkt->dts != AV_NOPTS_VALUE) {
Debug( 3, "code is audio, dts != AV_NOPTS_VALUE " );
Debug( 4, "code is audio, dts != AV_NOPTS_VALUE " );
int duration = av_get_audio_frame_duration(input_st->codec, ipkt->size);
if(!duration)
duration = input_st->codec->frame_size;
@ -324,7 +339,7 @@ Debug(3, "ipkt->dts == AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts );
if(ret!=0){
Fatal("Error encoding audio frame packet: %s\n", av_make_error_string(ret).c_str());
}
Debug(4,"Success writing audio frame" );
av_free_packet(&opkt);
return 0;
}

View File

@ -527,6 +527,7 @@ if ( !empty($action) )
'DoNativeMotDet' => 'toggle',
'Exif' => 'toggle',
'RTSPDescribe' => 'toggle',
'RecordAudio' => 'toggle',
);
$columns = getTableColumns( 'Monitors' );

View File

@ -15,7 +15,6 @@
#menuBar1 {
width: 100%;
height: 1.5em;
padding: 3px 0;
text-align: center;
clear: both;
@ -41,7 +40,6 @@
#menuBar2 {
width: 100%;
height: 1.2em;
padding: 3px 0;
margin-bottom: 4px;
}
@ -57,6 +55,16 @@
text-align: right;
}
#menuBar1:after,
#menuBar2:after {
content: ".";
display: block;
height: 0;
font-size: 0;
clear: both;
visibility: hidden;
}
#imageFeed {
text-align: center;
}

View File

@ -15,12 +15,12 @@
#menuBar1 {
width: 100%;
height: 1.5em;
padding: 3px 0;
text-align: center;
clear: both;
}
#menuBar1 #nameControl {
float: left;
}
@ -41,7 +41,6 @@
#menuBar2 {
width: 100%;
height: 1.2em;
padding: 3px 0;
margin-bottom: 4px;
}
@ -56,6 +55,15 @@
float: right;
text-align: right;
}
#menuBar1:after,
#menuBar2:after {
content: ".";
display: block;
height: 0;
font-size: 0;
clear: both;
visibility: hidden;
}
#imageFeed {
text-align: center;

View File

@ -12,18 +12,7 @@ function setButtonStates( element )
break;
}
}
else if ( form.elements[i].length )
{
for( var j = 0, j_length = form.elements[i].length; j < j_length; j += 1 ) {
if ( form.elements[j].type == "checkbox" ) {
if ( form.elements[j].checked ) {
if ( checked++ > 1 )
break;
}
}
} // end foreach element in array
}
} // end foreach element in array
}
$(element).getParent( 'tr' ).toggleClass( 'highlight' );
form.editBtn.disabled = (checked!=1);
form.deleteBtn.disabled = (checked==0);

View File

@ -35,6 +35,7 @@ function Monitor( index, id, connKey )
if ( this.streamCmdTimer )
this.streamCmdTimer = clearTimeout( this.streamCmdTimer );
var stream = document.getElementById( "liveStream"+this.id );
if ( respObj.result == 'Ok' )
{
this.status = respObj.status;
@ -57,7 +58,6 @@ function Monitor( index, id, connKey )
this.setStateClass( $('monitor'+this.index), stateClass );
/*Stream could be an applet so can't use moo tools*/
var stream = document.getElementById( "liveStream"+this.id );
stream.className = stateClass;
var isAlarmed = ( this.alarmState == STATE_ALARM || this.alarmState == STATE_ALERT );
@ -90,6 +90,10 @@ function Monitor( index, id, connKey )
else
{
console.error( respObj.message );
// Try to reload the image stream.
if ( stream )
stream.src = stream.src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) ));
}
var streamCmdTimeout = statusRefreshTimeout;
if ( this.alarmState == STATE_ALARM || this.alarmState == STATE_ALERT )

View File

@ -115,7 +115,10 @@ if ( canEdit( 'Monitors' ) )
if ( canEdit( 'Monitors' ) )
{
?>
<div id="forceCancelAlarm"><a id="forceAlarmLink" href="#" onclick="cmdForceAlarm()" class="hidden"><?php echo translate('ForceAlarm') ?></a><a id="cancelAlarmLink" href="#" onclick="cmdCancelForcedAlarm()" class="hidden"><?php echo translate('CancelForcedAlarm') ?></a></div>
<div id="forceCancelAlarm">
<a id="forceAlarmLink" href="#" onclick="cmdForceAlarm();"><?php echo translate('ForceAlarm') ?></a>
<a id="cancelAlarmLink" href="#" onclick="cmdCancelForcedAlarm();" class="hidden"><?php echo translate('CancelForcedAlarm') ?></a>
</div>
<?php
}
?>