import  platform 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  numpy  as  np 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  pyray  as  rl 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  msgq . visionipc  import  VisionIpcClient ,  VisionStreamType ,  VisionBuf 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  openpilot . common . swaglog  import  cloudlog 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  openpilot . system . hardware  import  TICI 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  openpilot . system . ui . lib . application  import  gui_app 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  openpilot . system . ui . lib . egl  import  init_egl ,  create_egl_image ,  destroy_egl_image ,  bind_egl_image_to_texture ,  EGLImage 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  openpilot . system . ui . widgets  import  Widget 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  openpilot . selfdrive . ui . ui_state  import  ui_state 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								CONNECTION_RETRY_INTERVAL  =  0.2   # seconds between connection attempts 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								VERSION  =  """ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#version 300 es 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								precision  mediump  float ; 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								""" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								if  platform . system ( )  ==  " Darwin " : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  VERSION  =  """ 
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    #version 330 core 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  """ 
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								VERTEX_SHADER  =  VERSION  +  """ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								in  vec3  vertexPosition ; 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								in  vec2  vertexTexCoord ; 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								in  vec3  vertexNormal ; 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								in  vec4  vertexColor ; 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								uniform  mat4  mvp ; 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								out  vec2  fragTexCoord ; 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								out  vec4  fragColor ; 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  main ( )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  fragTexCoord  =  vertexTexCoord ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  fragColor  =  vertexColor ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  gl_Position  =  mvp  *  vec4 ( vertexPosition ,  1.0 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								""" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# Choose fragment shader based on platform capabilities 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								if  TICI : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  FRAME_FRAGMENT_SHADER  =  """ 
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    #version 300 es 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    #extension GL_OES_EGL_image_external_essl3 : enable 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    precision  mediump  float ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    in  vec2  fragTexCoord ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    uniform  samplerExternalOES  texture0 ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    out  vec4  fragColor ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    void  main ( )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      vec4  color  =  texture ( texture0 ,  fragTexCoord ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      fragColor  =  vec4 ( pow ( color . rgb ,  vec3 ( 1.0 / 1.28 ) ) ,  color . a ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								else : 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  FRAME_FRAGMENT_SHADER  =  VERSION  +  """ 
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    in  vec2  fragTexCoord ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    uniform  sampler2D  texture0 ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    uniform  sampler2D  texture1 ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    out  vec4  fragColor ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    void  main ( )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      float  y  =  texture ( texture0 ,  fragTexCoord ) . r ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      vec2  uv  =  texture ( texture1 ,  fragTexCoord ) . ra  -  0.5 ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      fragColor  =  vec4 ( y  +  1.402 * uv . y ,  y  -  0.344 * uv . x  -  0.714 * uv . y ,  y  +  1.772 * uv . x ,  1.0 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								class  CameraView ( Widget ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  __init__ ( self ,  name :  str ,  stream_type :  VisionStreamType ) : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    super ( ) . __init__ ( ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # TODO: implement a receiver and connect thread 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . _name  =  name 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # Primary stream 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . client  =  VisionIpcClient ( name ,  stream_type ,  conflate = True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . _stream_type  =  stream_type 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    self . available_streams :  list [ VisionStreamType ]  =  [ ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Target stream for switching 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . _target_client :  VisionIpcClient  |  None  =  None 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . _target_stream_type :  VisionStreamType  |  None  =  None 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . _switching :  bool  =  False 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . _texture_needs_update  =  True 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . last_connection_attempt :  float  =  0.0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . shader  =  rl . load_shader_from_memory ( VERTEX_SHADER ,  FRAME_FRAGMENT_SHADER ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . _texture1_loc :  int  =  rl . get_shader_location ( self . shader ,  " texture1 " )  if  not  TICI  else  - 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . frame :  VisionBuf  |  None  =  None 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . texture_y :  rl . Texture  |  None  =  None 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . texture_uv :  rl . Texture  |  None  =  None 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # EGL resources 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . egl_images :  dict [ int ,  EGLImage ]  =  { } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . egl_texture :  rl . Texture  |  None  =  None 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    self . _placeholder_color :  rl . Color  |  None  =  None 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Initialize EGL for zero-copy rendering on TICI 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  TICI : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  not  init_egl ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        raise  RuntimeError ( " Failed to initialize EGL " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      # Create a 1x1 pixel placeholder texture for EGL image binding 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      temp_image  =  rl . gen_image_color ( 1 ,  1 ,  rl . BLACK ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . egl_texture  =  rl . load_texture_from_image ( temp_image ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      rl . unload_image ( temp_image ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ui_state . add_offroad_transition_callback ( self . _offroad_transition ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  _offroad_transition ( self ) : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # Reconnect if not first time going onroad 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ui_state . is_onroad ( )  and  self . frame  is  not  None : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      # Prevent old frames from showing when going onroad. Qt has a separate thread 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      # which drains the VisionIpcClient SubSocket for us. Re-connecting is not enough 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      # and only clears internal buffers, not the message queue. 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . frame  =  None 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  self . client : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        del  self . client 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . client  =  VisionIpcClient ( self . _name ,  self . _stream_type ,  conflate = True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  def  _set_placeholder_color ( self ,  color :  rl . Color ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ Set a placeholder color to be drawn when no frame is available. """ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . _placeholder_color  =  color 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  switch_stream ( self ,  stream_type :  VisionStreamType )  - >  None : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  self . _stream_type  ==  stream_type : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  self . _switching  and  self . _target_stream_type  ==  stream_type : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cloudlog . debug ( f ' Preparing switch from  { self . _stream_type }  to  { stream_type } ' ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  self . _target_client : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      del  self . _target_client 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . _target_stream_type  =  stream_type 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . _target_client  =  VisionIpcClient ( self . _name ,  stream_type ,  conflate = True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . _switching  =  True 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  @property 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  stream_type ( self )  - >  VisionStreamType : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  self . _stream_type 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  close ( self )  - >  None : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . _clear_textures ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Clean up EGL texture 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  TICI  and  self . egl_texture : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      rl . unload_texture ( self . egl_texture ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . egl_texture  =  None 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Clean up shader 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  self . shader  and  self . shader . id : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      rl . unload_shader ( self . shader ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . client  =  None 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  def  __del__ ( self ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . close ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  _calc_frame_matrix ( self ,  rect :  rl . Rectangle )  - >  np . ndarray : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  not  self . frame : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  np . eye ( 3 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Calculate aspect ratios 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    widget_aspect_ratio  =  rect . width  /  rect . height 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    frame_aspect_ratio  =  self . frame . width  /  self . frame . height 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Calculate scaling factors to maintain aspect ratio 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    zx  =  min ( frame_aspect_ratio  /  widget_aspect_ratio ,  1.0 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    zy  =  min ( widget_aspect_ratio  /  frame_aspect_ratio ,  1.0 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  np . array ( [ 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      [ zx ,  0.0 ,  0.0 ] , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      [ 0.0 ,  zy ,  0.0 ] , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      [ 0.0 ,  0.0 ,  1.0 ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ] ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  def  _render ( self ,  rect :  rl . Rectangle ) : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  self . _switching : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . _handle_switch ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  not  self . _ensure_connection ( ) : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      self . _draw_placeholder ( rect ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Try to get a new buffer without blocking 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    buffer  =  self . client . recv ( timeout_ms = 0 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  buffer : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . _texture_needs_update  =  True 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . frame  =  buffer 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  not  self . frame : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      self . _draw_placeholder ( rect ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    transform  =  self . _calc_frame_matrix ( rect ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    src_rect  =  rl . Rectangle ( 0 ,  0 ,  float ( self . frame . width ) ,  float ( self . frame . height ) ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # Flip driver camera horizontally 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  self . _stream_type  ==  VisionStreamType . VISION_STREAM_DRIVER : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      src_rect . width  =  - src_rect . width 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Calculate scale 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    scale_x  =  rect . width  *  transform [ 0 ,  0 ]   # zx 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    scale_y  =  rect . height  *  transform [ 1 ,  1 ]   # zy 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Calculate base position (centered) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    x_offset  =  rect . x  +  ( rect . width  -  scale_x )  /  2 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    y_offset  =  rect . y  +  ( rect . height  -  scale_y )  /  2 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    x_offset  + =  transform [ 0 ,  2 ]  *  rect . width  /  2 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    y_offset  + =  transform [ 1 ,  2 ]  *  rect . height  /  2 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dst_rect  =  rl . Rectangle ( x_offset ,  y_offset ,  scale_x ,  scale_y ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Render with appropriate method 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  TICI : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . _render_egl ( src_rect ,  dst_rect ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . _render_textures ( src_rect ,  dst_rect ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  def  _draw_placeholder ( self ,  rect :  rl . Rectangle ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  self . _placeholder_color : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      rl . draw_rectangle_rec ( rect ,  self . _placeholder_color ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  _render_egl ( self ,  src_rect :  rl . Rectangle ,  dst_rect :  rl . Rectangle )  - >  None : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ Render using EGL for direct buffer access """ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  self . frame  is  None  or  self . egl_texture  is  None : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    idx  =  self . frame . idx 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    egl_image  =  self . egl_images . get ( idx ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Create EGL image if needed 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  egl_image  is  None : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      egl_image  =  create_egl_image ( self . frame . width ,  self . frame . height ,  self . frame . stride ,  self . frame . fd ,  self . frame . uv_offset ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  egl_image : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . egl_images [ idx ]  =  egl_image 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Update texture dimensions to match current frame 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . egl_texture . width  =  self . frame . width 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . egl_texture . height  =  self . frame . height 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Bind the EGL image to our texture 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bind_egl_image_to_texture ( self . egl_texture . id ,  egl_image ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Render with shader 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    rl . begin_shader_mode ( self . shader ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    rl . draw_texture_pro ( self . egl_texture ,  src_rect ,  dst_rect ,  rl . Vector2 ( 0 ,  0 ) ,  0.0 ,  rl . WHITE ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    rl . end_shader_mode ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  _render_textures ( self ,  src_rect :  rl . Rectangle ,  dst_rect :  rl . Rectangle )  - >  None : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ Render using texture copies """ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  not  self . texture_y  or  not  self . texture_uv  or  self . frame  is  None : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Update textures with new frame data 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  self . _texture_needs_update : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      y_data  =  self . frame . data [ :  self . frame . uv_offset ] 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      uv_data  =  self . frame . data [ self . frame . uv_offset : ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      rl . update_texture ( self . texture_y ,  rl . ffi . cast ( " void * " ,  y_data . ctypes . data ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      rl . update_texture ( self . texture_uv ,  rl . ffi . cast ( " void * " ,  uv_data . ctypes . data ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . _texture_needs_update  =  False 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Render with shader 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    rl . begin_shader_mode ( self . shader ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    rl . set_shader_value_texture ( self . shader ,  self . _texture1_loc ,  self . texture_uv ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    rl . draw_texture_pro ( self . texture_y ,  src_rect ,  dst_rect ,  rl . Vector2 ( 0 ,  0 ) ,  0.0 ,  rl . WHITE ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    rl . end_shader_mode ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  _ensure_connection ( self )  - >  bool : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  not  self . client . is_connected ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . frame  =  None 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      self . available_streams . clear ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      # Throttle connection attempts 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      current_time  =  rl . get_time ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  current_time  -  self . last_connection_attempt  <  CONNECTION_RETRY_INTERVAL : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  False 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . last_connection_attempt  =  current_time 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  not  self . client . connect ( False )  or  not  self . client . num_buffers : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  False 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      cloudlog . debug ( f " Connected to  { self . _name }  stream:  { self . _stream_type } , buffers:  { self . client . num_buffers } " ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      self . _initialize_textures ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . available_streams  =  self . client . available_streams ( self . _name ,  block = False ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  True 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  _handle_switch ( self )  - >  None : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ Check if target stream is ready and switch immediately. """ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  not  self . _target_client  or  not  self . _switching : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      return 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Try to connect target if needed 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  not  self . _target_client . is_connected ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  not  self . _target_client . connect ( False )  or  not  self . _target_client . num_buffers : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      cloudlog . debug ( f " Target stream connected:  { self . _target_stream_type } " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Check if target has frames ready 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    target_frame  =  self . _target_client . recv ( timeout_ms = 0 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  target_frame : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      self . frame  =  target_frame   # Update current frame to target frame 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      self . _complete_switch ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  _complete_switch ( self )  - >  None : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    """ Instantly switch to target stream. """ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cloudlog . debug ( f " Switching to  { self . _target_stream_type } " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Clean up current resources 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  self . client : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      del  self . client 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Switch to target 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . client  =  self . _target_client 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . _stream_type  =  self . _target_stream_type 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . _texture_needs_update  =  True 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # Reset state 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . _target_client  =  None 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . _target_stream_type  =  None 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . _switching  =  False 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # Initialize textures for new stream 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . _initialize_textures ( ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  _initialize_textures ( self ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . _clear_textures ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  not  TICI : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . texture_y  =  rl . load_texture_from_image ( rl . Image ( None ,  int ( self . client . stride ) , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          int ( self . client . height ) ,  1 ,  rl . PixelFormat . PIXELFORMAT_UNCOMPRESSED_GRAYSCALE ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . texture_uv  =  rl . load_texture_from_image ( rl . Image ( None ,  int ( self . client . stride  / /  2 ) , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          int ( self . client . height  / /  2 ) ,  1 ,  rl . PixelFormat . PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  _clear_textures ( self ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  self . texture_y  and  self . texture_y . id : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      rl . unload_texture ( self . texture_y ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . texture_y  =  None 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  self . texture_uv  and  self . texture_uv . id : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      rl . unload_texture ( self . texture_uv ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . texture_uv  =  None 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Clean up EGL resources 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  TICI : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      for  data  in  self . egl_images . values ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        destroy_egl_image ( data ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . egl_images  =  { } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								if  __name__  ==  " __main__ " : 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  gui_app . init_window ( " camera view " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  road  =  CameraView ( " camerad " ,  VisionStreamType . VISION_STREAM_ROAD ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  for  _  in  gui_app . render ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    road . render ( rl . Rectangle ( 0 ,  0 ,  gui_app . width ,  gui_app . height ) )