Motion - Motion Loop Overview

Motion Loop Overview

Kenneth needed a quick overview of the code in the motion.c motion_loop() (the infinite loop part which is the heart of Motion)

Prepare for new frame

  • Store time for framerate calculation (timenow and timebefore used only for framerate calculation)
  • Resize frame ring buffer if needed
  • Get time for current frame (time_t cnt->currenttimep and struct tm cnt->currenttime)
  • ALERT! ALERT! ALERT! Reset shots to -1 if new second and decrement the minimum_frame_time_downcounter
  • Increment shots (frame number within current second)
  • ALERT! ALERT! ALERT! If minimum_frame_time_downcounter is zero set it to minimum_frame_time and skip down to "RE-ENTER LOOP HERE"
  • Store timestamp in ring buffer
  • Store shots in ring buffer
  • Adjust ring buffer pointers (if at the end of buffer go to top)

Retry Initializing Netcam Section

Note that cnt->video_dev is being defined during the initialization of the camera when we connect to it the first time. If the camera is a netcam we use the cnt->video_dev as a flag indicating that the camera is not yet available (value -1) and that we have to retry initializing until it is available.
  • If video_dev is -1 (not initialized) and it is a netcam and first frame every 10th second ...
    • Call netcam_cleanup. The seconds parameter 1 tells netcam_cleanup that the mode is not a restart or exit. netcam_cleanup frees all the many structs and buffers that netcam_start creates - allowing us to call vid_start (which calles netcam_start) again.
    • Call vid_start. Assign the return value to cnt->video_dev. If the value is -1 then the netcam is still not available. When the netcam finally replies the cnt->video_dev becomes 0.
    • Restart Motion is the netcam that just woke up returned am image with different dimensions than given in motion.conf. We need to restart to reset all the many buffers all over Motion.

Image Capture Section

  • Fetch next frame from camera (vid_next)
    • If the camera is a netcam call netcam_next.
      • If we succeed getting a frame from netcam return the frame and vid_return_code=0 (success)
      • If we fail return a failure code. -2 for fatal, >2 for non-fatal.
        • If the error is that netcam has changed dimensions we return value NETCAM_RESTART_ERROR
    • If the camera is a V4L camera
      • Call v4l_set_input to setup device
      • Fetch image with v4l_next
        • If fetching image fails return vid_return_code=-1 (fatal). We may later implement code=1 for non-fatal error when bttv type camera signal is missing.
      • Rotate image if enabled
      • Return image and vid_return_code=0 (success)
  • If vid_return_code is 0 (success) ...
    • Reset missing_frame_counter
    • Save the new image in cnt->imgs.image_virgin which will be kept unmodified (no texts or overlays added)
    • If camera is netcam we reset the timenow to current time so that it becomes the camera that sets the minimum pace and not Motion in order to avoid duplicate frames.
  • If vid_return_code is not 0 ...
    • If vid_return_code < 0 (fatal) exit thread
    • If vid_return_code > 0 (non-fatal) ...
      • If vid_return_code = NETCAM_RESTART_ERROR (dimensions of netcam has changed) restart Motion so we can re-size all the many buffers in a controlled way.
      • First missed frame (cnt->missing_frame_counter=0) - store timestamp in cnt->connectionlosttime
      • If we are waiting for camera initialization we set the cnt->missing_frame_counter = 1 to prevent cnt->connectionlosttime from being updated next time
      • If the netcam has been initialized and now connection is lost, we copy previous image to current image the first 30 seconds; after 30 seconds we change to showing grey picture with text and timestamp.

Motion Detection Section

  • Motion detection
    • Using standard diff if detecting motion or in setup mode else using fast diff. If fastdiff finds many changed pixels run normal diff.
      • Nightcompensate noise level if enabled.
      • Initiate pixels in motion frame (cnt->imgs.out) to black (YUV420P, Y=0, UV=0x80)
      • For each pixel apply mask and smartmask
      • Pixels with Motion detection are copied to the motion image (cnt->imgs.out) (Y channel only = B/W).
      • Increment diffs if pixels after masking changed more than noise level setting.
      • Return diffes
    • Lightswitch (set diffs to 0 if too many pixels changed)
    • Switchfilter (tried to ignore the noisy pictures when changing camera in round robin)
    • Despeckle
      • Adjust diffs with Erode and Dilate
        • Motion image (cnt->imgs.out) is adjusted accordingly by removing pixels and copying adjacent pixels.
      • Adjust diffs with Labeling (diffs in largest labeled area)
    • Motion detection results in one number diffs
  • Tune the smartmask
  • If tracking is enabled and camera moved (move counter > 0)...
    • Decrement the move counter
    • Set diff=0 to avoid detection.

Tuning Section

  • If noise tune is enabled, noise tune every second when not detecting motion.
  • If noise tune is not enabled, set the noise level = config option
  • If threshold tune is enabled, tune the threshold else set threshold = config option

Text And Graphics Overlay Section

  • Overlay fixed mask in red on motion frame (cnt->imgs.out)
  • Overlay smartmask in red on motion frame
  • Overlay largest label in blue on motion frame
  • Locate center and size of the detected motion if motion is detected.
    • Calculate the geometric mean of the labels larger than the threshold or of all detected pixels if labelling is not enabled.
    • Calculate the geometric mean of all pixels to the left and right of the center x and over and below the center y.
    • Calculate the location box as 2 x the just calculated means except the upper y coordinate which is multiplied by 3 because experience shows that the box better includes the human head.
    • Adjust the center y to the "human head" box.
  • Initialize the double sized characters if needed
  • If text_double is set to off, then reset the scaling text_size_factor if needed
  • Add image text - diffs in upper right corner
  • If setup mode add setup text to webcam image
  • Add text_left on image
  • Add text_right on image

Actions And Event Control Section

  • If output_all enabled act as if motion is detected (see step for motion_detected below)
  • Else if diffs > threshold
    • If first motion in event (detecting_motion = 0) start counting from 1.
    • Increment detecting_motion (ALERT! detecting_motion is number of frames with motion detected + 1)
    • If number of frames with motion is at least minimum_motion_frames (detecting_motion > cnt->conf.minimum_motion_frames) call motion_detected()
      • motion_detected()
        • If new event (cnt->event_nr!=cnt->prev_event)
          • Reset prev_event number to current event and save event time
          • Create the event_text_string used for the %C conversion specifier
          • EVENT_FIRST_MOTION (execute on_event_start command and run event_ffmpeg_newfile)
          • Process pre_capture frames (EVENT_IMAGE_DETECTED (save jpgs, add to mpeg) for each buffered picture)
          • If output_normal=first set the cnt->preview_shot flag = 1 so that event_image_detect saves this image.
        • If motion_detected was not called during post_capture or output_all (diffs > 0)
          • Draw the locate frame (frame around motion) if locate is "on"
          • EVENT_MOTION
            • beep if enabled
            • on_motion_detected_command
        • Check for most significant preview-shot when output_normal=best
        • EVENT_IMAGE_DETECTED (save jpgs, add to mpeg) for current image (only if framerate is not exceeded and we are not waiting for minimum_gap to pass ALERT! (funny place to check for this)).
        • Feed the webcam if webcam_motion is "on" and it is not the first shot in this second.
        • Clear the cnt->preview_shot flag (=0) now that we have saved the first image of the event.
        • Do tracking if enabled. Generic tracking feature has been added to track_move() but does nothing yet.
      • Reset the post_capture counter (postcap)
  • Else if no motion detected but the post_capture counter post_cap is not 0 we continue calling motion_detected()
  • Else we reset the detecting_motion counter to 0 ready for next event.

  • Current event too long? (set by max_mpeg_time) - End it and start a new by setting cnt->makemovie=1
  • End event if quiet longer than gap or event too long from above
    • Preview_best of enabled
    • EVENT_ENDMOTION (event_ffmpeg_closefile)
    • If we are tracking then center the camera
    • Increment event number
    • Unset the text_event_string to avoid that buffered images get a timestamp from previous event.

Reference Frame Section

  • If the camera has been moved or we have a sudden light intensity change prevent false motion detection by creating a fresh reference frame
  • Else update Reference Frame

Setup Mode Console Output Section

  • Output setup numbers to console if Setup mode enabled
  • If lightswitch detected or we moved camera with tracking reset the reference frame to current picture to avoid false triggering of motion.


Snapshot Feature Section

  • Take a snapshot (EVENT_IMAGE_SNAPSHOT) if it is time for it or we asked for it through remote control http or signal

Timelapse Feature Section

  • Rollover timelapse mpegs EVENT_TIMELAPSEEND (close timelapse mpeg)) if rollover is enabled and it is the right time for it
  • Timelapse mpeg gets appended by current picture if timelapse is enabled and time is right. EVENT_TIMELAPSE (create new mpeg if first time otherwise appends current timelapse mpeg).

Video Loopback Section

  • Feed video device pipes - normal and motion type (normally used by vloopback device)
  • Feed the webcam.
    • If setup_mode feed the webcam with special setup image
    • If webcam_motion is "on" feed the first image of each second to webcam.
    • If webcam_motion is "off" feed every captured image to the webcam. (Note that the webcam code will limit the actual webcam rate to what is set in webcam_maxrate)

Once per Second Parameter Update Section

  • Update output_normal, locate, smartmask and sql_mask variables every second

Framerate Timing And Sleeping Section

  • Work out expected frame rate based on config setting framerate (cnt->conf.frame_limit) which may have changed from http-control
  • Calculate elapsed time
  • Sleep to fit framerate
  • If cpu_low sleep even longer to fit cpu_low rate

  • Loop over again from beginning
Topic revision: r17 - 30 Jun 2006, KennethLavrsen
Copyright © 1999-2023 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Please do not email Kenneth for support questions (read why). Use the Support Requests page or join the Mailing List.
This website only use harmless session cookies. See Cookie Policy for details. By using this website you accept the use of these cookies.