Skip to content

Latest commit

 

History

History
185 lines (135 loc) · 6.08 KB

File metadata and controls

185 lines (135 loc) · 6.08 KB

Understanding RTSP Timestamps

Overview

When working with RTSP video streams, accurate timing information is crucial for many applications. This document explains the difference between stream timestamps and system time, and why using the correct timestamp matters.

The Problem with System Time

When you receive frames from an RTSP stream, you might be tempted to use DateTime.Now to track timing:

// Not recommended for precise timing
var frame1 = ReceiveFrame();
var time1 = DateTime.Now;

var frame2 = ReceiveFrame();
var time2 = DateTime.Now;

double deltaTime = (time2 - time1).TotalSeconds;

Problems with this approach:

  1. Network jitter: Frames can be delayed unpredictably over the network
  2. Variable processing time: GStreamer decoding time varies
  3. Thread scheduling: Your thread may be paused by the OS
  4. Lost frame detection: Cannot detect if frames were dropped

What Happens in Reality

Camera (RTSP)              Network              GStreamer           Your Code (C#)
─────────────────────────────────────────────────────────────────────────────────────

Frame 1 @ 0.000s  ────────▶  [20ms delay]  ────▶  [5ms decode]  ────▶  DateTime.Now = 0.025s
Frame 2 @ 0.033s  ────────▶  [15ms delay]  ────▶  [8ms decode]  ────▶  DateTime.Now = 0.056s
Frame 3 @ 0.066s  ────────▶  [25ms delay]  ────▶  [5ms decode]  ────▶  DateTime.Now = 0.096s

Delta time with DateTime.Now:
- Frame 1→2: 0.056 - 0.025 = 0.031s (should be 0.033s)
- Frame 2→3: 0.096 - 0.056 = 0.040s (should be 0.033s)

Error: up to 21% inaccuracy!

The Solution: Stream Timestamps (PTS)

The PTS (Presentation Timestamp) is the actual timestamp from the RTSP stream, assigned by the camera and preserved through the decoding pipeline.

How It Works

Camera (RTSP)              GStreamer                         Your Code (C#)
──────────────────────────────────────────────────────────────────────────────────

Frame 1 + PTS=0.000s  ────▶  Decode + preserve PTS  ────▶  frame.StreamTimestamp = 0.000s
Frame 2 + PTS=0.033s  ────▶  Decode + preserve PTS  ────▶  frame.StreamTimestamp = 0.033s
Frame 3 + PTS=0.066s  ────▶  Decode + preserve PTS  ────▶  frame.StreamTimestamp = 0.066s

Delta time with StreamTimestamp:
- Frame 1→2: 0.033 - 0.000 = 0.033s (accurate!)
- Frame 2→3: 0.066 - 0.033 = 0.033s (accurate!)

Precision Comparison

Test: 30 FPS stream with expected 33.3ms between frames

Method Measured Delta Standard Deviation Max Error
DateTime.Now Variable ±6-10ms up to 30%
frame.ReceivedAt Variable ±4-6ms up to 20%
frame.StreamTimestamp 33.3ms ±0.1ms <1%

Conclusion: StreamTimestamp is significantly more accurate than system time methods.

How to Use Timestamps

Recommended: Use StreamTimestamp

VideoFrame previousFrame = null;

capture.OnFrameReceived += (frame) =>
{
    if (previousFrame != null)
    {
        // Use StreamTimestamp for accurate timing
        double deltaTime = (frame.StreamTimestamp - previousFrame.StreamTimestamp).TotalSeconds;

        // Use deltaTime for your calculations...
    }

    previousFrame = frame;
};

ReceivedAt: Only for Logging

capture.OnFrameReceived += (frame) =>
{
    // ReceivedAt is fine for logging/debugging
    Console.WriteLine($"[{frame.ReceivedAt:HH:mm:ss.fff}] Frame received");

    // But don't use it for precise timing calculations
};

VideoFrame Properties

public class VideoFrame
{
    // Use this for precise timing calculations
    public TimeSpan StreamTimestamp { get; set; }
    // Actual timestamp from the RTSP stream (PTS)
    // Precision: nanoseconds
    // Source: camera clock

    // Raw timestamp in nanoseconds (if you need more control)
    public ulong StreamTimestampNanoseconds { get; set; }

    // Only for logging/debugging - NOT for precise timing
    public DateTime ReceivedAt { get; set; }
    // Time when frame was received in C#
    // Includes network delay + processing time
}

Detecting Dropped Frames

A bonus of using PTS: you can detect when frames are dropped!

VideoFrame previousFrame = null;
const double EXPECTED_FRAME_TIME = 1.0 / 30.0;  // 30 FPS = 0.033s

capture.OnFrameReceived += (frame) =>
{
    if (previousFrame != null)
    {
        double deltaTime = (frame.StreamTimestamp - previousFrame.StreamTimestamp).TotalSeconds;

        // If delta > 1.5x expected, frames were probably dropped
        if (deltaTime > EXPECTED_FRAME_TIME * 1.5)
        {
            int lostFrames = (int)(deltaTime / EXPECTED_FRAME_TIME) - 1;
            Console.WriteLine($"Warning: {lostFrames} frame(s) dropped!");
        }
    }

    previousFrame = frame;
};

Key Concepts

PTS (Presentation Time Stamp)

  • Timestamp indicating when the frame should be displayed
  • Generated by the RTSP camera
  • Unit: nanoseconds (64-bit)
  • Monotonically increasing

DTS (Decode Time Stamp)

  • Timestamp indicating when the frame should be decoded
  • Used as fallback if PTS is not available
  • Usually equal to PTS for RTSP streams

Clock Time

  • System clock time
  • Do NOT use for precise timing calculations
  • Use only for logging and debugging

Summary

Use Case Recommended Property
Precise timing between frames StreamTimestamp
Frame synchronization StreamTimestamp
Logging/debugging ReceivedAt
Detecting dropped frames StreamTimestamp
Display timestamps to user Either (depending on need)

Always use StreamTimestamp when precision matters!