matrice-streaming 0.1.71__tar.gz → 0.1.73__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.
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/PKG-INFO +1 -1
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/matrice_streaming.egg-info/PKG-INFO +1 -1
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/async_camera_worker.py +50 -17
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/worker_manager.py +8 -7
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/LICENSE.txt +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/README.md +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/matrice_streaming.egg-info/SOURCES.txt +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/matrice_streaming.egg-info/dependency_links.txt +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/matrice_streaming.egg-info/not-zip-safe +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/matrice_streaming.egg-info/top_level.txt +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/pyproject.toml +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/setup.cfg +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/setup.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/__init__.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/client/__init__.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/client/client.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/client/client_utils.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/deployment/__init__.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/deployment/camera_manager.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/deployment/deployment.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/deployment/inference_pipeline.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/deployment/streaming_gateway_manager.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/deployment/todo.txt +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/py.typed +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/__init__.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/ARCHITECTURE.md +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/__init__.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/async_ffmpeg_worker.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/camera_streamer.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/device_detection.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/encoder_manager.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/encoding_pool_manager.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/ffmpeg_camera_streamer.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/ffmpeg_config.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/ffmpeg_worker_manager.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/frame_processor.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/gstreamer_camera_streamer.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/gstreamer_worker.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/gstreamer_worker_manager.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/message_builder.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/nvdec.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/nvdec_worker_manager.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/platform_pipelines.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/retry_manager.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/stream_statistics.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/camera_streamer/video_capture_manager.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/debug/README.md +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/debug/__init__.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/debug/benchmark.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/debug/debug_gstreamer_gateway.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/debug/debug_stream_backend.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/debug/debug_streaming_gateway.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/debug/debug_utils.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/debug/example_debug_streaming.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/debug/test_videoplayback.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/dynamic_camera_manager.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/event_listener.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/metrics_reporter.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/streaming_action.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/streaming_gateway.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/streaming_gateway_utils.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/streaming_gateway/streaming_status_listener.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/tests/test_async_infrastructure.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/tests/test_batch_auto_calculation.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/tests/test_batching_verification.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/tests/test_e2e_production.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/tests/test_flatten_binary.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/tests/test_gstreamer_integration.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/tests/test_msgpack_fix.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/tests/test_phase1_unit.py +0 -0
- {matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/tests/test_phase2_scaling.py +0 -0
|
@@ -101,7 +101,7 @@ class AsyncCameraWorker:
|
|
|
101
101
|
# ================================================================
|
|
102
102
|
drop_stale_frames: bool = False, # Disabled for ML quality
|
|
103
103
|
use_simple_read: bool = True, # Use cap.read() directly instead of grab/retrieve
|
|
104
|
-
pin_cpu_affinity: bool =
|
|
104
|
+
pin_cpu_affinity: bool = False, # Let OS distribute threads (avoids cache contention)
|
|
105
105
|
total_workers: int = 1, # Total worker count for CPU affinity calculation
|
|
106
106
|
buffer_size: int = 1, # Minimal buffer for low latency (cv2_bench uses 1)
|
|
107
107
|
):
|
|
@@ -240,8 +240,8 @@ class AsyncCameraWorker:
|
|
|
240
240
|
# - But TOO many threads causes burst frame arrivals → Redis write queue backup
|
|
241
241
|
# - Cap at 64 threads to balance I/O parallelism vs write contention
|
|
242
242
|
num_cameras = len(camera_configs)
|
|
243
|
-
# Use 1 thread per camera,
|
|
244
|
-
num_capture_threads = min(64,
|
|
243
|
+
# Use 1 thread per camera, max 64 for reduced contention
|
|
244
|
+
num_capture_threads = min(64, num_cameras)
|
|
245
245
|
self.capture_executor = ThreadPoolExecutor(max_workers=num_capture_threads)
|
|
246
246
|
self.num_capture_threads = num_capture_threads
|
|
247
247
|
|
|
@@ -495,6 +495,9 @@ class AsyncCameraWorker:
|
|
|
495
495
|
cap = None
|
|
496
496
|
consecutive_failures = 0
|
|
497
497
|
frame_counter = 0
|
|
498
|
+
# PTS-based pacing for video files
|
|
499
|
+
first_video_ms = None
|
|
500
|
+
first_wall_time = None
|
|
498
501
|
|
|
499
502
|
try:
|
|
500
503
|
# Prepare source (download if URL)
|
|
@@ -570,6 +573,18 @@ class AsyncCameraWorker:
|
|
|
570
573
|
consecutive_failures = 0
|
|
571
574
|
frame_counter += 1
|
|
572
575
|
|
|
576
|
+
# Get video file timestamp (for video files, use video PTS instead of wall clock)
|
|
577
|
+
# This prevents timestamp jumps when pipeline stalls
|
|
578
|
+
video_ts_ms = cap.get(cv2.CAP_PROP_POS_MSEC) if source_type == "video_file" else None
|
|
579
|
+
|
|
580
|
+
# Frame decimation: Read ALL frames, skip based on target FPS
|
|
581
|
+
# This avoids sleep-based throttling which misses frames
|
|
582
|
+
source_fps = video_props.get('original_fps', 30) if video_props else 30
|
|
583
|
+
if fps > 0 and source_fps > fps:
|
|
584
|
+
skip_ratio = int(source_fps / fps)
|
|
585
|
+
if skip_ratio > 1 and frame_counter % skip_ratio != 0:
|
|
586
|
+
continue # Skip this frame, read next immediately
|
|
587
|
+
|
|
573
588
|
# Resize if needed
|
|
574
589
|
if width or height:
|
|
575
590
|
frame = FrameProcessor.resize_frame(frame, width, height)
|
|
@@ -581,7 +596,7 @@ class AsyncCameraWorker:
|
|
|
581
596
|
await self._process_frame_shm_mode(
|
|
582
597
|
frame, stream_key, stream_group_key, topic,
|
|
583
598
|
actual_width, actual_height, frame_counter,
|
|
584
|
-
camera_location, read_time
|
|
599
|
+
camera_location, read_time, video_ts_ms
|
|
585
600
|
)
|
|
586
601
|
else:
|
|
587
602
|
# EXISTING FLOW: JPEG encode and send full frame
|
|
@@ -589,16 +604,22 @@ class AsyncCameraWorker:
|
|
|
589
604
|
frame, stream_key, stream_group_key, topic,
|
|
590
605
|
source, video_props, fps, quality,
|
|
591
606
|
actual_width, actual_height, source_type,
|
|
592
|
-
frame_counter, camera_location, read_time
|
|
607
|
+
frame_counter, camera_location, read_time,
|
|
608
|
+
video_ts_ms
|
|
593
609
|
)
|
|
594
610
|
|
|
595
|
-
#
|
|
596
|
-
#
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
611
|
+
# PTS-based pacing for video files (smooth playback without drift)
|
|
612
|
+
# Instead of fixed-interval sleep, pace based on video timeline
|
|
613
|
+
if source_type == "video_file" and video_ts_ms is not None:
|
|
614
|
+
if first_video_ms is None:
|
|
615
|
+
first_video_ms = video_ts_ms
|
|
616
|
+
first_wall_time = time.time()
|
|
617
|
+
else:
|
|
618
|
+
# Calculate target wall time based on video PTS
|
|
619
|
+
target_wall = first_wall_time + (video_ts_ms - first_video_ms) / 1000.0
|
|
620
|
+
sleep_time = target_wall - time.time()
|
|
621
|
+
if sleep_time > 0:
|
|
622
|
+
await asyncio.sleep(sleep_time)
|
|
602
623
|
|
|
603
624
|
except asyncio.CancelledError:
|
|
604
625
|
self.logger.info(f"Worker {self.worker_id}: Camera {stream_key} task cancelled")
|
|
@@ -671,7 +692,8 @@ class AsyncCameraWorker:
|
|
|
671
692
|
source_type: str,
|
|
672
693
|
frame_counter: int,
|
|
673
694
|
camera_location: str,
|
|
674
|
-
read_time: float
|
|
695
|
+
read_time: float,
|
|
696
|
+
video_ts_ms: Optional[float] = None
|
|
675
697
|
):
|
|
676
698
|
"""Process frame and send to Redis asynchronously.
|
|
677
699
|
|
|
@@ -692,6 +714,7 @@ class AsyncCameraWorker:
|
|
|
692
714
|
frame_counter: Current frame number
|
|
693
715
|
camera_location: Camera location
|
|
694
716
|
read_time: Time taken to read frame
|
|
717
|
+
video_ts_ms: Video file timestamp in milliseconds (None for live streams)
|
|
695
718
|
"""
|
|
696
719
|
frame_start = time.time()
|
|
697
720
|
|
|
@@ -865,7 +888,8 @@ class AsyncCameraWorker:
|
|
|
865
888
|
height: int,
|
|
866
889
|
frame_counter: int,
|
|
867
890
|
camera_location: str,
|
|
868
|
-
read_time: float
|
|
891
|
+
read_time: float,
|
|
892
|
+
video_ts_ms: Optional[float] = None
|
|
869
893
|
):
|
|
870
894
|
"""SHM_MODE: Write raw frame to SHM, send metadata to Redis.
|
|
871
895
|
|
|
@@ -882,6 +906,7 @@ class AsyncCameraWorker:
|
|
|
882
906
|
frame_counter: Current frame number
|
|
883
907
|
camera_location: Camera location string
|
|
884
908
|
read_time: Time taken to read frame
|
|
909
|
+
video_ts_ms: Video file timestamp in milliseconds (None for live streams)
|
|
885
910
|
"""
|
|
886
911
|
frame_start = time.time()
|
|
887
912
|
|
|
@@ -895,7 +920,11 @@ class AsyncCameraWorker:
|
|
|
895
920
|
if is_similar and reference_frame_idx is not None:
|
|
896
921
|
# Frame is similar - send metadata with reference to previous frame
|
|
897
922
|
# Consumer can skip reading SHM and use previous result
|
|
898
|
-
|
|
923
|
+
# Use video PTS for video files, wall clock for live streams
|
|
924
|
+
if video_ts_ms is not None:
|
|
925
|
+
ts_ns = int(video_ts_ms * 1e6) # Convert ms to ns
|
|
926
|
+
else:
|
|
927
|
+
ts_ns = int(time.time() * 1e9)
|
|
899
928
|
shm_buffer = self._shm_buffers.get(stream_key)
|
|
900
929
|
|
|
901
930
|
await self.redis_client.add_shm_metadata(
|
|
@@ -950,7 +979,11 @@ class AsyncCameraWorker:
|
|
|
950
979
|
self._last_shm_frame_idx[stream_key] = frame_idx
|
|
951
980
|
|
|
952
981
|
# Send metadata-only message to Redis
|
|
953
|
-
|
|
982
|
+
# Use video PTS for video files, wall clock for live streams
|
|
983
|
+
if video_ts_ms is not None:
|
|
984
|
+
ts_ns = int(video_ts_ms * 1e6) # Convert ms to ns
|
|
985
|
+
else:
|
|
986
|
+
ts_ns = int(time.time() * 1e9)
|
|
954
987
|
write_start = time.time()
|
|
955
988
|
|
|
956
989
|
await self.redis_client.add_shm_metadata(
|
|
@@ -1335,7 +1368,7 @@ def run_async_worker(
|
|
|
1335
1368
|
# ================================================================
|
|
1336
1369
|
drop_stale_frames: bool = False, # Disabled for ML quality
|
|
1337
1370
|
use_simple_read: bool = True, # Use cap.read() directly instead of grab/retrieve
|
|
1338
|
-
pin_cpu_affinity: bool =
|
|
1371
|
+
pin_cpu_affinity: bool = False, # Let OS distribute (avoids cache contention)
|
|
1339
1372
|
total_workers: int = 1,
|
|
1340
1373
|
buffer_size: int = 1,
|
|
1341
1374
|
# ================================================================
|
|
@@ -45,7 +45,7 @@ class WorkerManager:
|
|
|
45
45
|
# ================================================================
|
|
46
46
|
drop_stale_frames: bool = False, # Use grab()/grab()/retrieve() for latest frame (disabled for ML quality)
|
|
47
47
|
use_simple_read: bool = True, # Use cap.read() directly instead of grab/retrieve
|
|
48
|
-
pin_cpu_affinity: bool =
|
|
48
|
+
pin_cpu_affinity: bool = False, # Let OS distribute (avoids cache contention)
|
|
49
49
|
buffer_size: int = 1, # VideoCapture buffer size (1 = minimal latency)
|
|
50
50
|
# ================================================================
|
|
51
51
|
# FRAME OPTIMIZER: Control frame similarity detection
|
|
@@ -78,17 +78,18 @@ class WorkerManager:
|
|
|
78
78
|
cpu_count = os.cpu_count() or 4 # Fallback to 4 if can't detect
|
|
79
79
|
num_cameras = len(camera_configs)
|
|
80
80
|
|
|
81
|
-
#
|
|
82
|
-
#
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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:
|
|
86
87
|
# Use camera-based calculation for better distribution
|
|
87
88
|
# 1000 cameras / 25 cameras per worker = 40 workers
|
|
88
89
|
target_cameras_per_worker = 25
|
|
89
90
|
calculated_workers = max(4, min(num_cameras // target_cameras_per_worker, 50))
|
|
90
91
|
else:
|
|
91
|
-
# Standard calculation for
|
|
92
|
+
# Standard calculation for medium systems
|
|
92
93
|
calculated_workers = max(4, int(cpu_count * cpu_percentage))
|
|
93
94
|
|
|
94
95
|
# Cap at camera count (no point having more workers than cameras)
|
|
File without changes
|
|
File without changes
|
{matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/matrice_streaming.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/matrice_streaming.egg-info/not-zip-safe
RENAMED
|
File without changes
|
{matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/matrice_streaming.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/client/__init__.py
RENAMED
|
File without changes
|
{matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/client/client.py
RENAMED
|
File without changes
|
{matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/client/client_utils.py
RENAMED
|
File without changes
|
{matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/deployment/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/deployment/deployment.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{matrice_streaming-0.1.71 → matrice_streaming-0.1.73}/src/matrice_streaming/deployment/todo.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|