1212from fractions import Fraction
1313import ctypes
1414import time
15+ from win32api import GetSystemMetrics
1516import dxcam
1617import hashlib
1718import getpass
19+ import win32api
20+ import win32con
21+ import pywintypes
22+ #import rotatescreen
23+ import signal
24+ import atexit
25+
26+ originalwidth = GetSystemMetrics (0 )
27+ originalheight = GetSystemMetrics (1 )
28+
29+ FrameRate = 60
30+
31+ devmode = pywintypes .DEVMODEType ()
32+
33+ devmode .DisplayFrequency = 60
34+ #rotate_screen = rotatescreen.get_primary_display()
35+ #screen = rotate_screen.current_orientation
36+ #rotate_screen.rotate_to(0)
1837
1938os .environ ['DXGIDebug' ] = '1'
2039ROOT = os .path .dirname (__file__ )
2140
2241class POINT (ctypes .Structure ):
23- _fields_ = [('x' , ctypes .c_int ),
42+ _fields_ = [('x' , ctypes .c_int ),
2443 ('y' , ctypes .c_int )]
2544
2645class CURSORINFO (ctypes .Structure ):
@@ -32,76 +51,111 @@ class CURSORINFO(ctypes.Structure):
3251GetCursorInfo = ctypes .windll .user32 .GetCursorInfo
3352GetCursorInfo .argtypes = [ctypes .POINTER (CURSORINFO )]
3453
35- def force_codec (pc , sender , forced_codec ):
36- kind = forced_codec .split ("/" )[0 ]
37- codecs = RTCRtpSender .getCapabilities (kind ).codecs
38- transceiver = next (t for t in pc .getTransceivers () if t .sender == sender )
39- transceiver .setCodecPreferences (
40- [codec for codec in codecs if codec .mimeType == forced_codec ]
41- )
54+ def force_codec (pc , sender , forced_codec ):
55+ try :
56+ kind = forced_codec .split ("/" )[0 ]
57+ codecs = RTCRtpSender .getCapabilities (kind ).codecs
58+ transceiver = next (t for t in pc .getTransceivers () if t .sender == sender )
59+ transceiver .setCodecPreferences (
60+ [codec for codec in codecs if codec .mimeType == forced_codec ]
61+ )
62+ except Exception as e :
63+ logging .error (f"Error in force_codec: { e } " )
64+
65+ def exit_handler ():
66+ print ("Program Exiting" )
67+ #rotate_screen.rotate_to(screen)
4268
4369def encrypt_string (input_string ):
44- sha256 = hashlib .sha256 ()
45- sha256 .update (input_string .encode ('utf-8' ))
46- encrypted_string = sha256 .hexdigest ()
47- return encrypted_string
70+ try :
71+ sha256 = hashlib .sha256 ()
72+ sha256 .update (input_string .encode ('utf-8' ))
73+ encrypted_string = sha256 .hexdigest ()
74+ return encrypted_string
75+ except Exception as e :
76+ logging .error (f"Error in encrypt_string: { e } " )
4877
4978def save_to_file (encrypted_string , filename = 'password.txt' ):
50- with open (filename , 'w' ) as file :
51- file .write (encrypted_string )
79+ try :
80+ with open (filename , 'w' ) as file :
81+ file .write (encrypted_string )
82+ except Exception as e :
83+ logging .error (f"Error in save_to_file: { e } " )
5284
5385def is_cursor_hidden ():
54- info = CURSORINFO ()
55- info .cbSize = ctypes .sizeof (info )
86+ try :
87+ info = CURSORINFO ()
88+ info .cbSize = ctypes .sizeof (info )
5689
57- if GetCursorInfo (ctypes .byref (info )):
58- return not bool (info .flags & 0x00000001 )
59- else :
90+ if GetCursorInfo (ctypes .byref (info )):
91+ return not bool (info .flags & 0x00000001 )
92+ else :
93+ return False
94+ except Exception as e :
95+ logging .error (f"Error in is_cursor_hidden: { e } " )
6096 return False
6197
6298def getsecurity ():
63- global passwordtext
64- filename = 'password.txt'
65- if os .path .exists (filename ):
66- with open (filename , 'r' ) as file :
67- existing_content = file .read ()
68- passwordtext = existing_content
69- print (f"{ filename } already exists. The encrypted password is:\n { existing_content } " )
70- else :
71- user_input = getpass .getpass ("Enter your password: " )
72- checkpass = getpass .getpass ("Please re-enter your password: " )
73- if user_input == checkpass :
74- encrypted_string = encrypt_string (user_input )
75- save_to_file (encrypted_string )
76- passwordtext = encrypted_string
77- print (f"Password encrypted and saved to '{ filename } ':\n { encrypted_string } " )
78-
99+ try :
100+ global passwordtext
101+ filename = 'password.txt'
102+ if os .path .exists (filename ):
103+ with open (filename , 'r' ) as file :
104+ existing_content = file .read ()
105+ passwordtext = existing_content
106+ print (f"{ filename } already exists. The encrypted password is:\n { existing_content } " )
79107 else :
80- print ("The two passwords do not match. Please try again." )
81- getsecurity ()
108+ user_input = getpass .getpass ("Enter your password: " )
109+ checkpass = getpass .getpass ("Please re-enter your password: " )
110+ if user_input == checkpass :
111+ encrypted_string = encrypt_string (user_input )
112+ save_to_file (encrypted_string )
113+ passwordtext = encrypted_string
114+ print (f"Password encrypted and saved to '{ filename } ':\n { encrypted_string } " )
115+
116+ else :
117+ print ("The two passwords do not match. Please try again." )
118+ getsecurity ()
119+ except Exception as e :
120+ logging .error (f"Error in getsecurity: { e } " )
121+
82122getsecurity ()
83123
84124class DxCamTrack (MediaStreamTrack ):
85125 kind = "video"
86126
87127 camera = None
128+ original_width = GetSystemMetrics (0 )
129+ original_height = GetSystemMetrics (1 )
88130
89131 def __init__ (self ):
90132 super ().__init__ ()
91133 self .start_time = time .time ()
92- self .frame_rate = 61
134+ self .frame_rate = FrameRate
93135 self .framedex = 90000
94136 self .previous_state = None
95-
137+
96138 if DxCamTrack .camera is None :
97- DxCamTrack .camera = dxcam .create (output_idx = 0 , output_color = "BGR" )
98- DxCamTrack .camera .start (target_fps = self .frame_rate , video_mode = True )
99- print ("Created a new DXCamera instance." )
139+ try :
140+ DxCamTrack .camera = dxcam .create (output_idx = 0 , output_color = "BGR" )#region=region1
141+ DxCamTrack .camera .start (target_fps = self .frame_rate , video_mode = True )
142+ print ("Created a new DXCamera instance." )
143+ except Exception as e :
144+ logging .error (f"Error in DxCamTrack initialization: { e } " )
100145
101146 async def recv (self ):
102147 try :
148+ if DxCamTrack .original_width != GetSystemMetrics (0 ) or DxCamTrack .original_height != GetSystemMetrics (1 ):
149+ DxCamTrack .original_width = GetSystemMetrics (0 )
150+ DxCamTrack .original_height = GetSystemMetrics (1 )
151+ DxCamTrack .camera .stop ()
152+ DxCamTrack .camera = None
153+ DxCamTrack .camera = dxcam .create (output_idx = 0 , output_color = "BGR" )#region=region1
154+ DxCamTrack .camera .start (target_fps = self .frame_rate , video_mode = True )
155+ print ("DXCamera stopped." )
156+
103157 img = DxCamTrack .camera .get_latest_frame ()
104-
158+
105159 cursor_position = pyautogui .position ()
106160 cursor_hidden = is_cursor_hidden ()
107161 if cursor_hidden != self .previous_state :
@@ -112,65 +166,84 @@ async def recv(self):
112166 frame = VideoFrame .from_ndarray (img , format = "rgb24" )
113167 elapsed_time = time .time () - self .start_time
114168 frame_index = int (elapsed_time * self .frame_rate )
115- frame .pts = frame_index * int (self .framedex / self .frame_rate ) # Calculate RTP timestamp
169+ frame .pts = frame_index * int (self .framedex / self .frame_rate )
116170 frame .time_base = Fraction (1 , self .framedex )
117171
118172 return frame
119173 except Exception as e :
120- self . camera . stop ( )
121- print ( f"Error receiving frame: { str ( e ) } " )
174+ logging . error ( f"Error receiving frame: { e } " )
175+
122176
123177async def index (request ):
124- content = open (os .path .join (ROOT , "templates/index.html" ), "r" ).read ()
125- return web .Response (content_type = "text/html" , text = content )
178+ try :
179+ content = open (os .path .join (ROOT , "templates/index.html" ), "r" ).read ()
180+ return web .Response (content_type = "text/html" , text = content )
181+ except Exception as e :
182+ logging .error (f"Error in index request handling: { e } " )
126183
127184async def offer (request ):
128- params = await request .json ()
129- password = params .get ("password" )
130-
131- if passwordtext != encrypt_string (password ):
132- return web .Response (status = 401 , text = "Unauthorized" )
133-
134- offer = RTCSessionDescription (sdp = params ["sdp" ], type = params ["type" ])
135-
136- pc = RTCPeerConnection ()
137- pcs .add (pc )
138-
139- screenshot_track = DxCamTrack ()
140- pc .addTrack (screenshot_track )
141-
142- video_sender = pc .getSenders ()[0 ]
143- force_codec (pc , video_sender , "video/VP8" )
144-
145- await pc .setRemoteDescription (offer )
146-
147- answer = await pc .createAnswer ()
148- await pc .setLocalDescription (answer )
149-
150- return web .Response (
151- content_type = "application/json" ,
152- text = json .dumps (
153- {"sdp" : pc .localDescription .sdp , "type" : pc .localDescription .type }
154- ),
155- )
185+ try :
186+ #devmode.Fields = win32con.DM_DISPLAYFREQUENCY
187+ #win32api.ChangeDisplaySettings(devmode, 0)
188+
189+ params = await request .json ()
190+ password = params .get ("password" )
191+
192+ if passwordtext != encrypt_string (password ):
193+ return web .Response (status = 401 , text = "Unauthorized" )
194+
195+ offer = RTCSessionDescription (sdp = params ["sdp" ], type = params ["type" ])
196+
197+ pc = RTCPeerConnection ()
198+ pcs .add (pc )
199+
200+ screenshot_track = DxCamTrack ()
201+ pc .addTrack (screenshot_track )
202+
203+ video_sender = pc .getSenders ()[0 ]
204+ force_codec (pc , video_sender , "video/VP8" )
205+
206+ await pc .setRemoteDescription (offer )
207+
208+ answer = await pc .createAnswer ()
209+ await pc .setLocalDescription (answer )
210+
211+ return web .Response (
212+ content_type = "application/json" ,
213+ text = json .dumps (
214+ {"sdp" : pc .localDescription .sdp , "type" : pc .localDescription .type }
215+ ),
216+ )
217+ except Exception as e :
218+ logging .error (f"Error in offer request handling: { e } " )
156219
157220pcs = set ()
158221
159222async def on_shutdown (app ):
160- coros = [pc .close () for pc in pcs ]
161- await asyncio .gather (* coros )
162- pcs .clear ()
223+ try :
224+ coros = [pc .close () for pc in pcs ]
225+ await asyncio .gather (* coros )
226+ pcs .clear ()
227+ except Exception as e :
228+ logging .error (f"Error in on_shutdown: { e } " )
163229
164230if __name__ == "__main__" :
165- file_path = "background.exe"
166- if os .path .exists (file_path ):
167- subprocess .Popen ([file_path ])
168- else :
169- subprocess .Popen (["python" , "background.py" ])
170- logging .basicConfig (level = logging .INFO )
171-
172- app = web .Application ()
173- app .on_shutdown .append (on_shutdown )
174- app .router .add_get ("/" , index )
175- app .router .add_post ("/offer" , offer )
176- web .run_app (app , host = "0.0.0.0" , port = 6966 )
231+ try :
232+ atexit .register (exit_handler )
233+ signal .signal (signal .SIGTERM , exit_handler )
234+ signal .signal (signal .SIGINT , exit_handler )
235+ file_path = "background.exe"
236+ if os .path .exists (file_path ):
237+ subprocess .Popen ([file_path ])
238+ else :
239+ subprocess .Popen (["python" , "background.py" ])
240+ logging .basicConfig (level = logging .INFO )
241+
242+ app = web .Application ()
243+ app .on_shutdown .append (on_shutdown )
244+ app .router .add_get ("/" , index )
245+ app .router .add_post ("/offer" , offer )
246+ web .run_app (app , host = "0.0.0.0" , port = 6966 )
247+
248+ except Exception as e :
249+ logging .error (f"Error in main: { e } " )
0 commit comments