From 6ac1a70b9ca71a4b3ccf1ca5c2dbf1ce827378da Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 10 Aug 2016 12:22:04 -0400 Subject: [PATCH] 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);