Merge branch 'storageareas' into record_audio
This commit is contained in:
commit
b8c7b6ae77
|
@ -328,22 +328,22 @@ CREATE TABLE `Monitors` (
|
||||||
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL') NOT NULL default 'Local',
|
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL') NOT NULL default 'Local',
|
||||||
`Function` enum('None','Monitor','Modect','Record','Mocord','Nodect') NOT NULL default 'Monitor',
|
`Function` enum('None','Monitor','Modect','Record','Mocord','Nodect') NOT NULL default 'Monitor',
|
||||||
`Enabled` tinyint(3) unsigned NOT NULL default '1',
|
`Enabled` tinyint(3) unsigned NOT NULL default '1',
|
||||||
`LinkedMonitors` varchar(255) NOT NULL default '',
|
`LinkedMonitors` varchar(255),
|
||||||
`Triggers` set('X10') NOT NULL default '',
|
`Triggers` set('X10') NOT NULL default '',
|
||||||
`Device` tinytext NOT NULL default '',
|
`Device` tinytext NOT NULL default '',
|
||||||
`Channel` tinyint(3) unsigned NOT NULL default '0',
|
`Channel` tinyint(3) unsigned NOT NULL default '0',
|
||||||
`Format` int(10) unsigned NOT NULL default '0',
|
`Format` int(10) unsigned NOT NULL default '0',
|
||||||
`V4LMultiBuffer` tinyint(1) unsigned,
|
`V4LMultiBuffer` tinyint(1) unsigned,
|
||||||
`V4LCapturesPerFrame` tinyint(3) unsigned,
|
`V4LCapturesPerFrame` tinyint(3) unsigned,
|
||||||
`Protocol` varchar(16) NOT NULL default '',
|
`Protocol` varchar(16),
|
||||||
`Method` varchar(16) NOT NULL default '',
|
`Method` varchar(16) NOT NULL default '',
|
||||||
`Host` varchar(64) NOT NULL default '',
|
`Host` varchar(64),
|
||||||
`Port` varchar(8) NOT NULL default '',
|
`Port` varchar(8) NOT NULL default '',
|
||||||
`SubPath` varchar(64) NOT NULL default '',
|
`SubPath` varchar(64) NOT NULL default '',
|
||||||
`Path` varchar(255) NOT NULL default '',
|
`Path` varchar(255) NOT NULL default '',
|
||||||
`Options` varchar(255) not null default '',
|
`Options` varchar(255),
|
||||||
`User` varchar(64) NOT NULL default '',
|
`User` varchar(64),
|
||||||
`Pass` varchar(64) NOT NULL default '',
|
`Pass` varchar(64),
|
||||||
`Width` smallint(5) unsigned NOT NULL default '0',
|
`Width` smallint(5) unsigned NOT NULL default '0',
|
||||||
`Height` smallint(5) unsigned NOT NULL default '0',
|
`Height` smallint(5) unsigned NOT NULL default '0',
|
||||||
`Colours` tinyint(3) unsigned NOT NULL default '1',
|
`Colours` tinyint(3) unsigned NOT NULL default '1',
|
||||||
|
@ -354,13 +354,13 @@ CREATE TABLE `Monitors` (
|
||||||
`VideoWriter` TINYINT NOT NULL DEFAULT '0',
|
`VideoWriter` TINYINT NOT NULL DEFAULT '0',
|
||||||
`EncoderParameters` TEXT NOT NULL,
|
`EncoderParameters` TEXT NOT NULL,
|
||||||
`RecordAudio` TINYINT NOT NULL DEFAULT '0',
|
`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',
|
`Brightness` mediumint(7) NOT NULL default '-1',
|
||||||
`Contrast` mediumint(7) NOT NULL default '-1',
|
`Contrast` mediumint(7) NOT NULL default '-1',
|
||||||
`Hue` mediumint(7) NOT NULL default '-1',
|
`Hue` mediumint(7) NOT NULL default '-1',
|
||||||
`Colour` mediumint(7) NOT NULL default '-1',
|
`Colour` mediumint(7) NOT NULL default '-1',
|
||||||
`EventPrefix` varchar(32) NOT NULL default 'Event-',
|
`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',
|
`LabelX` smallint(5) unsigned NOT NULL default '0',
|
||||||
`LabelY` smallint(5) unsigned NOT NULL default '0',
|
`LabelY` smallint(5) unsigned NOT NULL default '0',
|
||||||
`LabelSize` smallint(5) unsigned NOT NULL DEFAULT '1',
|
`LabelSize` smallint(5) unsigned NOT NULL DEFAULT '1',
|
||||||
|
@ -381,14 +381,14 @@ CREATE TABLE `Monitors` (
|
||||||
`RefBlendPerc` tinyint(3) unsigned NOT NULL default '6',
|
`RefBlendPerc` tinyint(3) unsigned NOT NULL default '6',
|
||||||
`AlarmRefBlendPerc` tinyint(3) unsigned NOT NULL default '6',
|
`AlarmRefBlendPerc` tinyint(3) unsigned NOT NULL default '6',
|
||||||
`Controllable` tinyint(3) unsigned NOT NULL default '0',
|
`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,
|
`ControlDevice` varchar(255) default NULL,
|
||||||
`ControlAddress` varchar(255) default NULL,
|
`ControlAddress` varchar(255) default NULL,
|
||||||
`AutoStopTimeout` decimal(5,2) default NULL,
|
`AutoStopTimeout` decimal(5,2) default NULL,
|
||||||
`TrackMotion` tinyint(3) unsigned NOT NULL default '0',
|
`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',
|
`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',
|
`DefaultView` enum('Events','Control') NOT NULL default 'Events',
|
||||||
`DefaultRate` smallint(5) unsigned NOT NULL default '100',
|
`DefaultRate` smallint(5) unsigned NOT NULL default '100',
|
||||||
`DefaultScale` 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,
|
`Id` int(10) unsigned NOT NULL auto_increment,
|
||||||
`Username` varchar(32) character set latin1 collate latin1_bin NOT NULL default '',
|
`Username` varchar(32) character set latin1 collate latin1_bin NOT NULL default '',
|
||||||
`Password` varchar(64) 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',
|
`Enabled` tinyint(3) unsigned NOT NULL default '1',
|
||||||
`Stream` enum('None','View') NOT NULL default 'None',
|
`Stream` enum('None','View') NOT NULL default 'None',
|
||||||
`Events` enum('None','View','Edit') 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',
|
`Groups` enum('None','View','Edit') NOT NULL default 'None',
|
||||||
`Devices` 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',
|
`System` enum('None','View','Edit') NOT NULL default 'None',
|
||||||
`MaxBandwidth` varchar(16) NOT NULL default '',
|
`MaxBandwidth` varchar(16),
|
||||||
`MonitorIds` tinytext NOT NULL,
|
`MonitorIds` tinytext,
|
||||||
PRIMARY KEY (`Id`),
|
PRIMARY KEY (`Id`),
|
||||||
UNIQUE KEY `UC_Username` (`Username`)
|
UNIQUE KEY `UC_Username` (`Username`)
|
||||||
) ENGINE=@ZM_MYSQL_ENGINE@;
|
) ENGINE=@ZM_MYSQL_ENGINE@;
|
||||||
|
|
|
@ -4,5 +4,7 @@
|
||||||
-- Changing StorageId to be NOT NULL and default 0
|
-- 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;
|
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;
|
ALTER TABLE Events MODIFY `StorageId` smallint(5) unsigned NOT NULL default 0;
|
||||||
|
|
|
@ -37,7 +37,7 @@ Package: zoneminder
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
|
Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
|
||||||
,javascript-common
|
,javascript-common
|
||||||
,libav-tools
|
,libav-tools | ffmpeg
|
||||||
,libdate-manip-perl, libmime-lite-perl, libmime-tools-perl
|
,libdate-manip-perl, libmime-lite-perl, libmime-tools-perl
|
||||||
,libdbd-mysql-perl
|
,libdbd-mysql-perl
|
||||||
,libphp-serialization-perl
|
,libphp-serialization-perl
|
||||||
|
|
|
@ -206,11 +206,11 @@ MAIN: while( $loop ) {
|
||||||
Debug( "Checking day dir $day_dir" );
|
Debug( "Checking day dir $day_dir" );
|
||||||
( $day_dir ) = ( $day_dir =~ /^(.*)$/ ); # De-taint
|
( $day_dir ) = ( $day_dir =~ /^(.*)$/ ); # De-taint
|
||||||
if ( ! chdir( $day_dir ) ) {
|
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;
|
next;
|
||||||
}
|
}
|
||||||
if ( ! opendir( DIR, '.' ) ) {
|
if ( ! opendir( DIR, '.' ) ) {
|
||||||
Error( "Can't open directory $$Storage{Path}/$monitor_dir/'$day_dir': $!" );
|
Error( "Can't open directory '$$Storage{Path}/$day_dir': $!" );
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
my @event_links = sort { $b <=> $a } grep { -l $_ } readdir( DIR );
|
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 " );
|
Debug( "Checking link $event_link points to $event_path " );
|
||||||
my $Event = $fs_events->{$event} = new ZoneMinder::Event();
|
my $Event = $fs_events->{$event} = new ZoneMinder::Event();
|
||||||
$$Event{Id} = $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->MonitorId( $monitor_dir );
|
||||||
$Event->StorageId( $Storage->Id() );
|
$Event->StorageId( $Storage->Id() );
|
||||||
} # event path exists
|
} # event path exists
|
||||||
|
|
|
@ -424,6 +424,7 @@ static void zm_log_fps(double d, const char *postfix) {
|
||||||
/* "user interface" functions */
|
/* "user interface" functions */
|
||||||
void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output) {
|
void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output) {
|
||||||
char buf[256];
|
char buf[256];
|
||||||
|
Debug(1, "Dumping stream index i(%d) index(%d)", i, index );
|
||||||
int flags = (is_output ? ic->oformat->flags : ic->iformat->flags);
|
int flags = (is_output ? ic->oformat->flags : ic->iformat->flags);
|
||||||
AVStream *st = ic->streams[i];
|
AVStream *st = ic->streams[i];
|
||||||
AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0);
|
AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0);
|
||||||
|
@ -437,8 +438,7 @@ void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output)
|
||||||
Debug(1, "[0x%x]", st->id);
|
Debug(1, "[0x%x]", st->id);
|
||||||
if (lang)
|
if (lang)
|
||||||
Debug(1, "(%s)", lang->value);
|
Debug(1, "(%s)", lang->value);
|
||||||
av_log(NULL, AV_LOG_DEBUG, ", %d, %d/%d", st->codec_info_nb_frames,
|
Debug(1, ", %d, %d/%d", st->codec_info_nb_frames, st->time_base.num, st->time_base.den);
|
||||||
st->time_base.num, st->time_base.den);
|
|
||||||
Debug(1, ": %s", buf);
|
Debug(1, ": %s", buf);
|
||||||
|
|
||||||
if (st->sample_aspect_ratio.num && // default
|
if (st->sample_aspect_ratio.num && // default
|
||||||
|
@ -464,9 +464,9 @@ void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output)
|
||||||
if (fps)
|
if (fps)
|
||||||
zm_log_fps(av_q2d(st->avg_frame_rate), tbn || tbc ? "fps, " : "fps");
|
zm_log_fps(av_q2d(st->avg_frame_rate), tbn || tbc ? "fps, " : "fps");
|
||||||
if (tbn)
|
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)
|
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)
|
if (st->disposition & AV_DISPOSITION_DEFAULT)
|
||||||
|
|
|
@ -323,8 +323,8 @@ static av_always_inline av_const int64_t av_clip64_c(int64_t a, int64_t amin, in
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output);
|
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_unref_packet( packet )
|
#define zm_av_unref_packet( packet ) av_packet_unref( packet )
|
||||||
#else
|
#else
|
||||||
#define zm_av_unref_packet( packet ) av_free_packet( packet )
|
#define zm_av_unref_packet( packet ) av_free_packet( packet )
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -146,8 +146,6 @@ int FfmpegCamera::Capture( Image &image )
|
||||||
mReopenThread = 0;
|
mReopenThread = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
AVPacket packet;
|
|
||||||
|
|
||||||
int frameComplete = false;
|
int frameComplete = false;
|
||||||
while ( !frameComplete ) {
|
while ( !frameComplete ) {
|
||||||
int avResult = av_read_frame( mFormatContext, &packet );
|
int avResult = av_read_frame( mFormatContext, &packet );
|
||||||
|
@ -167,7 +165,7 @@ int FfmpegCamera::Capture( Image &image )
|
||||||
Error( "Unable to read packet from stream %d: error %d \"%s\".", packet.stream_index, avResult, errbuf );
|
Error( "Unable to read packet from stream %d: error %d \"%s\".", packet.stream_index, avResult, errbuf );
|
||||||
return( -1 );
|
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...
|
// What about audio stream? Maybe someday we could do sound detection...
|
||||||
if ( packet.stream_index == mVideoStreamId ) {
|
if ( packet.stream_index == mVideoStreamId ) {
|
||||||
#if LIBAVCODEC_VERSION_CHECK(52, 23, 0, 23, 0)
|
#if LIBAVCODEC_VERSION_CHECK(52, 23, 0, 23, 0)
|
||||||
|
@ -290,7 +288,6 @@ int FfmpegCamera::OpenFfmpeg() {
|
||||||
Debug ( 1, "Opened input" );
|
Debug ( 1, "Opened input" );
|
||||||
|
|
||||||
Info( "Stream open %s", mPath.c_str() );
|
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...
|
//FIXME can speed up initial analysis but need sensible parameters...
|
||||||
//mFormatContext->probesize = 32;
|
//mFormatContext->probesize = 32;
|
||||||
|
@ -305,6 +302,7 @@ int FfmpegCamera::OpenFfmpeg() {
|
||||||
#endif
|
#endif
|
||||||
Fatal( "Unable to find stream info from %s due to: %s", mPath.c_str(), strerror(errno) );
|
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" );
|
Debug ( 1, "Got stream info" );
|
||||||
|
|
||||||
// Find first video stream present
|
// Find first video stream present
|
||||||
|
@ -386,9 +384,6 @@ int FfmpegCamera::OpenFfmpeg() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
Debug ( 1, "Opened codec" );
|
Debug ( 1, "Opened codec" );
|
||||||
|
|
||||||
// Allocate space for the native video frame
|
// Allocate space for the native video frame
|
||||||
|
@ -555,11 +550,11 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
|
||||||
|
|
||||||
int frameComplete = false;
|
int frameComplete = false;
|
||||||
while ( !frameComplete ) {
|
while ( !frameComplete ) {
|
||||||
// We are now allocating dynamically because we need to queue these and may go out of scope.
|
Debug(5, "Before av_init_packe");
|
||||||
AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket));
|
av_init_packet( &packet );
|
||||||
av_init_packet( packet );
|
|
||||||
Debug(5, "Before av_read_frame");
|
Debug(5, "Before av_read_frame");
|
||||||
ret = av_read_frame( mFormatContext, packet );
|
ret = av_read_frame( mFormatContext, &packet );
|
||||||
Debug(5, "After av_read_frame (%d)", ret );
|
Debug(5, "After av_read_frame (%d)", ret );
|
||||||
if ( ret < 0 ) {
|
if ( ret < 0 ) {
|
||||||
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
||||||
|
@ -573,21 +568,32 @@ Debug(5, "After av_read_frame (%d)", ret );
|
||||||
ReopenFfmpeg();
|
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 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
Debug( 5, "Got packet from stream %d", packet->stream_index );
|
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
|
//Video recording
|
||||||
if ( recording ) {
|
if ( recording ) {
|
||||||
|
|
||||||
// The directory we are recording to is no longer tied to the current event.
|
// 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
|
// 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...
|
// 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?...
|
// 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?
|
// if we store our key frame location with the event will that be enough?
|
||||||
Info("Re-starting video storage module");
|
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;
|
delete videoStore;
|
||||||
videoStore = NULL;
|
videoStore = NULL;
|
||||||
}
|
}
|
||||||
|
@ -628,11 +634,11 @@ Debug(5, "After av_read_frame (%d)", ret );
|
||||||
while ( ( queued_packet = packetqueue.popPacket() ) ) {
|
while ( ( queued_packet = packetqueue.popPacket() ) ) {
|
||||||
packet_count += 1;
|
packet_count += 1;
|
||||||
//Write the packet to our video store
|
//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, queued_packet->flags & AV_PKT_FLAG_KEY, packetqueue.size() );
|
||||||
if ( queued_packet->stream_index == mVideoStreamId ) {
|
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 ) {
|
} else if ( queued_packet->stream_index == mAudioStreamId ) {
|
||||||
ret = videoStore->writeAudioFramePacket( queued_packet, mFormatContext->streams[mAudioStreamId]);
|
ret = videoStore->writeAudioFramePacket( queued_packet );
|
||||||
} else {
|
} else {
|
||||||
Warning("Unknown stream id in queued packet (%d)", queued_packet->stream_index );
|
Warning("Unknown stream id in queued packet (%d)", queued_packet->stream_index );
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
@ -641,6 +647,7 @@ Debug(5, "After av_read_frame (%d)", ret );
|
||||||
//Less than zero and we skipped a frame
|
//Less than zero and we skipped a frame
|
||||||
}
|
}
|
||||||
zm_av_unref_packet( queued_packet );
|
zm_av_unref_packet( queued_packet );
|
||||||
|
av_free( queued_packet );
|
||||||
} // end while packets in the packetqueue
|
} // end while packets in the packetqueue
|
||||||
Debug(2, "Wrote %d queued packets", packet_count );
|
Debug(2, "Wrote %d queued packets", packet_count );
|
||||||
} // end if ! wasRecording
|
} // end if ! wasRecording
|
||||||
|
@ -653,27 +660,32 @@ Debug(5, "After av_read_frame (%d)", ret );
|
||||||
videoStore = NULL;
|
videoStore = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Buffer video packets, since we are not recording
|
//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 ) ) {
|
if ( (packet.stream_index == mVideoStreamId) && ( packet.flags & AV_PKT_FLAG_KEY ) ) {
|
||||||
|
Debug(3, "Clearing queue");
|
||||||
packetqueue.clearQueue();
|
packetqueue.clearQueue();
|
||||||
}
|
}
|
||||||
packetqueue.queuePacket(packet);
|
if ( packet.stream_index != mAudioStreamId || record_audio ) {
|
||||||
} // end if
|
Debug(3, "Queuing");
|
||||||
|
packetqueue.queuePacket( &packet );
|
||||||
|
}
|
||||||
|
} // end if recording or not
|
||||||
|
|
||||||
if ( packet->stream_index == mVideoStreamId ) {
|
if ( packet.stream_index == mVideoStreamId ) {
|
||||||
if ( videoStore ) {
|
if ( videoStore ) {
|
||||||
//Write the packet to our video store
|
//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
|
if ( ret < 0 ) { //Less than zero and we skipped a frame
|
||||||
zm_av_unref_packet( packet );
|
zm_av_unref_packet( &packet );
|
||||||
return 0;
|
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 ) {
|
if ( ret < 0 ) {
|
||||||
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
||||||
Error( "Unable to decode frame at frame %d: %s, continuing", frameCount, errbuf );
|
Error( "Unable to decode frame at frame %d: %s, continuing", frameCount, errbuf );
|
||||||
zm_av_unref_packet( packet );
|
zm_av_unref_packet( &packet );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -688,7 +700,7 @@ Debug(5, "After av_read_frame (%d)", ret );
|
||||||
directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
|
directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
|
||||||
if ( directbuffer == NULL ) {
|
if ( directbuffer == NULL ) {
|
||||||
Error("Failed requesting writeable buffer for the captured image.");
|
Error("Failed requesting writeable buffer for the captured image.");
|
||||||
zm_av_unref_packet( packet );
|
zm_av_unref_packet( &packet );
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height);
|
avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height);
|
||||||
|
@ -717,16 +729,16 @@ Debug(5, "After av_read_frame (%d)", ret );
|
||||||
} else {
|
} else {
|
||||||
Debug( 3, "Not framecomplete after av_read_frame" );
|
Debug( 3, "Not framecomplete after av_read_frame" );
|
||||||
} // end if frameComplete
|
} // end if frameComplete
|
||||||
} else if ( packet->stream_index == mAudioStreamId ) { //FIXME best way to copy all other streams
|
} else if ( packet.stream_index == mAudioStreamId ) { //FIXME best way to copy all other streams
|
||||||
Debug( 4, "Audio stream index %d", packet->stream_index );
|
|
||||||
if ( videoStore ) {
|
if ( videoStore ) {
|
||||||
if ( record_audio ) {
|
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
|
//Write the packet to our video store
|
||||||
//FIXME no relevance of last key frame
|
//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
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -735,12 +747,16 @@ Debug(5, "After av_read_frame (%d)", ret );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#if LIBAVUTIL_VERSION_CHECK(54, 23, 0, 23, 0)
|
#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
|
#else
|
||||||
Debug( 3, "Some other stream index %d", packet->stream_index );
|
Debug( 3, "Some other stream index %d", packet.stream_index );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
zm_av_unref_packet( 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
|
} // end while ! frameComplete
|
||||||
return (frameCount);
|
return (frameCount);
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,11 @@ class FfmpegCamera : public Camera
|
||||||
AVFrame *mFrame;
|
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 OpenFfmpeg();
|
||||||
int ReopenFfmpeg();
|
int ReopenFfmpeg();
|
||||||
int CloseFfmpeg();
|
int CloseFfmpeg();
|
||||||
|
@ -67,11 +72,9 @@ class FfmpegCamera : public Camera
|
||||||
bool wasRecording;
|
bool wasRecording;
|
||||||
VideoStore *videoStore;
|
VideoStore *videoStore;
|
||||||
char oldDirectory[4096];
|
char oldDirectory[4096];
|
||||||
|
unsigned int old_event_id;
|
||||||
zm_packetqueue packetqueue;
|
zm_packetqueue packetqueue;
|
||||||
|
|
||||||
// Last Key frame
|
|
||||||
//AVPacket lastKeyframePkt;
|
|
||||||
|
|
||||||
#if HAVE_LIBSWSCALE
|
#if HAVE_LIBSWSCALE
|
||||||
struct SwsContext *mConvertContext;
|
struct SwsContext *mConvertContext;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -179,6 +179,12 @@ Image::~Image()
|
||||||
delete decodejpg_dcinfo;
|
delete decodejpg_dcinfo;
|
||||||
decodejpg_dcinfo = 0;
|
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()
|
void Image::Initialise()
|
||||||
|
|
|
@ -35,12 +35,19 @@ zm_packetqueue::~zm_packetqueue() {
|
||||||
|
|
||||||
bool zm_packetqueue::queuePacket( AVPacket* packet ) {
|
bool zm_packetqueue::queuePacket( AVPacket* packet ) {
|
||||||
|
|
||||||
//AVPacket *input_ref = (AVPacket *)av_malloc(sizeof(AVPacket));
|
AVPacket *input_ref = (AVPacket *)av_malloc(sizeof(AVPacket));
|
||||||
//if ( av_packet_ref( input_ref, packet ) < 0 ) {
|
av_init_packet( input_ref );
|
||||||
//free(input_ref);
|
if ( av_packet_ref( input_ref, packet ) < 0 ) {
|
||||||
//return false;
|
Error("error refing packet");
|
||||||
//}
|
av_free(input_ref);
|
||||||
pktQueue.push( packet );
|
return false;
|
||||||
|
} else {
|
||||||
|
Debug(3, "made a ref");
|
||||||
|
}
|
||||||
|
|
||||||
|
pktQueue.push( input_ref );
|
||||||
|
Debug(3, "queued");
|
||||||
|
//pktQueue.push( input_ref );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -64,5 +71,10 @@ void zm_packetqueue::clearQueue() {
|
||||||
pktQueue.pop();
|
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.
|
// 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 );
|
zm_av_unref_packet( packet );
|
||||||
|
av_free( packet );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int zm_packetqueue::size() {
|
||||||
|
return pktQueue.size();
|
||||||
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ public:
|
||||||
bool popVideoPacket(AVPacket* packet);
|
bool popVideoPacket(AVPacket* packet);
|
||||||
bool popAudioPacket(AVPacket* packet);
|
bool popAudioPacket(AVPacket* packet);
|
||||||
void clearQueue( );
|
void clearQueue( );
|
||||||
|
unsigned int size();
|
||||||
private:
|
private:
|
||||||
std::queue<AVPacket *> pktQueue;
|
std::queue<AVPacket *> pktQueue;
|
||||||
|
|
||||||
|
|
|
@ -523,7 +523,7 @@ int RemoteCameraRtsp::CaptureAndRecord(Image &image, bool recording, char* event
|
||||||
|
|
||||||
if ( videoStore ) {
|
if ( videoStore ) {
|
||||||
//Write the packet to our video store
|
//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
|
if ( ret < 0 ) {//Less than zero and we skipped a frame
|
||||||
// Should not
|
// Should not
|
||||||
av_free_packet( &packet );
|
av_free_packet( &packet );
|
||||||
|
@ -553,7 +553,7 @@ int RemoteCameraRtsp::CaptureAndRecord(Image &image, bool recording, char* event
|
||||||
if ( videoStore && record_audio ) {
|
if ( videoStore && record_audio ) {
|
||||||
Debug( 4, "Storing Audio packet" );
|
Debug( 4, "Storing Audio packet" );
|
||||||
//Write the packet to our video store
|
//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 ( ret < 0 ) { //Less than zero and we skipped a frame
|
||||||
#if LIBAVCODEC_VERSION_CHECK(57, 8, 0, 12, 100)
|
#if LIBAVCODEC_VERSION_CHECK(57, 8, 0, 12, 100)
|
||||||
av_packet_unref( &packet );
|
av_packet_unref( &packet );
|
||||||
|
|
|
@ -33,11 +33,15 @@ extern "C"{
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
||||||
AVStream *input_video_stream,
|
AVStream *p_video_input_stream,
|
||||||
AVStream *input_audio_stream,
|
AVStream *p_audio_input_stream,
|
||||||
int64_t nStartTime,
|
int64_t nStartTime,
|
||||||
Monitor::Orientation orientation
|
Monitor::Orientation orientation
|
||||||
) {
|
) {
|
||||||
|
video_input_stream = p_video_input_stream;
|
||||||
|
audio_input_stream = p_audio_input_stream;
|
||||||
|
|
||||||
|
video_input_context = video_input_context;
|
||||||
|
|
||||||
//store inputs in variables local to class
|
//store inputs in variables local to class
|
||||||
filename = filename_in;
|
filename = filename_in;
|
||||||
|
@ -60,6 +64,8 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
||||||
filename,
|
filename,
|
||||||
av_make_error_string(ret).c_str()
|
av_make_error_string(ret).c_str()
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
Debug(2, "Success alocateing output context");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Couldn't deduce format from filename, trying from format name
|
//Couldn't deduce format from filename, trying from format name
|
||||||
|
@ -70,6 +76,8 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
||||||
" could not be assigned based on filename or format %s",
|
" could not be assigned based on filename or format %s",
|
||||||
filename, format);
|
filename, format);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Debug(2, "Success alocateing output context");
|
||||||
}
|
}
|
||||||
|
|
||||||
AVDictionary *pmetadata = NULL;
|
AVDictionary *pmetadata = NULL;
|
||||||
|
@ -80,93 +88,140 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
||||||
|
|
||||||
output_format = oc->oformat;
|
output_format = oc->oformat;
|
||||||
|
|
||||||
video_stream = avformat_new_stream(oc, (AVCodec *)input_video_stream->codec->codec);
|
video_output_stream = avformat_new_stream(oc, video_input_context->codec);
|
||||||
if (!video_stream) {
|
if (!video_output_stream) {
|
||||||
Fatal("Unable to create video out stream\n");
|
Fatal("Unable to create video out stream\n");
|
||||||
|
} else {
|
||||||
|
Debug(2, "Success creating video out stream" );
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = avcodec_copy_context(video_stream->codec, input_video_stream->codec);
|
video_output_context = video_output_stream->codec;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
ret = avcodec_copy_context(video_output_context, video_input_context );
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
Fatal("Unable to copy input video context to output video context %s\n",
|
Fatal("Unable to copy input video context to output video context %s\n",
|
||||||
av_make_error_string(ret).c_str());
|
av_make_error_string(ret).c_str());
|
||||||
|
} else {
|
||||||
|
Debug(3, "Success copying context" );
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
Debug(2, "getting parameters");
|
||||||
|
ret = avcodec_parameters_from_context( video_output_stream->codecpar, video_output_context );
|
||||||
|
if ( ret < 0 ) {
|
||||||
|
Error( "Could not initialize stream parameteres");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
Debug(2, "Success getting parameters");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( input_video_stream->codec->sample_aspect_ratio.den && ( video_stream->sample_aspect_ratio.den != input_video_stream->codec->sample_aspect_ratio.den ) ) {
|
#endif
|
||||||
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;
|
|
||||||
|
Debug(3, "Time bases input stream time base(%d/%d) input codec tb: (%d/%d) video_output_stream->time-base(%d/%d) output codec tb (%d/%d)",
|
||||||
|
video_input_stream->time_base.num,
|
||||||
|
video_input_stream->time_base.den,
|
||||||
|
video_input_context->time_base.num,
|
||||||
|
video_input_context->time_base.den,
|
||||||
|
video_output_stream->time_base.num,
|
||||||
|
video_output_stream->time_base.den,
|
||||||
|
video_output_context->time_base.num,
|
||||||
|
video_output_context->time_base.den
|
||||||
|
);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if ( video_input_context->sample_aspect_ratio.den && ( video_output_stream->sample_aspect_ratio.den != video_input_context->sample_aspect_ratio.den ) ) {
|
||||||
|
Warning("Fixing sample_aspect_ratio.den from (%d) to (%d)", video_output_stream->sample_aspect_ratio.den, video_input_context->sample_aspect_ratio.den );
|
||||||
|
video_output_stream->sample_aspect_ratio.den = video_input_context->sample_aspect_ratio.den;
|
||||||
} else {
|
} else {
|
||||||
Debug(3, "aspect ratio denominator is (%d)", video_stream->sample_aspect_ratio.den );
|
Debug(3, "aspect ratio denominator is (%d)", video_output_stream->sample_aspect_ratio.den );
|
||||||
}
|
}
|
||||||
if ( input_video_stream->codec->sample_aspect_ratio.num && ( video_stream->sample_aspect_ratio.num != input_video_stream->codec->sample_aspect_ratio.num ) ) {
|
if ( video_input_context->sample_aspect_ratio.num && ( video_output_stream->sample_aspect_ratio.num != video_input_context->sample_aspect_ratio.num ) ) {
|
||||||
Warning("Fixing sample_aspect_ratio.num from video_stream(%d) to input_video_stream(%d)", video_stream->sample_aspect_ratio.num, input_video_stream->codec->sample_aspect_ratio.num );
|
Warning("Fixing sample_aspect_ratio.num from video_output_stream(%d) to video_input_stream(%d)", video_output_stream->sample_aspect_ratio.num, video_input_context->sample_aspect_ratio.num );
|
||||||
video_stream->sample_aspect_ratio.num = input_video_stream->codec->sample_aspect_ratio.num;
|
video_output_stream->sample_aspect_ratio.num = video_input_context->sample_aspect_ratio.num;
|
||||||
} else {
|
} else {
|
||||||
Debug(3, "aspect ratio numerator is (%d)", video_stream->sample_aspect_ratio.num );
|
Debug(3, "aspect ratio numerator is (%d)", video_output_stream->sample_aspect_ratio.num );
|
||||||
}
|
}
|
||||||
if ( video_stream->codec->codec_id != input_video_stream->codec->codec_id ) {
|
if ( video_output_context->codec_id != video_input_context->codec_id ) {
|
||||||
Warning("Fixing video_stream->codec->codec_id");
|
Warning("Fixing video_output_context->codec_id");
|
||||||
video_stream->codec->codec_id = input_video_stream->codec->codec_id;
|
video_output_context->codec_id = video_input_context->codec_id;
|
||||||
}
|
}
|
||||||
if ( ! video_stream->codec->time_base.num ) {
|
if ( ! video_output_context->time_base.num ) {
|
||||||
Warning("video_stream->codec->time_base.num is not set%d/%d. Fixing by setting it to 1", video_stream->codec->time_base.num, video_stream->codec->time_base.den);
|
Warning("video_output_context->time_base.num is not set%d/%d. Fixing by setting it to 1", video_output_context->time_base.num, video_output_context->time_base.den);
|
||||||
Warning("video_stream->codec->time_base.num is not set%d/%d. Fixing by setting it to 1", video_stream->time_base.num, video_stream->time_base.den);
|
Warning("video_output_context->time_base.num is not set%d/%d. Fixing by setting it to 1", video_output_stream->time_base.num, video_output_stream->time_base.den);
|
||||||
video_stream->codec->time_base.num = video_stream->time_base.num;
|
video_output_context->time_base.num = video_output_stream->time_base.num;
|
||||||
video_stream->codec->time_base.den = video_stream->time_base.den;
|
video_output_context->time_base.den = video_output_stream->time_base.den;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( video_stream->sample_aspect_ratio.den != video_stream->codec->sample_aspect_ratio.den ) {
|
if ( video_output_stream->sample_aspect_ratio.den != video_output_context->sample_aspect_ratio.den ) {
|
||||||
Warning("Fixingample_aspect_ratio.den");
|
Warning("Fixingample_aspect_ratio.den");
|
||||||
video_stream->sample_aspect_ratio.den = video_stream->codec->sample_aspect_ratio.den;
|
video_output_stream->sample_aspect_ratio.den = video_output_context->sample_aspect_ratio.den;
|
||||||
}
|
}
|
||||||
if ( video_stream->sample_aspect_ratio.num != input_video_stream->codec->sample_aspect_ratio.num ) {
|
if ( video_output_stream->sample_aspect_ratio.num != video_input_context->sample_aspect_ratio.num ) {
|
||||||
Warning("Fixingample_aspect_ratio.num");
|
Warning("Fixingample_aspect_ratio.num");
|
||||||
video_stream->sample_aspect_ratio.num = input_video_stream->codec->sample_aspect_ratio.num;
|
video_output_stream->sample_aspect_ratio.num = video_input_context->sample_aspect_ratio.num;
|
||||||
}
|
}
|
||||||
if ( video_stream->codec->codec_id != input_video_stream->codec->codec_id ) {
|
if ( video_output_context->codec_id != video_input_context->codec_id ) {
|
||||||
Warning("Fixing video_stream->codec->codec_id");
|
Warning("Fixing video_output_context->codec_id");
|
||||||
video_stream->codec->codec_id = input_video_stream->codec->codec_id;
|
video_output_context->codec_id = video_input_context->codec_id;
|
||||||
|
}
|
||||||
|
if ( ! video_output_context->time_base.num ) {
|
||||||
|
Warning("video_output_context->time_base.num is not set%d/%d. Fixing by setting it to 1", video_output_context->time_base.num, video_output_context->time_base.den);
|
||||||
|
Warning("video_output_context->time_base.num is not set%d/%d. Fixing by setting it to 1", video_output_stream->time_base.num, video_output_stream->time_base.den);
|
||||||
|
video_output_context->time_base.num = video_output_stream->time_base.num;
|
||||||
|
video_output_context->time_base.den = video_output_stream->time_base.den;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// WHY?
|
||||||
|
//video_output_context->codec_tag = 0;
|
||||||
|
if (!video_output_context->codec_tag) {
|
||||||
|
Debug(2, "No codec_tag");
|
||||||
|
if (! oc->oformat->codec_tag
|
||||||
|
|| av_codec_get_id (oc->oformat->codec_tag, video_input_context->codec_tag) == video_output_context->codec_id
|
||||||
|
|| av_codec_get_tag(oc->oformat->codec_tag, video_input_context->codec_id) <= 0) {
|
||||||
|
Warning("Setting codec tag");
|
||||||
|
video_output_context->codec_tag = video_input_context->codec_tag;
|
||||||
}
|
}
|
||||||
if ( ! video_stream->codec->time_base.num ) {
|
|
||||||
Warning("video_stream->codec->time_base.num is not set%d/%d. Fixing by setting it to 1", video_stream->codec->time_base.num, video_stream->codec->time_base.den);
|
|
||||||
Warning("video_stream->codec->time_base.num is not set%d/%d. Fixing by setting it to 1", video_stream->time_base.num, video_stream->time_base.den);
|
|
||||||
video_stream->codec->time_base.num = video_stream->time_base.num;
|
|
||||||
video_stream->codec->time_base.den = video_stream->time_base.den;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
video_stream->codec->codec_tag = 0;
|
|
||||||
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
|
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
|
||||||
video_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
video_output_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( orientation ) {
|
if ( orientation ) {
|
||||||
if ( orientation == Monitor::ROTATE_0 ) {
|
if ( orientation == Monitor::ROTATE_0 ) {
|
||||||
|
|
||||||
} else if ( orientation == Monitor::ROTATE_90 ) {
|
} else if ( orientation == Monitor::ROTATE_90 ) {
|
||||||
dsr = av_dict_set( &video_stream->metadata, "rotate", "90", 0);
|
dsr = av_dict_set( &video_output_stream->metadata, "rotate", "90", 0);
|
||||||
if (dsr < 0) Warning("%s:%d: title set failed", __FILE__, __LINE__ );
|
if (dsr < 0) Warning("%s:%d: title set failed", __FILE__, __LINE__ );
|
||||||
} else if ( orientation == Monitor::ROTATE_180 ) {
|
} else if ( orientation == Monitor::ROTATE_180 ) {
|
||||||
dsr = av_dict_set( &video_stream->metadata, "rotate", "180", 0);
|
dsr = av_dict_set( &video_output_stream->metadata, "rotate", "180", 0);
|
||||||
if (dsr < 0) Warning("%s:%d: title set failed", __FILE__, __LINE__ );
|
if (dsr < 0) Warning("%s:%d: title set failed", __FILE__, __LINE__ );
|
||||||
} else if ( orientation == Monitor::ROTATE_270 ) {
|
} else if ( orientation == Monitor::ROTATE_270 ) {
|
||||||
dsr = av_dict_set( &video_stream->metadata, "rotate", "270", 0);
|
dsr = av_dict_set( &video_output_stream->metadata, "rotate", "270", 0);
|
||||||
if (dsr < 0) Warning("%s:%d: title set failed", __FILE__, __LINE__ );
|
if (dsr < 0) Warning("%s:%d: title set failed", __FILE__, __LINE__ );
|
||||||
} else {
|
} else {
|
||||||
Warning( "Unsupported Orientation(%d)", orientation );
|
Warning( "Unsupported Orientation(%d)", orientation );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
audio_output_codec = NULL;
|
audio_output_codec = NULL;
|
||||||
|
audio_input_context = NULL;
|
||||||
|
|
||||||
if (input_audio_stream) {
|
if (audio_input_stream) {
|
||||||
|
audio_input_context = audio_input_stream->codec;
|
||||||
|
|
||||||
if ( input_audio_stream->codec->codec_id != AV_CODEC_ID_AAC ) {
|
if ( audio_input_context->codec_id != AV_CODEC_ID_AAC ) {
|
||||||
Warning("Can't transcode to AAC at this time");
|
Warning("Can't transcode to AAC at this time");
|
||||||
audio_stream = NULL;
|
audio_output_stream = NULL;
|
||||||
|
|
||||||
audio_output_codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
|
audio_output_codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
|
||||||
if ( audio_output_codec ) {
|
if ( audio_output_codec ) {
|
||||||
audio_stream = avformat_new_stream(oc, audio_output_codec );
|
audio_output_stream = avformat_new_stream(oc, audio_output_codec );
|
||||||
|
|
||||||
audio_output_context = audio_stream->codec;
|
audio_output_context = audio_output_stream->codec;
|
||||||
|
|
||||||
//audio_output_context = avcodec_alloc_context3( audio_output_codec );
|
//audio_output_context = avcodec_alloc_context3( audio_output_codec );
|
||||||
if ( audio_output_context ) {
|
if ( audio_output_context ) {
|
||||||
|
@ -176,11 +231,11 @@ Debug(2, "Have audio_output_context");
|
||||||
av_dict_set(&opts, "strict", "experimental", 0);
|
av_dict_set(&opts, "strict", "experimental", 0);
|
||||||
|
|
||||||
/* put sample parameters */
|
/* put sample parameters */
|
||||||
audio_output_context->bit_rate = input_audio_stream->codec->bit_rate;
|
audio_output_context->bit_rate = audio_input_context->bit_rate;
|
||||||
audio_output_context->sample_rate = input_audio_stream->codec->sample_rate;
|
audio_output_context->sample_rate = audio_input_context->sample_rate;
|
||||||
audio_output_context->channels = input_audio_stream->codec->channels;
|
audio_output_context->channels = audio_input_context->channels;
|
||||||
audio_output_context->channel_layout = input_audio_stream->codec->channel_layout;
|
audio_output_context->channel_layout = audio_input_context->channel_layout;
|
||||||
audio_output_context->sample_fmt = input_audio_stream->codec->sample_fmt;
|
audio_output_context->sample_fmt = audio_input_context->sample_fmt;
|
||||||
|
|
||||||
/* check that the encoder supports s16 pcm input */
|
/* check that the encoder supports s16 pcm input */
|
||||||
if (!check_sample_fmt( audio_output_codec, audio_output_context->sample_fmt)) {
|
if (!check_sample_fmt( audio_output_codec, audio_output_context->sample_fmt)) {
|
||||||
|
@ -198,20 +253,23 @@ Debug(2, "Have audio_output_context");
|
||||||
);
|
);
|
||||||
|
|
||||||
/** Set the sample rate for the container. */
|
/** Set the sample rate for the container. */
|
||||||
audio_stream->time_base.den = input_audio_stream->codec->sample_rate;
|
audio_output_stream->time_base.den = audio_input_context->sample_rate;
|
||||||
audio_stream->time_base.num = 1;
|
audio_output_stream->time_base.num = 1;
|
||||||
|
|
||||||
ret = avcodec_open2(audio_output_context, audio_output_codec, &opts );
|
ret = avcodec_open2(audio_output_context, audio_output_codec, &opts );
|
||||||
if ( ret < 0 ) {
|
if ( ret < 0 ) {
|
||||||
av_strerror(ret, error_buffer, sizeof(error_buffer));
|
av_strerror(ret, error_buffer, sizeof(error_buffer));
|
||||||
Fatal( "could not open codec (%d) (%s)\n", ret, error_buffer );
|
Fatal( "could not open codec (%d) (%s)\n", ret, error_buffer );
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
#if 0
|
||||||
/** Create the FIFO buffer based on the specified output sample format. */
|
/** Create the FIFO buffer based on the specified output sample format. */
|
||||||
if (!(fifo = av_audio_fifo_alloc(audio_output_context->sample_fmt,
|
if (!(fifo = av_audio_fifo_alloc(audio_output_context->sample_fmt,
|
||||||
audio_output_context->channels, 1))) {
|
audio_output_context->channels, 1))) {
|
||||||
Error("Could not allocate FIFO\n");
|
Error("Could not allocate FIFO\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
output_frame_size = audio_output_context->frame_size;
|
output_frame_size = audio_output_context->frame_size;
|
||||||
Debug(2, "Success opening AAC codec");
|
Debug(2, "Success opening AAC codec");
|
||||||
}
|
}
|
||||||
|
@ -224,29 +282,29 @@ Debug(2, "Have audio_output_context");
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Debug(3, "Got something other than AAC (%d)", input_audio_stream->codec->codec_id );
|
Debug(3, "Got something other than AAC (%d)", audio_input_context->codec_id );
|
||||||
|
|
||||||
audio_stream = avformat_new_stream(oc, (AVCodec *)input_audio_stream->codec->codec);
|
audio_output_stream = avformat_new_stream(oc, (AVCodec *)audio_input_context->codec);
|
||||||
if (!audio_stream) {
|
if (!audio_output_stream) {
|
||||||
Error("Unable to create audio out stream\n");
|
Error("Unable to create audio out stream\n");
|
||||||
audio_stream = NULL;
|
audio_output_stream = NULL;
|
||||||
}
|
}
|
||||||
ret = avcodec_copy_context(audio_stream->codec, input_audio_stream->codec);
|
ret = avcodec_copy_context(audio_output_context, audio_input_context);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
Fatal("Unable to copy audio context %s\n", av_make_error_string(ret).c_str());
|
Fatal("Unable to copy audio context %s\n", av_make_error_string(ret).c_str());
|
||||||
}
|
}
|
||||||
audio_stream->codec->codec_tag = 0;
|
audio_output_context->codec_tag = 0;
|
||||||
if ( audio_stream->codec->channels > 1 ) {
|
if ( audio_output_context->channels > 1 ) {
|
||||||
Warning("Audio isn't mono, changing it.");
|
Warning("Audio isn't mono, changing it.");
|
||||||
audio_stream->codec->channels = 1;
|
audio_output_context->channels = 1;
|
||||||
}
|
}
|
||||||
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
|
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
|
||||||
audio_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
audio_output_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||||
}
|
}
|
||||||
} // end if is AAC
|
} // end if is AAC
|
||||||
} else {
|
} else {
|
||||||
Debug(3, "No Audio output stream");
|
Debug(3, "No Audio output stream");
|
||||||
audio_stream = NULL;
|
audio_output_stream = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* open the output file, if needed */
|
/* open the output file, if needed */
|
||||||
|
@ -269,7 +327,7 @@ Debug(2, "Have audio_output_context");
|
||||||
ret = avformat_write_header(oc, NULL);
|
ret = avformat_write_header(oc, NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
zm_dump_stream_format( oc, 0, 0, 1 );
|
zm_dump_stream_format( oc, 0, 0, 1 );
|
||||||
if ( audio_stream )
|
if ( audio_output_stream )
|
||||||
zm_dump_stream_format( oc, 1, 0, 1 );
|
zm_dump_stream_format( oc, 1, 0, 1 );
|
||||||
Error("Error occurred when writing output file header to %s: %s\n",
|
Error("Error occurred when writing output file header to %s: %s\n",
|
||||||
filename,
|
filename,
|
||||||
|
@ -277,12 +335,16 @@ Debug(2, "Have audio_output_context");
|
||||||
}
|
}
|
||||||
|
|
||||||
prevDts = 0;
|
prevDts = 0;
|
||||||
startPts = 0;
|
video_start_pts = 0;
|
||||||
startDts = 0;
|
video_start_dts = 0;
|
||||||
|
audio_start_pts = 0;
|
||||||
|
audio_start_dts = 0;
|
||||||
|
|
||||||
filter_in_rescale_delta_last = AV_NOPTS_VALUE;
|
filter_in_rescale_delta_last = AV_NOPTS_VALUE;
|
||||||
|
|
||||||
startTime=av_gettime()-nStartTime;//oc->start_time;
|
// now - when streaming started
|
||||||
Info("VideoStore startTime=%d\n",startTime);
|
//startTime=av_gettime()-nStartTime;//oc->start_time;
|
||||||
|
//Info("VideoStore startTime=%d\n",startTime);
|
||||||
} // VideoStore::VideoStore
|
} // VideoStore::VideoStore
|
||||||
|
|
||||||
|
|
||||||
|
@ -297,11 +359,11 @@ VideoStore::~VideoStore(){
|
||||||
// I wonder if we should be closing the file first.
|
// I wonder if we should be closing the file first.
|
||||||
// I also wonder if we really need to be doing all the context allocation/de-allocation constantly, or whether we can just re-use it. Just do a file open/close/writeheader/etc.
|
// I also wonder if we really need to be doing all the context allocation/de-allocation constantly, or whether we can just re-use it. Just do a file open/close/writeheader/etc.
|
||||||
// What if we were only doing audio recording?
|
// What if we were only doing audio recording?
|
||||||
if ( video_stream ) {
|
if ( video_output_stream ) {
|
||||||
avcodec_close(video_stream->codec);
|
avcodec_close(video_output_context);
|
||||||
}
|
}
|
||||||
if (audio_stream) {
|
if (audio_output_stream) {
|
||||||
avcodec_close(audio_stream->codec);
|
avcodec_close(audio_output_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
// WHen will be not using a file ?
|
// WHen will be not using a file ?
|
||||||
|
@ -330,63 +392,85 @@ void VideoStore::dumpPacket( AVPacket *pkt ){
|
||||||
, pkt->stream_index
|
, pkt->stream_index
|
||||||
, pkt->flags
|
, pkt->flags
|
||||||
, pkt->pos
|
, pkt->pos
|
||||||
, pkt->convergence_duration
|
, pkt->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){
|
int VideoStore::writeVideoFramePacket( AVPacket *ipkt ) {
|
||||||
|
|
||||||
Debug(4, "writeVideoFrame");
|
|
||||||
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 );
|
|
||||||
|
|
||||||
AVPacket opkt;
|
AVPacket opkt;
|
||||||
AVPicture pict;
|
AVPicture pict;
|
||||||
|
|
||||||
Debug(2, "writeVideoFrame init_packet");
|
Debug(4, "writeVideoFrame init_packet");
|
||||||
av_init_packet(&opkt);
|
av_init_packet(&opkt);
|
||||||
|
|
||||||
|
if ( 1 ) {
|
||||||
//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) {
|
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;
|
if ( ! video_start_pts ) {
|
||||||
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 );
|
//never gets set, so the first packet can set it.
|
||||||
|
video_start_pts = ipkt->pts;
|
||||||
|
}
|
||||||
|
opkt.pts = av_rescale_q(ipkt->pts - video_start_pts, video_input_stream->time_base, video_output_stream->time_base);
|
||||||
|
//- ost_tb_start_time;
|
||||||
|
Debug(3, "opkt.pts = %d from ipkt->pts(%d) - startPts(%d)", opkt.pts, ipkt->pts, video_start_pts );
|
||||||
} else {
|
} else {
|
||||||
|
Debug(3, "opkt.pts = undef");
|
||||||
opkt.pts = AV_NOPTS_VALUE;
|
opkt.pts = AV_NOPTS_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Scale the DTS of the outgoing packet to be the correct time base
|
//Scale the DTS of the outgoing packet to be the correct time base
|
||||||
if(ipkt->dts == AV_NOPTS_VALUE) {
|
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);
|
// why are we using cur_dts instead of packet.dts?
|
||||||
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 );
|
if ( ! video_start_dts ) video_start_dts = video_input_stream->cur_dts;
|
||||||
|
opkt.dts = av_rescale_q(video_input_stream->cur_dts - video_start_dts, AV_TIME_BASE_Q, video_output_stream->time_base);
|
||||||
|
Debug(3, "opkt.dts = %d from video_input_stream->cur_dts(%d) - startDts(%d)",
|
||||||
|
opkt.dts, video_input_stream->cur_dts, video_start_dts
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
opkt.dts = av_rescale_q(ipkt->dts-startDts, input_video_stream->time_base, video_stream->time_base);
|
if ( ! video_start_dts ) video_start_dts = ipkt->dts;
|
||||||
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 = av_rescale_q(ipkt->dts - video_start_dts, video_input_stream->time_base, video_output_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 ) {
|
||||||
|
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, video_input_stream->time_base, video_output_stream->time_base);
|
||||||
|
} else {
|
||||||
opkt.duration = av_rescale_q(ipkt->duration, input_video_stream->time_base, video_stream->time_base);
|
av_packet_rescale_ts( &opkt, video_input_stream->time_base, video_output_stream->time_base );
|
||||||
|
}
|
||||||
opkt.flags = ipkt->flags;
|
opkt.flags = ipkt->flags;
|
||||||
opkt.pos=-1;
|
opkt.pos=-1;
|
||||||
|
|
||||||
opkt.data = ipkt->data;
|
opkt.data = ipkt->data;
|
||||||
opkt.size = ipkt->size;
|
opkt.size = ipkt->size;
|
||||||
|
|
||||||
|
// 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_output_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.stream_index = ipkt->stream_index;
|
||||||
|
}
|
||||||
|
|
||||||
/*opkt.flags |= AV_PKT_FLAG_KEY;*/
|
/*opkt.flags |= AV_PKT_FLAG_KEY;*/
|
||||||
|
|
||||||
if (video_stream->codec->codec_type == AVMEDIA_TYPE_VIDEO && (output_format->flags & AVFMT_RAWPICTURE)) {
|
#if 0
|
||||||
|
if (video_output_context->codec_type == AVMEDIA_TYPE_VIDEO && (output_format->flags & AVFMT_RAWPICTURE)) {
|
||||||
Debug(3, "video and RAWPICTURE");
|
Debug(3, "video and RAWPICTURE");
|
||||||
/* store AVPicture in AVPacket, as expected by the output format */
|
/* store AVPicture in AVPacket, as expected by the output format */
|
||||||
avpicture_fill(&pict, opkt.data, video_stream->codec->pix_fmt, video_stream->codec->width, video_stream->codec->height);
|
avpicture_fill(&pict, opkt.data, video_output_context->pix_fmt, video_output_context->width, video_output_context->height, 0);
|
||||||
|
av_image_fill_arrays(
|
||||||
opkt.data = (uint8_t *)&pict;
|
opkt.data = (uint8_t *)&pict;
|
||||||
opkt.size = sizeof(AVPicture);
|
opkt.size = sizeof(AVPicture);
|
||||||
opkt.flags |= AV_PKT_FLAG_KEY;
|
opkt.flags |= AV_PKT_FLAG_KEY;
|
||||||
} else {
|
} else {
|
||||||
Debug(3, "Not video and RAWPICTURE");
|
Debug(4, "Not video and RAWPICTURE");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//memcpy(&safepkt, &opkt, sizeof(AVPacket));
|
//memcpy(&safepkt, &opkt, sizeof(AVPacket));
|
||||||
|
|
||||||
|
@ -404,6 +488,7 @@ Debug(3, "Not video and RAWPICTURE");
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
prevDts = opkt.dts; // Unsure if av_interleaved_write_frame() clobbers opkt.dts when out of order, so storing in advance
|
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);
|
ret = av_interleaved_write_frame(oc, &opkt);
|
||||||
if(ret<0){
|
if(ret<0){
|
||||||
// There's nothing we can really do if the frame is rejected, just drop it and get on with the next
|
// There's nothing we can really do if the frame is rejected, just drop it and get on with the next
|
||||||
|
@ -418,11 +503,11 @@ Debug(3, "Not video and RAWPICTURE");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int VideoStore::writeAudioFramePacket(AVPacket *ipkt, AVStream *input_audio_stream){
|
int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
|
||||||
Debug(2, "writeAudioFrame");
|
Debug(4, "writeAudioFrame");
|
||||||
|
|
||||||
if(!audio_stream) {
|
if(!audio_output_stream) {
|
||||||
Error("Called writeAudioFramePacket when no audio_stream");
|
Error("Called writeAudioFramePacket when no audio_output_stream");
|
||||||
return 0;//FIXME -ve return codes do not free packet in ffmpeg_camera at the moment
|
return 0;//FIXME -ve return codes do not free packet in ffmpeg_camera at the moment
|
||||||
}
|
}
|
||||||
/*if(!keyframeMessage)
|
/*if(!keyframeMessage)
|
||||||
|
@ -430,8 +515,6 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt, AVStream *input_audio_stre
|
||||||
//zm_dump_stream_format( oc, ipkt->stream_index, 0, 1 );
|
//zm_dump_stream_format( oc, ipkt->stream_index, 0, 1 );
|
||||||
|
|
||||||
int ret;
|
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;
|
AVPacket opkt;
|
||||||
|
|
||||||
|
@ -440,61 +523,45 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt, AVStream *input_audio_stre
|
||||||
|
|
||||||
//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) {
|
if (ipkt->pts != AV_NOPTS_VALUE) {
|
||||||
Debug(2, "Rescaling output pts");
|
if ( ! audio_start_pts ) {
|
||||||
opkt.pts = av_rescale_q(ipkt->pts-startPts, input_audio_stream->time_base, audio_stream->time_base) - ost_tb_start_time;
|
//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, audio_input_stream->time_base, audio_output_stream->time_base);
|
||||||
|
Debug(3, "opkt.pts = %d from ipkt->pts(%d) - startPts(%d)", opkt.pts, ipkt->pts, audio_start_pts );
|
||||||
} else {
|
} else {
|
||||||
Debug(2, "Setting output pts to AV_NOPTS_VALUE");
|
Debug(3, "opkt.pts = undef");
|
||||||
opkt.pts = AV_NOPTS_VALUE;
|
opkt.pts = AV_NOPTS_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Scale the DTS of the outgoing packet to be the correct time base
|
//Scale the DTS of the outgoing packet to be the correct time base
|
||||||
if(ipkt->dts == AV_NOPTS_VALUE) {
|
if(ipkt->dts == AV_NOPTS_VALUE) {
|
||||||
Debug(2, "ipkt->dts == AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts );
|
if ( ! audio_start_dts ) audio_start_dts = video_input_stream->cur_dts;
|
||||||
opkt.dts = av_rescale_q(input_audio_stream->cur_dts-startDts, AV_TIME_BASE_Q, audio_stream->time_base);
|
opkt.dts = av_rescale_q(video_input_stream->cur_dts - audio_start_dts, AV_TIME_BASE_Q, audio_output_stream->time_base);
|
||||||
Debug(2, "ipkt->dts == AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts );
|
Debug(3, "opkt.dts = %d from video_input_stream->cur_dts(%d) - startDts(%d)",
|
||||||
|
opkt.dts, audio_input_stream->cur_dts, audio_start_dts
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
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-startDts, input_audio_stream->time_base, audio_stream->time_base);
|
opkt.dts = av_rescale_q(ipkt->dts - audio_start_dts, audio_input_stream->time_base, audio_output_stream->time_base);
|
||||||
Debug(2, "ipkt->dts != AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts );
|
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 );
|
if ( opkt.dts > opkt.pts ) {
|
||||||
opkt.dts -= ost_tb_start_time;
|
Debug(1,"opkt.dts(%d) must be <= opkt.pts(%d). Decompression must happen before presentation.", opkt.dts, opkt.pts );
|
||||||
|
opkt.dts = opkt.pts;
|
||||||
// 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
|
opkt.duration = av_rescale_q(ipkt->duration, audio_input_stream->time_base, audio_output_stream->time_base);
|
||||||
//FIXME av_rescale_delta doesn't exist in ubuntu vivid libavtools
|
// pkt.pos: byte position in stream, -1 if unknown
|
||||||
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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
opkt.duration = av_rescale_q(ipkt->duration, input_audio_stream->time_base, audio_stream->time_base);
|
|
||||||
opkt.pos = -1;
|
opkt.pos = -1;
|
||||||
opkt.flags = ipkt->flags;
|
opkt.flags = ipkt->flags;
|
||||||
opkt.stream_index = ipkt->stream_index;
|
opkt.stream_index = ipkt->stream_index;
|
||||||
|
|
||||||
if ( audio_output_codec ) {
|
if ( audio_output_codec ) {
|
||||||
|
// we are transcoding
|
||||||
AVFrame *input_frame;
|
AVFrame *input_frame;
|
||||||
AVFrame *output_frame;
|
AVFrame *output_frame;
|
||||||
|
|
||||||
// Need to re-encode
|
|
||||||
if ( 0 ) {
|
|
||||||
//avcodec_send_packet( input_audio_stream->codec, ipkt);
|
|
||||||
//avcodec_receive_frame( input_audio_stream->codec, input_frame );
|
|
||||||
//avcodec_send_frame( audio_stream->codec, input_frame );
|
|
||||||
//
|
|
||||||
////avcodec_receive_packet( audio_stream->codec, &opkt );
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/** Create a new frame to store the audio samples. */
|
/** Create a new frame to store the audio samples. */
|
||||||
if (!(input_frame = zm_av_frame_alloc())) {
|
if (!(input_frame = zm_av_frame_alloc())) {
|
||||||
Error("Could not allocate input frame");
|
Error("Could not allocate input frame");
|
||||||
|
@ -504,13 +571,32 @@ if ( 0 ) {
|
||||||
Debug(2, "Got input frame alloc");
|
Debug(2, "Got input frame alloc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Create a new frame to store the audio samples. */
|
||||||
|
if (!(output_frame = zm_av_frame_alloc())) {
|
||||||
|
Error("Could not allocate output frame");
|
||||||
|
av_frame_free(&input_frame);
|
||||||
|
zm_av_unref_packet(&opkt);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
Debug(2, "Got output frame alloc");
|
||||||
|
}
|
||||||
|
// Need to re-encode
|
||||||
|
#if 1
|
||||||
|
avcodec_send_packet( audio_input_context, ipkt );
|
||||||
|
avcodec_receive_frame( audio_input_context, input_frame );
|
||||||
|
avcodec_send_frame( audio_output_context, input_frame );
|
||||||
|
//
|
||||||
|
avcodec_receive_packet( audio_output_context, &opkt );
|
||||||
|
#else
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode the audio frame stored in the packet.
|
* Decode the audio frame stored in the packet.
|
||||||
* The input audio stream decoder is used to do this.
|
* The input audio stream decoder is used to do this.
|
||||||
* If we are at the end of the file, pass an empty packet to the decoder
|
* If we are at the end of the file, pass an empty packet to the decoder
|
||||||
* to flush it.
|
* to flush it.
|
||||||
*/
|
*/
|
||||||
if ((ret = avcodec_decode_audio4(input_audio_stream->codec, input_frame,
|
if ((ret = avcodec_decode_audio4(audio_input_context, input_frame,
|
||||||
&data_present, ipkt)) < 0) {
|
&data_present, ipkt)) < 0) {
|
||||||
Error( "Could not decode frame (error '%s')\n",
|
Error( "Could not decode frame (error '%s')\n",
|
||||||
av_make_error_string(ret).c_str());
|
av_make_error_string(ret).c_str());
|
||||||
|
@ -549,6 +635,48 @@ av_make_error_string(ret).c_str() );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a resampler context for the conversion.
|
||||||
|
* Set the conversion parameters.
|
||||||
|
* Default channel layouts based on the number of channels
|
||||||
|
* are assumed for simplicity (they are sometimes not detected
|
||||||
|
* properly by the demuxer and/or decoder).
|
||||||
|
*/
|
||||||
|
*resample_context = swr_alloc_set_opts(NULL,
|
||||||
|
av_get_default_channel_layout(audio_output_context->channels),
|
||||||
|
audio_output_context->sample_fmt,
|
||||||
|
audio_output_context->sample_rate,
|
||||||
|
av_get_default_channel_layout( audio_input_context->channels),
|
||||||
|
audio_input_stream->sample_fmt,
|
||||||
|
audio_input_stream->sample_rate,
|
||||||
|
0, NULL);
|
||||||
|
if (!*resample_context) {
|
||||||
|
Error( "Could not allocate resample context\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Perform a sanity check so that the number of converted samples is
|
||||||
|
* not greater than the number of samples to be converted.
|
||||||
|
* If the sample rates differ, this case has to be handled differently
|
||||||
|
*/
|
||||||
|
av_assert0(audio_output_context->sample_rate == audio_input_context->sample_rate);
|
||||||
|
/** Open the resampler with the specified parameters. */
|
||||||
|
if ((ret = swr_init(*resample_context)) < 0) {
|
||||||
|
Error( "Could not open resample context\n");
|
||||||
|
swr_free(resample_context);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Convert the samples using the resampler. */
|
||||||
|
if ((error = swr_convert(resample_context,
|
||||||
|
converted_input_samples, frame_size,
|
||||||
|
input_data , frame_size)) < 0) {
|
||||||
|
fprintf(stderr, "Could not convert input samples (error '%s')\n",
|
||||||
|
get_error_text(error));
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if ((ret = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + frame_size)) < 0) {
|
if ((ret = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + frame_size)) < 0) {
|
||||||
Error( "Could not reallocate FIFO\n");
|
Error( "Could not reallocate FIFO\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -559,15 +687,6 @@ av_make_error_string(ret).c_str() );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Create a new frame to store the audio samples. */
|
|
||||||
if (!(output_frame = zm_av_frame_alloc())) {
|
|
||||||
Error("Could not allocate output frame");
|
|
||||||
av_frame_free(&input_frame);
|
|
||||||
zm_av_unref_packet(&opkt);
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
Debug(2, "Got output frame alloc");
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Set the frame's parameters, especially its size and format.
|
* Set the frame's parameters, especially its size and format.
|
||||||
* av_frame_get_buffer needs this to allocate memory for the
|
* av_frame_get_buffer needs this to allocate memory for the
|
||||||
|
@ -575,7 +694,7 @@ av_make_error_string(ret).c_str() );
|
||||||
* Default channel layouts based on the number of channels
|
* Default channel layouts based on the number of channels
|
||||||
* are assumed for simplicity.
|
* are assumed for simplicity.
|
||||||
*/
|
*/
|
||||||
output_frame->nb_samples = audio_stream->codec->frame_size;
|
output_frame->nb_samples = audio_output_context->frame_size;
|
||||||
output_frame->channel_layout = audio_output_context->channel_layout;
|
output_frame->channel_layout = audio_output_context->channel_layout;
|
||||||
output_frame->channels = audio_output_context->channels;
|
output_frame->channels = audio_output_context->channels;
|
||||||
output_frame->format = audio_output_context->sample_fmt;
|
output_frame->format = audio_output_context->sample_fmt;
|
||||||
|
@ -615,7 +734,7 @@ av_make_error_string(ret).c_str() );
|
||||||
} else {
|
} else {
|
||||||
Debug(2, "Not data present" );
|
Debug(2, "Not data present" );
|
||||||
} // end if data_present
|
} // end if data_present
|
||||||
}
|
#endif
|
||||||
} else {
|
} else {
|
||||||
opkt.data = ipkt->data;
|
opkt.data = ipkt->data;
|
||||||
opkt.size = ipkt->size;
|
opkt.size = ipkt->size;
|
||||||
|
|
|
@ -13,8 +13,15 @@ private:
|
||||||
|
|
||||||
AVOutputFormat *output_format;
|
AVOutputFormat *output_format;
|
||||||
AVFormatContext *oc;
|
AVFormatContext *oc;
|
||||||
AVStream *video_stream;
|
AVStream *video_output_stream;
|
||||||
AVStream *audio_stream;
|
AVStream *audio_output_stream;
|
||||||
|
AVCodecContext *video_output_context;
|
||||||
|
|
||||||
|
AVStream *video_input_stream;
|
||||||
|
AVStream *audio_input_stream;
|
||||||
|
|
||||||
|
AVCodecContext *video_input_context;
|
||||||
|
AVCodecContext *audio_input_context;
|
||||||
|
|
||||||
// The following are used when encoding the audio stream to AAC
|
// The following are used when encoding the audio stream to AAC
|
||||||
AVCodec *audio_output_codec;
|
AVCodec *audio_output_codec;
|
||||||
|
@ -29,33 +36,23 @@ private:
|
||||||
bool keyframeMessage;
|
bool keyframeMessage;
|
||||||
int keyframeSkipNumber;
|
int keyframeSkipNumber;
|
||||||
|
|
||||||
int64_t startTime;
|
int64_t video_start_pts;
|
||||||
int64_t startPts;
|
int64_t video_start_dts;
|
||||||
int64_t startDts;
|
int64_t audio_start_pts;
|
||||||
|
int64_t audio_start_dts;
|
||||||
|
|
||||||
int64_t prevDts;
|
int64_t prevDts;
|
||||||
int64_t filter_in_rescale_delta_last;
|
int64_t filter_in_rescale_delta_last;
|
||||||
|
|
||||||
public:
|
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(const char *filename_in, const char *format_in, AVStream *video_input_stream, AVStream *audio_input_stream, int64_t nStartTime, Monitor::Orientation p_orientation );
|
||||||
~VideoStore();
|
~VideoStore();
|
||||||
|
|
||||||
int writeVideoFramePacket(AVPacket *pkt, AVStream *input_st);//, AVPacket *lastKeyframePkt);
|
int writeVideoFramePacket( AVPacket *pkt );
|
||||||
int writeAudioFramePacket(AVPacket *pkt, AVStream *input_st);
|
int writeAudioFramePacket( AVPacket *pkt );
|
||||||
void dumpPacket( 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 //havelibav
|
||||||
#endif //zm_videostore_h
|
#endif //zm_videostore_h
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,10 @@ void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_
|
||||||
overload_frames = p_overload_frames;
|
overload_frames = p_overload_frames;
|
||||||
extend_alarm_frames = p_extend_alarm_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;
|
alarmed = false;
|
||||||
pixel_diff = 0;
|
pixel_diff = 0;
|
||||||
|
|
|
@ -171,7 +171,7 @@ private $control_fields = array(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public function getStreamSrc( $args, $querySep='&' ) {
|
public function getStreamSrc( $args, $querySep='&' ) {
|
||||||
if ( isset($this->{'ServerId'}) ) {
|
if ( isset($this->{'ServerId'}) and $this->{'ServerId'} ) {
|
||||||
$Server = new Server( $this->{'ServerId'} );
|
$Server = new Server( $this->{'ServerId'} );
|
||||||
$streamSrc = ZM_BASE_PROTOCOL.'://'.$Server->Hostname().ZM_PATH_ZMS;
|
$streamSrc = ZM_BASE_PROTOCOL.'://'.$Server->Hostname().ZM_PATH_ZMS;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -27,7 +27,14 @@ class Storage {
|
||||||
if ( isset( $this->{'Path'} ) and ( $this->{'Path'} != '' ) ) {
|
if ( isset( $this->{'Path'} ) and ( $this->{'Path'} != '' ) ) {
|
||||||
return $this->{'Path'};
|
return $this->{'Path'};
|
||||||
} else if ( ! isset($this->{'Id'}) ) {
|
} 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'};
|
return $this->{'Name'};
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,8 +39,6 @@ if ( !canView( 'Events' ) ) {
|
||||||
require_once('includes/Event.php');
|
require_once('includes/Event.php');
|
||||||
require_once('includes/Frame.php');
|
require_once('includes/Frame.php');
|
||||||
|
|
||||||
header( 'Content-type: image/jpeg' );
|
|
||||||
|
|
||||||
// Compatibility for PHP 5.4
|
// Compatibility for PHP 5.4
|
||||||
if (!function_exists('imagescale')) {
|
if (!function_exists('imagescale')) {
|
||||||
function imagescale($image, $new_width, $new_height = -1, $mode = 0) {
|
function imagescale($image, $new_width, $new_height = -1, $mode = 0) {
|
||||||
|
@ -85,6 +83,10 @@ if ( empty($_REQUEST['path']) ) {
|
||||||
$retval = 0;
|
$retval = 0;
|
||||||
exec( $command, $output, $retval );
|
exec( $command, $output, $retval );
|
||||||
Debug("Retval: $retval, output: " . implode("\n", $output));
|
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 {
|
} else {
|
||||||
header("HTTP/1.0 404 Not Found");
|
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() );
|
Fatal("Can't create frame images from video becuase there is no video file for this event (".$Event->DefaultVideo() );
|
||||||
|
@ -138,6 +140,10 @@ if( !empty($_REQUEST['height']) ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
header( 'Content-type: image/jpeg' );
|
||||||
|
ob_clean();
|
||||||
|
flush();
|
||||||
|
|
||||||
if ( $errorText ) {
|
if ( $errorText ) {
|
||||||
Error( $errorText );
|
Error( $errorText );
|
||||||
} else {
|
} else {
|
||||||
|
@ -167,13 +173,8 @@ if ( $errorText ) {
|
||||||
|
|
||||||
# Slight optimisation, thumbnails always specify width and height, so we can cache them.
|
# Slight optimisation, thumbnails always specify width and height, so we can cache them.
|
||||||
$scaled_path = preg_replace('/\.jpg$/', "-${width}x${height}.jpg", $path );
|
$scaled_path = preg_replace('/\.jpg$/', "-${width}x${height}.jpg", $path );
|
||||||
if ( file_exists( $scaled_path ) ) {
|
if ( ! file_exists( $scaled_path ) or ! readfile( $scaled_path ) ) {
|
||||||
Debug( "Using cached scaled image at $scaled_path.");
|
Debug( "Cached scaled image does not exist at $scaled_path or is no good.. Creating it");
|
||||||
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");
|
|
||||||
ob_start();
|
ob_start();
|
||||||
if ( ! $i )
|
if ( ! $i )
|
||||||
$i = imagecreatefromjpeg( $path );
|
$i = imagecreatefromjpeg( $path );
|
||||||
|
@ -188,4 +189,3 @@ if ( $errorText ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
|
||||||
|
|
|
@ -85,6 +85,10 @@ header("Content-Range: bytes $begin-$end/$size");
|
||||||
header("Content-Transfer-Encoding: binary\n");
|
header("Content-Transfer-Encoding: binary\n");
|
||||||
header('Connection: close');
|
header('Connection: close');
|
||||||
|
|
||||||
|
// Apparently without these we get a few extra bytes of output at the end...
|
||||||
|
ob_clean();
|
||||||
|
flush();
|
||||||
|
|
||||||
$cur = $begin;
|
$cur = $begin;
|
||||||
fseek( $fh, $begin, 0 );
|
fseek( $fh, $begin, 0 );
|
||||||
|
|
||||||
|
@ -94,5 +98,3 @@ while( ! feof( $fh ) && $cur < $end && ( connection_status() == 0 ) ) {
|
||||||
$cur += 1024*16;
|
$cur += 1024*16;
|
||||||
usleep(100);
|
usleep(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
|
||||||
|
|
Loading…
Reference in New Issue