From b9a48eb4645b8a13f68803b0a805d0ea276925a3 Mon Sep 17 00:00:00 2001 From: Steve Gilvarry Date: Sun, 17 Jul 2016 08:11:53 +1000 Subject: [PATCH 1/7] Pass swscale_ctx back in to getCachedContext or it will create new context every frame and leak memory like a mofo. --- src/zm_ffmpeg.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp index 4af4055a4..2eb475e11 100644 --- a/src/zm_ffmpeg.cpp +++ b/src/zm_ffmpeg.cpp @@ -154,10 +154,10 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint // Error("Invalid input or output pixel formats"); // return -2; // } - // if(!width || !height) { - // Error("Invalid width or height"); - // return -3; - // } + if (!width || !height) { + Error("Invalid width or height"); + return -3; + } #if LIBSWSCALE_VERSION_CHECK(0, 8, 0, 8, 0) /* Warn if the input or output pixelformat is not supported */ @@ -190,7 +190,7 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint } /* Get the context */ - swscale_ctx = sws_getCachedContext( NULL, width, height, in_pf, width, height, out_pf, 0, NULL, NULL, NULL ); + swscale_ctx = sws_getCachedContext(swscale_ctx, width, height, in_pf, width, height, out_pf, 0, NULL, NULL, NULL); if(swscale_ctx == NULL) { Error("Failed getting swscale context"); return -6; From 3543c37f5e7d673d65ee67ee43c743c6b1d91d12 Mon Sep 17 00:00:00 2001 From: Steve Gilvarry Date: Sun, 31 Jul 2016 08:24:52 +1000 Subject: [PATCH 2/7] Add libx264-dev and libmp4v2-dev to build requires to save hassle of ensuring they are installed before build. --- distros/ubuntu1604/control | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/distros/ubuntu1604/control b/distros/ubuntu1604/control index c1ee3cc0d..290d1af97 100644 --- a/distros/ubuntu1604/control +++ b/distros/ubuntu1604/control @@ -25,7 +25,9 @@ Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apa ,libphp-serialization-perl ,libsys-mmap-perl [!hurd-any] ,libwww-perl - ,libdata-uuid-perl + ,libdata-uuid-perl + ,libx264-dev + ,libmp4v2-dev # Unbundled (dh_linktree): ,libjs-jquery ,libjs-mootools @@ -60,7 +62,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends} ,libio-socket-multicast-perl ,libdigest-sha-perl ,libsys-cpu-perl, libsys-meminfo-perl - ,libdata-uuid-perl + ,libdata-uuid-perl ,mysql-client | virtual-mysql-client ,perl-modules ,php5-mysql | php-mysql, php5-gd | php-gd From 6ac1a70b9ca71a4b3ccf1ca5c2dbf1ce827378da Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 10 Aug 2016 12:22:04 -0400 Subject: [PATCH 3/7] Merge my Rotation/Orientation work and fixes for bad h264 streams --- src/zm_camera.cpp | 8 +++++-- src/zm_camera.h | 10 +++++++-- src/zm_ffmpeg_camera.cpp | 22 +++++++++++++----- src/zm_monitor.cpp | 13 +++++++++++ src/zm_monitor.h | 28 +++++++++-------------- src/zm_remote_camera_rtsp.cpp | 14 +++++++++--- src/zm_videostore.cpp | 42 +++++++++++++++++++++++++++++++++-- src/zm_videostore.h | 4 +++- 8 files changed, 108 insertions(+), 33 deletions(-) diff --git a/src/zm_camera.cpp b/src/zm_camera.cpp index 6f2c5b023..031511f04 100644 --- a/src/zm_camera.cpp +++ b/src/zm_camera.cpp @@ -47,7 +47,11 @@ Camera::Camera( int p_id, SourceType p_type, int p_width, int p_height, int p_co } } -Camera::~Camera() -{ +Camera::~Camera() { } +Monitor *Camera::getMonitor() { + if ( ! monitor ) + monitor = Monitor::Load( id, false, Monitor::QUERY ); + return monitor; +} diff --git a/src/zm_camera.h b/src/zm_camera.h index 461789178..c76b086f3 100644 --- a/src/zm_camera.h +++ b/src/zm_camera.h @@ -25,6 +25,10 @@ #include "zm_image.h" +class Camera; + +#include "zm_monitor.h" + // // Abstract base class for cameras. This is intended just to express // common attributes @@ -34,7 +38,8 @@ class Camera protected: typedef enum { LOCAL_SRC, REMOTE_SRC, FILE_SRC, FFMPEG_SRC, LIBVLC_SRC, CURL_SRC } SourceType; - int id; + int id; // This is actually monitor id + Monitor * monitor; // Null on instantiation, set as soon as possible. SourceType type; unsigned int width; unsigned int height; @@ -54,6 +59,7 @@ public: virtual ~Camera(); int getId() const { return( id ); } + Monitor *getMonitor(); SourceType Type() const { return( type ); } bool IsLocal() const { return( type == LOCAL_SRC ); } bool IsRemote() const { return( type == REMOTE_SRC ); } @@ -81,7 +87,7 @@ public: virtual int PreCapture()=0; virtual int Capture( Image &image )=0; virtual int PostCapture()=0; - virtual int CaptureAndRecord( Image &image, bool recording, char* event_directory)=0; + virtual int CaptureAndRecord( Image &image, bool recording, char* event_directory)=0; }; #endif // ZM_CAMERA_H diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index deb8db571..d70ba394c 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -591,19 +591,25 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi Debug(3, "Record Audio on but no audio stream found"); videoStore = new VideoStore((const char *) event_file, "mp4", mFormatContext->streams[mVideoStreamId], - NULL, startTime); + NULL, + startTime, + this->getMonitor()->getOrientation()); + } else { Debug(3, "Video module initiated with audio stream"); videoStore = new VideoStore((const char *) event_file, "mp4", mFormatContext->streams[mVideoStreamId], mFormatContext->streams[mAudioStreamId], - startTime); + startTime, + this->getMonitor()->getOrientation()); } } else { Debug(3, "Record_audio is false so exclude audio stream"); videoStore = new VideoStore((const char *) event_file, "mp4", mFormatContext->streams[mVideoStreamId], - NULL, startTime); + NULL, + startTime, + this->getMonitor()->getOrientation()); } wasRecording = true; strcpy(oldDirectory, event_file); @@ -633,19 +639,23 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi Debug(3, "Record Audio on but no audio stream found"); videoStore = new VideoStore((const char *) event_file, "mp4", mFormatContext->streams[mVideoStreamId], - NULL, startTime); + NULL, + startTime, + this->getMonitor()->getOrientation()); } else { Debug(3, "Video module initiated with audio stream"); videoStore = new VideoStore((const char *) event_file, "mp4", mFormatContext->streams[mVideoStreamId], mFormatContext->streams[mAudioStreamId], - startTime); + startTime, + this->getMonitor()->getOrientation()); } } else { Debug(3, "Record_audio is false so exclude audio stream"); videoStore = new VideoStore((const char *) event_file, "mp4", mFormatContext->streams[mVideoStreamId], - NULL, startTime); + NULL, startTime, + this->getMonitor()->getOrientation()); } strcpy(oldDirectory, event_file); } diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 7cbac5d15..216f9f4b1 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -4446,3 +4446,16 @@ void Monitor::SingleImageZip( int scale) fprintf( stdout, "Content-Type: image/x-rgbz\r\n\r\n" ); fwrite( img_buffer, img_buffer_size, 1, stdout ); } + +unsigned int Monitor::Colours() const { return( camera->Colours() ); } +unsigned int Monitor::SubpixelOrder() const { return( camera->SubpixelOrder() ); } +int Monitor::PrimeCapture() { + return( camera->PrimeCapture() ); +} +int Monitor::PreCapture() { + return( camera->PreCapture() ); +} +int Monitor::PostCapture() { + return( camera->PostCapture() ); +} +Monitor::Orientation Monitor::getOrientation()const { return orientation; } diff --git a/src/zm_monitor.h b/src/zm_monitor.h index cf27e1b0a..392bdea57 100644 --- a/src/zm_monitor.h +++ b/src/zm_monitor.h @@ -29,6 +29,7 @@ #include "zm_rgb.h" #include "zm_zone.h" #include "zm_event.h" +class Monitor; #include "zm_camera.h" #include "zm_utils.h" @@ -327,6 +328,7 @@ protected: MonitorLink **linked_monitors; public: + Monitor( int p_id ); // OurCheckAlarms seems to be unused. Check it on zm_monitor.cpp for more info. //bool OurCheckAlarms( Zone *zone, const Image *pImage ); Monitor( @@ -419,15 +421,16 @@ public: { return( embed_exif ); } + Orientation getOrientation() const; - unsigned int Width() const { return( width ); } - unsigned int Height() const { return( height ); } - unsigned int Colours() const { return( camera->Colours() ); } - unsigned int SubpixelOrder() const { return( camera->SubpixelOrder() ); } + unsigned int Width() const { return width; } + unsigned int Height() const { return height; } + unsigned int Colours() const; + unsigned int SubpixelOrder() const; int GetOptSaveJPEGs() const { return( savejpegspref ); } int GetOptVideoWriter() const { return( videowriterpref ); } - const std::vector* GetOptEncoderParams() const { return( &encoderparamsvec ); } + const std::vector* GetOptEncoderParams() const { return( &encoderparamsvec ); } State GetState() const; int GetImage( int index=-1, int scale=100 ); @@ -457,19 +460,10 @@ public: int actionColour( int p_colour=-1 ); int actionContrast( int p_contrast=-1 ); - inline int PrimeCapture() - { - return( camera->PrimeCapture() ); - } - inline int PreCapture() - { - return( camera->PreCapture() ); - } + int PrimeCapture(); + int PreCapture(); int Capture(); - int PostCapture() - { - return( camera->PostCapture() ); - } + int PostCapture(); unsigned int DetectMotion( const Image &comp_image, Event::StringSet &zoneSet ); // DetectBlack seems to be unused. Check it on zm_monitor.cpp for more info. diff --git a/src/zm_remote_camera_rtsp.cpp b/src/zm_remote_camera_rtsp.cpp index 85f7af340..7281c0512 100644 --- a/src/zm_remote_camera_rtsp.cpp +++ b/src/zm_remote_camera_rtsp.cpp @@ -467,7 +467,11 @@ int RemoteCameraRtsp::CaptureAndRecord( Image &image, bool recording, char* even if ( recording && !wasRecording ) { //Instantiate the video storage module - videoStore = new VideoStore((const char *)event_file, "mp4", mFormatContext->streams[mVideoStreamId],mAudioStreamId==-1?NULL:mFormatContext->streams[mAudioStreamId],startTime); + videoStore = new VideoStore((const char *)event_file, "mp4", + mFormatContext->streams[mVideoStreamId], + mAudioStreamId==-1?NULL:mFormatContext->streams[mAudioStreamId], + startTime, + this->getMonitor()->getOrientation() ); wasRecording = true; strcpy(oldDirectory, event_file); @@ -487,7 +491,11 @@ int RemoteCameraRtsp::CaptureAndRecord( Image &image, bool recording, char* even videoStore = NULL; } - videoStore = new VideoStore((const char *)event_file, "mp4", mFormatContext->streams[mVideoStreamId],mAudioStreamId==-1?NULL:mFormatContext->streams[mAudioStreamId],startTime); + videoStore = new VideoStore((const char *)event_file, "mp4", + mFormatContext->streams[mVideoStreamId], + mAudioStreamId==-1?NULL:mFormatContext->streams[mAudioStreamId], + startTime, + this->getMonitor()->getOrientation() ); strcpy( oldDirectory, event_file ); } @@ -537,7 +545,7 @@ int RemoteCameraRtsp::CaptureAndRecord( Image &image, bool recording, char* even } // end if video or audio packet #if LIBAVCODEC_VERSION_CHECK(57, 8, 0, 12, 100) - av_packet_unref( &packet); + av_packet_unref( &packet ); #else av_free_packet( &packet ); #endif diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index 47c1be13d..45cd1d280 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -35,7 +35,8 @@ extern "C"{ VideoStore::VideoStore(const char *filename_in, const char *format_in, AVStream *input_st, AVStream *inpaud_st, - int64_t nStartTime + int64_t nStartTime, + Monitor::Orientation orientation ) { AVDictionary *pmetadata = NULL; @@ -91,18 +92,55 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in, "%s\n", av_make_error_string(ret).c_str()); } + if ( video_st->sample_aspect_ratio.den != video_st->codec->sample_aspect_ratio.den ) { + Warning("Fixingample_aspect_ratio.den"); + video_st->sample_aspect_ratio.den = video_st->codec->sample_aspect_ratio.den; + } + if ( video_st->sample_aspect_ratio.num != input_st->codec->sample_aspect_ratio.num ) { + Warning("Fixingample_aspect_ratio.num"); + video_st->sample_aspect_ratio.num = input_st->codec->sample_aspect_ratio.num; + } + if ( video_st->codec->codec_id != input_st->codec->codec_id ) { + Warning("Fixing video_st->codec->codec_id"); + video_st->codec->codec_id = input_st->codec->codec_id; + } + if ( ! video_st->codec->time_base.num ) { + Warning("video_st->codec->time_base.num is not set%d/%d. Fixing by setting it to 1", video_st->codec->time_base.num, video_st->codec->time_base.den); + Warning("video_st->codec->time_base.num is not set%d/%d. Fixing by setting it to 1", video_st->time_base.num, video_st->time_base.den); + video_st->codec->time_base.num = video_st->time_base.num; + video_st->codec->time_base.den = video_st->time_base.den; + } + video_st->codec->codec_tag = 0; if (oc->oformat->flags & AVFMT_GLOBALHEADER) { video_st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; } + if ( orientation ) { + if ( orientation == Monitor::ROTATE_0 ) { + + } else if ( orientation == Monitor::ROTATE_90 ) { + dsr = av_dict_set( &video_st->metadata, "rotate", "90", 0); + if (dsr < 0) Warning("%s:%d: title set failed", __FILE__, __LINE__ ); + } else if ( orientation == Monitor::ROTATE_180 ) { + dsr = av_dict_set( &video_st->metadata, "rotate", "180", 0); + if (dsr < 0) Warning("%s:%d: title set failed", __FILE__, __LINE__ ); + } else if ( orientation == Monitor::ROTATE_270 ) { + dsr = av_dict_set( &video_st->metadata, "rotate", "270", 0); + if (dsr < 0) Warning("%s:%d: title set failed", __FILE__, __LINE__ ); + } else { + Warning( "Unsupported Orientation(%d)", orientation ); + } + } + + if (inpaud_st) { audio_st = avformat_new_stream(oc, inpaud_st->codec->codec); if (!audio_st) { Error("Unable to create audio out stream\n"); audio_st = NULL; } else { - ret=avcodec_copy_context(audio_st->codec, inpaud_st->codec); + ret = avcodec_copy_context(audio_st->codec, inpaud_st->codec); if (ret < 0) { Fatal("Unable to copy audio context %s\n", av_make_error_string(ret).c_str()); } diff --git a/src/zm_videostore.h b/src/zm_videostore.h index 0d72f42b6..a11973b4a 100644 --- a/src/zm_videostore.h +++ b/src/zm_videostore.h @@ -5,6 +5,8 @@ #if HAVE_LIBAVCODEC +#include "zm_monitor.h" + class VideoStore { private: @@ -26,7 +28,7 @@ private: int64_t filter_in_rescale_delta_last; public: - VideoStore(const char *filename_in, const char *format_in, AVStream *input_st, AVStream *inpaud_st, int64_t nStartTime); + VideoStore(const char *filename_in, const char *format_in, AVStream *input_st, AVStream *inpaud_st, int64_t nStartTime, Monitor::Orientation p_orientation ); ~VideoStore(); int writeVideoFramePacket(AVPacket *pkt, AVStream *input_st);//, AVPacket *lastKeyframePkt); From 1277f3c7920b2d84b239d349531edaa82db4edc3 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 10 Aug 2016 12:19:53 -0400 Subject: [PATCH 4/7] need arpa/inet for reverse lookups --- src/zm_camera.cpp | 8 ++++---- src/zm_camera.h | 6 +++--- src/zm_remote_camera.cpp | 4 ++-- src/zm_remote_camera.h | 3 ++- src/zm_remote_camera_http.cpp | 16 ++++++++++++---- src/zm_remote_camera_http.h | 2 +- src/zm_remote_camera_rtsp.cpp | 8 ++++---- src/zm_remote_camera_rtsp.h | 2 +- 8 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/zm_camera.cpp b/src/zm_camera.cpp index 031511f04..55a58ffca 100644 --- a/src/zm_camera.cpp +++ b/src/zm_camera.cpp @@ -20,8 +20,8 @@ #include "zm.h" #include "zm_camera.h" -Camera::Camera( int p_id, SourceType p_type, int p_width, int p_height, int p_colours, int p_subpixelorder, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ) : - id( p_id ), +Camera::Camera( unsigned int p_monitor_id, SourceType p_type, int p_width, int p_height, int p_colours, int p_subpixelorder, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ) : + monitor_id( p_monitor_id ), type( p_type ), width( p_width), height( p_height ), @@ -37,7 +37,7 @@ Camera::Camera( int p_id, SourceType p_type, int p_width, int p_height, int p_co pixels = width * height; imagesize = pixels * colours; - Debug(2,"New camera id: %d width: %d height: %d colours: %d subpixelorder: %d capture: %d",id,width,height,colours,subpixelorder,capture); + Debug(2,"New camera id: %d width: %d height: %d colours: %d subpixelorder: %d capture: %d",monitor_id,width,height,colours,subpixelorder,capture); /* Because many loops are unrolled and work on 16 colours/time or 4 pixels/time, we have to meet requirements */ if((colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB32) && (imagesize % 16) != 0) { @@ -52,6 +52,6 @@ Camera::~Camera() { Monitor *Camera::getMonitor() { if ( ! monitor ) - monitor = Monitor::Load( id, false, Monitor::QUERY ); + monitor = Monitor::Load( monitor_id, false, Monitor::QUERY ); return monitor; } diff --git a/src/zm_camera.h b/src/zm_camera.h index c76b086f3..1a90f037c 100644 --- a/src/zm_camera.h +++ b/src/zm_camera.h @@ -38,7 +38,7 @@ class Camera protected: typedef enum { LOCAL_SRC, REMOTE_SRC, FILE_SRC, FFMPEG_SRC, LIBVLC_SRC, CURL_SRC } SourceType; - int id; // This is actually monitor id + unsigned int monitor_id; Monitor * monitor; // Null on instantiation, set as soon as possible. SourceType type; unsigned int width; @@ -55,10 +55,10 @@ protected: bool record_audio; public: - Camera( int p_id, SourceType p_type, int p_width, int p_height, int p_colours, int p_subpixelorder, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ); + Camera( unsigned int p_monitor_id, SourceType p_type, int p_width, int p_height, int p_colours, int p_subpixelorder, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ); virtual ~Camera(); - int getId() const { return( id ); } + unsigned int getId() const { return( monitor_id ); } Monitor *getMonitor(); SourceType Type() const { return( type ); } bool IsLocal() const { return( type == LOCAL_SRC ); } diff --git a/src/zm_remote_camera.cpp b/src/zm_remote_camera.cpp index 1ffe5f568..be177c2c6 100644 --- a/src/zm_remote_camera.cpp +++ b/src/zm_remote_camera.cpp @@ -22,7 +22,7 @@ #include "zm_utils.h" RemoteCamera::RemoteCamera( - int p_id, + unsigned int p_monitor_id, const std::string &p_protocol, const std::string &p_host, const std::string &p_port, @@ -37,7 +37,7 @@ RemoteCamera::RemoteCamera( bool p_capture, bool p_record_audio ) : - Camera( p_id, REMOTE_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio ), + Camera( p_monitor_id, REMOTE_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio ), protocol( p_protocol ), host( p_host ), port( p_port ), diff --git a/src/zm_remote_camera.h b/src/zm_remote_camera.h index 6add0398a..b24d6a68f 100644 --- a/src/zm_remote_camera.h +++ b/src/zm_remote_camera.h @@ -27,6 +27,7 @@ #include #include #include +#include // // Class representing 'remote' cameras, i.e. those which are @@ -56,7 +57,7 @@ protected: public: RemoteCamera( - int p_id, + unsigned int p_monitor_id, const std::string &p_proto, const std::string &p_host, const std::string &p_port, diff --git a/src/zm_remote_camera_http.cpp b/src/zm_remote_camera_http.cpp index 02641632d..17f3969a4 100644 --- a/src/zm_remote_camera_http.cpp +++ b/src/zm_remote_camera_http.cpp @@ -30,9 +30,12 @@ #ifdef SOLARIS #include // FIONREAD and friends #endif +#ifdef __FreeBSD__ +#include +#endif RemoteCameraHttp::RemoteCameraHttp( - int p_id, + unsigned int p_monitor_id, const std::string &p_method, const std::string &p_host, const std::string &p_port, @@ -46,7 +49,7 @@ RemoteCameraHttp::RemoteCameraHttp( bool p_capture, bool p_record_audio ) : RemoteCamera( - p_id, + p_monitor_id, "http", p_host, p_port, @@ -71,7 +74,7 @@ RemoteCameraHttp::RemoteCameraHttp( else if ( p_method == "regexp" ) method = REGEXP; else - Fatal( "Unrecognised method '%s' when creating HTTP camera %d", p_method.c_str(), id ); + Fatal( "Unrecognised method '%s' when creating HTTP camera %d", p_method.c_str(), monitor_id ); if ( capture ) { Initialise(); @@ -135,7 +138,12 @@ int RemoteCameraHttp::Connect() { close(sd); sd = -1; - Warning("Can't connect to remote camera: %s", strerror(errno) ); + char buf[sizeof(struct in6_addr)]; + struct sockaddr_in *addr; + addr = (struct sockaddr_in *)p->ai_addr; + inet_ntop( AF_INET, &(addr->sin_addr), buf, INET6_ADDRSTRLEN ); + + Warning("Can't connect to remote camera mid: %d at %s: %s", monitor_id, buf, strerror(errno) ); continue; } diff --git a/src/zm_remote_camera_http.h b/src/zm_remote_camera_http.h index f0b8a4415..079dd8482 100644 --- a/src/zm_remote_camera_http.h +++ b/src/zm_remote_camera_http.h @@ -45,7 +45,7 @@ protected: enum { SIMPLE, REGEXP } method; public: - RemoteCameraHttp(int p_id, const std::string &method, const std::string &host, const std::string &port, const std::string &path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ); + RemoteCameraHttp( unsigned int p_monitor_id, const std::string &method, const std::string &host, const std::string &port, const std::string &path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ); ~RemoteCameraHttp(); void Initialise(); diff --git a/src/zm_remote_camera_rtsp.cpp b/src/zm_remote_camera_rtsp.cpp index 7281c0512..2e5e4b710 100644 --- a/src/zm_remote_camera_rtsp.cpp +++ b/src/zm_remote_camera_rtsp.cpp @@ -28,8 +28,8 @@ #include #include -RemoteCameraRtsp::RemoteCameraRtsp( int p_id, const std::string &p_method, const std::string &p_host, const std::string &p_port, const std::string &p_path, int p_width, int p_height, bool p_rtsp_describe, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ) : - RemoteCamera( p_id, "rtsp", p_host, p_port, p_path, p_width, p_height, p_colours, p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio ), +RemoteCameraRtsp::RemoteCameraRtsp( unsigned int p_monitor_id, const std::string &p_method, const std::string &p_host, const std::string &p_port, const std::string &p_path, int p_width, int p_height, bool p_rtsp_describe, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ) : + RemoteCamera( p_monitor_id, "rtsp", p_host, p_port, p_path, p_width, p_height, p_colours, p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio ), rtsp_describe( p_rtsp_describe ), rtspThread( 0 ) @@ -43,7 +43,7 @@ RemoteCameraRtsp::RemoteCameraRtsp( int p_id, const std::string &p_method, const else if ( p_method == "rtpRtspHttp" ) method = RtspThread::RTP_RTSP_HTTP; else - Fatal( "Unrecognised method '%s' when creating RTSP camera %d", p_method.c_str(), id ); + Fatal( "Unrecognised method '%s' when creating RTSP camera %d", p_method.c_str(), monitor_id ); if ( capture ) { @@ -137,7 +137,7 @@ void RemoteCameraRtsp::Terminate() int RemoteCameraRtsp::Connect() { - rtspThread = new RtspThread( id, method, protocol, host, port, path, auth, rtsp_describe ); + rtspThread = new RtspThread( monitor_id, method, protocol, host, port, path, auth, rtsp_describe ); rtspThread->start(); diff --git a/src/zm_remote_camera_rtsp.h b/src/zm_remote_camera_rtsp.h index 1a1da6999..3af753fea 100644 --- a/src/zm_remote_camera_rtsp.h +++ b/src/zm_remote_camera_rtsp.h @@ -73,7 +73,7 @@ protected: #endif public: - RemoteCameraRtsp( int p_id, const std::string &method, const std::string &host, const std::string &port, const std::string &path, int p_width, int p_height, bool p_rtsp_describe, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ); + RemoteCameraRtsp( unsigned int p_monitor_id, const std::string &method, const std::string &host, const std::string &port, const std::string &path, int p_width, int p_height, bool p_rtsp_describe, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ); ~RemoteCameraRtsp(); void Initialise(); From e74bf3fedf43e0b7e0fb926bb5ee25e6795e4f61 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 31 Aug 2016 10:58:50 -0400 Subject: [PATCH 5/7] pull in the new byte range code for viewing videos --- web/views/view_video.php | 82 +++++++++++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 22 deletions(-) diff --git a/web/views/view_video.php b/web/views/view_video.php index 5bf01ca6b..4e5e04c0c 100644 --- a/web/views/view_video.php +++ b/web/views/view_video.php @@ -25,36 +25,74 @@ // Does not support scaling at this time. // -if ( !canView( 'Events' ) ) -{ - $view = "error"; - return; +if ( !canView( 'Events' ) ) { + $view = "error"; + return; } -require_once('includes/Storage.php'); require_once('includes/Event.php'); - -$Storage = NULL; $errorText = false; +$path = ''; + if ( ! empty($_REQUEST['eid'] ) ) { - $Event = new Event( $_REQUEST['eid'] ); - $Storage = $Event->Storage(); - $path = $Event->Relative_Path().'/'.$Event->DefaultVideo(); - Error("Path: $path"); + $Event = new Event( $_REQUEST['eid'] ); + $path = $Event->Path().'/'.$Event->DefaultVideo(); + Debug("Path: $path"); } else { - $errorText = "No video path"; + $errorText = "No video path"; } -if ( $errorText ) - Error( $errorText ); -else{ -# FIXME guess it from the video file - header( 'Content-type: video/mp4' ); - if ( ! readfile( $Storage->Path().'/'.$path ) ) { - Error("No bytes read from ". $Storage->Path() . '/'.$path ); - } else { - Error("Success sending " . $Storage->Path().'/'.$path ); - } +if ( $errorText ) { + Error( $errorText ); + header ("HTTP/1.0 404 Not Found"); + die(); +} + +$size = filesize($path); + +$fh = @fopen($path,'rb'); +if ( ! $fh ) { + header ("HTTP/1.0 404 Not Found"); + die(); } + +$begin = 0; +$end = $size; + +if ( isset( $_SERVER['HTTP_RANGE'] ) ) { + Debug("Using Range " . $_SERVER['HTTP_RANGE'] ); + if ( preg_match( '/bytes=\h*(\d+)-(\d*)[\D.*]?/i', $_SERVER['HTTP_RANGE'], $matches) ) { + $begin = intval( $matches[1] ); + if ( ! empty( $matches[2]) ) { + $end = intval( $matches[2] ); + } + Debug("Using Range $begin $end size: $size"); + } +} # end if HTTP_RANGE + +if ( $begin > 0 || $end < $size ) { + header('HTTP/1.0 206 Partial Content'); +} else { + header('HTTP/1.0 200 OK'); +} + +header('Content-type: video/mp4'); +header('Accept-Ranges: bytes'); +header('Content-Length:'.($end-$begin)); +header("Content-Disposition: inline;"); +header("Content-Range: bytes $begin-$end/$size"); +header("Content-Transfer-Encoding: binary\n"); +header('Connection: close'); + +$cur = $begin; +fseek( $fh, $begin, 0 ); + +while( ! feof( $fh ) && $cur < $end && ( connection_status() == 0 ) ) { + #Error("Sending $cur"); + print fread( $fh, min( 1024*16, $end - $cur ) ); + $cur += 1024*16; + usleep(100); +} + ?> From fc060135fe1a9c38268c5d8aec3439d7f6d2e379 Mon Sep 17 00:00:00 2001 From: Steve Gilvarry Date: Tue, 13 Sep 2016 22:58:38 +1000 Subject: [PATCH 6/7] Move our recording flag deeper into closeevent --- src/zm_monitor.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 216f9f4b1..9106e6264 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -3304,16 +3304,15 @@ void Monitor::TimestampImage( Image *ts_image, const struct timeval *ts_time ) c } } -bool Monitor::closeEvent() -{ - video_store_data->recording = false; - if ( event ) +bool Monitor::closeEvent() { + if (event) { if ( function == RECORD || function == MOCORD ) { gettimeofday( &(event->EndTime()), NULL ); } delete event; + video_store_data->recording = false; event = 0; return( true ); } From 39e06b929f9130c2410450930c0cb01f905d37a9 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 13 Sep 2016 09:36:45 -0400 Subject: [PATCH 7/7] add braces and only call closeEvent if there is an event --- src/zm_monitor.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 9106e6264..c906d7fed 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -640,9 +640,10 @@ Monitor::~Monitor() privacy_bitmask = NULL; } if ( mem_ptr ) { - if ( event ) + if ( event ) { Info( "%s: %03d - Closing event %d, shutting down", name, image_count, event->Id() ); - closeEvent(); + closeEvent(); + } if ( (deinterlacing & 0xff) == 4) {