Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from connortechnology/monitor_packetqueue
Browse files Browse the repository at this point in the history
Monitor packetqueue
SteveGilvarry authored Sep 10, 2016
2 parents 34a85ba + dea094a commit 7c88ed8
Showing 8 changed files with 83 additions and 62 deletions.
5 changes: 5 additions & 0 deletions src/zm_camera.cpp
Original file line number Diff line number Diff line change
@@ -55,3 +55,8 @@ Monitor *Camera::getMonitor() {
monitor = Monitor::Load( monitor_id, false, Monitor::QUERY );
return monitor;
}

void Camera::setMonitor( Monitor *p_monitor ) {
monitor = p_monitor;
monitor_id = monitor->Id();
}
1 change: 1 addition & 0 deletions src/zm_camera.h
Original file line number Diff line number Diff line change
@@ -60,6 +60,7 @@ class Camera

unsigned int getId() const { return( monitor_id ); }
Monitor *getMonitor();
void setMonitor( Monitor *p_monitor );
SourceType Type() const { return( type ); }
bool IsLocal() const { return( type == LOCAL_SRC ); }
bool IsRemote() const { return( type == REMOTE_SRC ); }
5 changes: 5 additions & 0 deletions src/zm_ffmpeg.h
Original file line number Diff line number Diff line change
@@ -314,5 +314,10 @@ 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)
#define zm_av_unref_packet( packet ) av_unref_packet( packet )
#else
#define zm_av_unref_packet( packet ) av_free_packet( packet )
#endif

#endif // ZM_FFMPEG_H
78 changes: 37 additions & 41 deletions src/zm_ffmpeg_camera.cpp
Original file line number Diff line number Diff line change
@@ -223,11 +223,7 @@ int FfmpegCamera::Capture( Image &image )
} else {
Debug( 4, "Different stream_index %d", packet.stream_index );
} // end if packet.stream_index == mVideoStreamId
#if LIBAVCODEC_VERSION_CHECK(57, 8, 0, 12, 100)
av_packet_unref( &packet);
#else
av_free_packet( &packet );
#endif
zm_av_unref_packet( &packet );
} // end while ! frameComplete
return (0);
} // FfmpegCamera::Capture
@@ -551,16 +547,17 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
mReopenThread = 0;
}

AVPacket packet;
AVPacket queued_packet;

if (mVideoCodecContext->codec_id != AV_CODEC_ID_H264) {
Error( "Input stream is not h264. The stored event file may not be viewable in browser." );
}

int frameComplete = false;
while ( !frameComplete ) {
int avResult = av_read_frame( mFormatContext, &packet );
// 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);
int avResult = av_read_frame( mFormatContext, packet );
if ( avResult < 0 ) {
char errbuf[AV_ERROR_MAX_STRING_SIZE];
av_strerror(avResult, errbuf, AV_ERROR_MAX_STRING_SIZE);
@@ -574,18 +571,18 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
ReopenFfmpeg();
}

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 );
}
Debug( 5, "Got packet from stream %d", packet.stream_index );
Debug( 5, "Got packet from stream %d", packet->stream_index );

//Video recording
if ( 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");
@@ -625,24 +622,32 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi

// Need to write out all the frames from the last keyframe?
unsigned int packet_count = 0;
while ( packetqueue.popPacket( &queued_packet ) ) {
AVPacket *queued_packet;
while ( ( queued_packet = packetqueue.popPacket() ) ) {
packet_count += 1;
//Write the packet to our video store
if ( queued_packet.stream_index == mVideoStreamId ) {
ret = videoStore->writeVideoFramePacket(&queued_packet, mFormatContext->streams[mVideoStreamId]);
} else if ( queued_packet.stream_index == mAudioStreamId ) {
if ( queued_packet->stream_index == mVideoStreamId ) {
ret = videoStore->writeVideoFramePacket( queued_packet, mFormatContext->streams[mVideoStreamId]);
} else if ( queued_packet->stream_index == mAudioStreamId ) {
//ret = videoStore->writeAudioFramePacket(&queued_packet, mFormatContext->streams[mAudioStreamId]);
} 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;
}
if ( ret < 0 ) {
//Less than zero and we skipped a frame
//av_free_packet( &queued_packet );
}
zm_av_unref_packet( queued_packet );
} // end while packets in the packetqueue
Debug(2, "Wrote %d queued packets", packet_count );
} // end if ! wasRecording

//Write the packet to our video store
int ret = videoStore->writeVideoFramePacket( packet, mFormatContext->streams[mVideoStreamId] );
if ( ret < 0 ) { //Less than zero and we skipped a frame
zm_av_unref_packet( packet );
return 0;
}
} else {
if ( videoStore ) {
Info("Deleting videoStore instance");
@@ -651,17 +656,17 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
}

//Buffer video packets
if ( packet.flags & AV_PKT_FLAG_KEY ) {
if ( packet->flags & AV_PKT_FLAG_KEY ) {
packetqueue.clearQueue();
}
packetqueue.queuePacket(&packet);
packetqueue.queuePacket(packet);
} // end if

if ( packet.stream_index == mVideoStreamId ) {
if ( packet->stream_index == mVideoStreamId ) {
#if LIBAVCODEC_VERSION_CHECK(52, 23, 0, 23, 0)
if (avcodec_decode_video2(mVideoCodecContext, mRawFrame, &frameComplete, &packet) < 0)
if (avcodec_decode_video2(mVideoCodecContext, mRawFrame, &frameComplete, packet) < 0)
#else
if (avcodec_decode_video(mVideoCodecContext, mRawFrame, &frameComplete, packet.data, packet.size) < 0)
if (avcodec_decode_video(mVideoCodecContext, mRawFrame, &frameComplete, packet->data, packet->size) < 0)
#endif
Fatal( "Unable to decode frame at frame %d", frameCount );

@@ -674,22 +679,13 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi

/* Request a writeable buffer of the target image */
directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
if( directbuffer == NULL ) {
if ( directbuffer == NULL ) {
Error("Failed requesting writeable buffer for the captured image.");
av_free_packet( &packet );
zm_av_unref_packet( packet );
return (-1);
}
avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height);

if ( videoStore && recording ) {
//Write the packet to our video store
int ret = videoStore->writeVideoFramePacket(&packet, mFormatContext->streams[mVideoStreamId]);//, &lastKeyframePkt);
if ( ret < 0 ) { //Less than zero and we skipped a frame
av_free_packet( &packet );
return 0;
}
}

#if HAVE_LIBSWSCALE
if ( mConvertContext == NULL ) {
mConvertContext = sws_getContext(mVideoCodecContext->width,
@@ -714,16 +710,16 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
} 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
Debug( 4, "Audio stream index %d", packet->stream_index );
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, mFormatContext->streams[packet->stream_index] );
if ( ret < 0 ) {//Less than zero and we skipped a frame
av_free_packet( &packet );
zm_av_unref_packet( packet );
return 0;
}
} else {
@@ -732,12 +728,12 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
}
} 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
}
av_free_packet( &packet );
zm_av_unref_packet( packet );
} // end while ! frameComplete
return (frameCount);
}
13 changes: 10 additions & 3 deletions src/zm_monitor.cpp
Original file line number Diff line number Diff line change
@@ -462,8 +462,8 @@ Monitor::Monitor(
}

// Will this not happen every time a monitor is instantiated? Seems like all the calls to the Monitor constructor pass a zero for n_zones, then load zones after..
// In my storage areas branch, I took this out.. and didn't notice any problems.
if ( !n_zones ) {
// In my storage areas branch, I took this out.. and didn't notice any problems.
if ( false && !n_zones ) {
Debug( 1, "Monitor %s has no zones, adding one.", name );
n_zones = 1;
zones = new Zone *[1];
@@ -2254,10 +2254,11 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
track_motion,
signal_check_colour,
embed_exif,
purpose,
purpose,
0,
0
);
camera->setMonitor( monitors[i] );
Zone **zones = 0;
int n_zones = Zone::Load( monitors[i], zones );
monitors[i]->AddZones( n_zones, zones );
@@ -2446,6 +2447,7 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
0

);
camera->setMonitor( monitors[i] );
Zone **zones = 0;
int n_zones = Zone::Load( monitors[i], zones );
monitors[i]->AddZones( n_zones, zones );
@@ -2596,6 +2598,7 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu
0,
0
);
camera->setMonitor( monitors[i] );
Zone **zones = 0;
int n_zones = Zone::Load( monitors[i], zones );
monitors[i]->AddZones( n_zones, zones );
@@ -2751,6 +2754,8 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
0,
0
);

camera->setMonitor( monitors[i] );
Zone **zones = 0;
int n_zones = Zone::Load( monitors[i], zones );
monitors[i]->AddZones( n_zones, zones );
@@ -3080,6 +3085,8 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );

);

camera->setMonitor( monitor );

int n_zones = 0;
if ( load_zones )
{
27 changes: 17 additions & 10 deletions src/zm_packetqueue.cpp
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@


#include "zm_packetqueue.h"
#include "zm_ffmpeg.h"

#define VIDEO_QUEUESIZE 200
#define AUDIO_QUEUESIZE 50
@@ -34,28 +35,34 @@ zm_packetqueue::~zm_packetqueue() {

bool zm_packetqueue::queuePacket( AVPacket* packet ) {

AVPacket input_ref = { 0 };
if ( av_packet_ref(&input_ref, packet) < 0 ) {
return false;
}
pktQueue.push(*packet);
//AVPacket *input_ref = (AVPacket *)av_malloc(sizeof(AVPacket));
//if ( av_packet_ref( input_ref, packet ) < 0 ) {
//free(input_ref);
//return false;
//}
pktQueue.push( packet );

return true;
}

bool zm_packetqueue::popPacket( AVPacket* packet ) {
AVPacket* zm_packetqueue::popPacket( ) {
if ( pktQueue.empty() ) {
return false;
return NULL;
}

*packet = pktQueue.front();
AVPacket *packet = pktQueue.front();
pktQueue.pop();

return true;
return packet;
}

void zm_packetqueue::clearQueue() {
AVPacket *packet = NULL;
while(!pktQueue.empty()) {
pktQueue.pop();

packet = pktQueue.front();
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 );
}
}
4 changes: 2 additions & 2 deletions src/zm_packetqueue.h
Original file line number Diff line number Diff line change
@@ -34,12 +34,12 @@ class zm_packetqueue {
zm_packetqueue();
virtual ~zm_packetqueue();
bool queuePacket( AVPacket* packet );
bool popPacket( AVPacket* packet );
AVPacket * popPacket( );
bool popVideoPacket(AVPacket* packet);
bool popAudioPacket(AVPacket* packet);
void clearQueue( );
private:
std::queue<AVPacket> pktQueue;
std::queue<AVPacket *> pktQueue;

};

12 changes: 6 additions & 6 deletions src/zm_videostore.cpp
Original file line number Diff line number Diff line change
@@ -269,7 +269,7 @@ void VideoStore::dumpPacket( AVPacket *pkt ){
Info("%s:%d:DEBUG: %s", __FILE__, __LINE__, b);
}

int VideoStore::writeVideoFramePacket(AVPacket *ipkt, AVStream *input_video_stream){//, AVPacket *lastKeyframePkt){
int VideoStore::writeVideoFramePacket(AVPacket *ipkt, AVStream *input_video_stream){

Debug(2, "writeVideoFrame");
Debug(3, "before ost_tbcket starttime %d, timebase%d", startTime, video_stream->time_base );
@@ -279,7 +279,7 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt, AVStream *input_video_stre
Debug(3, "before ost_tbcket starttime %d, ost_tbcket %d", startTime, ost_tb_start_time );
Debug(2, "writeVideoFrame");

AVPacket opkt, safepkt;
AVPacket opkt;
AVPicture pict;

Debug(2, "writeVideoFrame init_packet");
@@ -321,7 +321,7 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt, AVStream *input_video_stre
opkt.flags |= AV_PKT_FLAG_KEY;
}

memcpy(&safepkt, &opkt, sizeof(AVPacket));
//memcpy(&safepkt, &opkt, sizeof(AVPacket));

if ((opkt.data == NULL)||(opkt.size < 1)) {
Warning("%s:%d: Mangled AVPacket: discarding frame", __FILE__, __LINE__ );
@@ -340,11 +340,11 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt, AVStream *input_video_stre
if(ret<0){
// There's nothing we can really do if the frame is rejected, just drop it and get on with the next
Warning("%s:%d: Writing frame [av_interleaved_write_frame()] failed: %s(%d) ", __FILE__, __LINE__, av_make_error_string(ret).c_str(), (ret));
dumpPacket(&safepkt);
dumpPacket(&opkt);
}
}

av_free_packet(&opkt);
zm_av_unref_packet(&opkt);

return 0;

@@ -418,6 +418,6 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt, AVStream *input_video_stre
Fatal("Error encoding audio frame packet: %s\n", av_make_error_string(ret).c_str());
}
Debug(4,"Success writing audio frame" );
av_free_packet(&opkt);
zm_av_unref_packet(&opkt);
return 0;
}

0 comments on commit 7c88ed8

Please sign in to comment.