11import os
2+ from threading import ThreadError
3+
24import cv2
35
6+ from util import threaded
7+
48
59class RtspClient :
10+ """
11+ Inspiration from:
12+ - https://benhowell.github.io/guide/2015/03/09/opencv-and-web-cam-streaming
13+ - https://stackoverflow.com/questions/19846332/python-threading-inside-a-class
14+ - https://stackoverflow.com/questions/55828451/video-streaming-from-ip-camera-in-python-using-opencv-cv2-videocapture
15+ """
616
7- def __init__ (self , ip , username , password , port = 554 , profile = "main" , use_udp = True , ** kwargs ):
17+ def __init__ (self , ip , username , password , port = 554 , profile = "main" , use_udp = True , callback = None , ** kwargs ):
818 """
19+ RTSP client is used to retrieve frames from the camera in a stream
920
1021 :param ip: Camera IP
1122 :param username: Camera Username
@@ -15,33 +26,86 @@ def __init__(self, ip, username, password, port=554, profile="main", use_udp=Tru
1526 :param use_upd: True to use UDP, False to use TCP
1627 :param proxies: {"host": "localhost", "port": 8000}
1728 """
29+ self .capture = None
30+ self .thread_cancelled = False
31+ self .callback = callback
32+
1833 capture_options = 'rtsp_transport;'
1934 self .ip = ip
2035 self .username = username
2136 self .password = password
2237 self .port = port
2338 self .proxy = kwargs .get ("proxies" )
2439 self .url = "rtsp://" + self .username + ":" + self .password + "@" + \
25- self .ip + ":" + str (self .port ) + "//h264Preview_01_" + profile
40+ self .ip + ":" + str (self .port ) + "//h264Preview_01_" + profile
2641 if use_udp :
2742 capture_options = capture_options + 'udp'
2843 else :
2944 capture_options = capture_options + 'tcp'
3045
3146 os .environ ["OPENCV_FFMPEG_CAPTURE_OPTIONS" ] = capture_options
3247
33- def preview (self ):
34- """ Blocking function. Opens OpenCV window to display stream. """
35- win_name = self .ip
36- cap = cv2 .VideoCapture (self .url , cv2 .CAP_FFMPEG )
37- ret , frame = cap .read ()
48+ # opens the stream capture, but does not retrieve any frames yet.
49+ self ._open_video_capture ()
50+
51+ def _open_video_capture (self ):
52+ # To CAP_FFMPEG or not To ?
53+ self .capture = cv2 .VideoCapture (self .url , cv2 .CAP_FFMPEG )
54+
55+ def _stream_blocking (self ):
56+ while True :
57+ try :
58+ if self .capture .isOpened ():
59+ ret , frame = self .capture .read ()
60+ if ret :
61+ yield frame
62+ else :
63+ print ("stream closed" )
64+ self .capture .release ()
65+ return
66+ except Exception as e :
67+ print (e )
68+ self .capture .release ()
69+ return
70+
71+ @threaded
72+ def _stream_non_blocking (self ):
73+ while not self .thread_cancelled :
74+ try :
75+ if self .capture .isOpened ():
76+ ret , frame = self .capture .read ()
77+ if ret :
78+ self .callback (frame )
79+ else :
80+ print ("stream is closed" )
81+ self .stop_stream ()
82+ except ThreadError as e :
83+ print (e )
84+ self .stop_stream ()
3885
39- while ret :
40- cv2 .imshow (win_name , frame )
86+ def stop_stream (self ):
87+ self .capture .release ()
88+ self .thread_cancelled = True
4189
42- ret , frame = cap .read ()
43- if (cv2 .waitKey (1 ) & 0xFF == ord ('q' )):
44- break
90+ def open_stream (self ):
91+ """
92+ Opens OpenCV Video stream and returns the result according to the OpenCV documentation
93+ https://docs.opencv.org/3.4/d8/dfe/classcv_1_1VideoCapture.html#a473055e77dd7faa4d26d686226b292c1
94+
95+ :param callback: The function to callback the cv::mat frame to if required to be non-blocking. If this is left
96+ as None, then the function returns a generator which is blocking.
97+ """
4598
46- cap .release ()
47- cv2 .destroyAllWindows ()
99+ # Reset the capture object
100+ if self .capture is None or not self .capture .isOpened ():
101+ self ._open_video_capture ()
102+
103+ print ("opening stream" )
104+
105+ if self .callback is None :
106+ return self ._stream_blocking ()
107+ else :
108+ # reset the thread status if the object was not re-created
109+ if not self .thread_cancelled :
110+ self .thread_cancelled = False
111+ return self ._stream_non_blocking ()
0 commit comments