Initial commit for saving events as videos :)

This commit is contained in:
Kfir Itzhak 2013-12-19 18:38:07 +02:00
parent 0556187a0f
commit 2b79ff2cbd
19 changed files with 1048 additions and 698 deletions

View File

@ -224,6 +224,40 @@ else(MYSQLCLIENT_LIBRARIES)
message(FATAL_ERROR "zm requires mysqlclient but it was not found on your system")
endif(MYSQLCLIENT_LIBRARIES)
# x264 (using find_library and find_path)
find_library(X264_LIBRARIES x264)
if(X264_LIBRARIES)
set(HAVE_LIBX264 1)
list(APPEND ZM_BIN_LIBS "${X264_LIBRARIES}")
find_path(X264_INCLUDE_DIR x264.h)
if(X264_INCLUDE_DIR)
include_directories("${X264_INCLUDE_DIR}")
set(CMAKE_REQUIRED_INCLUDES "${X264_INCLUDE_DIR}")
endif(X264_INCLUDE_DIR)
mark_as_advanced(FORCE X264_LIBRARIES X264_INCLUDE_DIR)
check_include_files("stdint.h;x264.h" HAVE_X264_H)
set(optlibsfound "${optlibsfound} x264")
else(X264_LIBRARIES)
set(optlibsnotfound "${optlibsnotfound} x264")
endif(X264_LIBRARIES)
# mp4v2 (using find_library and find_path)
find_library(MP4V2_LIBRARIES mp4v2)
if(MP4V2_LIBRARIES)
set(HAVE_LIBMP4V2 1)
list(APPEND ZM_BIN_LIBS "${MP4V2_LIBRARIES}")
find_path(MP4V2_INCLUDE_DIR mp4.h)
if(MP4V2_INCLUDE_DIR)
include_directories("${MP4V2_INCLUDE_DIR}")
set(CMAKE_REQUIRED_INCLUDES "${MP4V2_INCLUDE_DIR}")
endif(MP4V2_INCLUDE_DIR)
mark_as_advanced(FORCE MP4V2_LIBRARIES MP4V2_INCLUDE_DIR)
check_include_file("mp4.h" HAVE_MP4_H)
set(optlibsfound "${optlibsfound} mp4v2")
else(MP4V2_LIBRARIES)
set(optlibsnotfound "${optlibsnotfound} mp4v2")
endif(MP4V2_LIBRARIES)
set(PATH_FFMPEG "")
set(OPT_FFMPEG "no")
# Do not check for ffmpeg if ZM_NO_FFMPEG is on

View File

@ -266,6 +266,7 @@ fi
AC_CHECK_LIB(pcre,pcre_compile,,AC_MSG_WARN(libpcre.a may be required for remote/network camera support))
AC_CHECK_LIB(z,zlibVersion)
AC_CHECK_LIB(x264,x264_predict_16x16_init)
AC_CHECK_LIB(mp4v2,MP4AddH264VideoTrack)
AC_CHECK_LIB(avutil,av_malloc,,AC_MSG_WARN(libavutil.a may be required for MPEG streaming))
# Don't bother to warn about this one
AC_CHECK_LIB(avcore,av_image_copy,,)
@ -313,6 +314,8 @@ AC_CHECK_HEADERS(sys/ipc.h,,,)
AC_CHECK_HEADERS(sys/shm.h,,,)
fi
AC_CHECK_HEADERS(zlib.h,,,)
AC_CHECK_HEADERS(x264.h,,,)
AC_CHECK_HEADERS(mp4.h,,,)
if test "$ZM_SSL_LIB" == "openssl"; then
AC_CHECK_DECLS(MD5,,AC_MSG_ERROR([zm requires openssl/md5.h - use ZM_SSL_LIB option to select gnutls instead]),[#include <stdlib.h>

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.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_local_camera.cpp zm_monitor.cpp zm_ffmpeg.cpp zm_mpeg.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_sdp.cpp zm_signal.cpp zm_stream.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_zone.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.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_local_camera.cpp zm_monitor.cpp zm_ffmpeg.cpp zm_mpeg.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_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_zone.cpp)
# A fix for cmake recompiling the source files for every target.
add_library(zm STATIC ${ZM_BIN_SRC_FILES})

View File

@ -1,658 +0,0 @@
// The file is autogenerated by zmconfgen.pl
// Do not edit this file as any changes will be overwritten
#define ZM_LANG_DEFAULT 0
#define ZM_OPT_USE_AUTH 1
#define ZM_AUTH_TYPE 2
#define ZM_AUTH_RELAY 3
#define ZM_AUTH_HASH_SECRET 4
#define ZM_AUTH_HASH_IPS 5
#define ZM_AUTH_HASH_LOGINS 6
#define ZM_DIR_EVENTS 7
#define ZM_USE_DEEP_STORAGE 8
#define ZM_DIR_IMAGES 9
#define ZM_DIR_SOUNDS 10
#define ZM_PATH_ZMS 11
#define ZM_COLOUR_JPEG_FILES 12
#define ZM_ADD_JPEG_COMMENTS 13
#define ZM_JPEG_FILE_QUALITY 14
#define ZM_JPEG_ALARM_FILE_QUALITY 15
#define ZM_JPEG_IMAGE_QUALITY 16
#define ZM_JPEG_STREAM_QUALITY 17
#define ZM_MPEG_TIMED_FRAMES 18
#define ZM_MPEG_LIVE_FORMAT 19
#define ZM_MPEG_REPLAY_FORMAT 20
#define ZM_RAND_STREAM 21
#define ZM_OPT_CAMBOZOLA 22
#define ZM_PATH_CAMBOZOLA 23
#define ZM_RELOAD_CAMBOZOLA 24
#define ZM_TIMESTAMP_ON_CAPTURE 25
#define ZM_CPU_EXTENSIONS 26
#define ZM_FAST_IMAGE_BLENDS 27
#define ZM_OPT_ADAPTIVE_SKIP 28
#define ZM_MAX_SUSPEND_TIME 29
#define ZM_OPT_REMOTE_CAMERAS 30
#define ZM_NETCAM_REGEXPS 31
#define ZM_HTTP_VERSION 32
#define ZM_HTTP_UA 33
#define ZM_HTTP_TIMEOUT 34
#define ZM_MIN_RTP_PORT 35
#define ZM_MAX_RTP_PORT 36
#define ZM_OPT_FFMPEG 37
#define ZM_PATH_FFMPEG 38
#define ZM_FFMPEG_INPUT_OPTIONS 39
#define ZM_FFMPEG_OUTPUT_OPTIONS 40
#define ZM_FFMPEG_FORMATS 41
#define ZM_LOG_LEVEL_SYSLOG 42
#define ZM_LOG_LEVEL_FILE 43
#define ZM_LOG_LEVEL_WEBLOG 44
#define ZM_LOG_LEVEL_DATABASE 45
#define ZM_LOG_DATABASE_LIMIT 46
#define ZM_LOG_DEBUG 47
#define ZM_LOG_DEBUG_TARGET 48
#define ZM_LOG_DEBUG_LEVEL 49
#define ZM_LOG_DEBUG_FILE 50
#define ZM_LOG_CHECK_PERIOD 51
#define ZM_LOG_ALERT_WAR_COUNT 52
#define ZM_LOG_ALERT_ERR_COUNT 53
#define ZM_LOG_ALERT_FAT_COUNT 54
#define ZM_LOG_ALARM_WAR_COUNT 55
#define ZM_LOG_ALARM_ERR_COUNT 56
#define ZM_LOG_ALARM_FAT_COUNT 57
#define ZM_RECORD_EVENT_STATS 58
#define ZM_RECORD_DIAG_IMAGES 59
#define ZM_DUMP_CORES 60
#define ZM_PATH_MAP 61
#define ZM_PATH_SOCKS 62
#define ZM_PATH_LOGS 63
#define ZM_PATH_SWAP 64
#define ZM_WEB_TITLE_PREFIX 65
#define ZM_WEB_RESIZE_CONSOLE 66
#define ZM_WEB_POPUP_ON_ALARM 67
#define ZM_OPT_X10 68
#define ZM_X10_DEVICE 69
#define ZM_X10_HOUSE_CODE 70
#define ZM_X10_DB_RELOAD_INTERVAL 71
#define ZM_WEB_SOUND_ON_ALARM 72
#define ZM_WEB_ALARM_SOUND 73
#define ZM_WEB_COMPACT_MONTAGE 74
#define ZM_OPT_FAST_DELETE 75
#define ZM_STRICT_VIDEO_CONFIG 76
#define ZM_SIGNAL_CHECK_POINTS 77
#define ZM_V4L_MULTI_BUFFER 78
#define ZM_CAPTURES_PER_FRAME 79
#define ZM_FILTER_RELOAD_DELAY 80
#define ZM_FILTER_EXECUTE_INTERVAL 81
#define ZM_OPT_UPLOAD 82
#define ZM_UPLOAD_ARCH_FORMAT 83
#define ZM_UPLOAD_ARCH_COMPRESS 84
#define ZM_UPLOAD_ARCH_ANALYSE 85
#define ZM_UPLOAD_PROTOCOL 86
#define ZM_UPLOAD_FTP_HOST 87
#define ZM_UPLOAD_HOST 88
#define ZM_UPLOAD_PORT 89
#define ZM_UPLOAD_FTP_USER 90
#define ZM_UPLOAD_USER 91
#define ZM_UPLOAD_FTP_PASS 92
#define ZM_UPLOAD_PASS 93
#define ZM_UPLOAD_FTP_LOC_DIR 94
#define ZM_UPLOAD_LOC_DIR 95
#define ZM_UPLOAD_FTP_REM_DIR 96
#define ZM_UPLOAD_REM_DIR 97
#define ZM_UPLOAD_FTP_TIMEOUT 98
#define ZM_UPLOAD_TIMEOUT 99
#define ZM_UPLOAD_FTP_PASSIVE 100
#define ZM_UPLOAD_FTP_DEBUG 101
#define ZM_UPLOAD_DEBUG 102
#define ZM_OPT_EMAIL 103
#define ZM_EMAIL_ADDRESS 104
#define ZM_EMAIL_TEXT 105
#define ZM_EMAIL_SUBJECT 106
#define ZM_EMAIL_BODY 107
#define ZM_OPT_MESSAGE 108
#define ZM_MESSAGE_ADDRESS 109
#define ZM_MESSAGE_TEXT 110
#define ZM_MESSAGE_SUBJECT 111
#define ZM_MESSAGE_BODY 112
#define ZM_NEW_MAIL_MODULES 113
#define ZM_EMAIL_HOST 114
#define ZM_FROM_EMAIL 115
#define ZM_URL 116
#define ZM_MAX_RESTART_DELAY 117
#define ZM_WATCH_CHECK_INTERVAL 118
#define ZM_WATCH_MAX_DELAY 119
#define ZM_RUN_AUDIT 120
#define ZM_AUDIT_CHECK_INTERVAL 121
#define ZM_FORCED_ALARM_SCORE 122
#define ZM_BULK_FRAME_INTERVAL 123
#define ZM_EVENT_CLOSE_MODE 124
#define ZM_FORCE_CLOSE_EVENTS 125
#define ZM_CREATE_ANALYSIS_IMAGES 126
#define ZM_WEIGHTED_ALARM_CENTRES 127
#define ZM_EVENT_IMAGE_DIGITS 128
#define ZM_DEFAULT_ASPECT_RATIO 129
#define ZM_USER_SELF_EDIT 130
#define ZM_OPT_FRAME_SERVER 131
#define ZM_FRAME_SOCKET_SIZE 132
#define ZM_OPT_CONTROL 133
#define ZM_OPT_TRIGGERS 134
#define ZM_CHECK_FOR_UPDATES 135
#define ZM_UPDATE_CHECK_PROXY 136
#define ZM_SHM_KEY 137
#define ZM_WEB_REFRESH_METHOD 138
#define ZM_WEB_EVENT_SORT_FIELD 139
#define ZM_WEB_EVENT_SORT_ORDER 140
#define ZM_WEB_EVENTS_PER_PAGE 141
#define ZM_WEB_LIST_THUMBS 142
#define ZM_WEB_LIST_THUMB_WIDTH 143
#define ZM_WEB_LIST_THUMB_HEIGHT 144
#define ZM_WEB_USE_OBJECT_TAGS 145
#define ZM_WEB_H_REFRESH_MAIN 146
#define ZM_WEB_H_REFRESH_CYCLE 147
#define ZM_WEB_H_REFRESH_IMAGE 148
#define ZM_WEB_H_REFRESH_STATUS 149
#define ZM_WEB_H_REFRESH_EVENTS 150
#define ZM_WEB_H_CAN_STREAM 151
#define ZM_WEB_H_STREAM_METHOD 152
#define ZM_WEB_H_DEFAULT_SCALE 153
#define ZM_WEB_H_DEFAULT_RATE 154
#define ZM_WEB_H_VIDEO_BITRATE 155
#define ZM_WEB_H_VIDEO_MAXFPS 156
#define ZM_WEB_H_SCALE_THUMBS 157
#define ZM_WEB_H_EVENTS_VIEW 158
#define ZM_WEB_H_SHOW_PROGRESS 159
#define ZM_WEB_H_AJAX_TIMEOUT 160
#define ZM_WEB_M_REFRESH_MAIN 161
#define ZM_WEB_M_REFRESH_CYCLE 162
#define ZM_WEB_M_REFRESH_IMAGE 163
#define ZM_WEB_M_REFRESH_STATUS 164
#define ZM_WEB_M_REFRESH_EVENTS 165
#define ZM_WEB_M_CAN_STREAM 166
#define ZM_WEB_M_STREAM_METHOD 167
#define ZM_WEB_M_DEFAULT_SCALE 168
#define ZM_WEB_M_DEFAULT_RATE 169
#define ZM_WEB_M_VIDEO_BITRATE 170
#define ZM_WEB_M_VIDEO_MAXFPS 171
#define ZM_WEB_M_SCALE_THUMBS 172
#define ZM_WEB_M_EVENTS_VIEW 173
#define ZM_WEB_M_SHOW_PROGRESS 174
#define ZM_WEB_M_AJAX_TIMEOUT 175
#define ZM_WEB_L_REFRESH_MAIN 176
#define ZM_WEB_L_REFRESH_CYCLE 177
#define ZM_WEB_L_REFRESH_IMAGE 178
#define ZM_WEB_L_REFRESH_STATUS 179
#define ZM_WEB_L_REFRESH_EVENTS 180
#define ZM_WEB_L_CAN_STREAM 181
#define ZM_WEB_L_STREAM_METHOD 182
#define ZM_WEB_L_DEFAULT_SCALE 183
#define ZM_WEB_L_DEFAULT_RATE 184
#define ZM_WEB_L_VIDEO_BITRATE 185
#define ZM_WEB_L_VIDEO_MAXFPS 186
#define ZM_WEB_L_SCALE_THUMBS 187
#define ZM_WEB_L_EVENTS_VIEW 188
#define ZM_WEB_L_SHOW_PROGRESS 189
#define ZM_WEB_L_AJAX_TIMEOUT 190
#define ZM_WEB_P_CAN_STREAM 191
#define ZM_WEB_P_STREAM_METHOD 192
#define ZM_WEB_P_DEFAULT_SCALE 193
#define ZM_WEB_P_DEFAULT_RATE 194
#define ZM_WEB_P_VIDEO_BITRATE 195
#define ZM_WEB_P_VIDEO_MAXFPS 196
#define ZM_WEB_P_SCALE_THUMBS 197
#define ZM_WEB_P_AJAX_TIMEOUT 198
#define ZM_DYN_LAST_VERSION 199
#define ZM_DYN_CURR_VERSION 200
#define ZM_DYN_DB_VERSION 201
#define ZM_DYN_LAST_CHECK 202
#define ZM_DYN_NEXT_REMINDER 203
#define ZM_DYN_DONATE_REMINDER_TIME 204
#define ZM_DYN_SHOW_DONATE_REMINDER 205
#define ZM_EYEZM_DEBUG 206
#define ZM_EYEZM_LOG_TO_FILE 207
#define ZM_EYEZM_LOG_FILE 208
#define ZM_EYEZM_EVENT_VCODEC 209
#define ZM_EYEZM_FEED_VCODEC 210
#define ZM_EYEZM_H264_DEFAULT_BR 211
#define ZM_EYEZM_H264_DEFAULT_EVBR 212
#define ZM_EYEZM_H264_TIMEOUT 213
#define ZM_EYEZM_SEG_DURATION 214
#define ZM_MAX_CFG_ID 214
#define ZM_CFG_DECLARE_LIST \
const char *lang_default;\
bool opt_use_auth;\
const char *auth_type;\
const char *auth_relay;\
const char *auth_hash_secret;\
bool auth_hash_ips;\
bool auth_hash_logins;\
const char *dir_events;\
bool use_deep_storage;\
const char *dir_images;\
const char *dir_sounds;\
const char *path_zms;\
bool colour_jpeg_files;\
bool add_jpeg_comments;\
int jpeg_file_quality;\
int jpeg_alarm_file_quality;\
int jpeg_image_quality;\
int jpeg_stream_quality;\
bool mpeg_timed_frames;\
const char *mpeg_live_format;\
const char *mpeg_replay_format;\
bool rand_stream;\
bool opt_cambozola;\
const char *path_cambozola;\
int reload_cambozola;\
bool timestamp_on_capture;\
bool cpu_extensions;\
bool fast_image_blends;\
bool opt_adaptive_skip;\
int max_suspend_time;\
bool opt_remote_cameras;\
bool netcam_regexps;\
const char *http_version;\
const char *http_ua;\
int http_timeout;\
int min_rtp_port;\
int max_rtp_port;\
bool opt_ffmpeg;\
const char *path_ffmpeg;\
const char *ffmpeg_input_options;\
const char *ffmpeg_output_options;\
const char *ffmpeg_formats;\
int log_level_syslog;\
int log_level_file;\
int log_level_weblog;\
int log_level_database;\
const char *log_database_limit;\
bool log_debug;\
const char *log_debug_target;\
int log_debug_level;\
const char *log_debug_file;\
int log_check_period;\
int log_alert_war_count;\
int log_alert_err_count;\
int log_alert_fat_count;\
int log_alarm_war_count;\
int log_alarm_err_count;\
int log_alarm_fat_count;\
bool record_event_stats;\
bool record_diag_images;\
bool dump_cores;\
const char *path_map;\
const char *path_socks;\
const char *path_logs;\
const char *path_swap;\
const char *web_title_prefix;\
bool web_resize_console;\
bool web_popup_on_alarm;\
bool opt_x10;\
const char *x10_device;\
const char *x10_house_code;\
int x10_db_reload_interval;\
bool web_sound_on_alarm;\
const char *web_alarm_sound;\
bool web_compact_montage;\
bool opt_fast_delete;\
bool strict_video_config;\
int signal_check_points;\
bool v4l_multi_buffer;\
int captures_per_frame;\
int filter_reload_delay;\
int filter_execute_interval;\
bool opt_upload;\
const char *upload_arch_format;\
bool upload_arch_compress;\
bool upload_arch_analyse;\
const char *upload_protocol;\
const char *upload_ftp_host;\
const char *upload_host;\
int upload_port;\
const char *upload_ftp_user;\
const char *upload_user;\
const char *upload_ftp_pass;\
const char *upload_pass;\
const char *upload_ftp_loc_dir;\
const char *upload_loc_dir;\
const char *upload_ftp_rem_dir;\
const char *upload_rem_dir;\
int upload_ftp_timeout;\
int upload_timeout;\
bool upload_ftp_passive;\
bool upload_ftp_debug;\
bool upload_debug;\
bool opt_email;\
const char *email_address;\
const char *email_text;\
const char *email_subject;\
const char *email_body;\
bool opt_message;\
const char *message_address;\
const char *message_text;\
const char *message_subject;\
const char *message_body;\
bool new_mail_modules;\
const char *email_host;\
const char *from_email;\
const char *url;\
int max_restart_delay;\
int watch_check_interval;\
double watch_max_delay;\
bool run_audit;\
int audit_check_interval;\
int forced_alarm_score;\
int bulk_frame_interval;\
const char *event_close_mode;\
bool force_close_events;\
bool create_analysis_images;\
bool weighted_alarm_centres;\
int event_image_digits;\
const char *default_aspect_ratio;\
bool user_self_edit;\
bool opt_frame_server;\
int frame_socket_size;\
bool opt_control;\
bool opt_triggers;\
bool check_for_updates;\
const char *update_check_proxy;\
int shm_key;\
const char *web_refresh_method;\
const char *web_event_sort_field;\
const char *web_event_sort_order;\
int web_events_per_page;\
bool web_list_thumbs;\
int web_list_thumb_width;\
int web_list_thumb_height;\
bool web_use_object_tags;\
int web_h_refresh_main;\
int web_h_refresh_cycle;\
int web_h_refresh_image;\
int web_h_refresh_status;\
int web_h_refresh_events;\
const char *web_h_can_stream;\
const char *web_h_stream_method;\
int web_h_default_scale;\
int web_h_default_rate;\
int web_h_video_bitrate;\
int web_h_video_maxfps;\
bool web_h_scale_thumbs;\
const char *web_h_events_view;\
bool web_h_show_progress;\
int web_h_ajax_timeout;\
int web_m_refresh_main;\
int web_m_refresh_cycle;\
int web_m_refresh_image;\
int web_m_refresh_status;\
int web_m_refresh_events;\
const char *web_m_can_stream;\
const char *web_m_stream_method;\
int web_m_default_scale;\
int web_m_default_rate;\
int web_m_video_bitrate;\
int web_m_video_maxfps;\
bool web_m_scale_thumbs;\
const char *web_m_events_view;\
bool web_m_show_progress;\
int web_m_ajax_timeout;\
int web_l_refresh_main;\
int web_l_refresh_cycle;\
int web_l_refresh_image;\
int web_l_refresh_status;\
int web_l_refresh_events;\
const char *web_l_can_stream;\
const char *web_l_stream_method;\
int web_l_default_scale;\
int web_l_default_rate;\
int web_l_video_bitrate;\
int web_l_video_maxfps;\
bool web_l_scale_thumbs;\
const char *web_l_events_view;\
bool web_l_show_progress;\
int web_l_ajax_timeout;\
const char *web_p_can_stream;\
const char *web_p_stream_method;\
int web_p_default_scale;\
int web_p_default_rate;\
int web_p_video_bitrate;\
int web_p_video_maxfps;\
bool web_p_scale_thumbs;\
int web_p_ajax_timeout;\
const char *dyn_last_version;\
const char *dyn_curr_version;\
const char *dyn_db_version;\
int dyn_last_check;\
const char *dyn_next_reminder;\
int dyn_donate_reminder_time;\
bool dyn_show_donate_reminder;\
bool eyezm_debug;\
bool eyezm_log_to_file;\
const char *eyezm_log_file;\
const char *eyezm_event_vcodec;\
const char *eyezm_feed_vcodec;\
const char *eyezm_h264_default_br;\
const char *eyezm_h264_default_evbr;\
const char *eyezm_h264_timeout;\
const char *eyezm_seg_duration;\
#define ZM_CFG_ASSIGN_LIST \
lang_default = (const char *)config.Item( ZM_LANG_DEFAULT );\
opt_use_auth = (bool)config.Item( ZM_OPT_USE_AUTH );\
auth_type = (const char *)config.Item( ZM_AUTH_TYPE );\
auth_relay = (const char *)config.Item( ZM_AUTH_RELAY );\
auth_hash_secret = (const char *)config.Item( ZM_AUTH_HASH_SECRET );\
auth_hash_ips = (bool)config.Item( ZM_AUTH_HASH_IPS );\
auth_hash_logins = (bool)config.Item( ZM_AUTH_HASH_LOGINS );\
dir_events = (const char *)config.Item( ZM_DIR_EVENTS );\
use_deep_storage = (bool)config.Item( ZM_USE_DEEP_STORAGE );\
dir_images = (const char *)config.Item( ZM_DIR_IMAGES );\
dir_sounds = (const char *)config.Item( ZM_DIR_SOUNDS );\
path_zms = (const char *)config.Item( ZM_PATH_ZMS );\
colour_jpeg_files = (bool)config.Item( ZM_COLOUR_JPEG_FILES );\
add_jpeg_comments = (bool)config.Item( ZM_ADD_JPEG_COMMENTS );\
jpeg_file_quality = (int)config.Item( ZM_JPEG_FILE_QUALITY );\
jpeg_alarm_file_quality = (int)config.Item( ZM_JPEG_ALARM_FILE_QUALITY );\
jpeg_image_quality = (int)config.Item( ZM_JPEG_IMAGE_QUALITY );\
jpeg_stream_quality = (int)config.Item( ZM_JPEG_STREAM_QUALITY );\
mpeg_timed_frames = (bool)config.Item( ZM_MPEG_TIMED_FRAMES );\
mpeg_live_format = (const char *)config.Item( ZM_MPEG_LIVE_FORMAT );\
mpeg_replay_format = (const char *)config.Item( ZM_MPEG_REPLAY_FORMAT );\
rand_stream = (bool)config.Item( ZM_RAND_STREAM );\
opt_cambozola = (bool)config.Item( ZM_OPT_CAMBOZOLA );\
path_cambozola = (const char *)config.Item( ZM_PATH_CAMBOZOLA );\
reload_cambozola = (int)config.Item( ZM_RELOAD_CAMBOZOLA );\
timestamp_on_capture = (bool)config.Item( ZM_TIMESTAMP_ON_CAPTURE );\
cpu_extensions = (bool)config.Item( ZM_CPU_EXTENSIONS );\
fast_image_blends = (bool)config.Item( ZM_FAST_IMAGE_BLENDS );\
opt_adaptive_skip = (bool)config.Item( ZM_OPT_ADAPTIVE_SKIP );\
max_suspend_time = (int)config.Item( ZM_MAX_SUSPEND_TIME );\
opt_remote_cameras = (bool)config.Item( ZM_OPT_REMOTE_CAMERAS );\
netcam_regexps = (bool)config.Item( ZM_NETCAM_REGEXPS );\
http_version = (const char *)config.Item( ZM_HTTP_VERSION );\
http_ua = (const char *)config.Item( ZM_HTTP_UA );\
http_timeout = (int)config.Item( ZM_HTTP_TIMEOUT );\
min_rtp_port = (int)config.Item( ZM_MIN_RTP_PORT );\
max_rtp_port = (int)config.Item( ZM_MAX_RTP_PORT );\
opt_ffmpeg = (bool)config.Item( ZM_OPT_FFMPEG );\
path_ffmpeg = (const char *)config.Item( ZM_PATH_FFMPEG );\
ffmpeg_input_options = (const char *)config.Item( ZM_FFMPEG_INPUT_OPTIONS );\
ffmpeg_output_options = (const char *)config.Item( ZM_FFMPEG_OUTPUT_OPTIONS );\
ffmpeg_formats = (const char *)config.Item( ZM_FFMPEG_FORMATS );\
log_level_syslog = (int)config.Item( ZM_LOG_LEVEL_SYSLOG );\
log_level_file = (int)config.Item( ZM_LOG_LEVEL_FILE );\
log_level_weblog = (int)config.Item( ZM_LOG_LEVEL_WEBLOG );\
log_level_database = (int)config.Item( ZM_LOG_LEVEL_DATABASE );\
log_database_limit = (const char *)config.Item( ZM_LOG_DATABASE_LIMIT );\
log_debug = (bool)config.Item( ZM_LOG_DEBUG );\
log_debug_target = (const char *)config.Item( ZM_LOG_DEBUG_TARGET );\
log_debug_level = (int)config.Item( ZM_LOG_DEBUG_LEVEL );\
log_debug_file = (const char *)config.Item( ZM_LOG_DEBUG_FILE );\
log_check_period = (int)config.Item( ZM_LOG_CHECK_PERIOD );\
log_alert_war_count = (int)config.Item( ZM_LOG_ALERT_WAR_COUNT );\
log_alert_err_count = (int)config.Item( ZM_LOG_ALERT_ERR_COUNT );\
log_alert_fat_count = (int)config.Item( ZM_LOG_ALERT_FAT_COUNT );\
log_alarm_war_count = (int)config.Item( ZM_LOG_ALARM_WAR_COUNT );\
log_alarm_err_count = (int)config.Item( ZM_LOG_ALARM_ERR_COUNT );\
log_alarm_fat_count = (int)config.Item( ZM_LOG_ALARM_FAT_COUNT );\
record_event_stats = (bool)config.Item( ZM_RECORD_EVENT_STATS );\
record_diag_images = (bool)config.Item( ZM_RECORD_DIAG_IMAGES );\
dump_cores = (bool)config.Item( ZM_DUMP_CORES );\
path_map = (const char *)config.Item( ZM_PATH_MAP );\
path_socks = (const char *)config.Item( ZM_PATH_SOCKS );\
path_logs = (const char *)config.Item( ZM_PATH_LOGS );\
path_swap = (const char *)config.Item( ZM_PATH_SWAP );\
web_title_prefix = (const char *)config.Item( ZM_WEB_TITLE_PREFIX );\
web_resize_console = (bool)config.Item( ZM_WEB_RESIZE_CONSOLE );\
web_popup_on_alarm = (bool)config.Item( ZM_WEB_POPUP_ON_ALARM );\
opt_x10 = (bool)config.Item( ZM_OPT_X10 );\
x10_device = (const char *)config.Item( ZM_X10_DEVICE );\
x10_house_code = (const char *)config.Item( ZM_X10_HOUSE_CODE );\
x10_db_reload_interval = (int)config.Item( ZM_X10_DB_RELOAD_INTERVAL );\
web_sound_on_alarm = (bool)config.Item( ZM_WEB_SOUND_ON_ALARM );\
web_alarm_sound = (const char *)config.Item( ZM_WEB_ALARM_SOUND );\
web_compact_montage = (bool)config.Item( ZM_WEB_COMPACT_MONTAGE );\
opt_fast_delete = (bool)config.Item( ZM_OPT_FAST_DELETE );\
strict_video_config = (bool)config.Item( ZM_STRICT_VIDEO_CONFIG );\
signal_check_points = (int)config.Item( ZM_SIGNAL_CHECK_POINTS );\
v4l_multi_buffer = (bool)config.Item( ZM_V4L_MULTI_BUFFER );\
captures_per_frame = (int)config.Item( ZM_CAPTURES_PER_FRAME );\
filter_reload_delay = (int)config.Item( ZM_FILTER_RELOAD_DELAY );\
filter_execute_interval = (int)config.Item( ZM_FILTER_EXECUTE_INTERVAL );\
opt_upload = (bool)config.Item( ZM_OPT_UPLOAD );\
upload_arch_format = (const char *)config.Item( ZM_UPLOAD_ARCH_FORMAT );\
upload_arch_compress = (bool)config.Item( ZM_UPLOAD_ARCH_COMPRESS );\
upload_arch_analyse = (bool)config.Item( ZM_UPLOAD_ARCH_ANALYSE );\
upload_protocol = (const char *)config.Item( ZM_UPLOAD_PROTOCOL );\
upload_ftp_host = (const char *)config.Item( ZM_UPLOAD_FTP_HOST );\
upload_host = (const char *)config.Item( ZM_UPLOAD_HOST );\
upload_port = (int)config.Item( ZM_UPLOAD_PORT );\
upload_ftp_user = (const char *)config.Item( ZM_UPLOAD_FTP_USER );\
upload_user = (const char *)config.Item( ZM_UPLOAD_USER );\
upload_ftp_pass = (const char *)config.Item( ZM_UPLOAD_FTP_PASS );\
upload_pass = (const char *)config.Item( ZM_UPLOAD_PASS );\
upload_ftp_loc_dir = (const char *)config.Item( ZM_UPLOAD_FTP_LOC_DIR );\
upload_loc_dir = (const char *)config.Item( ZM_UPLOAD_LOC_DIR );\
upload_ftp_rem_dir = (const char *)config.Item( ZM_UPLOAD_FTP_REM_DIR );\
upload_rem_dir = (const char *)config.Item( ZM_UPLOAD_REM_DIR );\
upload_ftp_timeout = (int)config.Item( ZM_UPLOAD_FTP_TIMEOUT );\
upload_timeout = (int)config.Item( ZM_UPLOAD_TIMEOUT );\
upload_ftp_passive = (bool)config.Item( ZM_UPLOAD_FTP_PASSIVE );\
upload_ftp_debug = (bool)config.Item( ZM_UPLOAD_FTP_DEBUG );\
upload_debug = (bool)config.Item( ZM_UPLOAD_DEBUG );\
opt_email = (bool)config.Item( ZM_OPT_EMAIL );\
email_address = (const char *)config.Item( ZM_EMAIL_ADDRESS );\
email_text = (const char *)config.Item( ZM_EMAIL_TEXT );\
email_subject = (const char *)config.Item( ZM_EMAIL_SUBJECT );\
email_body = (const char *)config.Item( ZM_EMAIL_BODY );\
opt_message = (bool)config.Item( ZM_OPT_MESSAGE );\
message_address = (const char *)config.Item( ZM_MESSAGE_ADDRESS );\
message_text = (const char *)config.Item( ZM_MESSAGE_TEXT );\
message_subject = (const char *)config.Item( ZM_MESSAGE_SUBJECT );\
message_body = (const char *)config.Item( ZM_MESSAGE_BODY );\
new_mail_modules = (bool)config.Item( ZM_NEW_MAIL_MODULES );\
email_host = (const char *)config.Item( ZM_EMAIL_HOST );\
from_email = (const char *)config.Item( ZM_FROM_EMAIL );\
url = (const char *)config.Item( ZM_URL );\
max_restart_delay = (int)config.Item( ZM_MAX_RESTART_DELAY );\
watch_check_interval = (int)config.Item( ZM_WATCH_CHECK_INTERVAL );\
watch_max_delay = (double) config.Item( ZM_WATCH_MAX_DELAY );\
run_audit = (bool)config.Item( ZM_RUN_AUDIT );\
audit_check_interval = (int)config.Item( ZM_AUDIT_CHECK_INTERVAL );\
forced_alarm_score = (int)config.Item( ZM_FORCED_ALARM_SCORE );\
bulk_frame_interval = (int)config.Item( ZM_BULK_FRAME_INTERVAL );\
event_close_mode = (const char *)config.Item( ZM_EVENT_CLOSE_MODE );\
force_close_events = (bool)config.Item( ZM_FORCE_CLOSE_EVENTS );\
create_analysis_images = (bool)config.Item( ZM_CREATE_ANALYSIS_IMAGES );\
weighted_alarm_centres = (bool)config.Item( ZM_WEIGHTED_ALARM_CENTRES );\
event_image_digits = (int)config.Item( ZM_EVENT_IMAGE_DIGITS );\
default_aspect_ratio = (const char *)config.Item( ZM_DEFAULT_ASPECT_RATIO );\
user_self_edit = (bool)config.Item( ZM_USER_SELF_EDIT );\
opt_frame_server = (bool)config.Item( ZM_OPT_FRAME_SERVER );\
frame_socket_size = (int)config.Item( ZM_FRAME_SOCKET_SIZE );\
opt_control = (bool)config.Item( ZM_OPT_CONTROL );\
opt_triggers = (bool)config.Item( ZM_OPT_TRIGGERS );\
check_for_updates = (bool)config.Item( ZM_CHECK_FOR_UPDATES );\
update_check_proxy = (const char *)config.Item( ZM_UPDATE_CHECK_PROXY );\
shm_key = (int)config.Item( ZM_SHM_KEY );\
web_refresh_method = (const char *)config.Item( ZM_WEB_REFRESH_METHOD );\
web_event_sort_field = (const char *)config.Item( ZM_WEB_EVENT_SORT_FIELD );\
web_event_sort_order = (const char *)config.Item( ZM_WEB_EVENT_SORT_ORDER );\
web_events_per_page = (int)config.Item( ZM_WEB_EVENTS_PER_PAGE );\
web_list_thumbs = (bool)config.Item( ZM_WEB_LIST_THUMBS );\
web_list_thumb_width = (int)config.Item( ZM_WEB_LIST_THUMB_WIDTH );\
web_list_thumb_height = (int)config.Item( ZM_WEB_LIST_THUMB_HEIGHT );\
web_use_object_tags = (bool)config.Item( ZM_WEB_USE_OBJECT_TAGS );\
web_h_refresh_main = (int)config.Item( ZM_WEB_H_REFRESH_MAIN );\
web_h_refresh_cycle = (int)config.Item( ZM_WEB_H_REFRESH_CYCLE );\
web_h_refresh_image = (int)config.Item( ZM_WEB_H_REFRESH_IMAGE );\
web_h_refresh_status = (int)config.Item( ZM_WEB_H_REFRESH_STATUS );\
web_h_refresh_events = (int)config.Item( ZM_WEB_H_REFRESH_EVENTS );\
web_h_can_stream = (const char *)config.Item( ZM_WEB_H_CAN_STREAM );\
web_h_stream_method = (const char *)config.Item( ZM_WEB_H_STREAM_METHOD );\
web_h_default_scale = (int)config.Item( ZM_WEB_H_DEFAULT_SCALE );\
web_h_default_rate = (int)config.Item( ZM_WEB_H_DEFAULT_RATE );\
web_h_video_bitrate = (int)config.Item( ZM_WEB_H_VIDEO_BITRATE );\
web_h_video_maxfps = (int)config.Item( ZM_WEB_H_VIDEO_MAXFPS );\
web_h_scale_thumbs = (bool)config.Item( ZM_WEB_H_SCALE_THUMBS );\
web_h_events_view = (const char *)config.Item( ZM_WEB_H_EVENTS_VIEW );\
web_h_show_progress = (bool)config.Item( ZM_WEB_H_SHOW_PROGRESS );\
web_h_ajax_timeout = (int)config.Item( ZM_WEB_H_AJAX_TIMEOUT );\
web_m_refresh_main = (int)config.Item( ZM_WEB_M_REFRESH_MAIN );\
web_m_refresh_cycle = (int)config.Item( ZM_WEB_M_REFRESH_CYCLE );\
web_m_refresh_image = (int)config.Item( ZM_WEB_M_REFRESH_IMAGE );\
web_m_refresh_status = (int)config.Item( ZM_WEB_M_REFRESH_STATUS );\
web_m_refresh_events = (int)config.Item( ZM_WEB_M_REFRESH_EVENTS );\
web_m_can_stream = (const char *)config.Item( ZM_WEB_M_CAN_STREAM );\
web_m_stream_method = (const char *)config.Item( ZM_WEB_M_STREAM_METHOD );\
web_m_default_scale = (int)config.Item( ZM_WEB_M_DEFAULT_SCALE );\
web_m_default_rate = (int)config.Item( ZM_WEB_M_DEFAULT_RATE );\
web_m_video_bitrate = (int)config.Item( ZM_WEB_M_VIDEO_BITRATE );\
web_m_video_maxfps = (int)config.Item( ZM_WEB_M_VIDEO_MAXFPS );\
web_m_scale_thumbs = (bool)config.Item( ZM_WEB_M_SCALE_THUMBS );\
web_m_events_view = (const char *)config.Item( ZM_WEB_M_EVENTS_VIEW );\
web_m_show_progress = (bool)config.Item( ZM_WEB_M_SHOW_PROGRESS );\
web_m_ajax_timeout = (int)config.Item( ZM_WEB_M_AJAX_TIMEOUT );\
web_l_refresh_main = (int)config.Item( ZM_WEB_L_REFRESH_MAIN );\
web_l_refresh_cycle = (int)config.Item( ZM_WEB_L_REFRESH_CYCLE );\
web_l_refresh_image = (int)config.Item( ZM_WEB_L_REFRESH_IMAGE );\
web_l_refresh_status = (int)config.Item( ZM_WEB_L_REFRESH_STATUS );\
web_l_refresh_events = (int)config.Item( ZM_WEB_L_REFRESH_EVENTS );\
web_l_can_stream = (const char *)config.Item( ZM_WEB_L_CAN_STREAM );\
web_l_stream_method = (const char *)config.Item( ZM_WEB_L_STREAM_METHOD );\
web_l_default_scale = (int)config.Item( ZM_WEB_L_DEFAULT_SCALE );\
web_l_default_rate = (int)config.Item( ZM_WEB_L_DEFAULT_RATE );\
web_l_video_bitrate = (int)config.Item( ZM_WEB_L_VIDEO_BITRATE );\
web_l_video_maxfps = (int)config.Item( ZM_WEB_L_VIDEO_MAXFPS );\
web_l_scale_thumbs = (bool)config.Item( ZM_WEB_L_SCALE_THUMBS );\
web_l_events_view = (const char *)config.Item( ZM_WEB_L_EVENTS_VIEW );\
web_l_show_progress = (bool)config.Item( ZM_WEB_L_SHOW_PROGRESS );\
web_l_ajax_timeout = (int)config.Item( ZM_WEB_L_AJAX_TIMEOUT );\
web_p_can_stream = (const char *)config.Item( ZM_WEB_P_CAN_STREAM );\
web_p_stream_method = (const char *)config.Item( ZM_WEB_P_STREAM_METHOD );\
web_p_default_scale = (int)config.Item( ZM_WEB_P_DEFAULT_SCALE );\
web_p_default_rate = (int)config.Item( ZM_WEB_P_DEFAULT_RATE );\
web_p_video_bitrate = (int)config.Item( ZM_WEB_P_VIDEO_BITRATE );\
web_p_video_maxfps = (int)config.Item( ZM_WEB_P_VIDEO_MAXFPS );\
web_p_scale_thumbs = (bool)config.Item( ZM_WEB_P_SCALE_THUMBS );\
web_p_ajax_timeout = (int)config.Item( ZM_WEB_P_AJAX_TIMEOUT );\
dyn_last_version = (const char *)config.Item( ZM_DYN_LAST_VERSION );\
dyn_curr_version = (const char *)config.Item( ZM_DYN_CURR_VERSION );\
dyn_db_version = (const char *)config.Item( ZM_DYN_DB_VERSION );\
dyn_last_check = (int)config.Item( ZM_DYN_LAST_CHECK );\
dyn_next_reminder = (const char *)config.Item( ZM_DYN_NEXT_REMINDER );\
dyn_donate_reminder_time = (int)config.Item( ZM_DYN_DONATE_REMINDER_TIME );\
dyn_show_donate_reminder = (bool)config.Item( ZM_DYN_SHOW_DONATE_REMINDER );\
eyezm_debug = (bool)config.Item( ZM_EYEZM_DEBUG );\
eyezm_log_to_file = (bool)config.Item( ZM_EYEZM_LOG_TO_FILE );\
eyezm_log_file = (const char *)config.Item( ZM_EYEZM_LOG_FILE );\
eyezm_event_vcodec = (const char *)config.Item( ZM_EYEZM_EVENT_VCODEC );\
eyezm_feed_vcodec = (const char *)config.Item( ZM_EYEZM_FEED_VCODEC );\
eyezm_h264_default_br = (const char *)config.Item( ZM_EYEZM_H264_DEFAULT_BR );\
eyezm_h264_default_evbr = (const char *)config.Item( ZM_EYEZM_H264_DEFAULT_EVBR );\
eyezm_h264_timeout = (const char *)config.Item( ZM_EYEZM_H264_TIMEOUT );\
eyezm_seg_duration = (const char *)config.Item( ZM_EYEZM_SEG_DURATION );\

View File

@ -48,6 +48,7 @@ bool Event::initialised = false;
char Event::capture_file_format[PATH_MAX];
char Event::analyse_file_format[PATH_MAX];
char Event::general_file_format[PATH_MAX];
char Event::video_file_format[PATH_MAX];
int Event::pre_alarm_count = 0;
Event::PreAlarmData Event::pre_alarm_data[MAX_PRE_ALARM_FRAMES] = { { 0 } };
@ -161,6 +162,48 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
Fatal( "Can't fopen %s: %s", id_file, strerror(errno));
}
last_db_frame = 0;
video_name[0] = 0;
/* Save as video */
if ( monitor->GetOptVideoWriter() != 0 ) {
int nRet;
snprintf( video_name, sizeof(video_name), "%d-%s", id, "video.mp4" );
snprintf( video_file, sizeof(video_file), video_file_format, path, video_name );
snprintf( timecodes_name, sizeof(timecodes_name), "%d-%s", id, "video.timecodes" );
snprintf( timecodes_file, sizeof(timecodes_file), video_file_format, path, timecodes_name );
/* X264 MP4 video writer */
if(monitor->GetOptVideoWriter() == 1) {
#if ZM_HAVE_VIDEOWRITER_X264MP4
videowriter = new X264MP4Writer(video_file, monitor->Width(), monitor->Height(), monitor->Colours(), monitor->SubpixelOrder(), monitor->GetOptEncoderParams());
#else
videowriter = NULL;
Error("ZoneMinder was not compiled with the X264 MP4 video writer, check dependencies (x264 and mp4v2)");
#endif
}
if(videowriter != NULL) {
/* Open the video stream */
nRet = videowriter->Open();
if(nRet != 0) {
Error("Failed opening video stream");
delete videowriter;
videowriter = NULL;
}
/* Create timecodes file */
timecodes_fd = fopen(timecodes_file, "wb");
if(timecodes_fd == NULL) {
Error("Failed creating timecodes file");
}
}
} else {
/* No video object */
videowriter = NULL;
}
}
Event::~Event()
@ -180,12 +223,28 @@ Event::~Event()
}
}
/* Close the video file */
if ( videowriter != NULL ) {
int nRet;
nRet = videowriter->Close();
if(nRet != 0) {
Error("Failed closing video stream");
}
delete videowriter;
videowriter = NULL;
/* Close the timecodes file */
fclose(timecodes_fd);
timecodes_fd = NULL;
}
static char sql[ZM_SQL_MED_BUFSIZ];
struct DeltaTimeval delta_time;
DELTA_TIMEVAL( delta_time, end_time, start_time, DT_PREC_2 );
snprintf( sql, sizeof(sql), "update Events set Name='%s%d', EndTime = from_unixtime( %ld ), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d where Id = %d", monitor->EventPrefix(), id, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, frames, alarm_frames, tot_score, (int)(alarm_frames?(tot_score/alarm_frames):0), max_score, id );
snprintf( sql, sizeof(sql), "update Events set Name='%s%d', EndTime = from_unixtime( %ld ), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d, DefaultVideo = '%s' where Id = %d", monitor->EventPrefix(), id, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, frames, alarm_frames, tot_score, (int)(alarm_frames?(tot_score/alarm_frames):0), max_score, video_name, id );
if ( mysql_query( &dbconn, sql ) )
{
Error( "Can't update event: %s", mysql_error( &dbconn ) );
@ -368,6 +427,40 @@ bool Event::WriteFrameImage( Image *image, struct timeval timestamp, const char
return( true );
}
bool Event::WriteFrameVideo( const Image *image, const struct timeval timestamp, VideoWriter* videow )
{
const Image* frameimg = image;
Image ts_image;
/* Checking for invalid parameters */
if ( videow == NULL ) {
Error("NULL Video object");
return false;
}
/* If the image does not contain a timestamp, add the timestamp */
if (!config.timestamp_on_capture) {
ts_image = *image;
monitor->TimestampImage( &ts_image, &timestamp );
frameimg = &ts_image;
}
/* Calculate delta time */
struct DeltaTimeval delta_time3;
DELTA_TIMEVAL( delta_time3, timestamp, start_time, DT_PREC_3 );
unsigned int timeMS = (delta_time3.sec * delta_time3.prec) + delta_time3.fsec;
/* Encode and write the frame */
if(videowriter->Encode(image, timeMS) != 0) {
Error("Failed encoding video frame");
}
/* Add the frame to the timecodes file */
fprintf(timecodes_fd, "%u\n", timeMS);
return( true );
}
void Event::updateNotes( const StringSetMap &newNoteSetMap )
{
bool update = false;
@ -514,7 +607,13 @@ void Event::AddFramesInternal( int n_frames, int start_frame, Image **images, st
snprintf( event_file, sizeof(event_file), capture_file_format, path, frames );
Debug( 1, "Writing pre-capture frame %d", frames );
if ( monitor->GetOptSaveJPEGs() & 1) {
WriteFrameImage( images[i], *(timestamps[i]), event_file );
}
if ( videowriter != NULL ) {
WriteFrameVideo( images[i], *(timestamps[i]), videowriter );
}
struct DeltaTimeval delta_time;
DELTA_TIMEVAL( delta_time, *(timestamps[i]), start_time, DT_PREC_2 );
@ -556,7 +655,13 @@ void Event::AddFrame( Image *image, struct timeval timestamp, int score, Image *
snprintf( event_file, sizeof(event_file), capture_file_format, path, frames );
Debug( 1, "Writing capture frame %d", frames );
if( monitor->GetOptSaveJPEGs() & 1) {
WriteFrameImage( image, timestamp, event_file );
}
if ( videowriter != NULL ) {
WriteFrameVideo( image, timestamp, videowriter );
}
struct DeltaTimeval delta_time;
DELTA_TIMEVAL( delta_time, timestamp, start_time, DT_PREC_2 );
@ -604,9 +709,11 @@ void Event::AddFrame( Image *image, struct timeval timestamp, int score, Image *
snprintf( event_file, sizeof(event_file), analyse_file_format, path, frames );
Debug( 1, "Writing analysis frame %d", frames );
if ( monitor->GetOptSaveJPEGs() & 2) {
WriteFrameImage( alarm_image, timestamp, event_file, true );
}
}
}
/* This makes viewing the diagnostic images impossible because it keeps deleting them
if ( config.record_diag_images )

View File

@ -37,6 +37,7 @@
#include "zm.h"
#include "zm_image.h"
#include "zm_stream.h"
#include "zm_video.h"
class Zone;
class Monitor;
@ -55,6 +56,7 @@ protected:
static char capture_file_format[PATH_MAX];
static char analyse_file_format[PATH_MAX];
static char general_file_format[PATH_MAX];
static char video_file_format[PATH_MAX];
protected:
static int sd;
@ -89,6 +91,12 @@ protected:
unsigned int tot_score;
unsigned int max_score;
char path[PATH_MAX];
VideoWriter* videowriter;
FILE* timecodes_fd;
char video_name[PATH_MAX];
char video_file[PATH_MAX];
char timecodes_name[PATH_MAX];
char timecodes_file[PATH_MAX];
protected:
int last_db_frame;
@ -102,6 +110,7 @@ protected:
snprintf( capture_file_format, sizeof(capture_file_format), "%%s/%%0%dd-capture.jpg", config.event_image_digits );
snprintf( analyse_file_format, sizeof(analyse_file_format), "%%s/%%0%dd-analyse.jpg", config.event_image_digits );
snprintf( general_file_format, sizeof(general_file_format), "%%s/%%0%dd-%%s", config.event_image_digits );
snprintf( video_file_format, sizeof(video_file_format), "%%s/%%s");
initialised = true;
}
@ -127,6 +136,7 @@ public:
bool SendFrameImage( const Image *image, bool alarm_frame=false );
bool WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame=false );
bool WriteFrameVideo( const Image *image, const struct timeval timestamp, VideoWriter* videow );
void updateNotes( const StringSetMap &stringSetMap );

View File

@ -23,6 +23,16 @@
#if HAVE_LIBAVCODEC || HAVE_LIBAVUTIL || HAVE_LIBSWSCALE
void FFMPEGInit() {
static bool bInit = false;
if(!bInit) {
av_register_all();
av_log_set_level(AV_LOG_DEBUG);
bInit = true;
}
}
#if HAVE_LIBAVUTIL
enum PixelFormat GetFFMPEGPixelFormat(unsigned int p_colours, unsigned p_subpixelorder) {
enum PixelFormat pf;
@ -124,10 +134,7 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
Error("NULL Input or output buffer");
return -1;
}
if(in_pf == 0 || out_pf == 0) {
Error("Invalid input or output pixel formats");
return -2;
}
if(!width || !height) {
Error("Invalid width or height");
return -3;
@ -154,7 +161,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( NULL, width, height, in_pf, width, height, out_pf, SWS_FAST_BILINEAR, NULL, NULL, NULL );
if(swscale_ctx == NULL) {
Error("Failed getting swscale context");
return -6;

View File

@ -97,6 +97,8 @@ extern "C" {
#define SWS_CPU_CAPS_SSE2 0x02000000
#endif
/* A single function to initialize ffmpeg, to avoid multiple initializations */
void FFMPEGInit();
#if HAVE_LIBAVUTIL
enum PixelFormat GetFFMPEGPixelFormat(unsigned int p_colours, unsigned p_subpixelorder);

View File

@ -28,6 +28,7 @@
#include "zm_mpeg.h"
#include "zm_signal.h"
#include "zm_monitor.h"
#include "zm_video.h"
#if ZM_HAS_V4L
#include "zm_local_camera.h"
#endif // ZM_HAS_V4L
@ -274,6 +275,9 @@ Monitor::Monitor(
Camera *p_camera,
int p_orientation,
unsigned int p_deinterlacing,
int p_savejpegs,
int p_videowriter,
std::string p_encoderparams,
const char *p_event_prefix,
const char *p_label_format,
const Coord &p_label_coord,
@ -302,6 +306,9 @@ Monitor::Monitor(
height( (p_orientation==ROTATE_90||p_orientation==ROTATE_270)?p_camera->Width():p_camera->Height() ),
orientation( (Orientation)p_orientation ),
deinterlacing( p_deinterlacing ),
savejpegspref( p_savejpegs ),
videowriterpref( p_videowriter ),
encoderparams( p_encoderparams ),
label_coord( p_label_coord ),
image_buffer_count( p_image_buffer_count ),
warmup_count( p_warmup_count ),
@ -348,6 +355,9 @@ Monitor::Monitor(
}
}
/* Parse encoder parameters */
ParseEncoderParameters(encoderparams.c_str(), &encoderparamsvec);
fps = 0.0;
event_count = 0;
image_count = 0;
@ -1827,11 +1837,11 @@ int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose
static char sql[ZM_SQL_MED_BUFSIZ];
if ( !device[0] )
{
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Function != 'None' and Type = 'Local' order by Device, Channel", sizeof(sql) );
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Function != 'None' and Type = 'Local' order by Device, Channel", sizeof(sql) );
}
else
{
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Function != 'None' and Type = 'Local' and Device = '%s' order by Channel", device );
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Function != 'None' and Type = 'Local' and Device = '%s' order by Channel", device );
}
if ( mysql_query( &dbconn, sql ) )
{
@ -1870,6 +1880,11 @@ int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose
int palette = atoi(dbrow[col]); col++;
Orientation orientation = (Orientation)atoi(dbrow[col]); col++;
unsigned int deinterlacing = atoi(dbrow[col]); col++;
int savejpegs = atoi(dbrow[col]); col++;
int videowriter = atoi(dbrow[col]); col++;
std::string encoderparams = dbrow[col]; col++;
int brightness = atoi(dbrow[col]); col++;
int contrast = atoi(dbrow[col]); col++;
int hue = atoi(dbrow[col]); col++;
@ -1935,6 +1950,9 @@ int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose
camera,
orientation,
deinterlacing,
savejpegs,
videowriter,
encoderparams,
event_prefix,
label_format,
Coord( label_x, label_y ),
@ -1979,11 +1997,11 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
static char sql[ZM_SQL_MED_BUFSIZ];
if ( !protocol )
{
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Remote'", sizeof(sql) );
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Remote'", sizeof(sql) );
}
else
{
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Remote' and Protocol = '%s' and Host = '%s' and Port = '%s' and Path = '%s'", protocol, host, port, path );
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Remote' and Protocol = '%s' and Host = '%s' and Port = '%s' and Path = '%s'", protocol, host, port, path );
}
if ( mysql_query( &dbconn, sql ) )
{
@ -2023,6 +2041,11 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
/* int palette = atoi(dbrow[col]); */ col++;
Orientation orientation = (Orientation)atoi(dbrow[col]); col++;
unsigned int deinterlacing = atoi(dbrow[col]); col++;
int savejpegs = atoi(dbrow[col]); col++;
int videowriter = atoi(dbrow[col]); col++;
std::string encoderparams = dbrow[col]; col++;
int brightness = atoi(dbrow[col]); col++;
int contrast = atoi(dbrow[col]); col++;
int hue = atoi(dbrow[col]); col++;
@ -2106,6 +2129,9 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
camera,
orientation,
deinterlacing,
savejpegs,
videowriter,
encoderparams,
event_prefix.c_str(),
label_format.c_str(),
Coord( label_x, label_y ),
@ -2150,11 +2176,11 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu
static char sql[ZM_SQL_MED_BUFSIZ];
if ( !file[0] )
{
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'File'", sizeof(sql) );
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'File'", sizeof(sql) );
}
else
{
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'File' and Path = '%s'", file );
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'File' and Path = '%s'", file );
}
if ( mysql_query( &dbconn, sql ) )
{
@ -2190,6 +2216,11 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu
/* int palette = atoi(dbrow[col]); */ col++;
Orientation orientation = (Orientation)atoi(dbrow[col]); col++;
unsigned int deinterlacing = atoi(dbrow[col]); col++;
int savejpegs = atoi(dbrow[col]); col++;
int videowriter = atoi(dbrow[col]); col++;
std::string encoderparams = dbrow[col]; col++;
int brightness = atoi(dbrow[col]); col++;
int contrast = atoi(dbrow[col]); col++;
int hue = atoi(dbrow[col]); col++;
@ -2241,6 +2272,9 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu
camera,
orientation,
deinterlacing,
savejpegs,
videowriter,
encoderparams,
event_prefix,
label_format,
Coord( label_x, label_y ),
@ -2286,11 +2320,11 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
static char sql[ZM_SQL_MED_BUFSIZ];
if ( !file[0] )
{
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Ffmpeg'", sizeof(sql) );
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Ffmpeg'", sizeof(sql) );
}
else
{
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Ffmpeg' and Path = '%s'", file );
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Ffmpeg' and Path = '%s'", file );
}
if ( mysql_query( &dbconn, sql ) )
{
@ -2326,6 +2360,11 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
/* int palette = atoi(dbrow[col]); */ col++;
Orientation orientation = (Orientation)atoi(dbrow[col]); col++;
unsigned int deinterlacing = atoi(dbrow[col]); col++;
int savejpegs = atoi(dbrow[col]); col++;
int videowriter = atoi(dbrow[col]); col++;
std::string encoderparams = dbrow[col]; col++;
int brightness = atoi(dbrow[col]); col++;
int contrast = atoi(dbrow[col]); col++;
int hue = atoi(dbrow[col]); col++;
@ -2377,6 +2416,9 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
camera,
orientation,
deinterlacing,
savejpegs,
videowriter,
encoderparams,
event_prefix,
label_format,
Coord( label_x, label_y ),
@ -2419,7 +2461,7 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose )
{
static char sql[ZM_SQL_MED_BUFSIZ];
snprintf( sql, sizeof(sql), "select Id, Name, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Id = %d", id );
snprintf( sql, sizeof(sql), "select Id, Name, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Id = %d", id );
if ( mysql_query( &dbconn, sql ) )
{
Error( "Can't run query: %s", mysql_error( &dbconn ) );
@ -2462,6 +2504,11 @@ Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose )
int palette = atoi(dbrow[col]); col++;
Orientation orientation = (Orientation)atoi(dbrow[col]); col++;
unsigned int deinterlacing = atoi(dbrow[col]); col++;
int savejpegs = atoi(dbrow[col]); col++;
int videowriter = atoi(dbrow[col]); col++;
std::string encoderparams = dbrow[col]; col++;
int brightness = atoi(dbrow[col]); col++;
int contrast = atoi(dbrow[col]); col++;
int hue = atoi(dbrow[col]); col++;
@ -2618,6 +2665,9 @@ Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose )
camera,
orientation,
deinterlacing,
savejpegs,
videowriter,
encoderparams,
event_prefix.c_str(),
label_format.c_str(),
Coord( label_x, label_y ),

View File

@ -239,6 +239,11 @@ protected:
bool track_motion; // Whether this monitor tries to track detected motion
Rgb signal_check_colour; // The colour that the camera will emit when no video signal detected
int savejpegspref;
int videowriterpref;
std::string encoderparams;
std::vector<EncoderParameter_t> encoderparamsvec;
double fps;
Image delta_image;
Image ref_image;
@ -288,7 +293,7 @@ protected:
public:
// OurCheckAlarms seems to be unused. Check it on zm_monitor.cpp for more info.
//bool OurCheckAlarms( Zone *zone, const Image *pImage );
Monitor( int p_id, const char *p_name, int p_function, bool p_enabled, const char *p_linked_monitors, Camera *p_camera, int p_orientation, unsigned int p_deinterlacing, const char *p_event_prefix, const char *p_label_format, const Coord &p_label_coord, int p_image_buffer_count, int p_warmup_count, int p_pre_event_count, int p_post_event_count, int p_stream_replay_buffer, int p_alarm_frame_count, int p_section_length, int p_frame_skip, int p_capture_delay, int p_alarm_capture_delay, int p_fps_report_interval, int p_ref_blend_perc, int p_alarm_ref_blend_perc, bool p_track_motion, Rgb p_signal_check_colour, Purpose p_purpose, int p_n_zones=0, Zone *p_zones[]=0 );
Monitor( int p_id, const char *p_name, int p_function, bool p_enabled, const char *p_linked_monitors, Camera *p_camera, int p_orientation, unsigned int p_deinterlacing, int p_savejpegs, int p_videowriter, std::string p_encoderparams, const char *p_event_prefix, const char *p_label_format, const Coord &p_label_coord, int p_image_buffer_count, int p_warmup_count, int p_pre_event_count, int p_post_event_count, int p_stream_replay_buffer, int p_alarm_frame_count, int p_section_length, int p_frame_skip, int p_capture_delay, int p_alarm_capture_delay, int p_fps_report_interval, int p_ref_blend_perc, int p_alarm_ref_blend_perc, bool p_track_motion, Rgb p_signal_check_colour, Purpose p_purpose, int p_n_zones=0, Zone *p_zones[]=0 );
~Monitor();
void AddZones( int p_n_zones, Zone *p_zones[] );
@ -338,6 +343,9 @@ public:
unsigned int Colours() const { return( camera->Colours() ); }
unsigned int SubpixelOrder() const { return( camera->SubpixelOrder() ); }
int GetOptSaveJPEGs() const { return( savejpegspref ); }
int GetOptVideoWriter() const { return( videowriterpref ); }
const std::vector<EncoderParameter_t>* GetOptEncoderParams() const { return( &encoderparamsvec ); }
State GetState() const;
int GetImage( int index=-1, int scale=100 ) const;

492
src/zm_video.cpp Normal file
View File

@ -0,0 +1,492 @@
// This program 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 2
// of the License, or (at your option) any later version.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
#include "zm.h"
#include "zm_video.h"
#include "zm_image.h"
#include "zm_utils.h"
#include "zm_rgb.h"
#include <sstream>
VideoWriter::VideoWriter(const char* p_container, const char* p_codec, const char* p_path, const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder) :
container(p_container), codec(p_codec), path(p_path), width(p_width), height(p_height), colours(p_colours), subpixelorder(p_subpixelorder), frame_count(0) {
Debug(7,"Video object created");
/* Parameter checking */
if(path.empty()) {
Error("Invalid file path");
}
if(!width || !height) {
Error("Invalid width or height");
}
}
VideoWriter::~VideoWriter() {
Debug(7,"Video object destroyed");
}
int VideoWriter::Reset() {
/* Common variables reset */
frame_count = 0;
return 0;
}
#if ZM_HAVE_VIDEOWRITER_X264MP4
X264MP4Writer::X264MP4Writer(const char* p_path, const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder, const std::vector<EncoderParameter_t>* p_user_params) : VideoWriter("mp4", "h264", p_path, p_width, p_height, p_colours, p_subpixelorder), bOpen(false), bGotH264AVCInfo(false), bFirstFrame(true) {
/* Initialize ffmpeg if it hasn't been initialized yet */
FFMPEGInit();
/* Initialize swscale */
zm_pf = GetFFMPEGPixelFormat(colours,subpixelorder);
if(zm_pf == 0) {
Error("Unable to match ffmpeg pixelformat");
}
codec_pf = PIX_FMT_YUV420P;
swscaleobj.SetDefaults(zm_pf, codec_pf, width, height);
/* Calculate the image sizes. We will need this for parameter checking */
zm_imgsize = colours * width * height;
codec_imgsize = avpicture_get_size( codec_pf, width, height);
if(!codec_imgsize) {
Error("Failed calculating codec pixel format image size");
}
/* If supplied with user parameters to the encoder, copy them */
if(p_user_params != NULL) {
user_params = *p_user_params;
}
/* Setup x264 parameters */
if(x264config() < 0) {
Error("Failed setting x264 parameters");
}
/* Allocate x264 input picture */
x264_picture_alloc(&x264picin, X264_CSP_I420, x264params.i_width, x264params.i_height);
}
X264MP4Writer::~X264MP4Writer() {
/* Free x264 input picture */
x264_picture_clean(&x264picin);
if(bOpen)
Close();
//x264_picture_clean(&x264picout);
}
int X264MP4Writer::Open() {
/* Open the encoder */
x264enc = x264_encoder_open(&x264params);
if(x264enc == NULL) {
Error("Failed opening x264 encoder");
return -1;
}
// Debug(4,"x264 maximum delayed frames: %d",x264_encoder_maximum_delayed_frames(x264enc));
x264_nal_t* nals;
int i_nals;
if(!x264_encoder_headers(x264enc,&nals,&i_nals)) {
Error("Failed getting encoder headers");
return -2;
}
/* Search SPS NAL for AVC information */
for(int i=0;i<i_nals;i++) {
if(nals[i].i_type == NAL_SPS) {
x264_profleindication = nals[i].p_payload[5];
x264_profilecompat = nals[i].p_payload[6];
x264_levelindication = nals[i].p_payload[7];
bGotH264AVCInfo = true;
break;
}
}
if(!bGotH264AVCInfo) {
Warning("Missing AVC information");
}
/* Create the file */
mp4h = MP4Create((path + ".incomplete").c_str());
if(mp4h == MP4_INVALID_FILE_HANDLE) {
Error("Failed creating mp4 file: %s",path.c_str());
return -10;
}
/* Set the global timescale */
if(!MP4SetTimeScale(mp4h, 1000)) {
Error("Failed setting timescale");
return -11;
}
/* Set the global video profile */
/* I am a bit confused about this one.
I couldn't find what the value should be
Some use 0x15 while others use 0x7f. */
MP4SetVideoProfileLevel(mp4h, 0x7f);
/* Add H264 video track */
mp4vtid = MP4AddH264VideoTrack(mp4h,1000,MP4_INVALID_DURATION,width,height,x264_profleindication,x264_profilecompat,x264_levelindication,3);
if(mp4vtid == MP4_INVALID_TRACK_ID) {
Error("Failed adding H264 video track");
return -12;
}
bOpen = true;
return 0;
}
int X264MP4Writer::Close() {
/* Flush all pending frames */
for(int i = (x264_encoder_delayed_frames(x264enc) + 1); i > 0; i-- ) {
x264encodeloop(true);
}
/* Close the encoder */
x264_encoder_close(x264enc);
/* Close MP4 handle */
MP4Close(mp4h);
/* Required for proper HTTP streaming */
MP4Optimize((path + ".incomplete").c_str(), path.c_str());
/* Delete the temporary file */
unlink((path + ".incomplete").c_str());
bOpen = false;
Debug(7, "Video closed. Total frames: %d", frame_count);
return 0;
}
int X264MP4Writer::Reset() {
VideoWriter::Reset();
/* Close the encoder and file */
if(bOpen)
Close();
/* Reset variables */
bFirstFrame = true;
bGotH264AVCInfo = false;
prevnals.clear();
prevpayload.clear();
/* Reset x264 parameters */
x264config();
/* Open the encoder */
Open();
return 0;
}
int X264MP4Writer::Encode(const uint8_t* data, const size_t data_size, const unsigned int frame_time) {
/* Parameter checking */
if(data == NULL) {
Error("NULL buffer");
return -1;
}
if(data_size != zm_imgsize) {
Error("The data buffer size does not match the expected size. Expected: %d Current: %d", zm_imgsize, data_size);
return -2;
}
if(!bOpen) {
Warning("The encoder was not initialized, initializing now");
Open();
}
/* Convert the image into the x264 input picture */
if(swscaleobj.ConvertDefaults(data, data_size, x264picin.img.plane[0], codec_imgsize) < 0) {
Error("Image conversion failed");
return -3;
}
/* Set PTS */
x264picin.i_pts = frame_time;
/* Do the encoding */
x264encodeloop();
/* Increment frame counter */
frame_count++;
return 0;
}
int X264MP4Writer::Encode(const Image* img, const unsigned int frame_time) {
if(img->Width() != width) {
Error("Source image width differs. Source: %d Output: %d",img->Width(), width);
return -12;
}
if(img->Height() != height) {
Error("Source image height differs. Source: %d Output: %d",img->Height(), height);
return -13;
}
return Encode(img->Buffer(),img->Size(),frame_time);
}
int X264MP4Writer::x264config() {
/* Sets up the encoder configuration */
/* Set the defaults and enable the superfast preset and the stillimage tune */
if(x264_param_default_preset(&x264params,"veryfast","stillimage") != 0) {
Error("Failed setting x264 preset and tune");
return -1;
}
/* Set profile */
if(x264_param_apply_profile(&x264params, "main") != 0) {
Error("Failed setting x264 profile");
return -2;
}
/* Input format */
x264params.i_width = width;
x264params.i_height = height;
x264params.i_csp = X264_CSP_I420;
/* Quality control */
x264params.rc.i_rc_method = X264_RC_CRF;
x264params.rc.f_rf_constant = 23.0;
/* Enable b-frames */
x264params.i_bframe = 16;
x264params.i_bframe_adaptive = 1;
/* Timebase */
x264params.i_timebase_num = 1;
x264params.i_timebase_den = 1000;
/* Enable variable frame rate */
x264params.b_vfr_input = 1;
/* Disable annex-b (start codes) */
x264params.b_annexb = 0;
/* TODO: Setup error handler */
//x264params.i_log_level = X264_LOG_DEBUG;
/* Process user parameters */
x264userparams();
return 0;
}
int X264MP4Writer::x264userparams() {
/* Passes user parameters (for the encoder) to x264 */
int x264ret;
for(unsigned int i=0; i < user_params.size(); i++) {
x264ret = x264_param_parse(&x264params, user_params[i].pname, user_params[i].pvalue);
/* Error checking */
if(x264ret != 0) {
if(x264ret == X264_PARAM_BAD_NAME) {
Error("Failed parsing x264 user parameter %s=%s : Bad name", user_params[i].pname, user_params[i].pvalue);
} else if(x264ret == X264_PARAM_BAD_VALUE) {
Error("Failed parsing x264 user parameter %s=%s : Bad value", user_params[i].pname, user_params[i].pvalue);
} else {
Error("Failed parsing x264 user parameter %s=%s : Unknown error (%d)", user_params[i].pname, user_params[i].pvalue, x264ret);
}
}
}
return 0;
}
void X264MP4Writer::x264encodeloop(bool bFlush) {
x264_nal_t* nals;
int i_nals;
int frame_size;
if(bFlush) {
frame_size = x264_encoder_encode(x264enc, &nals, &i_nals, NULL, &x264picout);
} else {
frame_size = x264_encoder_encode(x264enc, &nals, &i_nals, &x264picin, &x264picout);
}
if (frame_size > 0 || bFlush) {
Debug(8, "x264 Frame: %d PTS: %d DTS: %d Size: %d\n",frame_count, x264picout.i_pts, x264picout.i_dts, frame_size);
/* Handle the previous frame */
if(!bFirstFrame) {
/* Process the NALs for the previous frame */
for(unsigned int i=0; i < prevnals.size(); i++) {
Debug(9,"Processing NAL: Type %d Size %d",prevnals[i].i_type,prevnals[i].i_payload);
switch(prevnals[i].i_type) {
case NAL_PPS:
/* PPS NAL */
MP4AddH264PictureParameterSet(mp4h, mp4vtid, prevnals[i].p_payload+4, prevnals[i].i_payload-4);
break;
case NAL_SPS:
/* SPS NAL */
MP4AddH264SequenceParameterSet(mp4h, mp4vtid, prevnals[i].p_payload+4, prevnals[i].i_payload-4);
break;
default:
/* Anything else, hopefully frames, so copy it into the sample */
buffer.append(prevnals[i].p_payload, prevnals[i].i_payload);
}
}
/* Calculate frame duration and offset */
int duration = x264picout.i_dts - prevDTS;
int offset = prevPTS - prevDTS;
/* Write the sample */
if(!buffer.empty()) {
if(!MP4WriteSample(mp4h, mp4vtid, buffer.extract(buffer.size()), buffer.size(), duration, offset, prevKeyframe)) {
Error("Failed writing sample");
}
}
/* Cleanup */
prevnals.clear();
prevpayload.clear();
}
/* Got a frame. Copy this new frame into the previous frame */
if(frame_size > 0) {
/* Copy the NALs and the payloads */
for(int i=0;i<i_nals;i++) {
prevnals.push_back(nals[i]);
prevpayload.append(nals[i].p_payload, nals[i].i_payload);
}
/* Update the payload pointers */
/* This is done in a separate loop because the previous loop might reallocate memory when appending,
making the pointers invalid */
unsigned int payload_head = 0;
for(unsigned int i=0;i<prevnals.size();i++) {
prevnals[i].p_payload = prevpayload.head() + payload_head;
payload_head += nals[i].i_payload;
}
/* We need this for the next frame */
prevPTS = x264picout.i_pts;
prevDTS = x264picout.i_dts;
prevKeyframe = x264picout.b_keyframe;
bFirstFrame = false;
}
} else if(frame_size == 0) {
Debug(7,"x264 encode returned zero. Delayed frames: %d",x264_encoder_delayed_frames(x264enc));
} else {
Error("x264 encode failed: %d",frame_size);
}
}
#endif // ZM_VIDEOWRITER_X264MP4
int ParseEncoderParameters(const char* str, std::vector<EncoderParameter_t>* vec) {
if(vec == NULL) {
Error("NULL Encoder parameters vector pointer");
return -1;
}
if(str == NULL) {
Error("NULL Encoder parameters string");
return -2;
}
if(str[0] == 0) {
/* Empty */
return 0;
}
std::string line;
std::stringstream ss(str);
size_t valueoffset;
size_t valuelen;
unsigned int lineno = 0;
EncoderParameter_t param;
vec->clear();
while(std::getline(ss, line) ) {
lineno++;
/* Remove CR if exists */
if(line.length() >= 1 && line[line.length()-1] == '\r') {
line.erase(line.length()-1);
}
/* Skip comments and empty lines */
if(line.empty() || line[0] == '#') {
continue;
}
valueoffset = line.find('=');
if(valueoffset == std::string::npos || valueoffset+1 >= line.length() || valueoffset == 0) {
Warning("Failed parsing encoder parameters line %d: Invalid pair", lineno);
continue;
}
if(valueoffset > (sizeof(param.pname)-1) ) {
Warning("Failed parsing encoder parameters line %d: Name too long", lineno);
continue;
}
valuelen = line.length() - (valueoffset+1);
if( valuelen > (sizeof(param.pvalue)-1) ) {
Warning("Failed parsing encoder parameters line %d: Value too long", lineno);
continue;
}
/* Copy and NULL terminate */
line.copy(param.pname, valueoffset, 0);
line.copy(param.pvalue, valuelen, valueoffset+1);
param.pname[valueoffset] = 0;
param.pvalue[valuelen] = 0;
/* Push to the vector */
vec->push_back(param);
Debug(7, "Parsed encoder parameter: %s = %s", param.pname, param.pvalue);
}
Debug(7, "Parsed %d lines", lineno);
return 0;
}

168
src/zm_video.h Normal file
View File

@ -0,0 +1,168 @@
// This program 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 2
// of the License, or (at your option) any later version.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
#ifndef ZM_VIDEO_H
#define ZM_VIDEO_H
#include "zm.h"
#include "zm_rgb.h"
#include "zm_utils.h"
#include "zm_ffmpeg.h"
#include "zm_buffer.h"
/*
#define HAVE_LIBX264 1
#define HAVE_LIBMP4V2 1
#define HAVE_X264_H 1
#define HAVE_MP4_H 1
*/
#if HAVE_MP4_H
#include <mp4.h>
#endif
#if HAVE_X264_H
#ifdef __cplusplus
extern "C" {
#endif
#include <x264.h>
#ifdef __cplusplus
}
#endif
#endif
/* Structure for user parameters to the encoder */
struct EncoderParameter_t {
char pname[48];
char pvalue[48];
};
int ParseEncoderParameters(const char* str, std::vector<EncoderParameter_t>* vec);
/* VideoWriter is a generic interface that ZM uses to save events as videos */
/* It is relatively simple and the functions are pure virtual, so they must be implemented by the deriving class */
class VideoWriter {
protected:
std::string container;
std::string codec;
std::string path;
unsigned int width;
unsigned int height;
unsigned int colours;
unsigned int subpixelorder;
unsigned int frame_count;
public:
VideoWriter(const char* p_container, const char* p_codec, const char* p_path, const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder);
virtual ~VideoWriter();
virtual int Encode(const uint8_t* data, const size_t data_size, const unsigned int frame_time) = 0;
virtual int Encode(const Image* img, const unsigned int frame_time) = 0;
virtual int Open() = 0;
virtual int Close() = 0;
virtual int Reset();
const char* GetContainer() const {
return container.c_str();
}
const char* GetCodec() const {
return codec.c_str();
}
const char* GetPath() const {
return path.c_str();
}
unsigned int GetWidth() const {
return width;
}
unsigned int GetHeight() const {
return height;
}
unsigned int GetColours() const {
return colours;
}
unsigned int GetSubpixelorder () const {
return subpixelorder;
}
unsigned int GetFrameCount() const {
return frame_count;
}
};
#if HAVE_LIBX264 && HAVE_LIBMP4V2 && HAVE_LIBAVUTIL && HAVE_LIBSWSCALE
#define ZM_HAVE_VIDEOWRITER_X264MP4 1
class X264MP4Writer : public VideoWriter {
protected:
bool bOpen;
bool bGotH264AVCInfo;
bool bFirstFrame;
/* SWScale */
SWScale swscaleobj;
enum PixelFormat zm_pf;
enum PixelFormat codec_pf;
size_t codec_imgsize;
size_t zm_imgsize;
/* User parameters */
std::vector<EncoderParameter_t> user_params;
/* AVC Information */
uint8_t x264_profleindication;
uint8_t x264_profilecompat;
uint8_t x264_levelindication;
/* NALs */
Buffer buffer;
/* Previous frame */
int prevPTS;
int prevDTS;
bool prevKeyframe;
Buffer prevpayload;
std::vector<x264_nal_t> prevnals;
/* Internal functions */
int x264config();
int x264userparams();
void x264encodeloop(bool bFlush = false);
/* x264 objects */
x264_t* x264enc;
x264_param_t x264params;
x264_picture_t x264picin;
x264_picture_t x264picout;
/* MP4v2 objects */
MP4FileHandle mp4h;
MP4TrackId mp4vtid;
public:
X264MP4Writer(const char* p_path, const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder, const std::vector<EncoderParameter_t>* p_user_params = NULL);
~X264MP4Writer();
int Encode(const uint8_t* data, const size_t data_size, const unsigned int frame_time);
int Encode(const Image* img, const unsigned int frame_time);
int Open();
int Close();
int Reset();
};
#endif // HAVE_LIBX264 && HAVE_LIBMP4V2 && HAVE_LIBAVUTIL && HAVE_LIBSWSCALE
#endif // ZM_VIDEO_H

View File

@ -382,31 +382,33 @@ function getNearEvents()
else
$midSql = '';
$sql = "select E.Id as Id from Events as E inner join Monitors as M on E.MonitorId = M.Id where ".dbEscape($sortColumn)." ".($sortOrder=='asc'?'<=':'>=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." order by $sortColumn ".($sortOrder=='asc'?'desc':'asc');
$sql = "select E.* as Id from Events as E inner join Monitors as M on E.MonitorId = M.Id where ".dbEscape($sortColumn)." ".($sortOrder=='asc'?'<=':'>=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." order by $sortColumn ".($sortOrder=='asc'?'desc':'asc');
$result = dbQuery( $sql );
while ( $id = dbFetchNext( $result, 'Id' ) )
{
if ( $id == $eventId )
{
$prevId = dbFetchNext( $result, 'Id' );
$prevEvent = dbFetchNext( $result );
break;
}
}
$sql = "select E.Id as Id from Events as E inner join Monitors as M on E.MonitorId = M.Id where $sortColumn ".($sortOrder=='asc'?'>=':'<=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." order by $sortColumn $sortOrder";
$sql = "select E.* as Id from Events as E inner join Monitors as M on E.MonitorId = M.Id where $sortColumn ".($sortOrder=='asc'?'>=':'<=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." order by $sortColumn $sortOrder";
$result = dbQuery( $sql );
while ( $id = dbFetchNext( $result, 'Id' ) )
{
if ( $id == $eventId )
{
$nextId = dbFetchNext( $result, 'Id' );
$nextEvent = dbFetchNext( $result );
break;
}
}
$result = array( 'EventId'=>$eventId );
$result['PrevEventId'] = empty($prevId)?0:$prevId;
$result['NextEventId'] = empty($nextId)?0:$nextId;
$result['PrevEventId'] = empty($prevEvent)?0:$prevEvent['Id'];
$result['NextEventId'] = empty($nextEvent)?0:$nextEvent['Id'];
$result['PrevEventDefVideoPath'] = empty($prevEvent)?0:(getEventDefaultVideoPath($prevEvent));
$result['NextEventDefVideoPath'] = empty($nextEvent)?0:(getEventDefaultVideoPath($nextEvent));
return( $result );
}

View File

@ -497,6 +497,9 @@ function getEventPath( $event )
return( $eventPath );
}
function getEventDefaultVideoPath( $event ) {
return ZM_DIR_EVENTS . "/" . getEventPath($event) . "/" . $event['DefaultVideo'];
}
function deletePath( $path )
{

View File

@ -57,6 +57,23 @@
text-align: right;
}
#videoBar1 div {
text-align: center;
float: center;
}
#videoBar1 #prevEvent {
float: left;
}
#videoBar1 #dlEvent {
float: center;
}
#videoBar1 #nextEvent {
float: right;
}
#imageFeed {
text-align: center;
}

View File

@ -125,6 +125,7 @@ if ( canEdit( 'Events' ) )
<div id="framesEvent"><a href="#" onclick="showEventFrames()"><?= $SLANG['Frames'] ?></a></div>
<div id="streamEvent"<?php if ( $streamMode == 'stream' ) { ?> class="hidden"<?php } ?>><a href="#" onclick="showStream()"><?= $SLANG['Stream'] ?></a></div>
<div id="stillsEvent"<?php if ( $streamMode == 'still' ) { ?> class="hidden"<?php } ?>><a href="#" onclick="showStills()"><?= $SLANG['Stills'] ?></a></div>
<div id="videoEvent"<?php if ( $streamMode == 'video' ) { ?> class="hidden"<?php } ?>><a href="#" onclick="showVideo()">HTML5Video</a></div>
<?php
if ( ZM_OPT_FFMPEG )
{
@ -184,6 +185,19 @@ else
?>
</div>
</div>
<div id="eventVideo" class="hidden">
<div id="videoFeed">
<video id="videoobj" width="<?= $event['Width'] ?>" height="<?= $event['Height'] ?>" controls autoplay>
<source src="<?= getEventDefaultVideoPath($event) ?>" type="video/mp4">
Your browser does not support the video tag.
</video>
</div>
<div id="videoBar1">
<div id="prevEvent"><a href="#" onclick="prevEvent()">Previous Event</a></div>
<div id="dlEvent"><a id="downloadlink" href="<?= getEventDefaultVideoPath($event) ?>" download>Download Video</a></div>
<div id="nextEvent"><a href="#" onclick="nextEvent()">Next Event</a></div>
</div>
</div>
<div id="eventStills" class="hidden">
<div id="eventThumbsPanel">
<div id="eventThumbs">

View File

@ -12,6 +12,12 @@ function changeScale()
var newWidth = ( baseWidth * scale ) / SCALE_BASE;
var newHeight = ( baseHeight * scale ) / SCALE_BASE;
if(streamMode == 'video') {
var videoid = document.getElementById('videoobj');
videoid.style.width = newWidth + "px";
videoid.style.height = newHeight + "px";
} else {
streamScale( scale );
/*Stream could be an applet so can't use moo tools*/
@ -19,6 +25,7 @@ function changeScale()
streamImg.style.width = newWidth + "px";
streamImg.style.height = newHeight + "px";
}
}
function changeReplayMode()
{
@ -160,16 +167,36 @@ function streamFastRev( action )
function streamPrev( action )
{
streamPlay( false );
if(streamMode == 'video') {
var videoid = document.getElementById('videoobj');
videoobj.src = PrevEventDefVideoPath;
videoobj.load();
updatedownloadlink();
} else {
if ( action )
streamReq.send( streamParms+"&command="+CMD_PREV );
}
}
function streamNext( action )
{
streamPlay( false );
if(streamMode == 'video') {
var videoid = document.getElementById('videoobj');
videoobj.src = NextEventDefVideoPath;
videoobj.load();
updatedownloadlink();
} else {
if ( action )
streamReq.send( streamParms+"&command="+CMD_NEXT );
}
}
function updatedownloadlink() {
var videoid = document.getElementById('videoobj');
var link = document.getElementById('downloadlink');
link.href = videoid.currentSrc;
}
function streamZoomIn( x, y )
{
@ -259,6 +286,8 @@ function eventQuery( eventId )
var prevEventId = 0;
var nextEventId = 0;
var PrevEventDefVideoPath = "";
var NextEventDefVideoPath = "";
function getNearEventsResponse( respObj, respText )
{
@ -266,6 +295,8 @@ function getNearEventsResponse( respObj, respText )
return;
prevEventId = respObj.nearevents.PrevEventId;
nextEventId = respObj.nearevents.NextEventId;
PrevEventDefVideoPath = respObj.nearevents.PrevEventDefVideoPath;
NextEventDefVideoPath = respObj.nearevents.NextEventDefVideoPath;
$('prevEventBtn').disabled = !prevEventId;
$('nextEventBtn').disabled = !nextEventId;
@ -634,18 +665,42 @@ function showStream()
{
$('eventStills').addClass( 'hidden' );
$('eventStream').removeClass( 'hidden' );
$('eventVideo').addClass( 'hidden' );
$('streamEvent').addClass( 'hidden' );
$('stillsEvent').removeClass( 'hidden' );
$('videoEvent').removeClass( 'hidden' );
//$(window).removeEvent( 'resize', updateStillsSizes );
streamMode = 'stream';
}
function showVideo()
{
$('eventStills').addClass( 'hidden' );
$('eventStream').addClass( 'hidden' );
$('eventVideo').removeClass( 'hidden' );
$('streamEvent').removeClass( 'hidden' );
$('stillsEvent').removeClass( 'hidden' );
$('videoEvent').addClass( 'hidden' );
streamMode = 'video';
var videoid = document.getElementById('videoobj');
}
function showStills()
{
$('eventStream').addClass( 'hidden' );
$('eventStills').removeClass( 'hidden' );
$('stillsEvent').addClass( 'hidden' );
$('eventStream').addClass( 'hidden' );
$('eventVideo').addClass( 'hidden' );
$('streamEvent').removeClass( 'hidden' );
$('stillsEvent').addClass( 'hidden' );
$('videoEvent').removeClass( 'hidden' );
streamMode = 'stills';
streamPause( true );
if ( !scroll )
{

View File

@ -27,6 +27,7 @@ if ( !canView( 'Monitors' ) )
$tabs = array();
$tabs["general"] = $SLANG['General'];
$tabs["source"] = $SLANG['Source'];
$tabs["storage"] = "Storage";
$tabs["timestamp"] = $SLANG['Timestamp'];
$tabs["buffers"] = $SLANG['Buffers'];
if ( ZM_OPT_CONTROL && canView( 'Control' ) )
@ -70,6 +71,9 @@ else
'Height' => "240",
'Orientation' => "0",
'Deinterlacing' => 0,
'SaveJPEGs' => "3",
'VideoWriter' => "0",
'EncoderParameters' => "# Lines beginning with # are a comment \n# For changing quality, use the crf option\n# 1 is best, 51 is worst quality\n#crf=23\n",
'LabelFormat' => '%N - %d/%m/%y %H:%M:%S',
'LabelX' => 0,
'LabelY' => 0,
@ -410,6 +414,19 @@ $fastblendopts_alarm = array(
"50% (Alarm lasts a moment)" => 50
);
$savejpegopts = array(
"Disabled" => 0,
"Frames only" => 1,
"Analysis images only (if available)" => 2,
"Frames + analysis images (if available)" => 3
);
$videowriteropts = array(
"Disabled" => 0,
"X264 : MP4V2" => 1,
"H264 Passthrough : MP4V2 (not implemented)" => 2
);
xhtmlHeaders(__FILE__, $SLANG['Monitor']." - ".validHtmlStr($monitor['Name']) );
?>
<body>
@ -518,6 +535,14 @@ if ( $tab != 'source' )
<input type="hidden" name="newMonitor[Deinterlacing]" value="<?= validHtmlStr($newMonitor['Deinterlacing']) ?>"/>
<?php
}
if ( $tab != 'storage' )
{
?>
<input type="hidden" name="newMonitor[SaveJPEGs]" value="<?= validHtmlStr($newMonitor['SaveJPEGs']) ?>"/>
<input type="hidden" name="newMonitor[VideoWriter]" value="<?= validHtmlStr($newMonitor['VideoWriter']) ?>"/>
<input type="hidden" name="newMonitor[EncoderParameters]" value="<?= validHtmlStr($newMonitor['EncoderParameters']) ?>"/>
<?php
}
if ( $tab != 'timestamp' )
{
?>
@ -742,6 +767,13 @@ switch ( $tab )
<?php
break;
}
case 'storage' :
?>
<tr><td>Save as JPEGs</td><td><select name="newMonitor[SaveJPEGs]"><?php foreach ( $savejpegopts as $name => $value ) { ?><option value="<?= $value ?>"<?php if ( $value == $newMonitor['SaveJPEGs'] ) { ?> selected="selected"<?php } ?>><?= $name ?></option><?php } ?></select></td></tr>
<tr><td>Video writer</td><td><select name="newMonitor[VideoWriter]"><?php foreach ( $videowriteropts as $name => $value ) { ?><option value="<?= $value ?>"<?php if ( $value == $newMonitor['VideoWriter'] ) { ?> selected="selected"<?php } ?>><?= $name ?></option><?php } ?></select></td></tr>
<tr><td>Optional encoder parameters</td><td><textarea name="newMonitor[EncoderParameters]" rows="4" cols="36"><?= validHtmlStr($newMonitor['EncoderParameters']) ?></textarea></td></tr>
<?php
break;
case 'timestamp' :
{
?>

View File

@ -37,6 +37,10 @@
#cmakedefine HAVE_GNUTLS_GNUTLS_H 1
#cmakedefine HAVE_LIBMYSQLCLIENT 1
#cmakedefine HAVE_MYSQL_H 1
#cmakedefine HAVE_LIBX264 1
#cmakedefine HAVE_X264_H 1
#cmakedefine HAVE_LIBMP4V2 1
#cmakedefine HAVE_MP4_H 1
#cmakedefine HAVE_LIBAVFORMAT 1
#cmakedefine HAVE_LIBAVFORMAT_AVFORMAT_H 1
#cmakedefine HAVE_LIBAVCODEC 1