matrice-streaming 0.1.70__tar.gz → 0.1.72__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/PKG-INFO +1 -1
  2. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/matrice_streaming.egg-info/PKG-INFO +1 -1
  3. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/async_camera_worker.py +36 -13
  4. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/worker_manager.py +12 -7
  5. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/LICENSE.txt +0 -0
  6. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/README.md +0 -0
  7. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/matrice_streaming.egg-info/SOURCES.txt +0 -0
  8. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/matrice_streaming.egg-info/dependency_links.txt +0 -0
  9. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/matrice_streaming.egg-info/not-zip-safe +0 -0
  10. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/matrice_streaming.egg-info/top_level.txt +0 -0
  11. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/pyproject.toml +0 -0
  12. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/setup.cfg +0 -0
  13. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/setup.py +0 -0
  14. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/__init__.py +0 -0
  15. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/client/__init__.py +0 -0
  16. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/client/client.py +0 -0
  17. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/client/client_utils.py +0 -0
  18. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/deployment/__init__.py +0 -0
  19. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/deployment/camera_manager.py +0 -0
  20. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/deployment/deployment.py +0 -0
  21. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/deployment/inference_pipeline.py +0 -0
  22. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/deployment/streaming_gateway_manager.py +0 -0
  23. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/deployment/todo.txt +0 -0
  24. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/py.typed +0 -0
  25. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/__init__.py +0 -0
  26. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/ARCHITECTURE.md +0 -0
  27. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/__init__.py +0 -0
  28. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/async_ffmpeg_worker.py +0 -0
  29. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/camera_streamer.py +0 -0
  30. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/device_detection.py +0 -0
  31. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/encoder_manager.py +0 -0
  32. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/encoding_pool_manager.py +0 -0
  33. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/ffmpeg_camera_streamer.py +0 -0
  34. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/ffmpeg_config.py +0 -0
  35. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/ffmpeg_worker_manager.py +0 -0
  36. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/frame_processor.py +0 -0
  37. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/gstreamer_camera_streamer.py +0 -0
  38. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/gstreamer_worker.py +0 -0
  39. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/gstreamer_worker_manager.py +0 -0
  40. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/message_builder.py +0 -0
  41. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/nvdec.py +0 -0
  42. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/nvdec_worker_manager.py +0 -0
  43. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/platform_pipelines.py +0 -0
  44. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/retry_manager.py +0 -0
  45. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/stream_statistics.py +0 -0
  46. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/camera_streamer/video_capture_manager.py +0 -0
  47. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/debug/README.md +0 -0
  48. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/debug/__init__.py +0 -0
  49. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/debug/benchmark.py +0 -0
  50. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/debug/debug_gstreamer_gateway.py +0 -0
  51. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/debug/debug_stream_backend.py +0 -0
  52. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/debug/debug_streaming_gateway.py +0 -0
  53. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/debug/debug_utils.py +0 -0
  54. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/debug/example_debug_streaming.py +0 -0
  55. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/debug/test_videoplayback.py +0 -0
  56. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/dynamic_camera_manager.py +0 -0
  57. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/event_listener.py +0 -0
  58. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/metrics_reporter.py +0 -0
  59. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/streaming_action.py +0 -0
  60. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/streaming_gateway.py +0 -0
  61. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/streaming_gateway_utils.py +0 -0
  62. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/src/matrice_streaming/streaming_gateway/streaming_status_listener.py +0 -0
  63. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/tests/test_async_infrastructure.py +0 -0
  64. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/tests/test_batch_auto_calculation.py +0 -0
  65. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/tests/test_batching_verification.py +0 -0
  66. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/tests/test_e2e_production.py +0 -0
  67. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/tests/test_flatten_binary.py +0 -0
  68. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/tests/test_gstreamer_integration.py +0 -0
  69. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/tests/test_msgpack_fix.py +0 -0
  70. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/tests/test_phase1_unit.py +0 -0
  71. {matrice_streaming-0.1.70 → matrice_streaming-0.1.72}/tests/test_phase2_scaling.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matrice_streaming
3
- Version: 0.1.70
3
+ Version: 0.1.72
4
4
  Summary: Common server utilities for Matrice.ai services
5
5
  Author-email: "Matrice.ai" <dipendra@matrice.ai>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matrice_streaming
3
- Version: 0.1.70
3
+ Version: 0.1.72
4
4
  Summary: Common server utilities for Matrice.ai services
5
5
  Author-email: "Matrice.ai" <dipendra@matrice.ai>
6
6
  License-Expression: MIT
@@ -100,7 +100,8 @@ class AsyncCameraWorker:
100
100
  # PERFORMANCE: New parameters for optimized frame capture
101
101
  # ================================================================
102
102
  drop_stale_frames: bool = False, # Disabled for ML quality
103
- pin_cpu_affinity: bool = True, # Pin worker to specific CPU cores
103
+ use_simple_read: bool = True, # Use cap.read() directly instead of grab/retrieve
104
+ pin_cpu_affinity: bool = False, # Let OS distribute threads (avoids cache contention)
104
105
  total_workers: int = 1, # Total worker count for CPU affinity calculation
105
106
  buffer_size: int = 1, # Minimal buffer for low latency (cv2_bench uses 1)
106
107
  ):
@@ -120,6 +121,7 @@ class AsyncCameraWorker:
120
121
  shm_slot_count: Number of frame slots per camera ring buffer
121
122
  shm_frame_format: Frame format for SHM storage ("BGR", "RGB", or "NV12")
122
123
  drop_stale_frames: Use grab()/grab()/retrieve() pattern to get latest frame
124
+ use_simple_read: Use cap.read() directly instead of grab/retrieve pattern
123
125
  pin_cpu_affinity: Pin worker process to specific CPU cores for cache locality
124
126
  total_workers: Total number of workers (for CPU affinity calculation)
125
127
  buffer_size: VideoCapture buffer size (1 = minimal latency)
@@ -207,6 +209,7 @@ class AsyncCameraWorker:
207
209
  # PERFORMANCE: Optimized frame capture configuration
208
210
  # ================================================================
209
211
  self.drop_stale_frames = drop_stale_frames
212
+ self.use_simple_read = use_simple_read
210
213
  self.pin_cpu_affinity = pin_cpu_affinity
211
214
  self.total_workers = total_workers
212
215
  self.buffer_size = buffer_size
@@ -225,6 +228,9 @@ class AsyncCameraWorker:
225
228
  if drop_stale_frames:
226
229
  self.logger.info(f"Worker {worker_id}: Frame dropping ENABLED (grab/grab/retrieve pattern)")
227
230
 
231
+ if use_simple_read:
232
+ self.logger.info(f"Worker {worker_id}: Simple read ENABLED (cap.read() directly)")
233
+
228
234
  # ThreadPoolExecutor for I/O-bound frame capture only
229
235
  # Encoding is done inline (cv2.imencode releases GIL, ~5ms for 480p)
230
236
  #
@@ -234,8 +240,8 @@ class AsyncCameraWorker:
234
240
  # - But TOO many threads causes burst frame arrivals → Redis write queue backup
235
241
  # - Cap at 64 threads to balance I/O parallelism vs write contention
236
242
  num_cameras = len(camera_configs)
237
- # Use 1 thread per camera, capped at 64 to prevent write burst contention
238
- num_capture_threads = min(64, max(8, num_cameras))
243
+ # Use 1 thread per camera, max 64 for reduced contention
244
+ num_capture_threads = min(64, num_cameras)
239
245
  self.capture_executor = ThreadPoolExecutor(max_workers=num_capture_threads)
240
246
  self.num_capture_threads = num_capture_threads
241
247
 
@@ -329,9 +335,10 @@ class AsyncCameraWorker:
329
335
 
330
336
  # Create MatriceStream with async support
331
337
  # Unpack stream_config as keyword arguments (MatriceStream expects **config)
338
+ # NOTE: enable_shm_batching=False for real-time frame delivery (avoids batch delays)
332
339
  self.stream = MatriceStream(
333
340
  stream_type=StreamType.REDIS,
334
- enable_shm_batching=True,
341
+ enable_shm_batching=False,
335
342
  **self.stream_config
336
343
  )
337
344
 
@@ -409,23 +416,33 @@ class AsyncCameraWorker:
409
416
  async def _read_latest_frame(
410
417
  self,
411
418
  cap: cv2.VideoCapture,
412
- drop_stale: bool = True
419
+ drop_stale: bool = False,
420
+ use_simple_read: bool = False,
413
421
  ) -> Tuple[bool, Optional[Any]]:
414
- """Read latest frame, optionally dropping stale buffered frames.
422
+ """Read frame from video capture.
415
423
 
416
- This optimization from cv2_bench.py uses grab()/grab()/retrieve()
417
- pattern to always get the most recent frame instead of reading
418
- stale frames from the buffer.
424
+ Three modes available:
425
+ 1. use_simple_read=True: Uses cap.read() directly - best for video files
426
+ 2. drop_stale=True: Uses grab/grab/retrieve to skip stale buffered frames
427
+ 3. drop_stale=False: Uses grab/retrieve (no frame dropping)
419
428
 
420
429
  Args:
421
430
  cap: OpenCV VideoCapture object
422
431
  drop_stale: If True, use grab/grab/retrieve pattern to skip stale frames
432
+ use_simple_read: If True, use cap.read() directly (ignores drop_stale)
423
433
 
424
434
  Returns:
425
435
  Tuple of (success, frame) where frame is None if read failed
426
436
  """
427
437
  loop = asyncio.get_event_loop()
428
438
 
439
+ # SIMPLE READ: Use cap.read() directly - best for video files
440
+ # This reads frames sequentially without any buffer manipulation
441
+ if use_simple_read:
442
+ ret, frame = await loop.run_in_executor(self.capture_executor, cap.read)
443
+ return ret, frame
444
+
445
+ # GRAB/RETRIEVE PATTERN: For live streams where we want latest frame
429
446
  if drop_stale:
430
447
  # Aggressive frame dropping: grab twice to get latest frame
431
448
  # First grab clears any stale frame, second grab gets current
@@ -514,7 +531,9 @@ class AsyncCameraWorker:
514
531
  # This gets the latest frame and drops stale buffered frames
515
532
  read_start = time.time()
516
533
  ret, frame = await self._read_latest_frame(
517
- cap, drop_stale=self.drop_stale_frames
534
+ cap,
535
+ drop_stale=self.drop_stale_frames,
536
+ use_simple_read=self.use_simple_read,
518
537
  )
519
538
  read_time = time.time() - read_start
520
539
 
@@ -586,7 +605,8 @@ class AsyncCameraWorker:
586
605
  return # Exit completely on cancellation
587
606
  except Exception as exc:
588
607
  self.logger.error(
589
- f"Worker {self.worker_id}: Error in camera {stream_key}: {exc}",
608
+ f"Worker {self.worker_id}: Error in camera {stream_key} "
609
+ f"at frame {frame_counter}: {exc}",
590
610
  exc_info=True
591
611
  )
592
612
  consecutive_failures += 1
@@ -596,7 +616,7 @@ class AsyncCameraWorker:
596
616
  f"max failures in inner loop, reconnecting..."
597
617
  )
598
618
  break # Break inner loop to reconnect
599
- await asyncio.sleep(1.0)
619
+ await asyncio.sleep(0.1) # Reduced from 1.0s to minimize frame loss
600
620
 
601
621
  except asyncio.CancelledError:
602
622
  self.logger.info(f"Worker {self.worker_id}: Camera {stream_key} task cancelled during setup")
@@ -1314,7 +1334,8 @@ def run_async_worker(
1314
1334
  # PERFORMANCE: New parameters for optimized frame capture
1315
1335
  # ================================================================
1316
1336
  drop_stale_frames: bool = False, # Disabled for ML quality
1317
- pin_cpu_affinity: bool = True,
1337
+ use_simple_read: bool = True, # Use cap.read() directly instead of grab/retrieve
1338
+ pin_cpu_affinity: bool = False, # Let OS distribute (avoids cache contention)
1318
1339
  total_workers: int = 1,
1319
1340
  buffer_size: int = 1,
1320
1341
  # ================================================================
@@ -1338,6 +1359,7 @@ def run_async_worker(
1338
1359
  shm_slot_count: Number of frame slots per camera ring buffer
1339
1360
  shm_frame_format: Frame format for SHM storage
1340
1361
  drop_stale_frames: Use grab()/grab()/retrieve() pattern for latest frame
1362
+ use_simple_read: Use cap.read() directly instead of grab/retrieve pattern
1341
1363
  pin_cpu_affinity: Pin worker process to specific CPU cores
1342
1364
  total_workers: Total number of workers for CPU affinity calculation
1343
1365
  buffer_size: VideoCapture buffer size (1 = minimal latency)
@@ -1380,6 +1402,7 @@ def run_async_worker(
1380
1402
  shm_frame_format=shm_frame_format,
1381
1403
  # PERFORMANCE: Pass through optimized frame capture parameters
1382
1404
  drop_stale_frames=drop_stale_frames,
1405
+ use_simple_read=use_simple_read,
1383
1406
  pin_cpu_affinity=pin_cpu_affinity,
1384
1407
  total_workers=total_workers,
1385
1408
  buffer_size=buffer_size,
@@ -44,7 +44,8 @@ class WorkerManager:
44
44
  # PERFORMANCE: New parameters for optimized frame capture
45
45
  # ================================================================
46
46
  drop_stale_frames: bool = False, # Use grab()/grab()/retrieve() for latest frame (disabled for ML quality)
47
- pin_cpu_affinity: bool = True, # Pin workers to specific CPU cores
47
+ use_simple_read: bool = True, # Use cap.read() directly instead of grab/retrieve
48
+ pin_cpu_affinity: bool = False, # Let OS distribute (avoids cache contention)
48
49
  buffer_size: int = 1, # VideoCapture buffer size (1 = minimal latency)
49
50
  # ================================================================
50
51
  # FRAME OPTIMIZER: Control frame similarity detection
@@ -64,6 +65,7 @@ class WorkerManager:
64
65
  shm_slot_count: Number of frame slots per camera ring buffer
65
66
  shm_frame_format: Frame format for SHM storage
66
67
  drop_stale_frames: Use grab()/grab()/retrieve() pattern for latest frame
68
+ use_simple_read: Use cap.read() directly instead of grab/retrieve pattern
67
69
  pin_cpu_affinity: Pin worker processes to specific CPU cores for cache locality
68
70
  buffer_size: VideoCapture buffer size (1 = minimal latency)
69
71
  frame_optimizer_enabled: Enable frame similarity detection (skip similar frames for bandwidth saving)
@@ -76,17 +78,18 @@ class WorkerManager:
76
78
  cpu_count = os.cpu_count() or 4 # Fallback to 4 if can't detect
77
79
  num_cameras = len(camera_configs)
78
80
 
79
- # For systems with 16+ cores OR large camera counts, use camera-based calculation
80
- # This applies to Docker containers with limited CPU allocation (e.g., 20 cores)
81
- # Too many workers = process overhead; too few = underutilization
82
- # Target: ~25 cameras per worker for better read parallelism with video files
83
- if cpu_count >= 16 or num_cameras >= 100:
81
+ # Small deployments: 1 worker per camera for maximum parallelism
82
+ # Each worker process has its own GIL, enabling true CPU parallelism
83
+ if num_cameras <= 10:
84
+ calculated_workers = max(1, num_cameras)
85
+ # Large deployments: use camera-based calculation
86
+ elif cpu_count >= 16 or num_cameras >= 100:
84
87
  # Use camera-based calculation for better distribution
85
88
  # 1000 cameras / 25 cameras per worker = 40 workers
86
89
  target_cameras_per_worker = 25
87
90
  calculated_workers = max(4, min(num_cameras // target_cameras_per_worker, 50))
88
91
  else:
89
- # Standard calculation for smaller systems
92
+ # Standard calculation for medium systems
90
93
  calculated_workers = max(4, int(cpu_count * cpu_percentage))
91
94
 
92
95
  # Cap at camera count (no point having more workers than cameras)
@@ -124,6 +127,7 @@ class WorkerManager:
124
127
  # PERFORMANCE: Store optimized frame capture configuration
125
128
  # ================================================================
126
129
  self.drop_stale_frames = drop_stale_frames
130
+ self.use_simple_read = use_simple_read
127
131
  self.pin_cpu_affinity = pin_cpu_affinity
128
132
  self.buffer_size = buffer_size
129
133
 
@@ -307,6 +311,7 @@ class WorkerManager:
307
311
  self.shm_frame_format,
308
312
  # PERFORMANCE: Pass optimized frame capture parameters
309
313
  self.drop_stale_frames,
314
+ self.use_simple_read,
310
315
  self.pin_cpu_affinity,
311
316
  self.num_workers, # Total workers for CPU affinity calculation
312
317
  self.buffer_size,