在多线程拉流的任务场景中,有时需要将一个rtsp拉取多次,每重新打开一次rtsp视频流就要多消耗一次带宽,为此基于类的静态对象实现rtsp视频流的复用。
1、实现代码
import threading
import cv2,time
#接收摄影机串流影像,采用多线程的方式,采用锁的方式进行实现
class VideoCaptureBase:def __init__(self, URL):self.URL = URLself.lifetime=1self.isstop = Falseself.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-=1if self.lifetime==0:self.isstop = Trueprint('VideoCapture stopped! %s'%self.URL)else:print('VideoCapture self.lifetime=%s'%self.lifetime)def read(self):self.lock.acquire()d=self.dataself.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=URLinlist=Falseprint(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 # 存活计数器+1inlist=Trueprint('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'):breakif not ok:continuecv2.imshow("cam", frame)cap.release()cv2.destroyAllWindows()
3、使用说明
使用代码如下所示,与cv2.VideoCapture是一模一样的用法,具备0缓存,自动断线重连的特点;同时在多线程同时打开一个rtsp流地址的情况下,可以只打开一次rtsp视频流。
代码运行时的输入如下所示