From 56bb2205d8c194689bce36778b3977277ba29348 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 14 Nov 2017 01:59:15 -0500 Subject: [PATCH] add mjpeg support --- db/zm_create.sql.in | 2 +- db/zm_update-1.31.13.sql | 5 +- src/zm_event.cpp | 11 +- src/zm_monitor.cpp | 36 ++++- src/zm_monitor.h | 6 + src/zm_videostore.cpp | 152 ++++++++++--------- web/skins/classic/js/skin.js | 2 +- web/skins/classic/views/_monitor_filters.php | 11 +- web/skins/classic/views/event.php | 8 +- 9 files changed, 147 insertions(+), 86 deletions(-) diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 6b4cabef9..df7a486c0 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -386,7 +386,7 @@ CREATE TABLE `Monitors` ( `SaveJPEGs` TINYINT NOT NULL DEFAULT '3' , `VideoWriter` TINYINT NOT NULL DEFAULT '0', `OutputCodec` enum('h264','mjpeg','mpeg1','mpeg2'), - `OutputContainer` enum('mp4','mkv'), + `OutputContainer` enum('auto','mp4','mkv'), `EncoderParameters` TEXT, `RecordAudio` TINYINT NOT NULL DEFAULT '0', `RTSPDescribe` tinyint(1) unsigned, diff --git a/db/zm_update-1.31.13.sql b/db/zm_update-1.31.13.sql index bd102043f..a68936e6b 100644 --- a/db/zm_update-1.31.13.sql +++ b/db/zm_update-1.31.13.sql @@ -1,4 +1,5 @@ -ALTER TABLE `Monitors` MODIFY `OutputCodec` enum('h264','mjpeg','mpeg1','mpeg2') +ALTER TABLE `Monitors` MODIFY `OutputCodec` enum('h264','mjpeg','mpeg1','mpeg2') default 'h264'; +ALTER TABLE `Monitors` MODIFY `OutputContainer` enum('auto','mp4','mkv') default 'auto'; SET @s = (SELECT IF( (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() @@ -6,7 +7,7 @@ SET @s = (SELECT IF( AND column_name = 'SaveJPEGs' ) > 0, "SELECT 'Column SaveJPEGs already exists in Events'", -"ALTER TABLE `Eventss` ADD `SaveJPEGs` TINYINT AFTER `DefaultVideo`" +"ALTER TABLE `Events` ADD `SaveJPEGs` TINYINT AFTER `DefaultVideo`" )); PREPARE stmt FROM @s; diff --git a/src/zm_event.cpp b/src/zm_event.cpp index a74d46038..10e58ad7b 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -167,7 +167,16 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string /* Save as video */ if ( monitor->GetOptVideoWriter() != 0 ) { - snprintf( video_name, sizeof(video_name), "%d-%s", id, "video.mp4" ); + std::string container = monitor->OutputContainer(); + if ( container == "auto" || container == "" ) { + if ( monitor->OutputCodec() == "h264" ) { + container = "mp4"; + } else { + container = "mkv"; + } + } + + snprintf( video_name, sizeof(video_name), "%d-%s.%s", id, "video", container.c_str() ); snprintf( video_file, sizeof(video_file), staticConfig.video_file_format, path, video_name ); Debug(1,"Writing video file to %s", video_file ); videowriter = NULL; diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index b5be3a9e9..750ab0b26 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -243,6 +243,8 @@ Monitor::Monitor( int p_savejpegs, VideoWriter p_videowriter, std::string p_encoderparams, + std::string p_output_codec, + std::string p_output_container, bool p_record_audio, const char *p_event_prefix, const char *p_label_format, @@ -282,6 +284,8 @@ Monitor::Monitor( savejpegspref( p_savejpegs ), videowriter( p_videowriter ), encoderparams( p_encoderparams ), + output_codec( p_output_codec ), + output_container( p_output_container ), record_audio( p_record_audio ), label_coord( p_label_coord ), label_size( p_label_size ), @@ -1781,7 +1785,7 @@ void Monitor::ReloadLinkedMonitors( const char *p_linked_monitors ) { #if ZM_HAS_V4L int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose purpose ) { - std::string sql = "select Id, Name, ServerId, StorageId, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Function != 'None' and Type = 'Local'"; + std::string sql = "select Id, Name, ServerId, StorageId, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, OutputCodec, OutputContainer, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Function != 'None' and Type = 'Local'"; ; if ( device[0] ) { sql += " AND Device='"; @@ -1846,6 +1850,8 @@ int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose int savejpegs = atoi(dbrow[col]); col++; VideoWriter videowriter = (VideoWriter)atoi(dbrow[col]); col++; std::string encoderparams = dbrow[col] ? dbrow[col] : ""; col++; + std::string output_codec = dbrow[col] ? dbrow[col] : ""; col++; + std::string output_container = dbrow[col] ? dbrow[col] : ""; col++; bool record_audio = (*dbrow[col] != '0'); col++; int brightness = atoi(dbrow[col]); col++; @@ -1923,6 +1929,8 @@ int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose savejpegs, videowriter, encoderparams, + output_codec, + output_container, record_audio, event_prefix, label_format, @@ -1970,7 +1978,7 @@ int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose #endif // ZM_HAS_V4L int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const char *port, const char *path, Monitor **&monitors, Purpose purpose ) { - std::string sql = "select Id, Name, ServerId, StorageId, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, SaveJPEGs, VideoWriter, EncoderParameters, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Remote'"; + std::string sql = "select Id, Name, ServerId, StorageId, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, SaveJPEGs, VideoWriter, EncoderParameters, OutputCodec, OutputContainer, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Remote'"; if ( staticConfig.SERVER_ID ) { sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID ); } @@ -2016,6 +2024,8 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c int savejpegs = atoi(dbrow[col]); col++; VideoWriter videowriter = (VideoWriter)atoi(dbrow[col]); col++; std::string encoderparams = dbrow[col] ? dbrow[col] : ""; col++; + std::string output_codec = dbrow[col] ? dbrow[col] : ""; col++; + std::string output_container = dbrow[col] ? dbrow[col] : ""; col++; bool record_audio = (*dbrow[col] != '0'); col++; int brightness = atoi(dbrow[col]); col++; @@ -2107,6 +2117,8 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c savejpegs, videowriter, encoderparams, + output_codec, + output_container, record_audio, event_prefix, label_format, @@ -2153,7 +2165,7 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c } int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose purpose ) { - std::string sql = "select Id, Name, ServerId, StorageId, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'File'"; + std::string sql = "select Id, Name, ServerId, StorageId, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, OutputCodec, OutputContainer, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'File'"; if ( file[0] ) { sql += " AND Path='"; sql += file; @@ -2195,6 +2207,8 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu int savejpegs = atoi(dbrow[col]); col++; VideoWriter videowriter = (VideoWriter)atoi(dbrow[col]); col++; std::string encoderparams = dbrow[col]; col++; + std::string output_codec = dbrow[col]; col++; + std::string output_container = dbrow[col]; col++; bool record_audio = (*dbrow[col] != '0'); col++; int brightness = atoi(dbrow[col]); col++; @@ -2256,6 +2270,8 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu savejpegs, videowriter, encoderparams, + output_codec, + output_container, record_audio, event_prefix, label_format, @@ -2303,7 +2319,7 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu #if HAVE_LIBAVFORMAT int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose purpose ) { - std::string sql = "select Id, Name, ServerId, StorageId, Function+0, Enabled, LinkedMonitors, Path, Method, Options, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Ffmpeg'"; + std::string sql = "select Id, Name, ServerId, StorageId, Function+0, Enabled, LinkedMonitors, Path, Method, Options, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, OutputCodec, OutputContainer, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Ffmpeg'"; if ( file[0] ) { sql += " AND Path = '"; sql += file; @@ -2348,6 +2364,8 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose int savejpegs = atoi(dbrow[col]); col++; VideoWriter videowriter = (VideoWriter)atoi(dbrow[col]); col++; std::string encoderparams = dbrow[col] ? dbrow[col] : ""; col++; + std::string output_codec = dbrow[col] ? dbrow[col] : ""; col++; + std::string output_container = dbrow[col] ? dbrow[col] : ""; col++; bool record_audio = (*dbrow[col] != '0'); col++; int brightness = atoi(dbrow[col]); col++; @@ -2415,6 +2433,8 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose savejpegs, videowriter, encoderparams, + output_codec, + output_container, record_audio, event_prefix, label_format, @@ -2463,7 +2483,7 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose #endif // HAVE_LIBAVFORMAT Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) { - std::string sql = stringtf( "select Id, Name, ServerId, StorageId, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Protocol, Method, Host, Port, Path, Options, User, Pass, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, SaveJPEGs, VideoWriter, EncoderParameters, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Id = %d", p_id ); + std::string sql = stringtf( "select Id, Name, ServerId, StorageId, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Protocol, Method, Host, Port, Path, Options, User, Pass, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, SaveJPEGs, VideoWriter, EncoderParameters, OutputCodec, OutputContainer, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Id = %d", p_id ); zmDbRow dbrow; if ( ! dbrow.fetch( sql.c_str() ) ) { @@ -2523,7 +2543,9 @@ Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) { bool rtsp_describe = (dbrow[col] && *dbrow[col] != '0'); col++; int savejpegs = atoi(dbrow[col]); col++; VideoWriter videowriter = (VideoWriter)atoi(dbrow[col]); col++; - std::string encoderparams = dbrow[col] ? dbrow[col] : ""; col++; + std::string encoderparams = dbrow[col] ? dbrow[col] : ""; col++; + std::string output_codec = dbrow[col] ? dbrow[col] : ""; col++; + std::string output_container = dbrow[col] ? dbrow[col] : ""; col++; bool record_audio = (*dbrow[col] != '0'); col++; int brightness = atoi(dbrow[col]); col++; @@ -2742,6 +2764,8 @@ Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) { savejpegs, videowriter, encoderparams, + output_codec, + output_container, record_audio, event_prefix, label_format, diff --git a/src/zm_monitor.h b/src/zm_monitor.h index 9cf303976..b59ad2a7f 100644 --- a/src/zm_monitor.h +++ b/src/zm_monitor.h @@ -166,6 +166,8 @@ protected: VideoStore *videoStore; zm_packetqueue packetqueue; Mutex mutex; + std::string output_codec; + std::string output_container; class MonitorLink { protected: @@ -346,6 +348,8 @@ public: int p_savejpegs, VideoWriter p_videowriter, std::string p_encoderparams, + std::string p_output_codec, + std::string p_output_container, bool p_record_audio, const char *p_event_prefix, const char *p_label_format, @@ -431,6 +435,8 @@ public: VideoWriter GetOptVideoWriter() const { return( videowriter ); } const std::vector* GetOptEncoderParams() const { return( &encoderparamsvec ); } const std::string &GetEncoderOptions() const { return( encoderparams ); } + const std::string &OutputCodec() const { return output_codec; } + const std::string &OutputContainer() const { return output_container; } uint32_t GetLastEventId() const { return shared_data->last_event_id; } uint32_t GetVideoWriterEventId() const { return video_store_data->current_event; } diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index 113d3b7e9..f86f0f190 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -129,78 +129,95 @@ Debug(2,"About to copy aparames"); Error("Could not allocate in frame"); return; } - video_out_codec = avcodec_find_encoder_by_name("h264_omx"); - if ( ! video_out_codec ) { - Debug(1, "Didn't find omx"); - video_out_codec = avcodec_find_encoder(AV_CODEC_ID_H264); - } - if ( !video_out_codec ) { - Fatal("Could not find codec for H264"); - } - Debug(2, "Have video out codec"); + video_out_ctx = avcodec_alloc_context3( video_out_codec ); + // Don't have an input stream, so need to tell it what we are sending it, or are transcoding + video_out_ctx->width = monitor->Width(); + video_out_ctx->height = monitor->Height(); + video_out_ctx->codec_type = AVMEDIA_TYPE_VIDEO; - video_out_ctx = avcodec_alloc_context3( video_out_codec ); - // Don't have an input stream, so need to tell it what we are sending it, or are transcoding - video_out_ctx->width = monitor->Width(); - video_out_ctx->height = monitor->Height(); - video_out_ctx->codec_id = AV_CODEC_ID_H264; - video_out_ctx->codec_type = AVMEDIA_TYPE_VIDEO; -//video_in_ctx->sample_aspect_ratio; - /* take first format from list of supported formats */ - //video_out_ctx->pix_fmt = video_out_codec->pix_fmts[0]; - video_out_ctx->pix_fmt = AV_PIX_FMT_YUV420P; - /* video time_base can be set to whatever is handy and supported by encoder */ - video_out_ctx->time_base = (AVRational){1, 1000000}; // microseconds as base frame rate - video_out_ctx->framerate = (AVRational){0,1}; // Unknown framerate - video_out_ctx->gop_size = 12; - video_out_ctx->bit_rate = 4000000; - video_out_ctx->qmin = 10; - video_out_ctx->qmax = 51; - video_out_ctx->qcompress = 0.6; - - AVDictionary *opts = 0; - std::string Options = monitor->GetEncoderOptions(); - ret = av_dict_parse_string(&opts, Options.c_str(), "=", ",#\n", 0); - if ( ret < 0 ) { - Warning("Could not parse ffmpeg encoder options list '%s'\n", Options.c_str()); - } else { - AVDictionaryEntry *e = NULL; - while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) { - Debug( 3, "Encoder Option %s=%s", e->key, e->value ); - } - } - - if ( ! av_dict_get( opts, "preset", NULL, 0 ) ) { - Debug(2,"Setting preset to superfast"); - av_dict_set( &opts, "preset", "superfast", 0 ); - } - - if ( (ret = avcodec_open2(video_out_ctx, video_out_codec, &opts)) < 0 ) { - Warning("Can't open video codec (%s)! %s, trying h264", - video_out_codec->name, - av_make_error_string(ret).c_str() - ); - video_out_codec = avcodec_find_encoder_by_name("h264"); + if ( monitor->OutputCodec() == "mjpeg" ) { + video_out_codec = avcodec_find_encoder_by_name("mjpeg"); if ( ! video_out_codec ) { - Error("Can't find h264 encoder"); - video_out_codec = avcodec_find_encoder_by_name("libx264"); + Debug(1, "Didn't find omx"); + video_out_codec = avcodec_find_encoder(AV_CODEC_ID_MJPEG); + } + video_out_ctx->codec_id = video_out_codec->id; + video_out_ctx->pix_fmt = AV_PIX_FMT_YUVJ422P; + + } else if ( monitor->OutputCodec() == "h264" ) { + video_out_codec = avcodec_find_encoder_by_name("h264_omx"); + if ( ! video_out_codec ) { + Debug(1, "Didn't find omx"); + video_out_codec = avcodec_find_encoder(AV_CODEC_ID_H264); + } + if ( !video_out_codec ) { + Fatal("Could not find codec for H264"); + } + Debug(2, "Have video out codec"); + + video_out_ctx->codec_id = AV_CODEC_ID_H264; + //video_in_ctx->sample_aspect_ratio; + /* take first format from list of supported formats */ + //video_out_ctx->pix_fmt = video_out_codec->pix_fmts[0]; + video_out_ctx->pix_fmt = AV_PIX_FMT_YUV420P; + /* video time_base can be set to whatever is handy and supported by encoder */ + video_out_ctx->time_base = (AVRational){1, 1000000}; // microseconds as base frame rate + video_out_ctx->framerate = (AVRational){0,1}; // Unknown framerate + video_out_ctx->gop_size = 12; + video_out_ctx->bit_rate = 4000000; + video_out_ctx->qmin = 10; + video_out_ctx->qmax = 51; + video_out_ctx->qcompress = 0.6; + + AVDictionary *opts = 0; + std::string Options = monitor->GetEncoderOptions(); + ret = av_dict_parse_string(&opts, Options.c_str(), "=", ",#\n", 0); + if ( ret < 0 ) { + Warning("Could not parse ffmpeg encoder options list '%s'\n", Options.c_str()); + } else { + AVDictionaryEntry *e = NULL; + while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) { + Debug( 3, "Encoder Option %s=%s", e->key, e->value ); + } + } + + if ( ! av_dict_get( opts, "preset", NULL, 0 ) ) { + Debug(2,"Setting preset to ultrafast"); + av_dict_set( &opts, "preset", "ultrafast", 0 ); + } + + if ( (ret = avcodec_open2(video_out_ctx, video_out_codec, &opts)) < 0 ) { + Warning("Can't open video codec (%s)! %s, trying h264", + video_out_codec->name, + av_make_error_string(ret).c_str() + ); + video_out_codec = avcodec_find_encoder_by_name("h264"); if ( ! video_out_codec ) { - Error("Can't find libx264 encoder"); + Error("Can't find h264 encoder"); + video_out_codec = avcodec_find_encoder_by_name("libx264"); + if ( ! video_out_codec ) { + Error("Can't find libx264 encoder"); + return; + } + } + if ( (ret = avcodec_open2(video_out_ctx, video_out_codec, &opts)) < 0 ) { + Error("Can't open video codec (%s)! %s", + video_out_codec->name, + av_make_error_string(ret).c_str() ); return; } } - if ( (ret = avcodec_open2(video_out_ctx, video_out_codec, &opts)) < 0 ) { - Error("Can't open video codec (%s)! %s", - video_out_codec->name, - av_make_error_string(ret).c_str() ); - return; + AVDictionaryEntry *e = NULL; + while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) { + Warning( "Encoder Option %s not recognized by ffmpeg codec", e->key); } - } - AVDictionaryEntry *e = NULL; - while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) { - Warning( "Encoder Option %s not recognized by ffmpeg codec", e->key); - } - av_dict_free(&opts); + av_dict_free(&opts); + if ( !video_out_ctx->codec_tag ) { + video_out_ctx->codec_tag = + av_codec_get_tag(oc->oformat->codec_tag, AV_CODEC_ID_H264 ); + Debug(2, "No codec_tag, setting to %d", video_out_ctx->codec_tag); + } + }// end if codec == h264 swscale.SetDefaults( video_in_ctx->pix_fmt, @@ -210,11 +227,6 @@ Debug(2,"About to copy aparames"); ); } // end if copying or trasncoding - if ( !video_out_ctx->codec_tag ) { - video_out_ctx->codec_tag = - av_codec_get_tag(oc->oformat->codec_tag, AV_CODEC_ID_H264 ); - Debug(2, "No codec_tag, setting to %d", video_out_ctx->codec_tag); - } video_out_stream = avformat_new_stream(oc, video_out_codec); if ( !video_out_stream ) { diff --git a/web/skins/classic/js/skin.js b/web/skins/classic/js/skin.js index 7f770b1cb..c3d225aa8 100644 --- a/web/skins/classic/js/skin.js +++ b/web/skins/classic/js/skin.js @@ -326,7 +326,7 @@ function changeGroup( e, depth ) { } function changeMonitor( e ) { var monitor_id = e.value; - Cookie.write( 'zmMonitorId', monitor_id, { duration: 10*365 } ); + Cookie.write( 'MonitorId', monitor_id, { duration: 10*365 } ); window.location = window.location; } function changeFilter( e ) { diff --git a/web/skins/classic/views/_monitor_filters.php b/web/skins/classic/views/_monitor_filters.php index c8607f845..1409d629e 100644 --- a/web/skins/classic/views/_monitor_filters.php +++ b/web/skins/classic/views/_monitor_filters.php @@ -97,12 +97,17 @@ $groupSql = Group::get_group_sql( $group_id ); $monitors_dropdown[$monitors[$i]['Id']] = $monitors[$i]['Name']; if ( $monitors[$i]['Id'] == $monitor_id ) { $found_selected_monitor = true; + } else { + Warning("didn't find monitor $monitor_id " . $monitors[$i]['Id'] ); } - } + } // end foreach monitor if ( ! $found_selected_monitor ) { $monitor_id = ''; } - } + } else { + Warning("Monitor id not specified"); + } // end if a monitor was specified + for ( $i = 0; $i < count($monitors); $i++ ) { if ( !visibleMonitor( $monitors[$i]['Id'] ) ) { continue; @@ -114,7 +119,7 @@ $groupSql = Group::get_group_sql( $group_id ); } $displayMonitors[] = $monitors[$i]; } - echo htmlSelect( 'MonitorId', $monitors_dropdown, $monitor_id, array('onchange'=>'changeMonitor(this);') ); + echo htmlSelect( 'MonitorId', $monitors_dropdown, $monitor_id, array('onchange'=>'changeFilter(this);') ); ?> DefaultVideo() and ( 'mp4' == pathinfo($Event->DefaultVideo(), PATHINFO_EXTENSION) ) ) { + $video_tag = true; +} // videojs zoomrotate only when direct recording $Zoom = 1; $Rotation = 0; @@ -150,7 +154,7 @@ if ( $Event->SaveJPEGs() & 3 ) { // Analysis or Jpegs
DefaultVideo() ) { +if ( $video_tag ) { ?>
@@ -170,7 +174,7 @@ if ( $Event->DefaultVideo() ) { -DefaultVideo()) { ?> +