From a03d2a393fd4acf03f554a5c19fb07bc12a03354 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 20 Sep 2016 13:22:49 -0400 Subject: [PATCH 01/27] add ffmpeg as an option to libav-tools --- distros/ubuntu1604/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distros/ubuntu1604/control b/distros/ubuntu1604/control index f2d94de48..bf5556c7b 100644 --- a/distros/ubuntu1604/control +++ b/distros/ubuntu1604/control @@ -37,7 +37,7 @@ Package: zoneminder Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends} ,javascript-common - ,libav-tools + ,libav-tools | ffmpeg ,libdate-manip-perl, libmime-lite-perl, libmime-tools-perl ,libdbd-mysql-perl ,libphp-serialization-perl From bc0b499697c32f44d03697c3babe00e1951fa6f1 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 20 Sep 2016 14:10:37 -0400 Subject: [PATCH 02/27] update zm_create.sql.in to match the update scripts --- db/zm_create.sql.in | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index a93437cda..21a4d4cc1 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -328,22 +328,22 @@ CREATE TABLE `Monitors` ( `Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL') NOT NULL default 'Local', `Function` enum('None','Monitor','Modect','Record','Mocord','Nodect') NOT NULL default 'Monitor', `Enabled` tinyint(3) unsigned NOT NULL default '1', - `LinkedMonitors` varchar(255) NOT NULL default '', + `LinkedMonitors` varchar(255), `Triggers` set('X10') NOT NULL default '', `Device` tinytext NOT NULL default '', `Channel` tinyint(3) unsigned NOT NULL default '0', `Format` int(10) unsigned NOT NULL default '0', `V4LMultiBuffer` tinyint(1) unsigned, `V4LCapturesPerFrame` tinyint(3) unsigned, - `Protocol` varchar(16) NOT NULL default '', + `Protocol` varchar(16), `Method` varchar(16) NOT NULL default '', - `Host` varchar(64) NOT NULL default '', + `Host` varchar(64), `Port` varchar(8) NOT NULL default '', `SubPath` varchar(64) NOT NULL default '', `Path` varchar(255) NOT NULL default '', - `Options` varchar(255) not null default '', - `User` varchar(64) NOT NULL default '', - `Pass` varchar(64) NOT NULL default '', + `Options` varchar(255), + `User` varchar(64), + `Pass` varchar(64), `Width` smallint(5) unsigned NOT NULL default '0', `Height` smallint(5) unsigned NOT NULL default '0', `Colours` tinyint(3) unsigned NOT NULL default '1', @@ -354,13 +354,13 @@ CREATE TABLE `Monitors` ( `VideoWriter` TINYINT NOT NULL DEFAULT '0', `EncoderParameters` TEXT NOT NULL, `RecordAudio` TINYINT NOT NULL DEFAULT '0', - `RTSPDescribe` tinyint(1) unsigned NOT NULL default '0', + `RTSPDescribe` tinyint(1) unsigned, `Brightness` mediumint(7) NOT NULL default '-1', `Contrast` mediumint(7) NOT NULL default '-1', `Hue` mediumint(7) NOT NULL default '-1', `Colour` mediumint(7) NOT NULL default '-1', `EventPrefix` varchar(32) NOT NULL default 'Event-', - `LabelFormat` varchar(64) NOT NULL default '%N - %y/%m/%d %H:%M:%S', + `LabelFormat` varchar(64) default '%N - %y/%m/%d %H:%M:%S', `LabelX` smallint(5) unsigned NOT NULL default '0', `LabelY` smallint(5) unsigned NOT NULL default '0', `LabelSize` smallint(5) unsigned NOT NULL DEFAULT '1', @@ -381,14 +381,14 @@ CREATE TABLE `Monitors` ( `RefBlendPerc` tinyint(3) unsigned NOT NULL default '6', `AlarmRefBlendPerc` tinyint(3) unsigned NOT NULL default '6', `Controllable` tinyint(3) unsigned NOT NULL default '0', - `ControlId` int(10) unsigned NOT NULL default '0', + `ControlId` int(10) unsigned, `ControlDevice` varchar(255) default NULL, `ControlAddress` varchar(255) default NULL, `AutoStopTimeout` decimal(5,2) default NULL, `TrackMotion` tinyint(3) unsigned NOT NULL default '0', - `TrackDelay` smallint(5) unsigned NOT NULL default '0', + `TrackDelay` smallint(5) unsigned, `ReturnLocation` tinyint(3) NOT NULL default '-1', - `ReturnDelay` smallint(5) unsigned NOT NULL default '0', + `ReturnDelay` smallint(5) unsigned, `DefaultView` enum('Events','Control') NOT NULL default 'Events', `DefaultRate` smallint(5) unsigned NOT NULL default '100', `DefaultScale` smallint(5) unsigned NOT NULL default '100', @@ -477,7 +477,7 @@ CREATE TABLE `Users` ( `Id` int(10) unsigned NOT NULL auto_increment, `Username` varchar(32) character set latin1 collate latin1_bin NOT NULL default '', `Password` varchar(64) NOT NULL default '', - `Language` varchar(8) NOT NULL default '', + `Language` varchar(8), `Enabled` tinyint(3) unsigned NOT NULL default '1', `Stream` enum('None','View') NOT NULL default 'None', `Events` enum('None','View','Edit') NOT NULL default 'None', @@ -486,8 +486,8 @@ CREATE TABLE `Users` ( `Groups` enum('None','View','Edit') NOT NULL default 'None', `Devices` enum('None','View','Edit') NOT NULL default 'None', `System` enum('None','View','Edit') NOT NULL default 'None', - `MaxBandwidth` varchar(16) NOT NULL default '', - `MonitorIds` tinytext NOT NULL, + `MaxBandwidth` varchar(16), + `MonitorIds` tinytext, PRIMARY KEY (`Id`), UNIQUE KEY `UC_Username` (`Username`) ) ENGINE=@ZM_MYSQL_ENGINE@; From f40c8d0da876f78dc687cb26605871c4885d92af Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 20 Sep 2016 15:54:37 -0400 Subject: [PATCH 03/27] contains due to glob --- scripts/zmaudit.pl.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/zmaudit.pl.in b/scripts/zmaudit.pl.in index ca4430c22..b1004d81d 100644 --- a/scripts/zmaudit.pl.in +++ b/scripts/zmaudit.pl.in @@ -206,11 +206,11 @@ MAIN: while( $loop ) { Debug( "Checking day dir $day_dir" ); ( $day_dir ) = ( $day_dir =~ /^(.*)$/ ); # De-taint if ( ! chdir( $day_dir ) ) { - Error( "Can't chdir to '$$Storage{Path}/$monitor_dir/$day_dir': $!" ); + Error( "Can't chdir to '$$Storage{Path}/$day_dir': $!" ); next; } if ( ! opendir( DIR, '.' ) ) { - Error( "Can't open directory $$Storage{Path}/$monitor_dir/'$day_dir': $!" ); + Error( "Can't open directory '$$Storage{Path}/$day_dir': $!" ); next; } my @event_links = sort { $b <=> $a } grep { -l $_ } readdir( DIR ); @@ -237,7 +237,7 @@ MAIN: while( $loop ) { Debug( "Checking link $event_link points to $event_path " ); my $Event = $fs_events->{$event} = new ZoneMinder::Event(); $$Event{Id} = $event; - $$Event{Path} = join('/', $Storage->Path(), $monitor_dir,$day_dir,$event_path); + $$Event{Path} = join('/', $Storage->Path(), $day_dir,$event_path); $Event->MonitorId( $monitor_dir ); $Event->StorageId( $Storage->Id() ); } # event path exists From 364a80fb94a821039ff18826f2adcaf97415fa9c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 20 Sep 2016 15:55:28 -0400 Subject: [PATCH 04/27] don't output jpeg header unless there is some kind of success --- web/views/image.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/web/views/image.php b/web/views/image.php index 17de2ec81..bce07e765 100644 --- a/web/views/image.php +++ b/web/views/image.php @@ -39,8 +39,6 @@ if ( !canView( 'Events' ) ) { require_once('includes/Event.php'); require_once('includes/Frame.php'); -header( 'Content-type: image/jpeg' ); - // Compatibility for PHP 5.4 if (!function_exists('imagescale')) { function imagescale($image, $new_width, $new_height = -1, $mode = 0) { @@ -85,6 +83,10 @@ if ( empty($_REQUEST['path']) ) { $retval = 0; exec( $command, $output, $retval ); Debug("Retval: $retval, output: " . implode("\n", $output)); + if ( ! file_exists( $path ) ) { + header("HTTP/1.0 404 Not Found"); + Fatal("Can't create frame images from video for this event (".$Event->DefaultVideo() ); + } } else { header("HTTP/1.0 404 Not Found"); Fatal("Can't create frame images from video becuase there is no video file for this event (".$Event->DefaultVideo() ); @@ -138,6 +140,8 @@ if( !empty($_REQUEST['height']) ) { } +header( 'Content-type: image/jpeg' ); + if ( $errorText ) { Error( $errorText ); } else { @@ -167,13 +171,8 @@ if ( $errorText ) { # Slight optimisation, thumbnails always specify width and height, so we can cache them. $scaled_path = preg_replace('/\.jpg$/', "-${width}x${height}.jpg", $path ); - if ( file_exists( $scaled_path ) ) { - Debug( "Using cached scaled image at $scaled_path."); - if ( ! readfile( $scaled_path ) ) { - Error("No bytes read from scaled image". $scaled_path ); - } - } else { - Debug( "Cached scaled image does not exist at $scaled_path. Creating it"); + if ( ! file_exists( $scaled_path ) or ! readfile( $scaled_path ) ) { + Debug( "Cached scaled image does not exist at $scaled_path or is no good.. Creating it"); ob_start(); if ( ! $i ) $i = imagecreatefromjpeg( $path ); From 19a60b01da16e23fa87500a693f8cf6655099c77 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 20 Sep 2016 16:59:43 -0400 Subject: [PATCH 05/27] maybe fixes, maybe big memleaks --- src/zm_ffmpeg_camera.cpp | 9 +++++---- src/zm_packetqueue.cpp | 14 +++++++++++--- src/zm_packetqueue.h | 1 + src/zm_videostore.cpp | 20 +++++++++++++++++--- 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index d04aca2db..bd72ae3a9 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -167,7 +167,7 @@ int FfmpegCamera::Capture( Image &image ) Error( "Unable to read packet from stream %d: error %d \"%s\".", packet.stream_index, avResult, errbuf ); return( -1 ); } - Debug( 5, "Got packet from stream %d", packet.stream_index ); + Debug( 5, "Got packet from stream %d dts (%d) pts(%d)", packet.stream_index, packet.pts, packet.dts ); // What about audio stream? Maybe someday we could do sound detection... if ( packet.stream_index == mVideoStreamId ) { #if LIBAVCODEC_VERSION_CHECK(52, 23, 0, 23, 0) @@ -290,7 +290,6 @@ int FfmpegCamera::OpenFfmpeg() { Debug ( 1, "Opened input" ); Info( "Stream open %s", mPath.c_str() ); - startTime=av_gettime();//FIXME here or after find_Stream_info //FIXME can speed up initial analysis but need sensible parameters... //mFormatContext->probesize = 32; @@ -305,6 +304,7 @@ int FfmpegCamera::OpenFfmpeg() { #endif Fatal( "Unable to find stream info from %s due to: %s", mPath.c_str(), strerror(errno) ); + startTime=av_gettime();//FIXME here or after find_Stream_info Debug ( 1, "Got stream info" ); // Find first video stream present @@ -584,7 +584,7 @@ Debug(5, "After av_read_frame (%d)", ret ); Error( "Unable to read packet from stream %d: error %d \"%s\".", packet->stream_index, ret, errbuf ); return( -1 ); } - Debug( 5, "Got packet from stream %d", packet->stream_index ); + Debug( 4, "Got packet from stream %d dts (%d) pts(%d)", packet->stream_index, packet->dts, packet->pts ); //Video recording if ( recording ) { @@ -636,7 +636,7 @@ Debug(5, "After av_read_frame (%d)", ret ); while ( ( queued_packet = packetqueue.popPacket() ) ) { packet_count += 1; //Write the packet to our video store - Debug(2, "Writing queued packet stream: %d KEY %d", queued_packet->stream_index, packet->flags & AV_PKT_FLAG_KEY ); + Debug(2, "Writing queued packet stream: %d KEY %d, remaining (%d)", queued_packet->stream_index, packet->flags & AV_PKT_FLAG_KEY, packetqueue.size() ); if ( queued_packet->stream_index == mVideoStreamId ) { ret = videoStore->writeVideoFramePacket( queued_packet, mFormatContext->streams[mVideoStreamId]); } else if ( queued_packet->stream_index == mAudioStreamId ) { @@ -748,6 +748,7 @@ Debug(5, "After av_read_frame (%d)", ret ); Debug( 3, "Some other stream index %d", packet->stream_index ); #endif } + if ( videoStore ) zm_av_unref_packet( packet ); } // end while ! frameComplete return (frameCount); diff --git a/src/zm_packetqueue.cpp b/src/zm_packetqueue.cpp index 42a74af98..5758e8871 100644 --- a/src/zm_packetqueue.cpp +++ b/src/zm_packetqueue.cpp @@ -37,10 +37,14 @@ bool zm_packetqueue::queuePacket( AVPacket* packet ) { //AVPacket *input_ref = (AVPacket *)av_malloc(sizeof(AVPacket)); //if ( av_packet_ref( input_ref, packet ) < 0 ) { - //free(input_ref); - //return false; - //} + if ( av_packet_ref( packet, packet ) < 0 ) { +Error("error refing packet"); + //av_free_packet(input_ref); + return false; + } + pktQueue.push( packet ); + //pktQueue.push( input_ref ); return true; } @@ -66,3 +70,7 @@ void zm_packetqueue::clearQueue() { zm_av_unref_packet( packet ); } } + +unsigned int zm_packetqueue::size() { + return pktQueue.size(); +} diff --git a/src/zm_packetqueue.h b/src/zm_packetqueue.h index f79502996..60a9620a4 100644 --- a/src/zm_packetqueue.h +++ b/src/zm_packetqueue.h @@ -38,6 +38,7 @@ public: bool popVideoPacket(AVPacket* packet); bool popAudioPacket(AVPacket* packet); void clearQueue( ); + unsigned int size(); private: std::queue pktQueue; diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index 311318a90..95dc9dd7f 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -274,6 +274,7 @@ Debug(2, "Have audio_output_context"); startDts = 0; filter_in_rescale_delta_last = AV_NOPTS_VALUE; + // now - when streaming started startTime=av_gettime()-nStartTime;//oc->start_time; Info("VideoStore startTime=%d\n",startTime); } // VideoStore::VideoStore @@ -342,26 +343,39 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt, AVStream *input_video_stre Debug(2, "writeVideoFrame init_packet"); av_init_packet(&opkt); +if ( 1 ) { + if ( ! startPts ) { + //never gets set, so the first packet can set it. + startPts = ipkt->pts; + } //Scale the PTS of the outgoing packet to be the correct time base if (ipkt->pts != AV_NOPTS_VALUE) { - opkt.pts = av_rescale_q(ipkt->pts-startPts, input_video_stream->time_base, video_stream->time_base) - ost_tb_start_time; + opkt.pts = av_rescale_q(ipkt->pts-startPts, input_video_stream->time_base, video_stream->time_base); + //- ost_tb_start_time; Debug(3, "opkt.pts = %d from ipkt->pts(%d) - startPts(%d), input->time_base(%d) video_stream->time-base(%d)", opkt.pts, ipkt->pts, startPts, input_video_stream->time_base, video_stream->time_base ); } else { + Debug(3, "opkt.pts = undef"); opkt.pts = AV_NOPTS_VALUE; } + if ( ! startDts ) { + startDts = input_video_stream->cur_dts; +} //Scale the DTS of the outgoing packet to be the correct time base if(ipkt->dts == AV_NOPTS_VALUE) { opkt.dts = av_rescale_q(input_video_stream->cur_dts-startDts, AV_TIME_BASE_Q, video_stream->time_base); - Debug(3, "opkt.dts = %d from input_video_stream->cur_dts(%d) - startDts(%d), video_stream->time-base(%d)", opkt.dts, input_video_stream->cur_dts, startDts, video_stream->time_base ); + Debug(3, "opkt.dts = %d from input_video_stream->cur_dts(%d) - startDts(%d), video_stream->time-base(%d)", opkt.dts, input_video_stream->cur_dts, startDts, video_stream->time_base ); } else { opkt.dts = av_rescale_q(ipkt->dts-startDts, input_video_stream->time_base, video_stream->time_base); Debug(3, "opkt.dts = %d from ipkt->dts(%d) - startDts(%d), video_stream->time-base(%d)", opkt.dts, ipkt->dts, startDts, video_stream->time_base ); } - opkt.dts -= ost_tb_start_time; + //opkt.dts -= ost_tb_start_time; opkt.duration = av_rescale_q(ipkt->duration, input_video_stream->time_base, video_stream->time_base); +} else { + av_packet_rescale_ts( &opkt, input_video_stream->time_base, video_stream->time_base ); +} opkt.flags = ipkt->flags; opkt.pos=-1; From f0a98200965d64e8802bcade608fd07c41be1249 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 20 Sep 2016 17:53:35 -0400 Subject: [PATCH 06/27] need to convert NULL values before saying not null --- db/zm_update-1.30.7.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/db/zm_update-1.30.7.sql b/db/zm_update-1.30.7.sql index 06d829c88..72641825b 100644 --- a/db/zm_update-1.30.7.sql +++ b/db/zm_update-1.30.7.sql @@ -4,5 +4,7 @@ -- Changing StorageId to be NOT NULL and default 0 -- +UPDATE Monitors SET StorageId = 0 WHERE StorageId IS NULL; ALTER TABLE Monitors MODIFY `StorageId` smallint(5) unsigned NOT NULL default 0; +UPDATE Events SET StorageId = 0 WHERE StorageId IS NULL; ALTER TABLE Events MODIFY `StorageId` smallint(5) unsigned NOT NULL default 0; From 288b03290c529c0eeeb32e65e9770eaedf15d876 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Sep 2016 09:05:55 -0400 Subject: [PATCH 07/27] remark out some debugging --- src/zm_ffmpeg.cpp | 1 + src/zm_videostore.cpp | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp index dd16cf7d3..02dca8ebb 100644 --- a/src/zm_ffmpeg.cpp +++ b/src/zm_ffmpeg.cpp @@ -357,6 +357,7 @@ static void zm_log_fps(double d, const char *postfix) { /* "user interface" functions */ void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output) { char buf[256]; + Debug(1, "Dumping stream index i(%d) index(%d)", i, index ); int flags = (is_output ? ic->oformat->flags : ic->iformat->flags); AVStream *st = ic->streams[i]; AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0); diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index 45cd1d280..d59a9b467 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -240,9 +240,9 @@ void VideoStore::dumpPacket( AVPacket *pkt ){ int VideoStore::writeVideoFramePacket(AVPacket *ipkt, AVStream *input_st){//, AVPacket *lastKeyframePkt){ - Debug(3, "before ost_tbcket %d", startTime ); - zm_dump_stream_format( oc, ipkt->stream_index, 0, 1 ); - Debug(3, "before ost_tbcket %d", startTime ); + //Debug(3, "before ost_tbcket %d", startTime ); + //zm_dump_stream_format( oc, ipkt->stream_index, 0, 1 ); + //Debug(3, "before ost_tbcket %d", startTime ); int64_t ost_tb_start_time = av_rescale_q(startTime, AV_TIME_BASE_Q, video_st->time_base); AVPacket opkt, safepkt; From 01d4ca96c7db0abd1658aa85ba8070f05547643f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Sep 2016 10:15:23 -0400 Subject: [PATCH 08/27] av_unref_packet should be av_packet_unref --- src/zm_ffmpeg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zm_ffmpeg.h b/src/zm_ffmpeg.h index ecfd6ba2c..1367ce2e5 100644 --- a/src/zm_ffmpeg.h +++ b/src/zm_ffmpeg.h @@ -324,7 +324,7 @@ static av_always_inline av_const int64_t av_clip64_c(int64_t a, int64_t amin, in void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output); #if LIBAVCODEC_VERSION_CHECK(57, 8, 0, 12, 100) - #define zm_av_unref_packet( packet ) av_unref_packet( packet ) + #define zm_av_unref_packet( packet ) av_packet_unref( packet ) #else #define zm_av_unref_packet( packet ) av_free_packet( packet ) #endif From e0b0b42966ef96ac0ffce0a5a8565975baac3cbd Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Sep 2016 10:29:49 -0400 Subject: [PATCH 09/27] fixup dts calcs --- src/zm_videostore.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index 95dc9dd7f..c73842d83 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -357,18 +357,22 @@ if ( 1 ) { Debug(3, "opkt.pts = undef"); opkt.pts = AV_NOPTS_VALUE; } - if ( ! startDts ) { - startDts = input_video_stream->cur_dts; } //Scale the DTS of the outgoing packet to be the correct time base if(ipkt->dts == AV_NOPTS_VALUE) { + if ( ! startDts ) startDts = input_video_stream->cur_dts; opkt.dts = av_rescale_q(input_video_stream->cur_dts-startDts, AV_TIME_BASE_Q, video_stream->time_base); Debug(3, "opkt.dts = %d from input_video_stream->cur_dts(%d) - startDts(%d), video_stream->time-base(%d)", opkt.dts, input_video_stream->cur_dts, startDts, video_stream->time_base ); } else { - opkt.dts = av_rescale_q(ipkt->dts-startDts, input_video_stream->time_base, video_stream->time_base); + if ( ! startDts ) startDts = ipkt->dts; + opkt.dts = av_rescale_q(ipkt->dts - startDts, input_video_stream->time_base, video_stream->time_base); Debug(3, "opkt.dts = %d from ipkt->dts(%d) - startDts(%d), video_stream->time-base(%d)", opkt.dts, ipkt->dts, startDts, video_stream->time_base ); } + if ( opkt.dts > opkt.pts ) { + Warning("opkt.dts(%d) must be <= opkt.pts(%d). Decompression must happen before presentation.", opkt.dts, opkt.pts ); + opkt.dts = opkt.pts; + } //opkt.dts -= ost_tb_start_time; From 091459004ce08cbc3463b193332571a19cd7342f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Sep 2016 10:30:31 -0400 Subject: [PATCH 10/27] ServerId can be 0 --- web/includes/Monitor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index 1e85d90ce..4dd2e6a2a 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -171,7 +171,7 @@ private $control_fields = array( } } public function getStreamSrc( $args, $querySep='&' ) { - if ( isset($this->{'ServerId'}) ) { + if ( isset($this->{'ServerId'}) and $this->{'ServerId'} ) { $Server = new Server( $this->{'ServerId'} ); $streamSrc = ZM_BASE_PROTOCOL.'://'.$Server->Hostname().ZM_PATH_ZMS; } else { From 4359c656015087540f950b846757d803466056e0 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Sep 2016 10:56:09 -0400 Subject: [PATCH 11/27] better debugging of timebase --- src/zm_ffmpeg.cpp | 3 +-- src/zm_videostore.cpp | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp index adc0047bf..e73badba8 100644 --- a/src/zm_ffmpeg.cpp +++ b/src/zm_ffmpeg.cpp @@ -437,8 +437,7 @@ void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output) Debug(1, "[0x%x]", st->id); if (lang) Debug(1, "(%s)", lang->value); - av_log(NULL, AV_LOG_DEBUG, ", %d, %d/%d", st->codec_info_nb_frames, - st->time_base.num, st->time_base.den); + Debug(1, ", %d, %d/%d", st->codec_info_nb_frames, st->time_base.num, st->time_base.den); Debug(1, ": %s", buf); if (st->sample_aspect_ratio.num && // default diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index c73842d83..24ce0370c 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -357,17 +357,27 @@ if ( 1 ) { Debug(3, "opkt.pts = undef"); opkt.pts = AV_NOPTS_VALUE; } -} //Scale the DTS of the outgoing packet to be the correct time base if(ipkt->dts == AV_NOPTS_VALUE) { if ( ! startDts ) startDts = input_video_stream->cur_dts; opkt.dts = av_rescale_q(input_video_stream->cur_dts-startDts, AV_TIME_BASE_Q, video_stream->time_base); - Debug(3, "opkt.dts = %d from input_video_stream->cur_dts(%d) - startDts(%d), video_stream->time-base(%d)", opkt.dts, input_video_stream->cur_dts, startDts, video_stream->time_base ); + Debug(3, "opkt.dts = %d from input_video_stream->cur_dts(%d) - startDts(%d), input time based(%d/%d) video_stream->time-base(%d/%d)", + opkt.dts, input_video_stream->cur_dts, startDts, + input_video_stream->time_base.num, + input_video_stream->time_base.den + video_stream->time_base.num, + video_stream->time_base.den + ); } else { if ( ! startDts ) startDts = ipkt->dts; opkt.dts = av_rescale_q(ipkt->dts - startDts, input_video_stream->time_base, video_stream->time_base); - Debug(3, "opkt.dts = %d from ipkt->dts(%d) - startDts(%d), video_stream->time-base(%d)", opkt.dts, ipkt->dts, startDts, video_stream->time_base ); + Debug(3, "opkt.dts = %d from ipkt->dts(%d) - startDts(%d), input time base (%d/%d) video_stream->time-base(%d/%d)", opkt.dts, ipkt->dts, startDts, + input_video_stream->time_base.num, + input_video_stream->time_base.den + video_stream->time_base.num, + video_stream->time_base.den + ); } if ( opkt.dts > opkt.pts ) { Warning("opkt.dts(%d) must be <= opkt.pts(%d). Decompression must happen before presentation.", opkt.dts, opkt.pts ); @@ -396,7 +406,7 @@ Debug(3, "video and RAWPICTURE"); opkt.size = sizeof(AVPicture); opkt.flags |= AV_PKT_FLAG_KEY; } else { -Debug(3, "Not video and RAWPICTURE"); +Debug(4, "Not video and RAWPICTURE"); } //memcpy(&safepkt, &opkt, sizeof(AVPacket)); From e1a29f47b9870f57f2d01a84cff3e0f213bb78d7 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Sep 2016 10:57:21 -0400 Subject: [PATCH 12/27] more debug --- src/zm_videostore.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index 24ce0370c..7e14cc773 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -425,6 +425,7 @@ Debug(4, "Not video and RAWPICTURE"); int ret; prevDts = opkt.dts; // Unsure if av_interleaved_write_frame() clobbers opkt.dts when out of order, so storing in advance + dumpPacket(&opkt); ret = av_interleaved_write_frame(oc, &opkt); if(ret<0){ // There's nothing we can really do if the frame is rejected, just drop it and get on with the next From a8c4fdd6166ab7f644cab8d5a83717d81abac362 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Sep 2016 10:58:02 -0400 Subject: [PATCH 13/27] more debug --- src/zm_videostore.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index 7e14cc773..e90ce5f34 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -365,7 +365,7 @@ if ( 1 ) { Debug(3, "opkt.dts = %d from input_video_stream->cur_dts(%d) - startDts(%d), input time based(%d/%d) video_stream->time-base(%d/%d)", opkt.dts, input_video_stream->cur_dts, startDts, input_video_stream->time_base.num, - input_video_stream->time_base.den + input_video_stream->time_base.den, video_stream->time_base.num, video_stream->time_base.den ); @@ -374,7 +374,7 @@ if ( 1 ) { opkt.dts = av_rescale_q(ipkt->dts - startDts, input_video_stream->time_base, video_stream->time_base); Debug(3, "opkt.dts = %d from ipkt->dts(%d) - startDts(%d), input time base (%d/%d) video_stream->time-base(%d/%d)", opkt.dts, ipkt->dts, startDts, input_video_stream->time_base.num, - input_video_stream->time_base.den + input_video_stream->time_base.den, video_stream->time_base.num, video_stream->time_base.den ); From 8b13401250c541b2ba8bc2948a7044f2096d9f55 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Sep 2016 11:37:59 -0400 Subject: [PATCH 14/27] more debugging --- src/zm_videostore.cpp | 45 ++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index e90ce5f34..6514b4319 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -326,33 +326,43 @@ void VideoStore::dumpPacket( AVPacket *pkt ){ , pkt->pos , pkt->convergence_duration ); - Info("%s:%d:DEBUG: %s", __FILE__, __LINE__, b); + Debug(1, "%s:%d:DEBUG: %s", __FILE__, __LINE__, b); } int VideoStore::writeVideoFramePacket(AVPacket *ipkt, AVStream *input_video_stream){ Debug(4, "writeVideoFrame"); - Debug(3, "before ost_tbcket starttime %d, timebase%d", startTime, video_stream->time_base ); + //Debug(3, "before ost_tbcket starttime %d, timebase%d", startTime, video_stream->time_base ); //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_stream->time_base); - Debug(2, "before ost_tbcket starttime %d, ost_tbcket %d", startTime, ost_tb_start_time ); + //Debug(2, "before ost_tbcket starttime %d, ost_tbcket %d", startTime, ost_tb_start_time ); AVPacket opkt; AVPicture pict; - Debug(2, "writeVideoFrame init_packet"); + Debug(4, "writeVideoFrame init_packet"); av_init_packet(&opkt); + Debug(3, "Time bases input stream time base(%d/%d) input codec tb: (%d/%d) video_stream->time-base(%d/%d) output codec tb (%d/%d)", + input_video_stream->time_base.num, + input_video_stream->time_base.den, + input_video_stream->codec->time_base.num, + input_video_stream->codec->time_base.den, + video_stream->time_base.num, + video_stream->time_base.den, + video_stream->codec->time_base.num, + video_stream->codec->time_base.den + ); if ( 1 ) { + //Scale the PTS of the outgoing packet to be the correct time base + if (ipkt->pts != AV_NOPTS_VALUE) { if ( ! startPts ) { //never gets set, so the first packet can set it. startPts = ipkt->pts; - } - //Scale the PTS of the outgoing packet to be the correct time base - if (ipkt->pts != AV_NOPTS_VALUE) { - opkt.pts = av_rescale_q(ipkt->pts-startPts, input_video_stream->time_base, video_stream->time_base); + } + opkt.pts = av_rescale_q(ipkt->pts-startPts, input_video_stream->time_base, video_stream->time_base); //- ost_tb_start_time; - Debug(3, "opkt.pts = %d from ipkt->pts(%d) - startPts(%d), input->time_base(%d) video_stream->time-base(%d)", opkt.pts, ipkt->pts, startPts, input_video_stream->time_base, video_stream->time_base ); + Debug(3, "opkt.pts = %d from ipkt->pts(%d) - startPts(%d)", opkt.pts, ipkt->pts, startPts ); } else { Debug(3, "opkt.pts = undef"); opkt.pts = AV_NOPTS_VALUE; @@ -362,22 +372,13 @@ if ( 1 ) { if(ipkt->dts == AV_NOPTS_VALUE) { if ( ! startDts ) startDts = input_video_stream->cur_dts; opkt.dts = av_rescale_q(input_video_stream->cur_dts-startDts, AV_TIME_BASE_Q, video_stream->time_base); - Debug(3, "opkt.dts = %d from input_video_stream->cur_dts(%d) - startDts(%d), input time based(%d/%d) video_stream->time-base(%d/%d)", - opkt.dts, input_video_stream->cur_dts, startDts, - input_video_stream->time_base.num, - input_video_stream->time_base.den, - video_stream->time_base.num, - video_stream->time_base.den + Debug(3, "opkt.dts = %d from input_video_stream->cur_dts(%d) - startDts(%d)", + opkt.dts, input_video_stream->cur_dts, startDts ); } else { if ( ! startDts ) startDts = ipkt->dts; opkt.dts = av_rescale_q(ipkt->dts - startDts, input_video_stream->time_base, video_stream->time_base); - Debug(3, "opkt.dts = %d from ipkt->dts(%d) - startDts(%d), input time base (%d/%d) video_stream->time-base(%d/%d)", opkt.dts, ipkt->dts, startDts, - input_video_stream->time_base.num, - input_video_stream->time_base.den, - video_stream->time_base.num, - video_stream->time_base.den - ); + Debug(3, "opkt.dts = %d from ipkt->dts(%d) - startDts(%d)", opkt.dts, ipkt->dts, startDts ); } if ( opkt.dts > opkt.pts ) { Warning("opkt.dts(%d) must be <= opkt.pts(%d). Decompression must happen before presentation.", opkt.dts, opkt.pts ); @@ -425,7 +426,7 @@ Debug(4, "Not video and RAWPICTURE"); int ret; prevDts = opkt.dts; // Unsure if av_interleaved_write_frame() clobbers opkt.dts when out of order, so storing in advance - dumpPacket(&opkt); + dumpPacket(&opkt); ret = av_interleaved_write_frame(oc, &opkt); if(ret<0){ // There's nothing we can really do if the frame is rejected, just drop it and get on with the next From ae63861cd1637ce838c61afa00dc3f6561e7c3fb Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Sep 2016 11:57:30 -0400 Subject: [PATCH 15/27] better codec_tag setting --- src/zm_videostore.cpp | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index 6514b4319..182e6b26e 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -80,17 +80,18 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in, output_format = oc->oformat; - video_stream = avformat_new_stream(oc, (AVCodec *)input_video_stream->codec->codec); - if (!video_stream) { - Fatal("Unable to create video out stream\n"); - } - ret = avcodec_copy_context(video_stream->codec, input_video_stream->codec); if (ret < 0) { Fatal("Unable to copy input video context to output video context %s\n", av_make_error_string(ret).c_str()); } + video_stream = avformat_new_stream(oc, (AVCodec *)video_stream->codec->codec); + if (!video_stream) { + Fatal("Unable to create video out stream\n"); + } + + if ( input_video_stream->codec->sample_aspect_ratio.den && ( video_stream->sample_aspect_ratio.den != input_video_stream->codec->sample_aspect_ratio.den ) ) { Warning("Fixing sample_aspect_ratio.den from (%d) to (%d)", video_stream->sample_aspect_ratio.den, input_video_stream->codec->sample_aspect_ratio.den ); video_stream->sample_aspect_ratio.den = input_video_stream->codec->sample_aspect_ratio.den; @@ -133,7 +134,18 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in, video_stream->codec->time_base.den = video_stream->time_base.den; } - video_stream->codec->codec_tag = 0; + // WHY? + //video_stream->codec->codec_tag = 0; + if (!video_stream->codec->codec_tag) { + if (! oc->oformat->codec_tag + || av_codec_get_id (oc->oformat->codec_tag, input_video_stream->codec->codec_tag) == video_stream->codec->codec_id + || av_codec_get_tag(oc->oformat->codec_tag, input_video_stream->codec->codec_id) <= 0) { + Warning("Setting codec tag"); + video_stream->codec->codec_tag = input_video_stream->codec->codec_tag; + } + } + + if (oc->oformat->flags & AVFMT_GLOBALHEADER) { video_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; } @@ -342,16 +354,6 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt, AVStream *input_video_stre Debug(4, "writeVideoFrame init_packet"); av_init_packet(&opkt); - Debug(3, "Time bases input stream time base(%d/%d) input codec tb: (%d/%d) video_stream->time-base(%d/%d) output codec tb (%d/%d)", - input_video_stream->time_base.num, - input_video_stream->time_base.den, - input_video_stream->codec->time_base.num, - input_video_stream->codec->time_base.den, - video_stream->time_base.num, - video_stream->time_base.den, - video_stream->codec->time_base.num, - video_stream->codec->time_base.den - ); if ( 1 ) { //Scale the PTS of the outgoing packet to be the correct time base From f5405a4131688d7930f753f3a4d45df323708451 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Sep 2016 11:57:42 -0400 Subject: [PATCH 16/27] clearer debug output --- src/zm_ffmpeg.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp index e73badba8..ec3ebeb91 100644 --- a/src/zm_ffmpeg.cpp +++ b/src/zm_ffmpeg.cpp @@ -463,9 +463,9 @@ void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output) if (fps) zm_log_fps(av_q2d(st->avg_frame_rate), tbn || tbc ? "fps, " : "fps"); if (tbn) - zm_log_fps(1 / av_q2d(st->time_base), tbc ? "tbn, " : "tbn"); + zm_log_fps(1 / av_q2d(st->time_base), tbc ? "stream tb numerator , " : "stream tb numerator"); if (tbc) - zm_log_fps(1 / av_q2d(st->codec->time_base), "tbc"); + zm_log_fps(1 / av_q2d(st->codec->time_base), "codec time base:"); } if (st->disposition & AV_DISPOSITION_DEFAULT) From 2f248cd4b1c6faf9f4bfef35c53fbc254a93366f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Sep 2016 11:58:59 -0400 Subject: [PATCH 17/27] log time bases on videostore instantiation instead of every packet --- src/zm_videostore.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index 182e6b26e..1a00b1756 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -91,6 +91,18 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in, Fatal("Unable to create video out stream\n"); } + Debug(3, "Time bases input stream time base(%d/%d) input codec tb: (%d/%d) video_stream->time-base(%d/%d) output codec tb (%d/%d)", + input_video_stream->time_base.num, + input_video_stream->time_base.den, + input_video_stream->codec->time_base.num, + input_video_stream->codec->time_base.den, + video_stream->time_base.num, + video_stream->time_base.den, + video_stream->codec->time_base.num, + video_stream->codec->time_base.den + ); + + if ( input_video_stream->codec->sample_aspect_ratio.den && ( video_stream->sample_aspect_ratio.den != input_video_stream->codec->sample_aspect_ratio.den ) ) { Warning("Fixing sample_aspect_ratio.den from (%d) to (%d)", video_stream->sample_aspect_ratio.den, input_video_stream->codec->sample_aspect_ratio.den ); From 6292ce3748c00961b7badddd4abb7b32b10786c9 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Sep 2016 12:07:58 -0400 Subject: [PATCH 18/27] undo stupid thing --- src/zm_videostore.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index 1a00b1756..3c22049ca 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -80,15 +80,19 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in, output_format = oc->oformat; + video_stream = avformat_new_stream(oc, (AVCodec *)video_stream->codec->codec); + if (!video_stream) { + Fatal("Unable to create video out stream\n"); + } else { + Debug(3, "Success creating video out stream" ); + } + ret = avcodec_copy_context(video_stream->codec, input_video_stream->codec); if (ret < 0) { Fatal("Unable to copy input video context to output video context %s\n", av_make_error_string(ret).c_str()); - } - - video_stream = avformat_new_stream(oc, (AVCodec *)video_stream->codec->codec); - if (!video_stream) { - Fatal("Unable to create video out stream\n"); + } else { + Debug(3, "Success copying context" ); } Debug(3, "Time bases input stream time base(%d/%d) input codec tb: (%d/%d) video_stream->time-base(%d/%d) output codec tb (%d/%d)", @@ -102,8 +106,6 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in, video_stream->codec->time_base.den ); - - if ( input_video_stream->codec->sample_aspect_ratio.den && ( video_stream->sample_aspect_ratio.den != input_video_stream->codec->sample_aspect_ratio.den ) ) { Warning("Fixing sample_aspect_ratio.den from (%d) to (%d)", video_stream->sample_aspect_ratio.den, input_video_stream->codec->sample_aspect_ratio.den ); video_stream->sample_aspect_ratio.den = input_video_stream->codec->sample_aspect_ratio.den; From 1310aee1cc1a95f79663f69aee90b68a8052dfe0 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Sep 2016 12:12:40 -0400 Subject: [PATCH 19/27] handle video stream at index 1 without audio --- src/zm_videostore.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index 3c22049ca..a5622d83b 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -80,7 +80,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in, output_format = oc->oformat; - video_stream = avformat_new_stream(oc, (AVCodec *)video_stream->codec->codec); + video_stream = avformat_new_stream(oc, input_video_stream->codec->codec); if (!video_stream) { Fatal("Unable to create video out stream\n"); } else { @@ -412,7 +412,13 @@ if ( 1 ) { opkt.data = ipkt->data; opkt.size = ipkt->size; + if ( ipkt->stream_index > 0 and ! audio_stream ) { +Warning("Setting stream index to 0 instead of %d", ipkt->stream_index ); + opkt.stream_index = 0; + } else { opkt.stream_index = ipkt->stream_index; + } + /*opkt.flags |= AV_PKT_FLAG_KEY;*/ if (video_stream->codec->codec_type == AVMEDIA_TYPE_VIDEO && (output_format->flags & AVFMT_RAWPICTURE)) { From 249d3cadc56cfaf74d68e28dfde7595884114b30 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Sep 2016 12:17:09 -0400 Subject: [PATCH 20/27] fix for video on stream 1 --- src/zm_videostore.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index d59a9b467..d9a6507b7 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -272,7 +272,15 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt, AVStream *input_st){//, AV opkt.data = ipkt->data; opkt.size = ipkt->size; - opkt.stream_index = ipkt->stream_index; + + // Some camera have audio on stream 0 and video on stream 1. So when we remove the audio, video stream has to go on 0 + if ( ipkt->stream_index > 0 and ! audio_stream ) { + Debug(1,"Setting stream index to 0 instead of %d", ipkt->stream_index ); + opkt.stream_index = 0; + } else { + opkt.stream_index = ipkt->stream_index; + } + /*opkt.flags |= AV_PKT_FLAG_KEY;*/ if (video_st->codec->codec_type == AVMEDIA_TYPE_VIDEO && (fmt->flags & AVFMT_RAWPICTURE)) { From d96febd9676f88722273c5a0fdd1c537a91fca16 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Sep 2016 16:00:23 -0400 Subject: [PATCH 21/27] when ZM_DIR_EVENTS is relative, append ZM_PATH_WEB --- web/includes/Storage.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/web/includes/Storage.php b/web/includes/Storage.php index e5814ef61..81b9ad48c 100644 --- a/web/includes/Storage.php +++ b/web/includes/Storage.php @@ -27,7 +27,14 @@ class Storage { if ( isset( $this->{'Path'} ) and ( $this->{'Path'} != '' ) ) { return $this->{'Path'}; } else if ( ! isset($this->{'Id'}) ) { - return ZM_DIR_EVENTS; + $path = ZM_DIR_EVENTS; + if ( $path[0] != '/' ) { + $this->{'Path'} = ZM_PATH_WEB.'/'.ZM_DIR_EVENTS; + } else { + $this->{'Path'} = ZM_DIR_EVENTS; + } + return $this->{'Path'}; + } return $this->{'Name'}; } From 32d145cf2e6a458e22b9c42900ec222318f07295 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Sep 2016 16:02:14 -0400 Subject: [PATCH 22/27] free writejpg_ccinfo structs as well --- src/zm_image.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/zm_image.cpp b/src/zm_image.cpp index a78410060..bab03b84a 100644 --- a/src/zm_image.cpp +++ b/src/zm_image.cpp @@ -179,6 +179,12 @@ Image::~Image() delete decodejpg_dcinfo; decodejpg_dcinfo = 0; } + for ( unsigned int quality=0; quality <= 100; quality += 1 ) { + if ( writejpg_ccinfo[quality] ) { + delete writejpg_ccinfo[quality]; + writejpg_ccinfo[quality] = NULL; + } + } // end foreach quality } void Image::Initialise() From 984394f920fcb7b3842ce98282e4f7e656053b03 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Sep 2016 16:02:51 -0400 Subject: [PATCH 23/27] packet needs to be both unref'd and freed when we use av_malloc to allocate a packet --- src/zm_ffmpeg_camera.cpp | 8 ++++++-- src/zm_packetqueue.cpp | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index bd72ae3a9..9dc897e20 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -566,6 +566,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi // We are now allocating dynamically because we need to queue these and may go out of scope. AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket)); av_init_packet( packet ); + Debug(5, "Before av_read_frame"); ret = av_read_frame( mFormatContext, packet ); Debug(5, "After av_read_frame (%d)", ret ); @@ -649,6 +650,7 @@ Debug(5, "After av_read_frame (%d)", ret ); //Less than zero and we skipped a frame } zm_av_unref_packet( queued_packet ); + av_free( queued_packet ); } // end while packets in the packetqueue Debug(2, "Wrote %d queued packets", packet_count ); } // end if ! wasRecording @@ -748,8 +750,10 @@ Debug(5, "After av_read_frame (%d)", ret ); Debug( 3, "Some other stream index %d", packet->stream_index ); #endif } - if ( videoStore ) - zm_av_unref_packet( packet ); + if ( videoStore ) { + zm_av_unref_packet( packet ); + av_free( packet ); + } } // end while ! frameComplete return (frameCount); } diff --git a/src/zm_packetqueue.cpp b/src/zm_packetqueue.cpp index 5758e8871..7ecba50a0 100644 --- a/src/zm_packetqueue.cpp +++ b/src/zm_packetqueue.cpp @@ -37,11 +37,13 @@ bool zm_packetqueue::queuePacket( AVPacket* packet ) { //AVPacket *input_ref = (AVPacket *)av_malloc(sizeof(AVPacket)); //if ( av_packet_ref( input_ref, packet ) < 0 ) { +if ( 0 ) { if ( av_packet_ref( packet, packet ) < 0 ) { Error("error refing packet"); //av_free_packet(input_ref); return false; } + } pktQueue.push( packet ); //pktQueue.push( input_ref ); @@ -68,6 +70,7 @@ void zm_packetqueue::clearQueue() { pktQueue.pop(); // If we clear it, then no freeing gets done, whereas when we pop off, we assume that the packet was freed somewhere else. zm_av_unref_packet( packet ); + av_free( packet ); } } From 95bbaf42b6d7f275abdbad5726e842c84897935f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Sep 2016 16:03:24 -0400 Subject: [PATCH 24/27] change the version test to include ffmpeg 56.60.100 for av_packet_unref --- src/zm_ffmpeg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zm_ffmpeg.h b/src/zm_ffmpeg.h index 1367ce2e5..33dfedae8 100644 --- a/src/zm_ffmpeg.h +++ b/src/zm_ffmpeg.h @@ -323,7 +323,7 @@ static av_always_inline av_const int64_t av_clip64_c(int64_t a, int64_t amin, in #endif void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output); -#if LIBAVCODEC_VERSION_CHECK(57, 8, 0, 12, 100) +#if LIBAVCODEC_VERSION_CHECK(56, 8, 0, 60, 100) #define zm_av_unref_packet( packet ) av_packet_unref( packet ) #else #define zm_av_unref_packet( packet ) av_free_packet( packet ) From 3dcc1c3697133da4ec0070fc0adcea63ee48329d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 22 Sep 2016 10:37:32 -0400 Subject: [PATCH 25/27] fix php outputting extra newlines after content --- web/views/image.php | 3 ++- web/views/view_video.php | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/web/views/image.php b/web/views/image.php index bce07e765..5278c44a5 100644 --- a/web/views/image.php +++ b/web/views/image.php @@ -141,6 +141,8 @@ if( !empty($_REQUEST['height']) ) { header( 'Content-type: image/jpeg' ); +ob_clean(); +flush(); if ( $errorText ) { Error( $errorText ); @@ -187,4 +189,3 @@ if ( $errorText ) { } } } -?> diff --git a/web/views/view_video.php b/web/views/view_video.php index 4e5e04c0c..d8bf39555 100644 --- a/web/views/view_video.php +++ b/web/views/view_video.php @@ -85,6 +85,10 @@ header("Content-Range: bytes $begin-$end/$size"); header("Content-Transfer-Encoding: binary\n"); header('Connection: close'); +// Apparently without these we get a few extra bytes of output at the end... +ob_clean(); +flush(); + $cur = $begin; fseek( $fh, $begin, 0 ); @@ -94,5 +98,3 @@ while( ! feof( $fh ) && $cur < $end && ( connection_status() == 0 ) ) { $cur += 1024*16; usleep(100); } - -?> From a5b7b6e74f1d1f1dca33ae110447ff1be92933f8 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 22 Sep 2016 10:43:20 -0400 Subject: [PATCH 26/27] move the input packet into a member of the camera. Fix packet copying in packetqueue. Implement separate start pts and dts for audio and video --- src/zm_ffmpeg_camera.cpp | 90 ++++++++++++++++------------- src/zm_ffmpeg_camera.h | 17 +++--- src/zm_packetqueue.cpp | 15 ++--- src/zm_remote_camera_rtsp.cpp | 4 +- src/zm_videostore.cpp | 103 ++++++++++++++++------------------ src/zm_videostore.h | 27 ++++----- src/zm_zone.cpp | 5 +- 7 files changed, 133 insertions(+), 128 deletions(-) diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index 9dc897e20..f980a2bc8 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -146,8 +146,6 @@ int FfmpegCamera::Capture( Image &image ) mReopenThread = 0; } - AVPacket packet; - int frameComplete = false; while ( !frameComplete ) { int avResult = av_read_frame( mFormatContext, &packet ); @@ -386,9 +384,6 @@ int FfmpegCamera::OpenFfmpeg() { } } - // - - Debug ( 1, "Opened codec" ); // Allocate space for the native video frame @@ -563,13 +558,12 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi int frameComplete = false; while ( !frameComplete ) { - // We are now allocating dynamically because we need to queue these and may go out of scope. - AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket)); - av_init_packet( packet ); +Debug(2, "Before av_init_packe"); + av_init_packet( &packet ); -Debug(5, "Before av_read_frame"); - ret = av_read_frame( mFormatContext, packet ); -Debug(5, "After av_read_frame (%d)", ret ); +Debug(2, "Before av_read_frame"); + ret = av_read_frame( mFormatContext, &packet ); +Debug(2, "After av_read_frame (%d)", ret ); if ( ret < 0 ) { av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE ); if ( @@ -582,21 +576,33 @@ Debug(5, "After av_read_frame (%d)", ret ); ReopenFfmpeg(); } - Error( "Unable to read packet from stream %d: error %d \"%s\".", packet->stream_index, ret, errbuf ); + Error( "Unable to read packet from stream %d: error %d \"%s\".", packet.stream_index, ret, errbuf ); return( -1 ); } - Debug( 4, "Got packet from stream %d dts (%d) pts(%d)", packet->stream_index, packet->dts, packet->pts ); + Debug( 3, "Got packet from stream %d dts (%d) pts(%d) key?(%d)", packet.stream_index, packet.dts, packet.pts, packet.flags & AV_PKT_FLAG_KEY ); + //av_packet_ref( &packet, &packet ); //Video recording if ( recording ) { - +Debug(3, "recording:"); // The directory we are recording to is no longer tied to the current event. // Need to re-init the videostore with the correct directory and start recording again // for efficiency's sake, we should test for keyframe before we test for directory change... - if ( videoStore && (packet->flags & AV_PKT_FLAG_KEY) && (strcmp(oldDirectory, event_file) != 0 ) ) { + if ( videoStore && (packet.flags & AV_PKT_FLAG_KEY) && (strcmp(oldDirectory, event_file) != 0 ) ) { // don't open new videostore until we're on a key frame..would this require an offset adjustment for the event as a result?... // if we store our key frame location with the event will that be enough? Info("Re-starting video storage module"); + + // I don't know if this is important or not... but I figure we might as well write this last packet out to the store before closing it. + // Also don't know how much it matters for audio. + if ( packet.stream_index == mVideoStreamId ) { + //Write the packet to our video store + int ret = videoStore->writeVideoFramePacket( &packet ); + if ( ret < 0 ) { //Less than zero and we skipped a frame + Warning("Error writing last packet to videostore."); + } + } // end if video + delete videoStore; videoStore = NULL; } @@ -637,11 +643,11 @@ Debug(5, "After av_read_frame (%d)", ret ); while ( ( queued_packet = packetqueue.popPacket() ) ) { packet_count += 1; //Write the packet to our video store - Debug(2, "Writing queued packet stream: %d KEY %d, remaining (%d)", queued_packet->stream_index, packet->flags & AV_PKT_FLAG_KEY, packetqueue.size() ); + Debug(2, "Writing queued packet stream: %d KEY %d, remaining (%d)", queued_packet->stream_index, queued_packet->flags & AV_PKT_FLAG_KEY, packetqueue.size() ); if ( queued_packet->stream_index == mVideoStreamId ) { - ret = videoStore->writeVideoFramePacket( queued_packet, mFormatContext->streams[mVideoStreamId]); + ret = videoStore->writeVideoFramePacket( queued_packet ); } else if ( queued_packet->stream_index == mAudioStreamId ) { - ret = videoStore->writeAudioFramePacket( queued_packet, mFormatContext->streams[mAudioStreamId]); + ret = videoStore->writeAudioFramePacket( queued_packet ); } else { Warning("Unknown stream id in queued packet (%d)", queued_packet->stream_index ); ret = -1; @@ -663,27 +669,32 @@ Debug(5, "After av_read_frame (%d)", ret ); videoStore = NULL; } - //Buffer video packets, since we are not recording - if ( (packet->stream_index == mVideoStreamId) && ( packet->flags & AV_PKT_FLAG_KEY ) ) { + //Buffer video packets, since we are not recording. All audio packets are keyframes, so only if it's a video keyframe + if ( (packet.stream_index == mVideoStreamId) && ( packet.flags & AV_PKT_FLAG_KEY ) ) { + Debug(3, "Clearing queue"); packetqueue.clearQueue(); } - packetqueue.queuePacket(packet); - } // end if + if ( packet.stream_index != mAudioStreamId || record_audio ) { +Debug(3, "Queuing"); + packetqueue.queuePacket( &packet ); + } + } // end if recording or not - if ( packet->stream_index == mVideoStreamId ) { + if ( packet.stream_index == mVideoStreamId ) { if ( videoStore ) { //Write the packet to our video store - int ret = videoStore->writeVideoFramePacket( packet, mFormatContext->streams[mVideoStreamId] ); + int ret = videoStore->writeVideoFramePacket( &packet ); if ( ret < 0 ) { //Less than zero and we skipped a frame - zm_av_unref_packet( packet ); + zm_av_unref_packet( &packet ); return 0; } } - ret = zm_avcodec_decode_video( mVideoCodecContext, mRawFrame, &frameComplete, packet ); + Debug(3, "about to decode video" ); + ret = zm_avcodec_decode_video( mVideoCodecContext, mRawFrame, &frameComplete, &packet ); if ( ret < 0 ) { av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE ); Error( "Unable to decode frame at frame %d: %s, continuing", frameCount, errbuf ); - zm_av_unref_packet( packet ); + zm_av_unref_packet( &packet ); continue; } @@ -698,7 +709,7 @@ Debug(5, "After av_read_frame (%d)", ret ); directbuffer = image.WriteBuffer(width, height, colours, subpixelorder); if ( directbuffer == NULL ) { Error("Failed requesting writeable buffer for the captured image."); - zm_av_unref_packet( packet ); + zm_av_unref_packet( &packet ); return (-1); } avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height); @@ -727,16 +738,16 @@ Debug(5, "After av_read_frame (%d)", ret ); } else { Debug( 3, "Not framecomplete after av_read_frame" ); } // end if frameComplete - } else if ( packet->stream_index == mAudioStreamId ) { //FIXME best way to copy all other streams - Debug( 4, "Audio stream index %d", packet->stream_index ); + } else if ( packet.stream_index == mAudioStreamId ) { //FIXME best way to copy all other streams if ( videoStore ) { if ( record_audio ) { - Debug(3, "Recording audio packet streamindex(%d) packetstreamindex(%d)", mAudioStreamId, packet->stream_index ); + Debug(3, "Recording audio packet streamindex(%d) packetstreamindex(%d)", mAudioStreamId, packet.stream_index ); //Write the packet to our video store //FIXME no relevance of last key frame - int ret = videoStore->writeAudioFramePacket( packet, mFormatContext->streams[packet->stream_index] ); + int ret = videoStore->writeAudioFramePacket( &packet ); if ( ret < 0 ) {//Less than zero and we skipped a frame - zm_av_unref_packet( packet ); + Warning("Failure to write audio packet."); + zm_av_unref_packet( &packet ); return 0; } } else { @@ -745,15 +756,16 @@ Debug(5, "After av_read_frame (%d)", ret ); } } else { #if LIBAVUTIL_VERSION_CHECK(54, 23, 0, 23, 0) - Debug( 3, "Some other stream index %d, %s", packet->stream_index, av_get_media_type_string( mFormatContext->streams[packet->stream_index]->codec->codec_type) ); + Debug( 3, "Some other stream index %d, %s", packet.stream_index, av_get_media_type_string( mFormatContext->streams[packet.stream_index]->codec->codec_type) ); #else - Debug( 3, "Some other stream index %d", packet->stream_index ); + Debug( 3, "Some other stream index %d", packet.stream_index ); #endif } - if ( videoStore ) { - zm_av_unref_packet( packet ); - av_free( packet ); - } + //if ( videoStore ) { + + // the packet contents are ref counted... when queuing, we allocate another packet and reference it with that one, so we should always need to unref here, which should not affect the queued version. + zm_av_unref_packet( &packet ); + //} } // end while ! frameComplete return (frameCount); } diff --git a/src/zm_ffmpeg_camera.h b/src/zm_ffmpeg_camera.h index 775561f0e..f45e559b4 100644 --- a/src/zm_ffmpeg_camera.h +++ b/src/zm_ffmpeg_camera.h @@ -36,8 +36,8 @@ class FfmpegCamera : public Camera { protected: std::string mPath; - std::string mMethod; - std::string mOptions; + std::string mMethod; + std::string mOptions; int frameCount; @@ -51,7 +51,12 @@ class FfmpegCamera : public Camera AVCodec *mAudioCodec; AVFrame *mRawFrame; AVFrame *mFrame; - _AVPIXELFORMAT imagePixFormat; + _AVPIXELFORMAT imagePixFormat; + + // Used to store the incoming packet, it will get copied when queued. + // We only ever need one at a time, so instead of constantly allocating + // and freeing this structure, we will just make it a member of the object. + AVPacket packet; int OpenFfmpeg(); int ReopenFfmpeg(); @@ -67,10 +72,8 @@ class FfmpegCamera : public Camera bool wasRecording; VideoStore *videoStore; char oldDirectory[4096]; - zm_packetqueue packetqueue; - - // Last Key frame - //AVPacket lastKeyframePkt; + unsigned int old_event_id; + zm_packetqueue packetqueue; #if HAVE_LIBSWSCALE struct SwsContext *mConvertContext; diff --git a/src/zm_packetqueue.cpp b/src/zm_packetqueue.cpp index 7ecba50a0..e394ecc60 100644 --- a/src/zm_packetqueue.cpp +++ b/src/zm_packetqueue.cpp @@ -35,17 +35,18 @@ zm_packetqueue::~zm_packetqueue() { bool zm_packetqueue::queuePacket( AVPacket* packet ) { - //AVPacket *input_ref = (AVPacket *)av_malloc(sizeof(AVPacket)); - //if ( av_packet_ref( input_ref, packet ) < 0 ) { -if ( 0 ) { - if ( av_packet_ref( packet, packet ) < 0 ) { + AVPacket *input_ref = (AVPacket *)av_malloc(sizeof(AVPacket)); + av_init_packet( input_ref ); + if ( av_packet_ref( input_ref, packet ) < 0 ) { Error("error refing packet"); - //av_free_packet(input_ref); + av_free(input_ref); return false; - } + } else { + Debug(3, "made a ref"); } - pktQueue.push( packet ); + pktQueue.push( input_ref ); + Debug(3, "queued"); //pktQueue.push( input_ref ); return true; diff --git a/src/zm_remote_camera_rtsp.cpp b/src/zm_remote_camera_rtsp.cpp index e70ff5c11..eeec27147 100644 --- a/src/zm_remote_camera_rtsp.cpp +++ b/src/zm_remote_camera_rtsp.cpp @@ -523,7 +523,7 @@ int RemoteCameraRtsp::CaptureAndRecord(Image &image, bool recording, char* event if ( videoStore ) { //Write the packet to our video store - int ret = videoStore->writeVideoFramePacket(&packet, mFormatContext->streams[mVideoStreamId]);//, &lastKeyframePkt); + int ret = videoStore->writeVideoFramePacket(&packet);//, &lastKeyframePkt); if ( ret < 0 ) {//Less than zero and we skipped a frame // Should not av_free_packet( &packet ); @@ -553,7 +553,7 @@ int RemoteCameraRtsp::CaptureAndRecord(Image &image, bool recording, char* event if ( videoStore && record_audio ) { Debug( 4, "Storing Audio packet" ); //Write the packet to our video store - int ret = videoStore->writeAudioFramePacket(&packet, mFormatContext->streams[packet.stream_index]); //FIXME no relevance of last key frame + int ret = videoStore->writeAudioFramePacket( &packet ); //FIXME no relevance of last key frame if ( ret < 0 ) { //Less than zero and we skipped a frame #if LIBAVCODEC_VERSION_CHECK(57, 8, 0, 12, 100) av_packet_unref( &packet ); diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index 6121dd09c..3d29b58b2 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -33,11 +33,13 @@ extern "C"{ } VideoStore::VideoStore(const char *filename_in, const char *format_in, - AVStream *input_video_stream, - AVStream *input_audio_stream, + AVStream *p_input_video_stream, + AVStream *p_input_audio_stream, int64_t nStartTime, Monitor::Orientation orientation ) { + input_video_stream = p_input_video_stream; + input_audio_stream = p_input_audio_stream; //store inputs in variables local to class filename = filename_in; @@ -296,13 +298,16 @@ Debug(2, "Have audio_output_context"); } prevDts = 0; - startPts = 0; - startDts = 0; + video_start_pts = 0; + video_start_dts = 0; + audio_start_pts = 0; + audio_start_dts = 0; + filter_in_rescale_delta_last = AV_NOPTS_VALUE; // now - when streaming started - startTime=av_gettime()-nStartTime;//oc->start_time; - Info("VideoStore startTime=%d\n",startTime); + //startTime=av_gettime()-nStartTime;//oc->start_time; + //Info("VideoStore startTime=%d\n",startTime); } // VideoStore::VideoStore @@ -355,7 +360,7 @@ void VideoStore::dumpPacket( AVPacket *pkt ){ Debug(1, "%s:%d:DEBUG: %s", __FILE__, __LINE__, b); } -int VideoStore::writeVideoFramePacket(AVPacket *ipkt, AVStream *input_video_stream){ +int VideoStore::writeVideoFramePacket( AVPacket *ipkt ) { AVPacket opkt; AVPicture pict; @@ -366,13 +371,13 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt, AVStream *input_video_stre if ( 1 ) { //Scale the PTS of the outgoing packet to be the correct time base if (ipkt->pts != AV_NOPTS_VALUE) { - if ( ! startPts ) { + if ( ! video_start_pts ) { //never gets set, so the first packet can set it. - startPts = ipkt->pts; + video_start_pts = ipkt->pts; } - opkt.pts = av_rescale_q(ipkt->pts-startPts, input_video_stream->time_base, video_stream->time_base); + opkt.pts = av_rescale_q(ipkt->pts - video_start_pts, input_video_stream->time_base, video_stream->time_base); //- ost_tb_start_time; - Debug(3, "opkt.pts = %d from ipkt->pts(%d) - startPts(%d)", opkt.pts, ipkt->pts, startPts ); + Debug(3, "opkt.pts = %d from ipkt->pts(%d) - startPts(%d)", opkt.pts, ipkt->pts, video_start_pts ); } else { Debug(3, "opkt.pts = undef"); opkt.pts = AV_NOPTS_VALUE; @@ -380,23 +385,22 @@ if ( 1 ) { //Scale the DTS of the outgoing packet to be the correct time base if(ipkt->dts == AV_NOPTS_VALUE) { - if ( ! startDts ) startDts = input_video_stream->cur_dts; - opkt.dts = av_rescale_q(input_video_stream->cur_dts-startDts, AV_TIME_BASE_Q, video_stream->time_base); + // why are we using cur_dts instead of packet.dts? + if ( ! video_start_dts ) video_start_dts = input_video_stream->cur_dts; + opkt.dts = av_rescale_q(input_video_stream->cur_dts - video_start_dts, AV_TIME_BASE_Q, video_stream->time_base); Debug(3, "opkt.dts = %d from input_video_stream->cur_dts(%d) - startDts(%d)", - opkt.dts, input_video_stream->cur_dts, startDts + opkt.dts, input_video_stream->cur_dts, video_start_dts ); } else { - if ( ! startDts ) startDts = ipkt->dts; - opkt.dts = av_rescale_q(ipkt->dts - startDts, input_video_stream->time_base, video_stream->time_base); - Debug(3, "opkt.dts = %d from ipkt->dts(%d) - startDts(%d)", opkt.dts, ipkt->dts, startDts ); + if ( ! video_start_dts ) video_start_dts = ipkt->dts; + opkt.dts = av_rescale_q(ipkt->dts - video_start_dts, input_video_stream->time_base, video_stream->time_base); + Debug(3, "opkt.dts = %d from ipkt->dts(%d) - startDts(%d)", opkt.dts, ipkt->dts, video_start_dts ); } if ( opkt.dts > opkt.pts ) { - Warning("opkt.dts(%d) must be <= opkt.pts(%d). Decompression must happen before presentation.", opkt.dts, opkt.pts ); + Debug( 1, "opkt.dts(%d) must be <= opkt.pts(%d). Decompression must happen before presentation.", opkt.dts, opkt.pts ); opkt.dts = opkt.pts; } - //opkt.dts -= ost_tb_start_time; - opkt.duration = av_rescale_q(ipkt->duration, input_video_stream->time_base, video_stream->time_base); } else { av_packet_rescale_ts( &opkt, input_video_stream->time_base, video_stream->time_base ); @@ -459,8 +463,8 @@ Debug(4, "Not video and RAWPICTURE"); } -int VideoStore::writeAudioFramePacket(AVPacket *ipkt, AVStream *input_audio_stream){ - Debug(2, "writeAudioFrame"); +int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) { + Debug(4, "writeAudioFrame"); if(!audio_stream) { Error("Called writeAudioFramePacket when no audio_stream"); @@ -471,61 +475,50 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt, AVStream *input_audio_stre //zm_dump_stream_format( oc, ipkt->stream_index, 0, 1 ); int ret; - // 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_stream->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 + //Scale the PTS of the outgoing packet to be the correct time base if (ipkt->pts != AV_NOPTS_VALUE) { - Debug(2, "Rescaling output pts"); - opkt.pts = av_rescale_q(ipkt->pts-startPts, input_audio_stream->time_base, audio_stream->time_base) - ost_tb_start_time; + if ( ! audio_start_pts ) { + //never gets set, so the first packet can set it. + audio_start_pts = ipkt->pts; + } + opkt.pts = av_rescale_q(ipkt->pts-audio_start_pts, input_audio_stream->time_base, audio_stream->time_base); + Debug(3, "opkt.pts = %d from ipkt->pts(%d) - startPts(%d)", opkt.pts, ipkt->pts, audio_start_pts ); } else { - Debug(2, "Setting output pts to AV_NOPTS_VALUE"); + Debug(3, "opkt.pts = undef"); 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(2, "ipkt->dts == AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts ); - opkt.dts = av_rescale_q(input_audio_stream->cur_dts-startDts, AV_TIME_BASE_Q, audio_stream->time_base); - Debug(2, "ipkt->dts == AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts ); + if ( ! audio_start_dts ) audio_start_dts = input_video_stream->cur_dts; + opkt.dts = av_rescale_q(input_video_stream->cur_dts - audio_start_dts, AV_TIME_BASE_Q, audio_stream->time_base); + Debug(3, "opkt.dts = %d from input_video_stream->cur_dts(%d) - startDts(%d)", + opkt.dts, input_audio_stream->cur_dts, audio_start_dts + ); } else { - Debug(2, "ipkt->dts != AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts ); - opkt.dts = av_rescale_q(ipkt->dts-startDts, input_audio_stream->time_base, audio_stream->time_base); - Debug(2, "ipkt->dts != AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts ); + if ( ! audio_start_dts ) audio_start_dts = ipkt->dts; + opkt.dts = av_rescale_q(ipkt->dts - audio_start_dts, input_audio_stream->time_base, audio_stream->time_base); + Debug(3, "opkt.dts = %d from ipkt->dts(%d) - startDts(%d)", opkt.dts, ipkt->dts, audio_start_dts ); } - Debug(2, "Not sure what ost_tb_start_time is (%d) - (%d)", opkt.dts, ost_tb_start_time ); - opkt.dts -= ost_tb_start_time; - - // Seems like it would be really weird for the codec type to NOT be audiu - if (audio_stream->codec->codec_type == AVMEDIA_TYPE_AUDIO && ipkt->dts != AV_NOPTS_VALUE) { - int duration = av_get_audio_frame_duration(input_audio_stream->codec, ipkt->size); - Debug( 1, "code is audio, dts != AV_NOPTS_VALUE got duration(%d)", duration ); - if ( ! duration ) { - duration = input_audio_stream->codec->frame_size; - Warning( "got no duration from av_get_audio_frame_duration. Using frame size(%d)", duration ); - } - - //FIXME where to get filter_in_rescale_delta_last - //FIXME av_rescale_delta doesn't exist in ubuntu vivid libavtools - opkt.dts = opkt.pts = av_rescale_delta(input_audio_stream->time_base, ipkt->dts, - (AVRational){1, input_audio_stream->codec->sample_rate}, duration, &filter_in_rescale_delta_last, - audio_stream->time_base) - ost_tb_start_time; - Debug(2, "rescaled dts is: (%d)", opkt.dts ); + if ( opkt.dts > opkt.pts ) { + Debug(1,"opkt.dts(%d) must be <= opkt.pts(%d). Decompression must happen before presentation.", opkt.dts, opkt.pts ); + opkt.dts = opkt.pts; } opkt.duration = av_rescale_q(ipkt->duration, input_audio_stream->time_base, audio_stream->time_base); - opkt.pos=-1; + // pkt.pos: byte position in stream, -1 if unknown + opkt.pos = -1; opkt.flags = ipkt->flags; opkt.stream_index = ipkt->stream_index; if ( audio_output_codec ) { - - + // we are transcoding AVFrame *input_frame; AVFrame *output_frame; diff --git a/src/zm_videostore.h b/src/zm_videostore.h index 8478285d7..9f6fb07a6 100644 --- a/src/zm_videostore.h +++ b/src/zm_videostore.h @@ -15,6 +15,9 @@ private: AVStream *video_stream; AVStream *audio_stream; + AVStream *input_video_stream; + AVStream *input_audio_stream; + // The following are used when encoding the audio stream to AAC AVCodec *audio_output_codec; AVCodecContext *audio_output_context; @@ -26,9 +29,11 @@ private: bool keyframeMessage; int keyframeSkipNumber; - int64_t startTime; - int64_t startPts; - int64_t startDts; + int64_t video_start_pts; + int64_t video_start_dts; + int64_t audio_start_pts; + int64_t audio_start_dts; + int64_t prevDts; int64_t filter_in_rescale_delta_last; @@ -36,23 +41,11 @@ public: VideoStore(const char *filename_in, const char *format_in, AVStream *input_video_stream, AVStream *input_audio_stream, int64_t nStartTime, Monitor::Orientation p_orientation ); ~VideoStore(); - int writeVideoFramePacket(AVPacket *pkt, AVStream *input_st);//, AVPacket *lastKeyframePkt); - int writeAudioFramePacket(AVPacket *pkt, AVStream *input_st); + int writeVideoFramePacket( AVPacket *pkt ); + int writeAudioFramePacket( AVPacket *pkt ); void dumpPacket( AVPacket *pkt ); }; -/* -class VideoEvent { -public: - VideoEvent(unsigned int eid); - ~VideoEvent(); - - int createEventImage(unsigned int fid, char *&pBuff); - -private: - unsigned int m_eid; -};*/ - #endif //havelibav #endif //zm_videostore_h diff --git a/src/zm_zone.cpp b/src/zm_zone.cpp index d13114345..e4f37455c 100644 --- a/src/zm_zone.cpp +++ b/src/zm_zone.cpp @@ -48,7 +48,10 @@ void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_ overload_frames = p_overload_frames; extend_alarm_frames = p_extend_alarm_frames; - Debug( 1, "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, CM:%d, MnAT:%d, MxAT:%d, MnAP:%d, MxAP:%d, FB:%dx%d, MnFP:%d, MxFP:%d, MnBS:%d, MxBS:%d, MnB:%d, MxB:%d, OF: %d, AF: %d", id, label, type, polygon.Width(), polygon.Height(), alarm_rgb, check_method, min_pixel_threshold, max_pixel_threshold, min_alarm_pixels, max_alarm_pixels, filter_box.X(), filter_box.Y(), min_filter_pixels, max_filter_pixels, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs, overload_frames, extend_alarm_frames ); + //Debug( 1, "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, CM:%d, MnAT:%d, MxAT:%d, MnAP:%d, MxAP:%d, FB:%dx%d, MnFP:%d, MxFP:%d, MnBS:%d, MxBS:%d, MnB:%d, MxB:%d, OF: %d, AF: %d", id, label, type, polygon.Width(), polygon.Height(), alarm_rgb, check_method, min_pixel_threshold, max_pixel_threshold, min_alarm_pixels, max_alarm_pixels, filter_box.X(), filter_box.Y(), min_filter_pixels, max_filter_pixels, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs, overload_frames, extend_alarm_frames ); + //Debug( 1, "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, CM:%d, MnAT:%d, MxAT:%d, MnAP:%d, MxAP:%d, FB:%dx%d, MnFP:%d, MxFP:%d, MnBS:%d, MxBS:%d, MnB:%d, MxB:%d, OF: %d", id, label, type, polygon.Width(), polygon.Height(), alarm_rgb, check_method, min_pixel_threshold, max_pixel_threshold, min_alarm_pixels, max_alarm_pixels, filter_box.X(), filter_box.Y(), min_filter_pixels, max_filter_pixels, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs, overload_frames ); + //Debug( 1, "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, CM:%d", id, label, type, polygon.Width(), polygon.Height(), alarm_rgb, check_method ); + Debug( 1, "Initialised zone %d/%s - %d - %dx%d", id, label, type, polygon.Width(), polygon.Height() ); alarmed = false; pixel_diff = 0; From 782f9395aedb9f43510f6955aa81aaca6a9bfcef Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 23 Sep 2016 09:51:03 -0400 Subject: [PATCH 27/27] turn down the debugging --- src/zm_ffmpeg_camera.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index f980a2bc8..00fb4c6ee 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -558,12 +558,12 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi int frameComplete = false; while ( !frameComplete ) { -Debug(2, "Before av_init_packe"); +Debug(5, "Before av_init_packe"); av_init_packet( &packet ); -Debug(2, "Before av_read_frame"); +Debug(5, "Before av_read_frame"); ret = av_read_frame( mFormatContext, &packet ); -Debug(2, "After av_read_frame (%d)", ret ); +Debug(5, "After av_read_frame (%d)", ret ); if ( ret < 0 ) { av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE ); if ( @@ -584,7 +584,6 @@ Debug(2, "After av_read_frame (%d)", ret ); //Video recording if ( recording ) { -Debug(3, "recording:"); // The directory we are recording to is no longer tied to the current event. // Need to re-init the videostore with the correct directory and start recording again // for efficiency's sake, we should test for keyframe before we test for directory change...