refactor: update FFmpegRTSPReader to use JPG format for single frame updates and improve image quality
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Build Worker Base and Application Images / check-base-changes (push) Successful in 7s
				
			
		
			
				
	
				Build Worker Base and Application Images / build-base (push) Has been skipped
				
			
		
			
				
	
				Build Worker Base and Application Images / build-docker (push) Successful in 2m48s
				
			
		
			
				
	
				Build Worker Base and Application Images / deploy-stack (push) Successful in 10s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Build Worker Base and Application Images / check-base-changes (push) Successful in 7s
				
			Build Worker Base and Application Images / build-base (push) Has been skipped
				
			Build Worker Base and Application Images / build-docker (push) Successful in 2m48s
				
			Build Worker Base and Application Images / deploy-stack (push) Successful in 10s
				
			This commit is contained in:
		
							parent
							
								
									95c39a008f
								
							
						
					
					
						commit
						73c3367681
					
				
					 1 changed files with 20 additions and 22 deletions
				
			
		| 
						 | 
				
			
			@ -94,16 +94,19 @@ class FFmpegRTSPReader:
 | 
			
		|||
        self.temp_file = f"/tmp/claude/camera_{self.camera_id.replace(' ', '_')}.raw"
 | 
			
		||||
        os.makedirs("/tmp/claude", exist_ok=True)
 | 
			
		||||
 | 
			
		||||
        # Change to JPG format which properly supports -update 1
 | 
			
		||||
        self.temp_file = f"/tmp/claude/camera_{self.camera_id.replace(' ', '_')}.jpg"
 | 
			
		||||
 | 
			
		||||
        cmd = [
 | 
			
		||||
            'ffmpeg',
 | 
			
		||||
            '-hwaccel', 'cuda',
 | 
			
		||||
            '-hwaccel_device', '0',
 | 
			
		||||
            '-rtsp_transport', 'tcp',
 | 
			
		||||
            '-i', self.rtsp_url,
 | 
			
		||||
            '-f', 'rawvideo',
 | 
			
		||||
            '-pix_fmt', 'bgr24',
 | 
			
		||||
            '-f', 'image2',
 | 
			
		||||
            '-update', '1',  # This actually works with image2 format
 | 
			
		||||
            '-q:v', '2',     # High quality JPEG
 | 
			
		||||
            '-an',  # No audio
 | 
			
		||||
            '-update', '1',  # Update single frame in place
 | 
			
		||||
            '-y',  # Overwrite output file
 | 
			
		||||
            self.temp_file
 | 
			
		||||
        ]
 | 
			
		||||
| 
						 | 
				
			
			@ -173,32 +176,27 @@ class FFmpegRTSPReader:
 | 
			
		|||
                if self.frame_ready_event.wait(timeout=restart_check_interval):
 | 
			
		||||
                    self.frame_ready_event.clear()
 | 
			
		||||
 | 
			
		||||
                    # Read current frame with concurrency safety
 | 
			
		||||
                    # Read JPEG frame with concurrency safety
 | 
			
		||||
                    try:
 | 
			
		||||
                        # Try to read frame multiple times to handle race conditions
 | 
			
		||||
                        frame_data = None
 | 
			
		||||
                        # Try to read JPEG multiple times to handle race conditions
 | 
			
		||||
                        frame = None
 | 
			
		||||
                        for attempt in range(3):
 | 
			
		||||
                            try:
 | 
			
		||||
                                with open(self.temp_file, 'rb') as f:
 | 
			
		||||
                                    frame_data = f.read(bytes_per_frame)
 | 
			
		||||
                                # Read and decode JPEG directly
 | 
			
		||||
                                frame = cv2.imread(self.temp_file)
 | 
			
		||||
 | 
			
		||||
                                    # Validate we got a complete frame
 | 
			
		||||
                                    if len(frame_data) == bytes_per_frame:
 | 
			
		||||
                                        break
 | 
			
		||||
                                    else:
 | 
			
		||||
                                        logger.debug(f"Camera {self.camera_id}: Partial read {len(frame_data)}/{bytes_per_frame}, attempt {attempt+1}")
 | 
			
		||||
                                        time.sleep(0.01)  # Brief wait before retry
 | 
			
		||||
                                if frame is not None and frame.shape == (self.height, self.width, 3):
 | 
			
		||||
                                    break
 | 
			
		||||
                                else:
 | 
			
		||||
                                    logger.debug(f"Camera {self.camera_id}: Invalid frame shape or None, attempt {attempt+1}")
 | 
			
		||||
                                    time.sleep(0.01)  # Brief wait before retry
 | 
			
		||||
 | 
			
		||||
                            except (IOError, OSError) as e:
 | 
			
		||||
                                logger.debug(f"Camera {self.camera_id}: Read error on attempt {attempt+1}: {e}")
 | 
			
		||||
                                time.sleep(0.01)
 | 
			
		||||
 | 
			
		||||
                        if frame_data and len(frame_data) == bytes_per_frame:
 | 
			
		||||
                            # Convert to numpy array
 | 
			
		||||
                            frame = np.frombuffer(frame_data, dtype=np.uint8)
 | 
			
		||||
                            frame = frame.reshape((self.height, self.width, 3))
 | 
			
		||||
 | 
			
		||||
                            # Call frame callback directly - trust the retry logic caught corruption
 | 
			
		||||
                        if frame is not None:
 | 
			
		||||
                            # Call frame callback directly
 | 
			
		||||
                            if self.frame_callback:
 | 
			
		||||
                                self.frame_callback(self.camera_id, frame)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -207,10 +205,10 @@ class FFmpegRTSPReader:
 | 
			
		|||
                            # Log progress
 | 
			
		||||
                            current_time = time.time()
 | 
			
		||||
                            if current_time - last_log_time >= 30:
 | 
			
		||||
                                logger.info(f"Camera {self.camera_id}: {frame_count} frames processed reactively")
 | 
			
		||||
                                logger.info(f"Camera {self.camera_id}: {frame_count} JPEG frames processed reactively")
 | 
			
		||||
                                last_log_time = current_time
 | 
			
		||||
                        else:
 | 
			
		||||
                            logger.debug(f"Camera {self.camera_id}: Failed to read complete frame after retries")
 | 
			
		||||
                            logger.debug(f"Camera {self.camera_id}: Failed to read valid JPEG after retries")
 | 
			
		||||
 | 
			
		||||
                    except (IOError, OSError) as e:
 | 
			
		||||
                        logger.debug(f"Camera {self.camera_id}: File read error: {e}")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue