opencv 十九 python下实现多线程间rtsp直播流的复用

发布于:2024-03-28 ⋅ 阅读:(27) ⋅ 点赞:(0)

在多线程拉流的任务场景中,有时需要将一个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视频流。
代码运行时的输入如下所示
在这里插入图片描述

本文含有隐藏内容,请 开通VIP 后查看