Skip to content

Latest commit

 

History

History
287 lines (206 loc) · 7.21 KB

File metadata and controls

287 lines (206 loc) · 7.21 KB

Motion Buffer System

Overview

The Motion Buffer System provides circular buffering for video packets to enable pre-event recording in motion-triggered recordings. When motion is detected, the buffer is flushed to include video from before the motion event started.

Architecture

Components

  1. Motion Buffer Pool - Global pool managing buffers for all streams
  2. Motion Buffer - Per-stream circular buffer for video packets
  3. Buffered Packet - Individual packet storage with metadata
  4. Integration - Hooks into ONVIF motion recording system

Buffer States

The motion recording system uses four states:

  • IDLE - No buffering, no recording
  • BUFFERING - Actively buffering packets, waiting for motion
  • RECORDING - Motion detected, actively recording
  • FINALIZING - Motion ended, post-buffer active

State Transitions

IDLE → BUFFERING (when buffer is enabled)
BUFFERING → RECORDING (when motion is detected)
RECORDING → FINALIZING (when motion ends)
FINALIZING → BUFFERING (when post-buffer timeout expires)
FINALIZING → RECORDING (if new motion detected during post-buffer)

Features

Circular Buffer

  • Configurable Duration: 5-30 seconds of pre-event video
  • Automatic Packet Management: Oldest packets automatically dropped when full
  • Memory Efficient: Only stores packet references, not decoded frames
  • Thread-Safe: Mutex-protected operations

Memory Management

  • Pool-Based Allocation: Centralized memory management
  • Per-Stream Limits: Configurable memory limits per buffer
  • Global Limits: Total memory limit across all buffers
  • Statistics Tracking: Real-time memory usage monitoring

Packet Storage

Each buffered packet stores:

  • AVPacket data (video/audio)
  • Timestamp
  • PTS/DTS values
  • Stream index
  • Keyframe flag
  • Data size

API Reference

Initialization

// Initialize the buffer pool
int init_motion_buffer_pool(size_t memory_limit_mb);

// Cleanup the buffer pool
void cleanup_motion_buffer_pool(void);

Buffer Management

// Create a buffer for a stream
motion_buffer_t* create_motion_buffer(
    const char *stream_name,
    int buffer_seconds,
    buffer_mode_t mode
);

// Destroy a buffer
void destroy_motion_buffer(motion_buffer_t *buffer);

// Get buffer by stream name
motion_buffer_t* get_motion_buffer(const char *stream_name);

Packet Operations

// Add a packet to the buffer
int motion_buffer_add_packet(
    motion_buffer_t *buffer,
    const AVPacket *packet,
    time_t timestamp
);

// Peek at oldest packet (without removing)
int motion_buffer_peek_oldest(
    motion_buffer_t *buffer,
    AVPacket **packet
);

// Remove and return oldest packet
int motion_buffer_pop_oldest(
    motion_buffer_t *buffer,
    AVPacket **packet
);

// Flush all packets to a callback
int motion_buffer_flush(
    motion_buffer_t *buffer,
    int (*callback)(const AVPacket *packet, void *user_data),
    void *user_data
);

// Clear all packets
void motion_buffer_clear(motion_buffer_t *buffer);

Statistics

// Get buffer statistics
int motion_buffer_get_stats(
    motion_buffer_t *buffer,
    int *count,
    size_t *memory_usage,
    int *duration
);

// Check if buffer is ready
bool motion_buffer_is_ready(motion_buffer_t *buffer);

// Get keyframe count
int motion_buffer_get_keyframe_count(motion_buffer_t *buffer);

// Get total memory usage
size_t motion_buffer_get_total_memory_usage(void);

Integration with Motion Recording

Feeding Packets

Video packets should be continuously fed to the buffer:

// Called for every video packet
int feed_packet_to_motion_buffer(
    const char *stream_name,
    const AVPacket *packet
);

Buffer Flush on Motion Detection

When motion is detected, the buffer is automatically flushed:

  1. Motion event triggers start_motion_recording_internal()
  2. Function checks if buffer exists and hasn't been flushed
  3. Calls motion_buffer_flush() with callback
  4. Callback writes packets to recording file
  5. Sets buffer_flushed flag to prevent duplicate flush

Overlapping Events

The system handles overlapping motion events intelligently:

  • During RECORDING: Updates last_motion_time to extend recording
  • During FINALIZING: Transitions back to RECORDING
  • Result: Single continuous recording instead of multiple files

Configuration

Buffer Modes

  • BUFFER_MODE_MEMORY: Store packets in RAM (default)
  • BUFFER_MODE_DISK: Store packets on disk (placeholder)
  • BUFFER_MODE_HYBRID: Memory with disk fallback (placeholder)

Memory Considerations

Memory Usage Calculation

For a single stream:

Memory = FPS × buffer_seconds × avg_packet_size × 1.2

Example (15 FPS, 5 second buffer, 50KB avg packet):

Memory = 15 × 5 × 50KB × 1.2 = 4.5 MB

Recommendations

  • Low Memory Systems (< 256MB RAM): 5 second buffer, 2-3 streams max
  • Medium Systems (256-512MB RAM): 10 second buffer, 4-8 streams
  • High Memory Systems (> 512MB RAM): 30 second buffer, 16 streams

Memory Pool Limits

The default pool limit is 50MB. Adjust based on system resources:

// Initialize with custom limit (100MB)
init_motion_buffer_pool(100);

Performance

Benchmarks

  • Add Packet: < 1ms (packet clone + metadata)
  • Flush Buffer: ~10-50ms (depends on packet count)
  • Memory Overhead: ~100 bytes per packet + packet data

Optimization Tips

  1. Reduce Buffer Duration: Shorter buffers use less memory
  2. Lower FPS: Fewer packets to buffer
  3. Keyframe-Only Buffering: Store only keyframes (future enhancement)
  4. Compression: Use higher compression for lower bitrates

Troubleshooting

Buffer Not Filling

Symptoms: Buffer shows 0 packets Causes:

  • feed_packet_to_motion_buffer() not being called
  • Buffer not enabled in configuration
  • Stream not active

Solution: Verify packet feeding integration

High Memory Usage

Symptoms: System running out of memory Causes:

  • Too many streams with large buffers
  • High bitrate streams
  • Memory leak

Solution:

  • Reduce buffer duration
  • Lower stream bitrate
  • Check for memory leaks with valgrind

Buffer Flush Not Working

Symptoms: Pre-event video not in recording Causes:

  • Callback function not writing packets
  • Buffer already flushed
  • Buffer empty when motion detected

Solution: Verify callback implementation and buffer state

Future Enhancements

Planned Features

  1. Disk-Based Buffering: Full implementation for low-memory systems
  2. Keyframe-Only Mode: Store only keyframes to reduce memory
  3. Adaptive Buffering: Automatically adjust buffer size based on available memory
  4. Buffer Compression: Compress buffered packets to save memory
  5. Multi-Stream Optimization: Share buffers between similar streams

API Extensions

// Future APIs (not yet implemented)
int motion_buffer_set_keyframe_only(motion_buffer_t *buffer, bool enabled);
int motion_buffer_set_compression(motion_buffer_t *buffer, bool enabled);
int motion_buffer_set_adaptive_size(motion_buffer_t *buffer, bool enabled);

See Also