create zm_packet

pull/1857/head
Isaac Connor 2017-02-18 15:22:56 -05:00
parent 980b088d57
commit f19b3d5505
8 changed files with 150 additions and 39 deletions

View File

@ -4,7 +4,7 @@
configure_file(zm_config.h.in "${CMAKE_CURRENT_BINARY_DIR}/zm_config.h" @ONLY)
# Group together all the source files that are used by all the binaries (zmc, zma, zmu, zms etc)
set(ZM_BIN_SRC_FILES zm_box.cpp zm_buffer.cpp zm_camera.cpp zm_comms.cpp zm_config.cpp zm_coord.cpp zm_curl_camera.cpp zm.cpp zm_db.cpp zm_logger.cpp zm_event.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_camera.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_ffmpeg.cpp zm_mpeg.cpp zm_packetqueue.cpp zm_poly.cpp zm_regexp.cpp zm_remote_camera.cpp zm_remote_camera_http.cpp zm_remote_camera_rtsp.cpp zm_rtp.cpp zm_rtp_ctrl.cpp zm_rtp_data.cpp zm_rtp_source.cpp zm_rtsp.cpp zm_rtsp_auth.cpp zm_sdp.cpp zm_signal.cpp zm_stream.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_video.cpp zm_videostore.cpp zm_zone.cpp zm_storage.cpp)
set(ZM_BIN_SRC_FILES zm_box.cpp zm_buffer.cpp zm_camera.cpp zm_comms.cpp zm_config.cpp zm_coord.cpp zm_curl_camera.cpp zm.cpp zm_db.cpp zm_logger.cpp zm_event.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_camera.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_ffmpeg.cpp zm_mpeg.cpp zm_packet.cpp zm_packetqueue.cpp zm_poly.cpp zm_regexp.cpp zm_remote_camera.cpp zm_remote_camera_http.cpp zm_remote_camera_rtsp.cpp zm_rtp.cpp zm_rtp_ctrl.cpp zm_rtp_data.cpp zm_rtp_source.cpp zm_rtsp.cpp zm_rtsp_auth.cpp zm_sdp.cpp zm_signal.cpp zm_stream.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_video.cpp zm_videostore.cpp zm_zone.cpp zm_storage.cpp)
# A fix for cmake recompiling the source files for every target.
add_library(zm STATIC ${ZM_BIN_SRC_FILES})

View File

@ -63,6 +63,7 @@ FfmpegCamera::FfmpegCamera( int p_id, const std::string &p_path, const std::stri
mOpenStart = 0;
mReopenThread = 0;
videoStore = NULL;
video_last_pts = 0;
#if HAVE_LIBSWSCALE
mConvertContext = NULL;
@ -645,24 +646,24 @@ Debug(5, "After av_read_frame (%d)", ret );
// Need to write out all the frames from the last keyframe?
unsigned int packet_count = 0;
AVPacket *queued_packet;
ZMPacket *queued_packet;
while ( ( queued_packet = packetqueue.popPacket() ) ) {
AVPacket *avp = queued_packet->av_packet();
packet_count += 1;
//Write the packet to our video store
Debug(2, "Writing queued packet stream: %d KEY %d, remaining (%d)", queued_packet->stream_index, queued_packet->flags & AV_PKT_FLAG_KEY, packetqueue.size() );
if ( queued_packet->stream_index == mVideoStreamId ) {
ret = videoStore->writeVideoFramePacket( queued_packet );
} else if ( queued_packet->stream_index == mAudioStreamId ) {
ret = videoStore->writeAudioFramePacket( queued_packet );
Debug(2, "Writing queued packet stream: %d KEY %d, remaining (%d)", avp->stream_index, avp->flags & AV_PKT_FLAG_KEY, packetqueue.size() );
if ( avp->stream_index == mVideoStreamId ) {
ret = videoStore->writeVideoFramePacket( avp );
} else if ( avp->stream_index == mAudioStreamId ) {
ret = videoStore->writeAudioFramePacket( avp );
} else {
Warning("Unknown stream id in queued packet (%d)", queued_packet->stream_index );
Warning("Unknown stream id in queued packet (%d)", avp->stream_index );
ret = -1;
}
if ( ret < 0 ) {
//Less than zero and we skipped a frame
}
zm_av_packet_unref( queued_packet );
av_free( queued_packet );
delete queued_packet;
} // end while packets in the packetqueue
Debug(2, "Wrote %d queued packets", packet_count );
} // end if ! wasRecording
@ -682,7 +683,7 @@ Debug(5, "After av_read_frame (%d)", ret );
packetqueue.clearQueue();
}
if ( packet.pts && video_last_pts > packet.pts ) {
Warning( "Clearing queue due to out of order pts");
Warning( "Clearing queue due to out of order pts packet.pts=%d video_last_pts=%d", packet.pts, video_last_pts );
packetqueue.clearQueue();
}
}
@ -706,6 +707,24 @@ Debug(5, "After av_read_frame (%d)", ret );
}
}
Debug(4, "about to decode video" );
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
ret = avcodec_send_packet( mVideoCodecContext, &packet );
if ( ret < 0 ) {
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
Error( "Unable to send packet at frame %d: %s, continuing", frameCount, errbuf );
zm_av_packet_unref( &packet );
continue;
}
ret = avcodec_receive_frame( mVideoCodecContext, mRawFrame );
if ( ret < 0 ) {
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
Error( "Unable to send packet at frame %d: %s, continuing", frameCount, errbuf );
zm_av_packet_unref( &packet );
continue;
}
frameComplete = 1;
# else
ret = zm_avcodec_decode_video( mVideoCodecContext, mRawFrame, &frameComplete, &packet );
if ( ret < 0 ) {
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
@ -713,6 +732,7 @@ Debug(5, "After av_read_frame (%d)", ret );
zm_av_packet_unref( &packet );
continue;
}
#endif
Debug( 4, "Decoded video packet at frame %d", frameCount );
@ -728,7 +748,9 @@ Debug(5, "After av_read_frame (%d)", ret );
zm_av_packet_unref( &packet );
return (-1);
}
avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height);
// avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height);
av_image_fill_arrays(mFrame->data, mFrame->linesize, directbuffer, imagePixFormat, width, height, 1);
if (sws_scale(mConvertContext, mRawFrame->data, mRawFrame->linesize,
0, mVideoCodecContext->height, mFrame->data, mFrame->linesize) < 0) {
@ -758,7 +780,7 @@ Debug(5, "After av_read_frame (%d)", ret );
}
} else {
#if LIBAVUTIL_VERSION_CHECK(54, 23, 0, 23, 0)
Debug( 3, "Some other stream index %d, %s", packet.stream_index, av_get_media_type_string( mFormatContext->streams[packet.stream_index]->codec->codec_type) );
Debug( 3, "Some other stream index %d, %s", packet.stream_index, av_get_media_type_string( mFormatContext->streams[packet.stream_index]->codecpar->codec_type) );
#else
Debug( 3, "Some other stream index %d", packet.stream_index );
#endif

View File

@ -1357,6 +1357,7 @@ bool Monitor::Analyse() {
if ( event ) {
//TODO: We shouldn't have to do this every time. Not sure why it clears itself if this isn't here??
snprintf(video_store_data->event_file, sizeof(video_store_data->event_file), "%s", event->getEventFile());
Debug( 3, "Detected new event at (%d.%d)", timestamp->tv_sec,timestamp->tv_usec );
if ( section_length ) {
int section_mod = timestamp->tv_sec%section_length;
@ -3029,7 +3030,7 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
ref_image.WriteJpeg( diag_path );
}
ref_image.Delta( comp_image, &delta_image);
ref_image.Delta( comp_image, &delta_image );
if ( config.record_diag_images ) {
static char diag_path[PATH_MAX] = "";
@ -3117,6 +3118,7 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
if ( alarm ) {
for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) {
Zone *zone = zones[n_zone];
// Wasn't this zone already checked above?
if ( !zone->IsInclusive() ) {
continue;
}
@ -3151,7 +3153,7 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
zoneSet.insert( zone->Label() );
}
}
} // end if alaram or not
} // end if alarm or not
}
if ( top_score > 0 ) {

44
src/zm_packet.cpp Normal file
View File

@ -0,0 +1,44 @@
//ZoneMinder Packet Implementation Class
//Copyright 2017 ZoneMinder LLC
//
//This file is part of ZoneMinder.
//
//ZoneMinder is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//ZoneMinder is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with ZoneMinder. If not, see <http://www.gnu.org/licenses/>.
#include "zm_packet.h"
#include "zm_ffmpeg.h"
using namespace std;
ZMPacket::ZMPacket( AVPacket *p ) {
av_init_packet( &packet );
if ( zm_av_packet_ref( &packet, p ) < 0 ) {
Error("error refing packet");
}
gettimeofday( &timestamp, NULL );
}
ZMPacket::ZMPacket( AVPacket *p, struct timeval *t ) {
av_init_packet( &packet );
if ( zm_av_packet_ref( &packet, p ) < 0 ) {
Error("error refing packet");
}
timestamp = *t;
}
ZMPacket::~ZMPacket() {
zm_av_packet_unref( &packet );
}

39
src/zm_packet.h Normal file
View File

@ -0,0 +1,39 @@
//ZoneMinder Packet Wrapper Class
//Copyright 2017 ZoneMinder LLC
//
//This file is part of ZoneMinder.
//
//ZoneMinder is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//ZoneMinder is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with ZoneMinder. If not, see <http://www.gnu.org/licenses/>.
#ifndef ZM_PACKET_H
#define ZM_PACKET_H
extern "C" {
#include <libavformat/avformat.h>
}
class ZMPacket {
public:
AVPacket packet;
struct timeval timestamp;
public:
AVPacket *av_packet() { return &packet; }
ZMPacket( AVPacket *packet, struct timeval *timestamp );
ZMPacket( AVPacket *packet );
~ZMPacket();
};
#endif /* ZM_PACKET_H */

View File

@ -33,41 +33,38 @@ zm_packetqueue::~zm_packetqueue() {
}
bool zm_packetqueue::queuePacket( AVPacket* packet ) {
bool zm_packetqueue::queuePacket( ZMPacket* zm_packet ) {
pktQueue.push( zm_packet );
return true;
}
bool zm_packetqueue::queuePacket( AVPacket* av_packet ) {
AVPacket *input_ref = (AVPacket *)av_malloc(sizeof(AVPacket));
av_init_packet( input_ref );
if ( zm_av_packet_ref( input_ref, packet ) < 0 ) {
Error("error refing packet");
av_free(input_ref);
return false;
}
ZMPacket *zm_packet = new ZMPacket( av_packet );
pktQueue.push( input_ref );
pktQueue.push( zm_packet );
return true;
}
AVPacket* zm_packetqueue::popPacket( ) {
ZMPacket* zm_packetqueue::popPacket( ) {
if ( pktQueue.empty() ) {
return NULL;
}
AVPacket *packet = pktQueue.front();
ZMPacket *packet = pktQueue.front();
pktQueue.pop();
return packet;
}
void zm_packetqueue::clearQueue() {
AVPacket *packet = NULL;
ZMPacket *packet = NULL;
while(!pktQueue.empty()) {
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_packet_unref( packet );
av_free( packet );
delete packet;
}
}

View File

@ -24,6 +24,7 @@
//#include <boost/interprocess/containers/map.hpp>
//#include <boost/interprocess/allocators/allocator.hpp>
#include <queue>
#include "zm_packet.h"
extern "C" {
#include <libavformat/avformat.h>
@ -33,18 +34,17 @@ class zm_packetqueue {
public:
zm_packetqueue();
virtual ~zm_packetqueue();
bool queuePacket( AVPacket* packet, struct timeval *timestamp );
bool queuePacket( ZMPacket* packet );
bool queuePacket( AVPacket* packet );
AVPacket * popPacket( );
bool popVideoPacket(AVPacket* packet);
bool popAudioPacket(AVPacket* packet);
ZMPacket * popPacket( );
bool popVideoPacket(ZMPacket* packet);
bool popAudioPacket(ZMPacket* packet);
void clearQueue( );
unsigned int size();
private:
std::queue<AVPacket *> pktQueue;
std::queue<ZMPacket *> pktQueue;
};
#endif /* ZM_PACKETQUEUE_H */

View File

@ -470,7 +470,11 @@ Debug(1, "Have audio encoder, need to flush it's output" );
int64_t size;
while(1) {
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
ret = avcodec_receive_packet( audio_output_context, &pkt );
#else
ret = avcodec_encode_audio2( audio_output_context, &pkt, NULL, &got_packet );
#endif
if (ret < 0) {
Error("ERror encoding audio while flushing");
break;
@ -871,8 +875,11 @@ av_frame_get_best_effort_timestamp(output_frame)
* Encode the audio frame and store it in the temporary packet.
* The output audio stream encoder is used to do this.
*/
if (( ret = avcodec_encode_audio2( audio_output_context, &opkt,
output_frame, &data_present )) < 0) {
#if LIBAVCODEC_VERSION_CHECK(58, 0, 0, 0, 0)
if (( ret = avcodec_receive_packet( audio_output_context, &opkt )) < 0 ) {
#else
if (( ret = avcodec_encode_audio2( audio_output_context, &opkt, output_frame, &data_present )) < 0) {
#endif
Error( "Could not encode frame (error '%s')",
av_make_error_string(ret).c_str());
zm_av_packet_unref(&opkt);