sources: 1, lots of NVIDIA forum, v4l2
to explore: using opencv, sync two webcams

I have to extract the timestamp from an ArduCam B0497 (USB 8.3 MP) for synchronization purposes inside SeaClear

What is a UVC camera?

From ChatGPT: UVCH / uvch264 is a term used to describe enhanced support for H.264 video streaming in UVC devices under Linux. While you can’t modify the camera’s internal clock or encoding in hardware, using uvch264 (or a similarly capable driver) ensures that the H.264 stream is handled optimally by your operating system.

UVC cameras (USB video class) are USB-powered devices that incorporate standard video streaming functionality and connect seamlessly with host machines (makes sense because of the USB which would mean no additional drivers). In my case, it’s version 1.1

Extracting the hardware timestamps

How do I exactly extract the timestamps?

Using v4l2 - an open source library that can make direct calls to the memory such as requesting buffers, query and queue them, start streaming and dequeue (in that exact order).

  • Open the metadata device (/dev/video5) to access the UVC metadata stream.
  • Request buffers (VIDIOC_REQBUFS) to allocate memory for metadata capture.
  • Query buffer details (VIDIOC_QUERYBUF) to check buffer properties.
  • Queue a buffer (VIDIOC_QBUF) so it can be filled with metadata.
  • Start streaming (VIDIOC_STREAMON) to begin metadata collection.
  • Dequeue the buffer (VIDIOC_DQBUF) to retrieve the latest metadata packet.
  • Extract the timestamp which is generated by the camera’s internal monotonic clock.

metadata_capture

Apparently, it works through 4 buffers which ensures they exist and are properly mapped. It also allows continuous metadata streaming without data loss (in the image above, there is no jump in sequences.)

What would happen if it only used 1 buffer?

  • Higher risk of missing timestamps if a buffer isn’t dequeued fast enough.
  • Less efficient metadata streaming, since the camera waits for a free buffer.
  • More CPU overhead, as you must dequeue/requeue a buffer as fast as possible.

Converting to wall time

The stream is operated by my operating system and as it is an USB Camera, it follows the internal clock of the host machine (in my case — Ubuntu on my VM).

Must Consider

  • The metadata timestamp is monotonic (starts from boot and is unaffected by system time adjustments).
  • System time is wall-clock time(UTC-based).

difference_in_timestamps

As mentioned in system monotonic clock, I need to compute a Offset = CLOCK_REALTIME - CLOCK_MONOTONIC and add it to my camera’s timestamps everytime.

How do I test all this?

I will point the camera at my monitor and record the unix timestamp. I will include the video in a rosbag with the timestamps assigned to each frame and see if there is significant drift.

HOW TO

  • Before capturing raw frames from the camera, I transpose the data to rosrun image_transport republish raw in:=/usb_camera/image_raw compressed out:=/camera/image_compressed — this way, I compress high resolution stream and can record more and save space on my laptop.
  • rosrun rov_tf_tree camera_sync_recorder.py — Start the streaming
self.bag.write('/camera/image_compressed', msg, rospy.Time.from_sec(camera_wall_time))
self.bag.write('/camera_wall_time', Float64(camera_wall_time), rospy.Time.from_sec(camera_wall_time))
  • rqt_bag — Load the .bag file and view the frame with the timestamp attached

One way to record multiple topics in a rosbag would be something like this rosbag record -O my_data.bag /camera/image_raw /imu/data

Conversation between me and my prof

Me: I wonder why there is a constant delay of ~100[ms]

Prof: idk, because the Universe is never precise?

He’s such a diva