在多线程拉流的任务场景中,有时需要将一个rtsp拉取多次,每重新打开一次rtsp视频流就要多消耗一次带宽,为此基于类的静态对象实现rtsp视频流的复用。
1、实现代码
import threading
import cv2,time
#接收摄影机串流影像,采用多线程的方式,采用锁的方式进行实现
class VideoCaptureBase:
def __init__(self, URL):
self.URL = URL
self.lifetime=1
self.isstop = False
self.lock = threading.RLock()
self.data=(None,None)
# 摄影机连接。
self.capture = cv2.VideoCapture(self.URL, cv2.CAP_FFMPEG, [cv2.CAP_PROP_HW_ACCELERATION, cv2.VIDEO_ACCELERATION_ANY])
threading.Thread(target=self.readframe, daemon=True, args=()).start()
print('VideoCapture started! %s'%self.URL)
def release(self):
# 记得要设计停止无限循环的开关。
self.lifetime-=1
if self.lifetime==0:
self.isstop = True
print('VideoCapture stopped! %s'%self.URL)
else:
print('VideoCapture self.lifetime=%s'%self.lifetime)
def read(self):
self.lock.acquire()
d=self.data
self.lock.release()
return d
#进行实时数据读取
def readframe(self):
while (not self.isstop):
ok, frame = self.capture.read()
if ok:
self.lock.acquire()
self.data=(ok, frame)
self.lock.release()
else:
time.sleep(0.2)
self.capture = cv2.VideoCapture(self.URL) #掉线重连
self.capture.release()
class VideoCapture:
CapList=[]
def __init__(self, URL):
self.URL=URL
inlist=False
print(self.URL,'CapList.length:=====>',len(VideoCapture.CapList))
for i in range(len(VideoCapture.CapList)):
cap=VideoCapture.CapList[i]
print(i,cap.URL,self.URL,cap.URL==self.URL)
if cap.URL==self.URL:
cap.lifetime+=1 # 存活计数器+1
inlist=True
print('use exit rtsp stream!!!!')
if not inlist:
cap=VideoCaptureBase(self.URL)
VideoCapture.CapList.append(cap)
print('CapList.length:=====>',len(VideoCapture.CapList),self.URL)
def read(self):
for cap in VideoCapture.CapList:
if cap.URL==self.URL:
return cap.read()
def release(self):
for cap in VideoCapture.CapList:
if cap.URL==self.URL:
cap.release() # 存活计数器-1,当计数器为0时断开流
if __name__ == '__main__':
path="rtmp://rtmp.rtc.qq.com/pull/19"
cap = VideoCapture(path)
time.sleep(5)
cap2 = VideoCapture(path)
time.sleep(5)
cap3 = VideoCapture(path)
cap2.release()
time.sleep(3)
cap3.release()
while True:
ok, frame = cap.read()
if cv2.waitKey(1) & 0xFF == ord('q'):
break
if not ok:
continue
cv2.imshow("cam", frame)
cap.release()
cv2.destroyAllWindows()
3、使用说明
使用代码如下所示,与cv2.VideoCapture是一模一样的用法,具备0缓存,自动断线重连的特点;同时在多线程同时打开一个rtsp流地址的情况下,可以只打开一次rtsp视频流。
代码运行时的输入如下所示