<reponame>freewebfish/lightweight-human-pose-estimation-3d-demo.pytorch<filename>modules/thread_video_streaming.py
from os import path
from threading import Thread, Lock
import cv2
import queue
from modules.myconst import frame_queue
import logging

class ThreadVideoStreaming :
    
    def __init__(self, src = 0, mirror_flip = False, width = 640, height = 480) :
        self.src = src
        self.width = width
        self.height = height
        self.mirror_flip = mirror_flip

        if isinstance(self.src, int):
            self.stream = cv2.VideoCapture(self.src, cv2.CAP_DSHOW)
            self.stream.set(cv2.CAP_PROP_FRAME_WIDTH, self.width)
            self.stream.set(cv2.CAP_PROP_FRAME_HEIGHT, self.height)
            if (self.stream.isOpened()== False): 
                raise IOError("Camera {self.src} cannot be opened")
        elif isinstance(self.src, str):
            if path.exists(self.src):
                self.stream = cv2.VideoCapture(self.src)                           
                if (self.stream.isOpened()== False): 
                    raise IOError("Video {self.src} cannot be opened")
            else:
                raise IOError("Video {self.src} does not exist")
        else:
            raise IOError("Invalid src parameter for WebcamVideoStream")

        (self.grabbed, self.frame) = self.stream.read()
        if (self.grabbed == False): 
            raise IOError("Camera {self.src} frame read failure")
        else:
            self.width = int(self.stream.get(cv2.CAP_PROP_FRAME_WIDTH))
            self.height = int(self.stream.get(cv2.CAP_PROP_FRAME_HEIGHT))
        if self.mirror_flip: 
            self.frame = cv2.flip(self.frame, 1)        
        self.started = False
        self.read_lock = Lock()

    def isOpened(self) :
        return self.stream.isOpened()

    def start(self) :
        if self.started :
            print("already started!!")
            return None
        self.thread = Thread(target=self.update, args=())
        self.thread.daemon = True  #https://www.geeksforgeeks.org/python-different-ways-to-kill-a-thread/
        self.thread.start()    
        self.started = True
        print(f"@{__name__}: created streaming thread: {self.thread.ident}")     
        logging.info(f"@{__name__}: created streaming thread: {self.thread.ident}")            
        return self

    def update(self) :
        while self.started :
            (grabbed, frame) = self.stream.read()
            self.read_lock.acquire()
            self.grabbed, self.frame = grabbed, frame
            if not self.grabbed: self.started = False
            if self.mirror_flip: self.frame = cv2.flip(self.frame, 1)        
            while self.started:
                try:
                    frame_queue.put(self.frame, timeout=1)
                    break
                except queue.Full:
                    pass
            self.read_lock.release()

    def read(self) :
        if self.started:
            self.read_lock.acquire()
            frame = self.frame.copy()
            grabbed = self.grabbed
            self.read_lock.release()
            return grabbed, frame
        else:
            return False, None

    def stop(self) :
        self.started = False
        logging.info(f"@{__name__}: closed streaming thread: {self.thread.ident}")                    
        self.thread.join()

    def __exit__(self, exc_type, exc_value, traceback) :
        self.stream.release()

from os import path
from threading import Thread, Lock
import cv2
import queue
from modules.myconst import frame_queue
import logging

class ThreadVideoStreaming :
    
    def __init__(self, src = 0, mirror_flip = False, width = 640, height = 480) :
        self.src = src
        self.width = width
        self.height = height
        self.mirror_flip = mirror_flip

        if isinstance(self.src, int):
            self.stream = cv2.VideoCapture(self.src, cv2.CAP_DSHOW)
            self.stream.set(cv2.CAP_PROP_FRAME_WIDTH, self.width)
            self.stream.set(cv2.CAP_PROP_FRAME_HEIGHT, self.height)
            if (self.stream.isOpened()== False): 
                raise IOError("Camera {self.src} cannot be opened")
        elif isinstance(self.src, str):
            if path.exists(self.src):
                self.stream = cv2.VideoCapture(self.src)                           
                if (self.stream.isOpened()== False): 
                    raise IOError("Video {self.src} cannot be opened")
            else:
                raise IOError("Video {self.src} does not exist")
        else:
            raise IOError("Invalid src parameter for WebcamVideoStream")

        (self.grabbed, self.frame) = self.stream.read()
        if (self.grabbed == False): 
            raise IOError("Camera {self.src} frame read failure")
        else:
            self.width = int(self.stream.get(cv2.CAP_PROP_FRAME_WIDTH))
            self.height = int(self.stream.get(cv2.CAP_PROP_FRAME_HEIGHT))
        if self.mirror_flip: 
            self.frame = cv2.flip(self.frame, 1)        
        self.started = False
        self.read_lock = Lock()

    def isOpened(self) :
        return self.stream.isOpened()

    def start(self) :
        if self.started :
            print("already started!!")
            return None
        self.thread = Thread(target=self.update, args=())
        self.thread.daemon = True  #https://www.geeksforgeeks.org/python-different-ways-to-kill-a-thread/
        self.thread.start()    
        self.started = True
        print(f"@{__name__}: created streaming thread: {self.thread.ident}")     
        logging.info(f"@{__name__}: created streaming thread: {self.thread.ident}")            
        return self

    def update(self) :
        while self.started :
            (grabbed, frame) = self.stream.read()
            self.read_lock.acquire()
            self.grabbed, self.frame = grabbed, frame
            if not self.grabbed: self.started = False
            if self.mirror_flip: self.frame = cv2.flip(self.frame, 1)        
            while self.started:
                try:
                    frame_queue.put(self.frame, timeout=1)
                    break
                except queue.Full:
                    pass
            self.read_lock.release()

    def read(self) :
        if self.started:
            self.read_lock.acquire()
            frame = self.frame.copy()
            grabbed = self.grabbed
            self.read_lock.release()
            return grabbed, frame
        else:
            return False, None

    def stop(self) :
        self.started = False
        logging.info(f"@{__name__}: closed streaming thread: {self.thread.ident}")                    
        self.thread.join()

    def __exit__(self, exc_type, exc_value, traceback) :
        self.stream.release()
#https://www.geeksforgeeks.org/python-different-ways-to-kill-a-thread/