From e45bbceab999d76b97570dcefe49e40b58e381e7 Mon Sep 17 00:00:00 2001 From: MrDave Date: Sun, 29 Sep 2019 21:13:01 -0600 Subject: [PATCH] Update time methods and types --- src/event.c | 70 ++++++------ src/event.h | 4 +- src/jpegutils.c | 12 +-- src/jpegutils.h | 4 +- src/motion.c | 265 +++++++++++++++------------------------------- src/motion.h | 23 ++-- src/movie.c | 30 +++--- src/movie.h | 6 +- src/netcam.c | 57 +++------- src/netcam.h | 14 +-- src/picture.c | 51 ++++----- src/picture.h | 2 +- src/track.c | 2 +- src/webu.h | 2 +- src/webu_stream.c | 10 +- 15 files changed, 213 insertions(+), 339 deletions(-) diff --git a/src/event.c b/src/event.c index 3b2f2d49..12e79c19 100644 --- a/src/event.c +++ b/src/event.c @@ -76,7 +76,7 @@ static const char *eventToString(motion_event e) static void exec_command(struct ctx_cam *cam, char *command, char *filename, int filetype) { char stamp[PATH_MAX]; - mystrftime(cam, stamp, sizeof(stamp), command, &cam->current_image->timestamp_tv, filename, filetype); + mystrftime(cam, stamp, sizeof(stamp), command, &cam->current_image->imgts, filename, filetype); if (!fork()) { int i; @@ -106,7 +106,7 @@ static void exec_command(struct ctx_cam *cam, char *command, char *filename, int static void event_newfile(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { (void)cam; (void)evnt; @@ -121,7 +121,7 @@ static void event_newfile(struct ctx_cam *cam, motion_event evnt static void event_beep(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { (void)evnt; (void)img_data; @@ -143,7 +143,7 @@ static void event_beep(struct ctx_cam *cam, motion_event evnt */ static void on_picture_save_command(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { int filetype = (unsigned long)ftype; @@ -160,7 +160,7 @@ static void on_picture_save_command(struct ctx_cam *cam, motion_event evnt static void on_motion_detected_command(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { (void)evnt; (void)img_data; @@ -291,7 +291,7 @@ static void do_sql_query(char *sqlquery, struct ctx_cam *cam, int save_id) static void event_sqlfirstmotion(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { char sqlquery[PATH_MAX]; @@ -307,7 +307,7 @@ static void event_sqlfirstmotion(struct ctx_cam *cam, motion_event evnt } mystrftime(cam, sqlquery, sizeof(sqlquery), cam->conf.sql_query_start, - &cam->current_image->timestamp_tv, NULL, 0); + &cam->current_image->imgts, NULL, 0); do_sql_query(sqlquery, cam, 1); @@ -315,7 +315,7 @@ static void event_sqlfirstmotion(struct ctx_cam *cam, motion_event evnt static void event_sqlnewfile(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { int sqltype = (unsigned long)ftype; char sqlquery[PATH_MAX]; @@ -335,7 +335,7 @@ static void event_sqlnewfile(struct ctx_cam *cam, motion_event evnt static void event_sqlfileclose(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { int sqltype = (unsigned long)ftype; char sqlquery[PATH_MAX]; @@ -355,7 +355,7 @@ static void event_sqlfileclose(struct ctx_cam *cam, motion_event evnt static void on_area_command(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { (void)evnt; (void)img_data; @@ -369,7 +369,7 @@ static void on_area_command(struct ctx_cam *cam, motion_event evnt static void on_event_start_command(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { (void)evnt; (void)img_data; @@ -383,7 +383,7 @@ static void on_event_start_command(struct ctx_cam *cam, motion_event evnt static void on_event_end_command(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { (void)evnt; (void)img_data; @@ -397,7 +397,7 @@ static void on_event_end_command(struct ctx_cam *cam, motion_event evnt static void event_stream_put(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { int subsize; @@ -499,7 +499,7 @@ static void event_stream_put(struct ctx_cam *cam, motion_event evnt static void event_vlp_putpipe(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { (void)evnt; (void)fname; @@ -525,7 +525,7 @@ const char *imageext(struct ctx_cam *cam) { static void event_image_detect(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { char fullfilename[PATH_MAX]; char filename[PATH_MAX]; @@ -565,7 +565,7 @@ static void event_image_detect(struct ctx_cam *cam, motion_event evnt static void event_imagem_detect(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { struct config *conf = &cam->conf; char fullfilenamem[PATH_MAX]; @@ -606,7 +606,7 @@ static void event_imagem_detect(struct ctx_cam *cam, motion_event evnt static void event_image_snapshot(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { char fullfilename[PATH_MAX]; char filename[PATH_MAX]; @@ -680,7 +680,7 @@ static void event_image_snapshot(struct ctx_cam *cam, motion_event evnt static void event_image_preview(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { int use_imagepath; const char *imagepath; @@ -756,7 +756,7 @@ static void event_image_preview(struct ctx_cam *cam, motion_event evnt else imagepath = (char *)DEF_IMAGEPATH; - mystrftime(cam, filename, sizeof(filename), imagepath, &cam->imgs.preview_image.timestamp_tv, NULL, 0); + mystrftime(cam, filename, sizeof(filename), imagepath, &cam->imgs.preview_image.imgts, NULL, 0); snprintf(previewname, PATH_MAX, "%.*s/%.*s.%s" , (int)(PATH_MAX-2-strlen(filename)-strlen(imageext(cam))) , cam->conf.target_dir @@ -779,7 +779,7 @@ static void event_image_preview(struct ctx_cam *cam, motion_event evnt static void event_camera_lost(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { (void)evnt; (void)img_data; @@ -793,7 +793,7 @@ static void event_camera_lost(struct ctx_cam *cam, motion_event evnt static void event_camera_found(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { (void)evnt; (void)img_data; @@ -807,7 +807,7 @@ static void event_camera_found(struct ctx_cam *cam, motion_event evnt static void on_movie_end_command(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { int filetype = (unsigned long) ftype; @@ -821,7 +821,7 @@ static void on_movie_end_command(struct ctx_cam *cam, motion_event evnt static void event_extpipe_end(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { (void)evnt; (void)img_data; @@ -842,7 +842,7 @@ static void event_extpipe_end(struct ctx_cam *cam, motion_event evnt static void event_create_extpipe(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { int retcd; char stamp[PATH_MAX] = ""; @@ -923,7 +923,7 @@ static void event_create_extpipe(struct ctx_cam *cam, motion_event evnt static void event_extpipe_put(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { int passthrough; @@ -956,7 +956,7 @@ static void event_extpipe_put(struct ctx_cam *cam, motion_event evnt static void event_new_video(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { (void)evnt; (void)img_data; @@ -976,7 +976,7 @@ static void event_new_video(struct ctx_cam *cam, motion_event evnt static void event_movie_newfile(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { char stamp[PATH_MAX]; const char *moviepath; @@ -1098,7 +1098,7 @@ static void event_movie_newfile(struct ctx_cam *cam, motion_event evnt cam->movie_output->filename = cam->newfilename; cam->movie_output->quality = cam->conf.movie_quality; cam->movie_output->start_time.tv_sec = ts1->tv_sec; - cam->movie_output->start_time.tv_usec = ts1->tv_usec; + cam->movie_output->start_time.tv_nsec = ts1->tv_nsec; cam->movie_output->last_pts = -1; cam->movie_output->base_pts = 0; cam->movie_output->gop_cnt = 0; @@ -1134,7 +1134,7 @@ static void event_movie_newfile(struct ctx_cam *cam, motion_event evnt cam->movie_output_motion->filename = cam->motionfilename; cam->movie_output_motion->quality = cam->conf.movie_quality; cam->movie_output_motion->start_time.tv_sec = ts1->tv_sec; - cam->movie_output_motion->start_time.tv_usec = ts1->tv_usec; + cam->movie_output_motion->start_time.tv_nsec = ts1->tv_nsec; cam->movie_output_motion->last_pts = -1; cam->movie_output_motion->base_pts = 0; cam->movie_output_motion->gop_cnt = 0; @@ -1162,7 +1162,7 @@ static void event_movie_newfile(struct ctx_cam *cam, motion_event evnt static void event_movie_timelapse(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { int retcd; int passthrough; @@ -1209,7 +1209,7 @@ static void event_movie_timelapse(struct ctx_cam *cam, motion_event evnt cam->movie_timelapse->filename = cam->timelapsefilename; cam->movie_timelapse->quality = cam->conf.movie_quality; cam->movie_timelapse->start_time.tv_sec = ts1->tv_sec; - cam->movie_timelapse->start_time.tv_usec = ts1->tv_usec; + cam->movie_timelapse->start_time.tv_nsec = ts1->tv_nsec; cam->movie_timelapse->last_pts = -1; cam->movie_timelapse->base_pts = 0; cam->movie_timelapse->test_mode = FALSE; @@ -1259,7 +1259,7 @@ static void event_movie_timelapse(struct ctx_cam *cam, motion_event evnt static void event_movie_put(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { (void)evnt; (void)fname; @@ -1279,7 +1279,7 @@ static void event_movie_put(struct ctx_cam *cam, motion_event evnt static void event_movie_closefile(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { (void)evnt; (void)img_data; @@ -1304,7 +1304,7 @@ static void event_movie_closefile(struct ctx_cam *cam, motion_event evnt static void event_movie_timelapseend(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { (void)evnt; (void)img_data; @@ -1467,7 +1467,7 @@ struct event_handlers event_handlers[] = { */ void event(struct ctx_cam *cam, motion_event evnt ,struct image_data *img_data, char *fname - ,void *ftype, struct timeval *ts1) { + ,void *ftype, struct timespec *ts1) { int i=-1; while (event_handlers[++i].handler) { diff --git a/src/event.h b/src/event.h index be8146ce..306b9d8d 100644 --- a/src/event.h +++ b/src/event.h @@ -36,9 +36,9 @@ typedef enum { } motion_event; typedef void(* event_handler)(struct ctx_cam *cam, motion_event, struct image_data *, - char *, void *, struct timeval *); + char *, void *, struct timespec *); -void event(struct ctx_cam *cam, motion_event, struct image_data *img_data, char *, void *, struct timeval *); +void event(struct ctx_cam *cam, motion_event, struct image_data *img_data, char *, void *, struct timespec *); const char * imageext(struct ctx_cam *cam); #endif /* _INCLUDE_EVENT_H_ */ diff --git a/src/jpegutils.c b/src/jpegutils.c index 25ffc48a..549305c0 100644 --- a/src/jpegutils.c +++ b/src/jpegutils.c @@ -422,11 +422,11 @@ static GLOBAL(int) _jpeg_mem_size(j_compress_ptr cinfo) */ static void put_jpeg_exif(j_compress_ptr cinfo, const struct ctx_cam *cam, - const struct timeval *tv1, + const struct timespec *ts1, const struct coord *box) { unsigned char *exif = NULL; - unsigned exif_len = prepare_exif(&exif, cam, tv1, box); + unsigned exif_len = prepare_exif(&exif, cam, ts1, box); if(exif_len > 0) { /* EXIF data lives in a JPEG APP1 marker */ @@ -549,7 +549,7 @@ int jpgutl_decode_jpeg (unsigned char *jpeg_data_in, int jpeg_data_len, int jpgutl_put_yuv420p(unsigned char *dest_image, int image_size, unsigned char *input_image, int width, int height, int quality, - struct ctx_cam *cam, struct timeval *tv1, struct coord *box) + struct ctx_cam *cam, struct timespec *ts1, struct coord *box) { int i, j, jpeg_image_size; @@ -606,7 +606,7 @@ int jpgutl_put_yuv420p(unsigned char *dest_image, int image_size, jpeg_start_compress(&cinfo, TRUE); - put_jpeg_exif(&cinfo, cam, tv1, box); + put_jpeg_exif(&cinfo, cam, ts1, box); /* If the image is not a multiple of 16, this overruns the buffers * we'll just pad those last bytes with zeros @@ -638,7 +638,7 @@ int jpgutl_put_yuv420p(unsigned char *dest_image, int image_size, int jpgutl_put_grey(unsigned char *dest_image, int image_size, unsigned char *input_image, int width, int height, int quality, - struct ctx_cam *cam, struct timeval *tv1, struct coord *box) + struct ctx_cam *cam, struct timespec *ts1, struct coord *box) { int y, dest_image_size; JSAMPROW row_ptr[1]; @@ -674,7 +674,7 @@ int jpgutl_put_grey(unsigned char *dest_image, int image_size, jpeg_start_compress (&cjpeg, TRUE); - put_jpeg_exif(&cjpeg, cam, tv1, box); + put_jpeg_exif(&cjpeg, cam, ts1, box); row_ptr[0] = input_image; diff --git a/src/jpegutils.h b/src/jpegutils.h index 0570b7b7..82b9a81a 100644 --- a/src/jpegutils.h +++ b/src/jpegutils.h @@ -14,7 +14,7 @@ int jpgutl_decode_jpeg (unsigned char *jpeg_data_in, int jpeg_data_len, unsigned int width, unsigned int height, unsigned char *volatile img_out); - int jpgutl_put_yuv420p(unsigned char *, int image, unsigned char *, int, int, int, struct ctx_cam *cam, struct timeval *, struct coord *); - int jpgutl_put_grey(unsigned char *, int image, unsigned char *, int, int, int, struct ctx_cam *cam, struct timeval *, struct coord *); + int jpgutl_put_yuv420p(unsigned char *, int image, unsigned char *, int, int, int, struct ctx_cam *cam, struct timespec *, struct coord *); + int jpgutl_put_grey(unsigned char *, int image, unsigned char *, int, int, int, struct ctx_cam *cam, struct timespec *, struct coord *); #endif diff --git a/src/motion.c b/src/motion.c index 18faf3ec..06a7a40e 100644 --- a/src/motion.c +++ b/src/motion.c @@ -569,39 +569,26 @@ static void motion_detected(struct ctx_cam *cam, int dev, struct image_data *img /* Do things only if we have got minimum_motion_frames */ if (img->flags & IMAGE_TRIGGER) { - /* Take action if this is a new event and we have a trigger image */ if (cam->event_nr != cam->prev_event) { - /* - * Reset prev_event number to current event and save event time - * in both time_t and struct tm format. - */ + cam->prev_event = cam->event_nr; - cam->eventtime = img->timestamp_tv.tv_sec; - localtime_r(&cam->eventtime, cam->eventtime_tm); + cam->eventtime = img->imgts.tv_sec; - /* - * Since this is a new event we create the event_text_string used for - * the %C conversion specifier. We may already need it for - * on_motion_detected_commend so it must be done now. - */ mystrftime(cam, cam->text_event_string, sizeof(cam->text_event_string), - cam->conf.text_event, &img->timestamp_tv, NULL, 0); + cam->conf.text_event, &img->imgts, NULL, 0); - /* EVENT_FIRSTMOTION triggers on_event_start_command and event_movie_newfile */ event(cam, EVENT_FIRSTMOTION, img, NULL, NULL, - &cam->imgs.image_ring[cam->imgs.image_ring_out].timestamp_tv); + &cam->imgs.image_ring[cam->imgs.image_ring_out].imgts); MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Motion detected - starting event %d"), cam->event_nr); - /* always save first motion frame as preview-shot, may be changed to an other one later */ if (cam->new_img & (NEWIMG_FIRST | NEWIMG_BEST | NEWIMG_CENTER)) image_save_as_preview(cam, img); } - /* EVENT_MOTION triggers event_beep and on_motion_detected_command */ - event(cam, EVENT_MOTION, NULL, NULL, NULL, &img->timestamp_tv); + event(cam, EVENT_MOTION, NULL, NULL, NULL, &img->imgts); } /* Limit framerate */ @@ -613,14 +600,14 @@ static void motion_detected(struct ctx_cam *cam, int dev, struct image_data *img * We also disable this in setup_mode. */ if (conf->stream_motion && !conf->setup_mode && img->shot != 1) - event(cam, EVENT_STREAM, img, NULL, NULL, &img->timestamp_tv); + event(cam, EVENT_STREAM, img, NULL, NULL, &img->imgts); /* * Save motion jpeg, if configured * Output the image_out (motion) picture. */ if (conf->picture_output_motion) - event(cam, EVENT_IMAGEM_DETECTED, NULL, NULL, NULL, &img->timestamp_tv); + event(cam, EVENT_IMAGEM_DETECTED, NULL, NULL, NULL, &img->imgts); } /* if track enabled and auto track on */ @@ -677,7 +664,7 @@ static void process_image_ring(struct ctx_cam *cam, unsigned int max_images) t = "Other"; mystrftime(cam, tmp, sizeof(tmp), "%H%M%S-%q", - &cam->imgs.image_ring[cam->imgs.image_ring_out].timestamp_tv, NULL, 0); + &cam->imgs.image_ring[cam->imgs.image_ring_out].imgts, NULL, 0); draw_text(cam->imgs.image_ring[cam->imgs.image_ring_out].image_norm, cam->imgs.width, cam->imgs.height, 10, 20, tmp, cam->text_scale); draw_text(cam->imgs.image_ring[cam->imgs.image_ring_out].image_norm, @@ -687,7 +674,7 @@ static void process_image_ring(struct ctx_cam *cam, unsigned int max_images) /* Output the picture to jpegs and ffmpeg */ event(cam, EVENT_IMAGE_DETECTED, &cam->imgs.image_ring[cam->imgs.image_ring_out], NULL, NULL, - &cam->imgs.image_ring[cam->imgs.image_ring_out].timestamp_tv); + &cam->imgs.image_ring[cam->imgs.image_ring_out].imgts); /* @@ -722,7 +709,7 @@ static void process_image_ring(struct ctx_cam *cam, unsigned int max_images) /* Add a filler frame into encoder */ event(cam, EVENT_MOVIE_PUT, &cam->imgs.image_ring[cam->imgs.image_ring_out], NULL, NULL, - &cam->imgs.image_ring[cam->imgs.image_ring_out].timestamp_tv); + &cam->imgs.image_ring[cam->imgs.image_ring_out].imgts); cam->movie_last_shot++; } @@ -1250,18 +1237,15 @@ static void dbse_sqlmask_update(struct ctx_cam *cam){ static int motion_init(struct ctx_cam *cam) { FILE *picture; - int indx, retcd; + int retcd; util_threadname_set("ml",cam->threadnr,cam->conf.camera_name); /* Store thread number in TLS. */ pthread_setspecific(tls_key_threadnr, (void *)((unsigned long)cam->threadnr)); - cam->currenttime_tm = mymalloc(sizeof(struct tm)); - cam->eventtime_tm = mymalloc(sizeof(struct tm)); - /* Init frame time */ - cam->currenttime = time(NULL); - localtime_r(&cam->currenttime, cam->currenttime_tm); + clock_gettime(CLOCK_REALTIME, &cam->frame_last_ts); + clock_gettime(CLOCK_REALTIME, &cam->frame_curr_ts); cam->smartmask_speed = 0; @@ -1544,19 +1528,6 @@ static int motion_init(struct ctx_cam *cam) cam->frame_delay = cam->required_frame_time; - /* - * Reserve enough space for a 10 second timing history buffer. Note that, - * if there is any problem on the allocation, mymalloc does not return. - */ - cam->rolling_average_data = NULL; - cam->rolling_average_limit = 10 * cam->conf.framerate; - cam->rolling_average_data = mymalloc(sizeof(cam->rolling_average_data) * cam->rolling_average_limit); - - /* Preset history buffer with expected frame rate */ - for (indx = 0; indx < cam->rolling_average_limit; indx++) - cam->rolling_average_data[indx] = cam->required_frame_time; - - cam->track_posx = 0; cam->track_posy = 0; if (cam->track.type) @@ -1710,17 +1681,6 @@ static void motion_cleanup(struct ctx_cam *cam) { cam->mpipe = -1; } - if (cam->rolling_average_data != NULL) free(cam->rolling_average_data); - - - /* Cleanup the current time structure */ - free(cam->currenttime_tm); - cam->currenttime_tm = NULL; - - /* Cleanup the event time structure */ - free(cam->eventtime_tm); - cam->eventtime_tm = NULL; - dbse_deinit(cam); } @@ -1818,7 +1778,7 @@ static void mlp_areadetect(struct ctx_cam *cam){ cam->current_image->location.x < cam->area_maxx[z] && cam->current_image->location.y > cam->area_miny[z] && cam->current_image->location.y < cam->area_maxy[z]) { - event(cam, EVENT_AREA_DETECTED, NULL, NULL, NULL, &cam->current_image->timestamp_tv); + event(cam, EVENT_AREA_DETECTED, NULL, NULL, NULL, &cam->current_image->imgts); cam->areadetect_eventnbr = cam->event_nr; /* Fire script only once per event */ MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO ,_("Motion in area %d detected."), z + 1); @@ -1833,19 +1793,14 @@ static void mlp_areadetect(struct ctx_cam *cam){ static void mlp_prepare(struct ctx_cam *cam){ int frame_buffer_size; - struct timeval tv1; - /***** MOTION LOOP - PREPARE FOR NEW FRAME SECTION *****/ cam->watchdog = WATCHDOG_TMO; - /* Get current time and preserver last time for frame interval calc. */ - - /* This may be better at the end of the loop or moving the part in - * the end doing elapsed time calc in here - */ cam->timebefore = cam->timenow; - gettimeofday(&tv1, NULL); - cam->timenow = tv1.tv_usec + 1000000L * tv1.tv_sec; + + cam->frame_last_ts.tv_sec = cam->frame_curr_ts.tv_sec; + cam->frame_last_ts.tv_nsec = cam->frame_curr_ts.tv_nsec; + clock_gettime(CLOCK_REALTIME, &cam->frame_curr_ts); /* * Calculate detection rate limit. Above 5fps we limit the detection @@ -1858,42 +1813,23 @@ static void mlp_prepare(struct ctx_cam *cam){ cam->process_thisframe = 1; } - /* - * Since we don't have sanity checks done when options are set, - * this sanity check must go in the main loop :(, before pre_captures - * are attempted. - */ if (cam->conf.minimum_motion_frames < 1) cam->conf.minimum_motion_frames = 1; if (cam->conf.pre_capture < 0) cam->conf.pre_capture = 0; - /* - * Check if our buffer is still the right size - * If pre_capture or minimum_motion_frames has been changed - * via the http remote control we need to re-size the ring buffer - */ frame_buffer_size = cam->conf.pre_capture + cam->conf.minimum_motion_frames; if (cam->imgs.image_ring_size != frame_buffer_size) image_ring_resize(cam, frame_buffer_size); - /* Get time for current frame */ - cam->currenttime = time(NULL); - - /* - * localtime returns static data and is not threadsafe - * so we use localtime_r which is reentrant and threadsafe - */ - localtime_r(&cam->currenttime, cam->currenttime_tm); - /* * If we have started on a new second we reset the shots variable * lastrate is updated to be the number of the last frame. last rate * is used as the ffmpeg framerate when motion is detected. */ - if (cam->lastframetime != cam->currenttime) { + if (cam->frame_last_ts.tv_sec != cam->frame_curr_ts.tv_sec) { cam->lastrate = cam->shots + 1; cam->shots = -1; cam->lastframetime = cam->currenttime; @@ -1955,7 +1891,7 @@ static void mlp_resetimages(struct ctx_cam *cam){ } else if (cam->current_image && old_image) { /* not processing this frame: save some important values for next image */ cam->current_image->diffs = old_image->diffs; - cam->current_image->timestamp_tv = old_image->timestamp_tv; + cam->current_image->imgts = old_image->imgts; cam->current_image->shot = old_image->shot; cam->current_image->cent_dist = old_image->cent_dist; cam->current_image->flags = old_image->flags & (~IMAGE_SAVED); @@ -1963,8 +1899,7 @@ static void mlp_resetimages(struct ctx_cam *cam){ cam->current_image->total_labels = old_image->total_labels; } - /* Store time with pre_captured image */ - gettimeofday(&cam->current_image->timestamp_tv, NULL); + clock_gettime(CLOCK_REALTIME, &cam->current_image->imgts); /* Store shot number with pre_captured image */ cam->current_image->shot = cam->shots; @@ -2037,7 +1972,7 @@ static int mlp_capture(struct ctx_cam *cam){ const char *tmpin; char tmpout[80]; int vid_return_code = 0; /* Return code used when calling vid_next */ - struct timeval tv1; + struct timespec ts1; /***** MOTION LOOP - IMAGE CAPTURE SECTION *****/ /* @@ -2077,16 +2012,6 @@ static int mlp_capture(struct ctx_cam *cam){ memcpy(cam->imgs.image_vprvcy.image_norm, cam->current_image->image_norm, cam->imgs.size_norm); - /* - * If the camera is a netcam we let the camera decide the pace. - * Otherwise we will keep on adding duplicate frames. - * By resetting the timer the framerate becomes maximum the rate - * of the Netcam. - */ - if (cam->conf.netcam_url) { - gettimeofday(&tv1, NULL); - cam->timenow = tv1.tv_usec + 1000000L * tv1.tv_sec; - } // FATAL ERROR - leave the thread by breaking out of the main loop } else if (vid_return_code < 0) { /* Fatal error - Close video device */ @@ -2159,10 +2084,10 @@ static int mlp_capture(struct ctx_cam *cam){ else tmpin = "UNABLE TO OPEN VIDEO DEVICE\\nSINCE %Y-%m-%d %T"; - tv1.tv_sec=cam->connectionlosttime; - tv1.tv_usec = 0; + ts1.tv_sec=cam->connectionlosttime; + ts1.tv_nsec = 0; memset(cam->current_image->image_norm, 0x80, cam->imgs.size_norm); - mystrftime(cam, tmpout, sizeof(tmpout), tmpin, &tv1, NULL, 0); + mystrftime(cam, tmpout, sizeof(tmpout), tmpin, &ts1, NULL, 0); draw_text(cam->current_image->image_norm, cam->imgs.width, cam->imgs.height, 10, 20 * cam->text_scale, tmpout, cam->text_scale); @@ -2171,7 +2096,7 @@ static int mlp_capture(struct ctx_cam *cam){ MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO ,_("Video signal lost - Adding grey image")); // Event for lost video signal can be called from here - event(cam, EVENT_CAMERA_LOST, NULL, NULL, NULL, &tv1); + event(cam, EVENT_CAMERA_LOST, NULL, NULL, NULL, &ts1); } /* @@ -2441,7 +2366,7 @@ static void mlp_overlay(struct ctx_cam *cam){ /* Add text in lower left corner of the pictures */ if (cam->conf.text_left) { mystrftime(cam, tmp, sizeof(tmp), cam->conf.text_left, - &cam->current_image->timestamp_tv, NULL, 0); + &cam->current_image->imgts, NULL, 0); draw_text(cam->current_image->image_norm, cam->imgs.width, cam->imgs.height, 10, cam->imgs.height - (10 * cam->text_scale), tmp, cam->text_scale); } @@ -2449,7 +2374,7 @@ static void mlp_overlay(struct ctx_cam *cam){ /* Add text in lower right corner of the pictures */ if (cam->conf.text_right) { mystrftime(cam, tmp, sizeof(tmp), cam->conf.text_right, - &cam->current_image->timestamp_tv, NULL, 0); + &cam->current_image->imgts, NULL, 0); draw_text(cam->current_image->image_norm, cam->imgs.width, cam->imgs.height, cam->imgs.width - 10, cam->imgs.height - (10 * cam->text_scale), tmp, cam->text_scale); @@ -2485,7 +2410,7 @@ static void mlp_actions(struct ctx_cam *cam){ * get a pause in the movie. */ if ( (cam->detecting_motion == 0) && (cam->movie_output != NULL) ) - movie_reset_movie_start_time(cam->movie_output, &cam->current_image->timestamp_tv); + movie_reset_movie_start_time(cam->movie_output, &cam->current_image->imgts); cam->detecting_motion = 1; if (cam->conf.post_capture > 0) { /* Setup the postcap counter */ @@ -2528,7 +2453,7 @@ static void mlp_actions(struct ctx_cam *cam){ * get a pause in the movie. */ if ( (cam->detecting_motion == 0) && (cam->movie_output != NULL) ) - movie_reset_movie_start_time(cam->movie_output, &cam->current_image->timestamp_tv); + movie_reset_movie_start_time(cam->movie_output, &cam->current_image->imgts); cam->detecting_motion = 1; @@ -2567,7 +2492,7 @@ static void mlp_actions(struct ctx_cam *cam){ /* Update last frame saved time, so we can end event after gap time */ if (cam->current_image->flags & IMAGE_SAVE) - cam->lasttime = cam->current_image->timestamp_tv.tv_sec; + cam->lasttime = cam->current_image->imgts.tv_sec; mlp_areadetect(cam); @@ -2593,11 +2518,11 @@ static void mlp_actions(struct ctx_cam *cam){ /* Save preview_shot here at the end of event */ if (cam->imgs.preview_image.diffs) { - event(cam, EVENT_IMAGE_PREVIEW, NULL, NULL, NULL, &cam->current_image->timestamp_tv); + event(cam, EVENT_IMAGE_PREVIEW, NULL, NULL, NULL, &cam->current_image->imgts); cam->imgs.preview_image.diffs = 0; } - event(cam, EVENT_ENDMOTION, NULL, NULL, NULL, &cam->current_image->timestamp_tv); + event(cam, EVENT_ENDMOTION, NULL, NULL, NULL, &cam->current_image->imgts); /* * If tracking is enabled we center our camera so it does not @@ -2683,9 +2608,10 @@ static void mlp_snapshot(struct ctx_cam *cam){ cam->time_current_frame = cam->currenttime; if ((cam->conf.snapshot_interval > 0 && cam->shots == 0 && - cam->time_current_frame % cam->conf.snapshot_interval <= cam->time_last_frame % cam->conf.snapshot_interval) || + cam->frame_curr_ts.tv_sec % cam->conf.snapshot_interval <= + cam->frame_last_ts.tv_sec % cam->conf.snapshot_interval) || cam->snapshot) { - event(cam, EVENT_IMAGE_SNAPSHOT, cam->current_image, NULL, NULL, &cam->current_image->timestamp_tv); + event(cam, EVENT_IMAGE_SNAPSHOT, cam->current_image, NULL, NULL, &cam->current_image->imgts); cam->snapshot = 0; } @@ -2696,7 +2622,7 @@ static void mlp_timelapse(struct ctx_cam *cam){ struct tm timestamp_tm; if (cam->conf.timelapse_interval) { - localtime_r(&cam->current_image->timestamp_tv.tv_sec, ×tamp_tm); + localtime_r(&cam->current_image->imgts.tv_sec, ×tamp_tm); /* * Check to see if we should start a new timelapse file. We start one when @@ -2704,7 +2630,7 @@ static void mlp_timelapse(struct ctx_cam *cam){ * to prevent the timelapse file from getting reset multiple times during the minute. */ if (timestamp_tm.tm_min == 0 && - (cam->time_current_frame % 60 < cam->time_last_frame % 60) && + (cam->frame_curr_ts.tv_sec % 60 < cam->frame_last_ts.tv_sec % 60) && cam->shots == 0) { if (strcasecmp(cam->conf.timelapse_mode, "manual") == 0) { @@ -2713,27 +2639,27 @@ static void mlp_timelapse(struct ctx_cam *cam){ /* If we are daily, raise timelapseend event at midnight */ } else if (strcasecmp(cam->conf.timelapse_mode, "daily") == 0) { if (timestamp_tm.tm_hour == 0) - event(cam, EVENT_TIMELAPSEEND, NULL, NULL, NULL, &cam->current_image->timestamp_tv); + event(cam, EVENT_TIMELAPSEEND, NULL, NULL, NULL, &cam->current_image->imgts); /* handle the hourly case */ } else if (strcasecmp(cam->conf.timelapse_mode, "hourly") == 0) { - event(cam, EVENT_TIMELAPSEEND, NULL, NULL, NULL, &cam->current_image->timestamp_tv); + event(cam, EVENT_TIMELAPSEEND, NULL, NULL, NULL, &cam->current_image->imgts); /* If we are weekly-sunday, raise timelapseend event at midnight on sunday */ } else if (strcasecmp(cam->conf.timelapse_mode, "weekly-sunday") == 0) { if (timestamp_tm.tm_wday == 0 && timestamp_tm.tm_hour == 0) - event(cam, EVENT_TIMELAPSEEND, NULL, NULL, NULL, &cam->current_image->timestamp_tv); + event(cam, EVENT_TIMELAPSEEND, NULL, NULL, NULL, &cam->current_image->imgts); /* If we are weekly-monday, raise timelapseend event at midnight on monday */ } else if (strcasecmp(cam->conf.timelapse_mode, "weekly-monday") == 0) { if (timestamp_tm.tm_wday == 1 && timestamp_tm.tm_hour == 0) - event(cam, EVENT_TIMELAPSEEND, NULL, NULL, NULL, &cam->current_image->timestamp_tv); + event(cam, EVENT_TIMELAPSEEND, NULL, NULL, NULL, &cam->current_image->imgts); /* If we are monthly, raise timelapseend event at midnight on first day of month */ } else if (strcasecmp(cam->conf.timelapse_mode, "monthly") == 0) { if (timestamp_tm.tm_mday == 1 && timestamp_tm.tm_hour == 0) - event(cam, EVENT_TIMELAPSEEND, NULL, NULL, NULL, &cam->current_image->timestamp_tv); + event(cam, EVENT_TIMELAPSEEND, NULL, NULL, NULL, &cam->current_image->imgts); /* If invalid we report in syslog once and continue in manual mode */ } else { MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO @@ -2744,22 +2670,20 @@ static void mlp_timelapse(struct ctx_cam *cam){ } } - /* - * If ffmpeg timelapse is enabled and time since epoch MOD movie_timelaps = 0 - * add a timelapse frame to the timelapse movie. - */ - if (cam->shots == 0 && cam->time_current_frame % cam->conf.timelapse_interval <= - cam->time_last_frame % cam->conf.timelapse_interval) { - event(cam, EVENT_TIMELAPSE, cam->current_image, NULL, NULL, - &cam->current_image->timestamp_tv); + if (cam->shots == 0 && + cam->frame_curr_ts.tv_sec % cam->conf.timelapse_interval <= + cam->frame_last_ts.tv_sec % cam->conf.timelapse_interval) { + event(cam, EVENT_TIMELAPSE, cam->current_image, NULL + , NULL, &cam->current_image->imgts); } + } else if (cam->movie_timelapse) { /* * If timelapse movie is in progress but conf.timelapse_interval is zero then close timelapse file * This is an important feature that allows manual roll-over of timelapse file using the http * remote control via a cron job. */ - event(cam, EVENT_TIMELAPSEEND, NULL, NULL, NULL, &cam->current_image->timestamp_tv); + event(cam, EVENT_TIMELAPSEEND, NULL, NULL, NULL, &cam->current_image->imgts); } cam->time_last_frame = cam->time_current_frame; @@ -2780,18 +2704,18 @@ static void mlp_loopback(struct ctx_cam *cam){ */ if (cam->conf.setup_mode) { - event(cam, EVENT_IMAGE, &cam->imgs.img_motion, NULL, &cam->pipe, &cam->current_image->timestamp_tv); - event(cam, EVENT_STREAM, &cam->imgs.img_motion, NULL, NULL, &cam->current_image->timestamp_tv); + event(cam, EVENT_IMAGE, &cam->imgs.img_motion, NULL, &cam->pipe, &cam->current_image->imgts); + event(cam, EVENT_STREAM, &cam->imgs.img_motion, NULL, NULL, &cam->current_image->imgts); } else { event(cam, EVENT_IMAGE, cam->current_image, NULL, - &cam->pipe, &cam->current_image->timestamp_tv); + &cam->pipe, &cam->current_image->imgts); if (!cam->conf.stream_motion || cam->shots == 1) event(cam, EVENT_STREAM, cam->current_image, NULL, NULL, - &cam->current_image->timestamp_tv); + &cam->current_image->imgts); } - event(cam, EVENT_IMAGEM, &cam->imgs.img_motion, NULL, &cam->mpipe, &cam->current_image->timestamp_tv); + event(cam, EVENT_IMAGEM, &cam->imgs.img_motion, NULL, &cam->mpipe, &cam->current_image->imgts); } @@ -2871,59 +2795,40 @@ static void mlp_parmsupdate(struct ctx_cam *cam){ static void mlp_frametiming(struct ctx_cam *cam){ int indx; - struct timeval tv2; - unsigned long int elapsedtime; //TODO: Need to evaluate logic for needing this. - long int delay_time_nsec; + struct timespec ts2; + int64_t avgtime; - /***** MOTION LOOP - FRAMERATE TIMING AND SLEEPING SECTION *****/ - /* - * Work out expected frame rate based on config setting which may - * have changed from http-control - */ - if (cam->conf.framerate) - cam->required_frame_time = 1000000L / cam->conf.framerate; - else - cam->required_frame_time = 0; + /* Shuffle the last wait times*/ + for (indx=0; indxframe_wait[indx]=cam->frame_wait[indx+1]; + } - /* Get latest time to calculate time taken to process video data */ - gettimeofday(&tv2, NULL); - elapsedtime = (tv2.tv_usec + 1000000L * tv2.tv_sec) - cam->timenow; + if (cam->conf.framerate) { + cam->frame_wait[AVGCNT-1] = 1000000L / cam->conf.framerate; + } else { + cam->frame_wait[AVGCNT-1] = 0; + } - /* - * Update history buffer but ignore first pass as timebefore - * variable will be inaccurate - */ - if (cam->passflag) - cam->rolling_average_data[cam->rolling_frame] = cam->timenow - cam->timebefore; - else - cam->passflag = 1; + clock_gettime(CLOCK_REALTIME, &ts2); - cam->rolling_frame++; - if (cam->rolling_frame >= cam->rolling_average_limit) - cam->rolling_frame = 0; + cam->frame_wait[AVGCNT-1] = cam->frame_wait[AVGCNT-1] - + (1000000L * (ts2.tv_sec - cam->frame_curr_ts.tv_sec)) - + ((ts2.tv_nsec - cam->frame_curr_ts.tv_nsec)/1000); - /* Calculate 10 second average and use deviation in delay calculation */ - cam->rolling_average = 0L; + avgtime = 0; + for (indx=0; indxframe_wait[indx]; + } + avgtime = (avgtime/AVGCNT); - for (indx = 0; indx < cam->rolling_average_limit; indx++) - cam->rolling_average += cam->rolling_average_data[indx]; - - cam->rolling_average /= cam->rolling_average_limit; - cam->frame_delay = cam->required_frame_time - elapsedtime - (cam->rolling_average - cam->required_frame_time); - - if (cam->frame_delay > 0) { - /* Apply delay to meet frame time */ - if (cam->frame_delay > cam->required_frame_time) - cam->frame_delay = cam->required_frame_time; - - /* Delay time in nanoseconds for SLEEP */ - delay_time_nsec = cam->frame_delay * 1000; - - if (delay_time_nsec > 999999999) - delay_time_nsec = 999999999; - - /* SLEEP as defined in motion.h A safe sleep using nanosleep */ - SLEEP(0, delay_time_nsec); + if (avgtime > 0) { + avgtime = avgtime * 1000; + /* If over 1 second, just do one*/ + if (avgtime > 999999999) { + SLEEP(1, 0); + } else { + SLEEP(0, avgtime); + } } } @@ -3923,7 +3828,7 @@ static void mystrftime_long (const struct ctx_cam *cam, * Returns: number of bytes written to the string s */ size_t mystrftime(const struct ctx_cam *cam, char *s, size_t max, const char *userformat, - const struct timeval *tv1, const char *filename, int sqltype) + const struct timespec *ts1, const char *filename, int sqltype) { char formatstring[PATH_MAX] = ""; char tempstring[PATH_MAX] = ""; @@ -3932,7 +3837,7 @@ size_t mystrftime(const struct ctx_cam *cam, char *s, size_t max, const char *us int width; struct tm timestamp_tm; - localtime_r(&tv1->tv_sec, ×tamp_tm); + localtime_r(&ts1->tv_sec, ×tamp_tm); format = formatstring; diff --git a/src/motion.h b/src/motion.h index 15e2510b..3ef70c11 100644 --- a/src/motion.h +++ b/src/motion.h @@ -83,10 +83,10 @@ int nls_enabled; * If a signal such as SIG_CHLD interrupts the sleep we just continue sleeping */ #define SLEEP(seconds, nanoseconds) { \ - struct timespec tv; \ - tv.tv_sec = (seconds); \ - tv.tv_nsec = (nanoseconds); \ - while (nanosleep(&tv, &tv) == -1); \ + struct timespec ts1; \ + ts1.tv_sec = (seconds); \ + ts1.tv_nsec = (nanoseconds); \ + while (nanosleep(&ts1, &ts1) == -1); \ } #define DEF_PALETTE 17 @@ -172,7 +172,7 @@ int nls_enabled; #define TRUE 1 #define FALSE 0 - +#define AVGCNT 30 /* * Structure to hold images information @@ -227,7 +227,7 @@ struct image_data { int diffs; int64_t idnbr_norm; int64_t idnbr_high; - struct timeval timestamp_tv; + struct timespec imgts; int shot; /* Sub second timestamp count */ /* @@ -422,8 +422,9 @@ struct ctx_cam { int postcap; /* downcounter, frames left to to send post event */ int shots; unsigned int detecting_motion; - struct tm *currenttime_tm; - struct tm *eventtime_tm; + long frame_wait[AVGCNT]; /* Last wait times through motion loop*/ + struct timespec frame_curr_ts; + struct timespec frame_last_ts; time_t currenttime; time_t lasttime; @@ -483,10 +484,6 @@ struct ctx_cam { long int required_frame_time, frame_delay; - long int rolling_average_limit; - long int *rolling_average_data; - unsigned long int rolling_average; - int olddiffs; //only need this in here for a printf later...do we need that printf? int smartmask_ratio; int smartmask_count; @@ -527,7 +524,7 @@ void * mymalloc(size_t); void * myrealloc(void *, size_t, const char *); FILE * myfopen(const char *, const char *); int myfclose(FILE *); -size_t mystrftime(const struct ctx_cam *, char *, size_t, const char *, const struct timeval *, const char *, int); +size_t mystrftime(const struct ctx_cam *, char *, size_t, const char *, const struct timespec *, const char *, int); int create_path(const char *); void util_threadname_set(const char *abbr, int threadnbr, const char *threadname); diff --git a/src/movie.c b/src/movie.c index f34eef2c..040831cf 100644 --- a/src/movie.c +++ b/src/movie.c @@ -523,7 +523,7 @@ static int movie_encode_video(struct ctx_movie *movie){ } -static int movie_set_pts(struct ctx_movie *movie, const struct timeval *tv1){ +static int movie_set_pts(struct ctx_movie *movie, const struct timespec *ts1){ int64_t pts_interval; @@ -531,10 +531,10 @@ static int movie_set_pts(struct ctx_movie *movie, const struct timeval *tv1){ movie->last_pts++; movie->picture->pts = movie->last_pts; } else { - pts_interval = ((1000000L * (tv1->tv_sec - movie->start_time.tv_sec)) + tv1->tv_usec - movie->start_time.tv_usec); + pts_interval = ((1000000L * (ts1->tv_sec - movie->start_time.tv_sec)) + (ts1->tv_nsec/1000) - (movie->start_time.tv_nsec/1000)); if (pts_interval < 0){ /* This can occur when we have pre-capture frames. Reset start time of video. */ - movie_reset_movie_start_time(movie, tv1); + movie_reset_movie_start_time(movie, ts1); pts_interval = 0; } if (movie->last_pts < 0) { @@ -562,7 +562,7 @@ static int movie_set_pts(struct ctx_movie *movie, const struct timeval *tv1){ return 0; } -static int movie_set_pktpts(struct ctx_movie *movie, const struct timeval *tv1){ +static int movie_set_pktpts(struct ctx_movie *movie, const struct timespec *ts1){ int64_t pts_interval; @@ -570,10 +570,10 @@ static int movie_set_pktpts(struct ctx_movie *movie, const struct timeval *tv1){ movie->last_pts++; movie->pkt.pts = movie->last_pts; } else { - pts_interval = ((1000000L * (tv1->tv_sec - movie->start_time.tv_sec)) + tv1->tv_usec - movie->start_time.tv_usec); + pts_interval = ((1000000L * (ts1->tv_sec - movie->start_time.tv_sec)) + (ts1->tv_nsec/1000) - (movie->start_time.tv_nsec/1000)); if (pts_interval < 0){ /* This can occur when we have pre-capture frames. Reset start time of video. */ - movie_reset_movie_start_time(movie, tv1); + movie_reset_movie_start_time(movie, ts1); pts_interval = 0; } movie->pkt.pts = av_rescale_q(pts_interval,(AVRational){1, 1000000L},movie->video_st->time_base) + movie->base_pts; @@ -1098,14 +1098,14 @@ static int movie_flush_codec(struct ctx_movie *movie){ } -static int movie_put_frame(struct ctx_movie *movie, const struct timeval *tv1){ +static int movie_put_frame(struct ctx_movie *movie, const struct timespec *ts1){ int retcd; av_init_packet(&movie->pkt); movie->pkt.data = NULL; movie->pkt.size = 0; - retcd = movie_set_pts(movie, tv1); + retcd = movie_set_pts(movie, ts1); if (retcd < 0) { //If there is an error, it has already been reported. my_packet_unref(movie->pkt); @@ -1168,7 +1168,7 @@ static void movie_passthru_write(struct ctx_movie *movie, int indx){ return; } - retcd = movie_set_pktpts(movie, &movie->netcam_data->pktarray[indx].timestamp_tv); + retcd = movie_set_pktpts(movie, &movie->netcam_data->pktarray[indx].timestamp_ts); if (retcd < 0) { my_packet_unref(movie->pkt); return; @@ -1548,7 +1548,7 @@ void movie_close(struct ctx_movie *movie){ } -int movie_put_image(struct ctx_movie *movie, struct image_data *img_data, const struct timeval *tv1){ +int movie_put_image(struct ctx_movie *movie, struct image_data *img_data, const struct timespec *ts1){ int retcd = 0; int cnt = 0; @@ -1582,9 +1582,9 @@ int movie_put_image(struct ctx_movie *movie, struct image_data *img_data, const * never want a frame buffered so we keep sending back the * the same pic until it flushes or fails in a different way */ - retcd = movie_put_frame(movie, tv1); + retcd = movie_put_frame(movie, ts1); while ((retcd == -2) && (movie->tlapse != TIMELAPSE_NONE)) { - retcd = movie_put_frame(movie, tv1); + retcd = movie_put_frame(movie, ts1); cnt++; if (cnt > 50){ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO @@ -1603,13 +1603,13 @@ int movie_put_image(struct ctx_movie *movie, struct image_data *img_data, const } -void movie_reset_movie_start_time(struct ctx_movie *movie, const struct timeval *tv1){ +void movie_reset_movie_start_time(struct ctx_movie *movie, const struct timespec *ts1){ int64_t one_frame_interval = av_rescale_q(1,(AVRational){1, movie->fps},movie->video_st->time_base); if (one_frame_interval <= 0) one_frame_interval = 1; movie->base_pts = movie->last_pts + one_frame_interval; - movie->start_time.tv_sec = tv1->tv_sec; - movie->start_time.tv_usec = tv1->tv_usec; + movie->start_time.tv_sec = ts1->tv_sec; + movie->start_time.tv_nsec = ts1->tv_nsec; } diff --git a/src/movie.h b/src/movie.h index e4ec7ae3..3e58395d 100644 --- a/src/movie.h +++ b/src/movie.h @@ -60,7 +60,7 @@ struct ctx_movie { int64_t base_pts; int test_mode; int gop_cnt; - struct timeval start_time; + struct timespec start_time; int high_resolution; int motion_images; int passthrough; @@ -84,8 +84,8 @@ void movie_global_deinit(void); void movie_avcodec_log(void *, int, const char *, va_list); int movie_open(struct ctx_movie *ffmpeg); -int movie_put_image(struct ctx_movie *ffmpeg, struct image_data *img_data, const struct timeval *tv1); +int movie_put_image(struct ctx_movie *ffmpeg, struct image_data *img_data, const struct timespec *tv1); void movie_close(struct ctx_movie *ffmpeg); -void movie_reset_movie_start_time(struct ctx_movie *ffmpeg, const struct timeval *tv1); +void movie_reset_movie_start_time(struct ctx_movie *ffmpeg, const struct timespec *tv1); #endif /* _INCLUDE_MOVIE_H_ */ diff --git a/src/netcam.c b/src/netcam.c index bcd934ab..99fde6ac 100644 --- a/src/netcam.c +++ b/src/netcam.c @@ -16,6 +16,7 @@ #include #include +#include #include "rotate.h" /* already includes motion.h */ #include "netcam.h" #include "video_v4l2.h" /* Needed to validate palette for v4l2 via netcam */ @@ -414,8 +415,8 @@ static void netcam_pktarray_add(struct ctx_netcam *netcam){ netcam->pktarray[indx_next].iskey = FALSE; } netcam->pktarray[indx_next].iswritten = FALSE; - netcam->pktarray[indx_next].timestamp_tv.tv_sec = netcam->img_recv->image_time.tv_sec; - netcam->pktarray[indx_next].timestamp_tv.tv_usec = netcam->img_recv->image_time.tv_usec; + netcam->pktarray[indx_next].timestamp_ts.tv_sec = netcam->img_recv->image_time.tv_sec; + netcam->pktarray[indx_next].timestamp_ts.tv_nsec = netcam->img_recv->image_time.tv_nsec; netcam->pktarray_index = indx_next; pthread_mutex_unlock(&netcam->mutex_pktarray); @@ -662,9 +663,7 @@ static int netcam_interrupt(void *ctx){ if (netcam->status == NETCAM_CONNECTED) { return FALSE; } else if (netcam->status == NETCAM_READINGIMAGE) { - if (gettimeofday(&netcam->interruptcurrenttime, NULL) < 0) { - MOTION_LOG(ERR, TYPE_NETCAM, SHOW_ERRNO, "gettimeofday"); - } + clock_gettime(CLOCK_REALTIME, &netcam->interruptcurrenttime); if ((netcam->interruptcurrenttime.tv_sec - netcam->interruptstarttime.tv_sec ) > netcam->interruptduration){ MOTION_LOG(INF, TYPE_NETCAM, NO_ERRNO ,_("%s: Camera reading (%s) timed out") @@ -680,9 +679,7 @@ static int netcam_interrupt(void *ctx){ * netcam_connect function will use the same start time. Otherwise we * would need to reset the time before each call to a ffmpeg function. */ - if (gettimeofday(&netcam->interruptcurrenttime, NULL) < 0) { - MOTION_LOG(ERR, TYPE_NETCAM, SHOW_ERRNO, "gettimeofday"); - } + clock_gettime(CLOCK_REALTIME, &netcam->interruptcurrenttime); if ((netcam->interruptcurrenttime.tv_sec - netcam->interruptstarttime.tv_sec ) > netcam->interruptduration){ MOTION_LOG(INF, TYPE_NETCAM, NO_ERRNO ,_("%s: Camera (%s) timed out") @@ -797,9 +794,7 @@ static int netcam_read_image(struct ctx_netcam *netcam){ netcam->packet_recv.size = 0; netcam->interrupted=FALSE; - if (gettimeofday(&netcam->interruptstarttime, NULL) < 0) { - MOTION_LOG(ERR, TYPE_NETCAM, SHOW_ERRNO, "gettimeofday"); - } + clock_gettime(CLOCK_REALTIME, &netcam->interruptstarttime); netcam->interruptduration = 10; netcam->status = NETCAM_READINGIMAGE; @@ -843,10 +838,7 @@ static int netcam_read_image(struct ctx_netcam *netcam){ return -1; } } - if (gettimeofday(&netcam->img_recv->image_time, NULL) < 0) { - MOTION_LOG(ERR, TYPE_NETCAM, SHOW_ERRNO, "gettimeofday"); - } - + clock_gettime(CLOCK_REALTIME, &netcam->img_recv->image_time); /* Skip status change on our first image to keep the "next" function waiting * until the handler thread gets going */ @@ -1197,12 +1189,9 @@ static void netcam_set_parms (struct ctx_cam *cam, struct ctx_netcam *netcam ) { snprintf(netcam->threadname, 15, "%s",_("Unknown")); - if (gettimeofday(&netcam->interruptstarttime, NULL) < 0) { - MOTION_LOG(ERR, TYPE_NETCAM, SHOW_ERRNO, "gettimeofday"); - } - if (gettimeofday(&netcam->interruptcurrenttime, NULL) < 0) { - MOTION_LOG(ERR, TYPE_NETCAM, SHOW_ERRNO, "gettimeofday"); - } + clock_gettime(CLOCK_REALTIME, &netcam->interruptstarttime); + clock_gettime(CLOCK_REALTIME, &netcam->interruptcurrenttime); + /* If this is the norm and we have a highres, then disable passthru on the norm */ if ((!netcam->high_resolution) && (cam->conf.netcam_highres)) { @@ -1213,12 +1202,8 @@ static void netcam_set_parms (struct ctx_cam *cam, struct ctx_netcam *netcam ) { netcam->interruptduration = 5; netcam->interrupted = FALSE; - if (gettimeofday(&netcam->frame_curr_tm, NULL) < 0) { - MOTION_LOG(ERR, TYPE_NETCAM, SHOW_ERRNO, "gettimeofday"); - } - if (gettimeofday(&netcam->frame_prev_tm, NULL) < 0) { - MOTION_LOG(ERR, TYPE_NETCAM, SHOW_ERRNO, "gettimeofday"); - } + clock_gettime(CLOCK_REALTIME, &netcam->frame_curr_tm); + clock_gettime(CLOCK_REALTIME, &netcam->frame_prev_tm); netcam_set_path(cam, netcam); @@ -1331,9 +1316,7 @@ static int netcam_open_context(struct ctx_netcam *netcam){ netcam->format_context->interrupt_callback.opaque = netcam; netcam->interrupted = FALSE; - if (gettimeofday(&netcam->interruptstarttime, NULL) < 0) { - MOTION_LOG(ERR, TYPE_NETCAM, SHOW_ERRNO, "gettimeofday"); - } + clock_gettime(CLOCK_REALTIME, &netcam->interruptstarttime); netcam->interruptduration = 20; @@ -1544,13 +1527,11 @@ static void netcam_handler_wait(struct ctx_netcam *netcam){ usec_maxrate = (1000000L / (framerate + 3)); } - if (gettimeofday(&netcam->frame_curr_tm, NULL) < 0) { - MOTION_LOG(ERR, TYPE_NETCAM, SHOW_ERRNO, "gettimeofday"); - } + clock_gettime(CLOCK_REALTIME, &netcam->frame_curr_tm); usec_delay = usec_maxrate - ((netcam->frame_curr_tm.tv_sec - netcam->frame_prev_tm.tv_sec) * 1000000L) - - (netcam->frame_curr_tm.tv_usec - netcam->frame_prev_tm.tv_usec); + ((netcam->frame_curr_tm.tv_nsec - netcam->frame_prev_tm.tv_nsec)/1000); if ((usec_delay > 0) && (usec_delay < 1000000L)){ SLEEP(0, usec_delay * 1000); } @@ -1609,15 +1590,11 @@ static void *netcam_handler(void *arg){ while (!netcam->finish) { if (!netcam->format_context) { /* We must have disconnected. Try to reconnect */ - if (gettimeofday(&netcam->frame_prev_tm, NULL) < 0) { - MOTION_LOG(ERR, TYPE_NETCAM, SHOW_ERRNO, "gettimeofday"); - } + clock_gettime(CLOCK_REALTIME, &netcam->frame_prev_tm); netcam_handler_reconnect(netcam); continue; } else { /* We think we are connected...*/ - if (gettimeofday(&netcam->frame_prev_tm, NULL) < 0) { - MOTION_LOG(ERR, TYPE_NETCAM, SHOW_ERRNO, "gettimeofday"); - } + clock_gettime(CLOCK_REALTIME, &netcam->frame_prev_tm); if (netcam_read_image(netcam) < 0) { if (!netcam->finish) { /* Nope. We are not or got bad image. Reconnect*/ netcam_handler_reconnect(netcam); diff --git a/src/netcam.h b/src/netcam.h index a03e02ae..789c9a60 100644 --- a/src/netcam.h +++ b/src/netcam.h @@ -42,7 +42,7 @@ typedef struct netcam_image_buff { int content_length; size_t size; /* total allocated size */ size_t used; /* bytes already used */ - struct timeval image_time; /* time this image was received */ + struct timespec image_time; /* time this image was received */ } netcam_buff; typedef netcam_buff *netcam_buff_ptr; @@ -58,7 +58,7 @@ struct packet_item{ int64_t idnbr; int iskey; int iswritten; - struct timeval timestamp_tv; + struct timespec timestamp_ts; }; struct ctx_netcam { @@ -79,8 +79,8 @@ struct ctx_netcam { int video_stream_index; /* Stream index associated with video from camera */ enum NETCAM_STATUS status; /* Status of whether the camera is connecting, closed, etc*/ - struct timeval interruptstarttime; /* The time set before calling the av functions */ - struct timeval interruptcurrenttime; /* Time during the interrupt to determine duration since start*/ + struct timespec interruptstarttime; /* The time set before calling the av functions */ + struct timespec interruptcurrenttime; /* Time during the interrupt to determine duration since start*/ int interruptduration; /* Seconds permitted before triggering a interrupt */ netcam_buff_ptr img_recv; /* The image buffer that is currently being processed */ @@ -105,9 +105,9 @@ struct ctx_netcam { int reconnect_count; /* Count of the times reconnection is tried*/ int src_fps; /* The fps provided from source*/ - struct timeval frame_prev_tm; /* The time set before calling the av functions */ - struct timeval frame_curr_tm; /* Time during the interrupt to determine duration since start*/ - struct config *conf; /* Pointer to conf parms of parent cam*/ + struct timespec frame_prev_tm; /* The time set before calling the av functions */ + struct timespec frame_curr_tm; /* Time during the interrupt to determine duration since start*/ + struct config *conf; /* Pointer to conf parms of parent cam*/ char threadname[16]; /* The thread name*/ int threadnbr; /* The thread number */ diff --git a/src/picture.c b/src/picture.c index e59fe242..bdcca196 100644 --- a/src/picture.c +++ b/src/picture.c @@ -162,7 +162,7 @@ static void put_subjectarea(struct tiff_writing *into, const struct coord *box) */ unsigned prepare_exif(unsigned char **exif, const struct ctx_cam *cam, - const struct timeval *tv_in1, + const struct timespec *ts_in1, const struct coord *box) { /* description, datetime, and subtime are the values that are actually @@ -172,15 +172,15 @@ unsigned prepare_exif(unsigned char **exif, char datetime_buf[22]; char tmpbuf[45]; struct tm timestamp_tm; - struct timeval tv1; + struct timespec ts1; - gettimeofday(&tv1, NULL); - if (tv_in1 != NULL) { - tv1.tv_sec = tv_in1->tv_sec; - tv1.tv_usec = tv_in1->tv_usec; + clock_gettime(CLOCK_REALTIME, &ts1); + if (ts_in1 != NULL) { + ts1.tv_sec = ts_in1->tv_sec; + ts1.tv_nsec = ts_in1->tv_nsec; } - localtime_r(&tv1.tv_sec, ×tamp_tm); + localtime_r(&ts1.tv_sec, ×tamp_tm); /* Exif requires this exact format */ /* The compiler is twitchy on truncating formats and the exif is twitchy * on the length of the whole string. So we do it in two steps of printing @@ -203,7 +203,7 @@ unsigned prepare_exif(unsigned char **exif, if (cam->conf.picture_exif) { description = malloc(PATH_MAX); - mystrftime(cam, description, PATH_MAX-1, cam->conf.picture_exif, &tv1, NULL, 0); + mystrftime(cam, description, PATH_MAX-1, cam->conf.picture_exif, &ts1, NULL, 0); } else { description = NULL; } @@ -353,11 +353,11 @@ unsigned prepare_exif(unsigned char **exif, */ static void put_webp_exif(WebPMux* webp_mux, const struct ctx_cam *cam, - const struct timeval *tv1, + const struct timespec *ts1, const struct coord *box) { unsigned char *exif = NULL; - unsigned exif_len = prepare_exif(&exif, cam, tv1, box); + unsigned exif_len = prepare_exif(&exif, cam, ts1, box); if(exif_len > 0) { WebPData webp_exif; @@ -395,7 +395,7 @@ static void put_webp_exif(WebPMux* webp_mux, */ static void put_webp_yuv420p_file(FILE *fp, unsigned char *image, int width, int height, - int quality, struct ctx_cam *cam, struct timeval *tv1, struct coord *box) + int quality, struct ctx_cam *cam, struct timespec *ts1, struct coord *box) { /* Create a config present and check for compatible library version */ WebPConfig webp_config; @@ -441,7 +441,7 @@ static void put_webp_yuv420p_file(FILE *fp, /* Create a mux from the prepared image data */ WebPMux* webp_mux = WebPMuxCreate(&webp_bitstream, 1); - put_webp_exif(webp_mux, cam, tv1, box); + put_webp_exif(webp_mux, cam, ts1, box); /* Add Exif data to the webp image data */ WebPData webp_output; @@ -489,13 +489,13 @@ static void put_webp_yuv420p_file(FILE *fp, static void put_jpeg_yuv420p_file(FILE *fp, unsigned char *image, int width, int height, int quality, - struct ctx_cam *cam, struct timeval *tv1, struct coord *box) + struct ctx_cam *cam, struct timespec *ts1, struct coord *box) { int sz = 0; int image_size = cam->imgs.size_norm; unsigned char *buf = mymalloc(image_size); - sz = jpgutl_put_yuv420p(buf, image_size, image, width, height, quality, cam ,tv1, box); + sz = jpgutl_put_yuv420p(buf, image_size, image, width, height, quality, cam ,ts1, box); fwrite(buf, sz, 1, fp); free(buf); @@ -518,14 +518,14 @@ static void put_jpeg_yuv420p_file(FILE *fp, * Returns nothing */ static void put_jpeg_grey_file(FILE *picture, unsigned char *image, int width, int height, - int quality, struct ctx_cam *cam, struct timeval *tv1, struct coord *box) + int quality, struct ctx_cam *cam, struct timespec *ts1, struct coord *box) { int sz = 0; int image_size = cam->imgs.size_norm; unsigned char *buf = mymalloc(image_size); - sz = jpgutl_put_grey(buf, image_size, image, width, height, quality, cam ,tv1, box); + sz = jpgutl_put_grey(buf, image_size, image, width, height, quality, cam ,ts1, box); fwrite(buf, sz, 1, picture); free(buf); @@ -754,20 +754,15 @@ void overlay_largest_label(struct ctx_cam *cam, unsigned char *out) int put_picture_memory(struct ctx_cam *cam, unsigned char* dest_image, int image_size, unsigned char *image, int quality, int width, int height) { - struct timeval tv1; - - /* - * Reset the time for the current image since it is not reliable - * for putting images to memory. - */ - gettimeofday(&tv1, NULL); + struct timespec ts1; + clock_gettime(CLOCK_REALTIME, &ts1); if (!cam->conf.stream_grey){ return jpgutl_put_yuv420p(dest_image, image_size, image, - width, height, quality, cam ,&tv1,NULL); + width, height, quality, cam ,&ts1, NULL); } else { return jpgutl_put_grey(dest_image, image_size, image, - width, height, quality, cam,&tv1,NULL); + width, height, quality, cam,&ts1, NULL); } return 0; @@ -795,12 +790,12 @@ static void put_picture_fd(struct ctx_cam *cam, FILE *picture, unsigned char *im if (dummy == 1){ #ifdef HAVE_WEBP if (cam->imgs.picture_type == IMAGE_TYPE_WEBP) - put_webp_yuv420p_file(picture, image, width, height, quality, cam, &(cam->current_image->timestamp_tv), &(cam->current_image->location)); + put_webp_yuv420p_file(picture, image, width, height, quality, cam, &(cam->current_image->imgts), &(cam->current_image->location)); #endif /* HAVE_WEBP */ if (cam->imgs.picture_type == IMAGE_TYPE_JPEG) - put_jpeg_yuv420p_file(picture, image, width, height, quality, cam, &(cam->current_image->timestamp_tv), &(cam->current_image->location)); + put_jpeg_yuv420p_file(picture, image, width, height, quality, cam, &(cam->current_image->imgts), &(cam->current_image->location)); } else { - put_jpeg_grey_file(picture, image, width, height, quality, cam, &(cam->current_image->timestamp_tv), &(cam->current_image->location)); + put_jpeg_grey_file(picture, image, width, height, quality, cam, &(cam->current_image->imgts), &(cam->current_image->location)); } } } diff --git a/src/picture.h b/src/picture.h index 423b92b9..ba3a2e9e 100644 --- a/src/picture.h +++ b/src/picture.h @@ -22,6 +22,6 @@ void preview_save(struct ctx_cam *cam); void pic_scale_img(int width_src, int height_src, unsigned char *img_src, unsigned char *img_dst); - unsigned prepare_exif(unsigned char **, const struct ctx_cam *cam, const struct timeval *, const struct coord *); + unsigned prepare_exif(unsigned char **, const struct ctx_cam *cam, const struct timespec *, const struct coord *); #endif /* _INCLUDE_PICTURE_H_ */ diff --git a/src/track.c b/src/track.c index 1f4dc77d..2bceb65f 100644 --- a/src/track.c +++ b/src/track.c @@ -1312,7 +1312,7 @@ static unsigned int generic_move(struct ctx_cam *cam, enum track_action action, cam->track_posx += cent->x; cam->track_posy += cent->y; - mystrftime(cam, fmtcmd, sizeof(fmtcmd), cam->track.generic_move, &cam->current_image->timestamp_tv, NULL, 0); + mystrftime(cam, fmtcmd, sizeof(fmtcmd), cam->track.generic_move, &cam->current_image->imgts, NULL, 0); if (!fork()) { int i; diff --git a/src/webu.h b/src/webu.h index baa95362..32b512ff 100644 --- a/src/webu.h +++ b/src/webu.h @@ -60,7 +60,7 @@ size_t resp_used; /* The amount of the response page used */ uint64_t stream_pos; /* Stream position of sent image */ int stream_fps; /* Stream rate per second */ - struct timeval time_last; /* Keep track of processing time for stream thread*/ + struct timespec time_last; /* Keep track of processing time for stream thread*/ int mhd_first; /* Boolean for whether it is the first connection*/ struct MHD_Connection *connection; /* The MHD connection value from the client */ diff --git a/src/webu_stream.c b/src/webu_stream.c index 7aaa45ac..b473377a 100644 --- a/src/webu_stream.c +++ b/src/webu_stream.c @@ -35,15 +35,15 @@ static void webu_stream_mjpeg_delay(struct webui_ctx *webui) { */ long stream_rate; - struct timeval time_curr; + struct timespec time_curr; long stream_delay; - gettimeofday(&time_curr, NULL); + clock_gettime(CLOCK_REALTIME, &time_curr); /* The stream rate MUST be less than 1000000000 otherwise undefined behaviour * will occur with the SLEEP function. */ - stream_delay = ((time_curr.tv_usec - webui->time_last.tv_usec)*1000) + + stream_delay = ((time_curr.tv_nsec - webui->time_last.tv_nsec)) + ((time_curr.tv_sec - webui->time_last.tv_sec)*1000000000); if (stream_delay < 0) stream_delay = 0; if (stream_delay > 1000000000 ) stream_delay = 1000000000; @@ -56,7 +56,7 @@ static void webu_stream_mjpeg_delay(struct webui_ctx *webui) { SLEEP(1,0); } } - gettimeofday(&webui->time_last, NULL); + clock_gettime(CLOCK_REALTIME, &webui->time_last); } @@ -270,7 +270,7 @@ int webu_stream_mjpeg(struct webui_ctx *webui) { webu_stream_mjpeg_checkbuffers(webui); - gettimeofday(&webui->time_last, NULL); + clock_gettime(CLOCK_REALTIME, &webui->time_last); response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN, 1024 ,&webu_stream_mjpeg_response, webui, NULL);