pythonpython-3.xmultiprocessingeoferror

Why did multiprocessing giving me EOFError : Ran out of Input Error?


videoPlayerThreading is my own made library to basically making 2 class with each using threading to get and show frames. objDect is also my own library to basically return frame after object detection. I got EOFError : Ran out of Input error and from the traceback I think it is caused by the multiprocessing itself hence I don't post my library because it is so long. Can anyone help me with what is wrong with it? Thank you

from multiprocessing import Process
import sys

import videoPlayerThreading as vpt
from objDect import objDect as od


def main(videoSource):
    obd = od( videoSources = videoSource )
    
    getFrame = vpt.getFrames(videoSource).start()
    showFrame = vpt.showFrames(videoSource).start()

    while True:
        frame = getFrame.frame
        frame=Process(target=obd.predictYolo, args=(frame,)).start()
        showFrame.frame = frame

        if getFrame.doVideo == False or showFrame.doVideo == False:
            getFrame.stop()
            showFrame.stop()
            sys.exit()


if __name__=="__main__":
   main(0) 

Edit :
Here is the show frames and get frames class it basically only get and show frame using threading.

class getFrames():
    def __init__(self, 
                 videoSource:Union[int,str]=0):
        self.stream = self.videoInit(videoSource)
        self.hasFrame, self.frame = self.stream.read()
        self.doVideo = True

    def videoInit(self,
                  videoSource:Union[int,str]):
        try:
            cap = cv2.VideoCapture(videoSource)
        except Exception as e:
            raise Exception(f"Video source error: {e}")

        return cap

    def start(self):
        Thread(target=self.getFrames, args=()).start()
        return self

    def getFrames(self):
        while self.doVideo:
            if not self.hasFrame:
                self.stop()
            else:
                (self.hasFrame, self.frame) = self.stream.read()

    def stop(self):
        self.doVideo = False
        self.stream.release()

class showFrames():
    def __init__(self, 
                 frame:cv2=None):
        self.frame = frame
        self.doVideo = True

    def start(self):
        Thread(target=self.showFrame, args=()).start()
        return self

    def showFrame(self):
        while self.doVideo:
            cv2.imshow("Video", self.frame)
            if cv2.waitKey(1) == ord("q"):
                self.doVideo = False

    def stop(self):
        self.doVideo = False

Solution

  • The best I can understand your program logic you need something like the following. Generator function read_frames (which may or may not need correction), reads the frames one by one yielding each frame. The main process creates a multiprocessing pool and passes each input frame to the multiprocessing pool to be processed by obd.predictYolo and sets vpt.frame with the returned frame. This continues until either there are no more frames to process or showFrame.doVideo is False. In short, I have done away with your getFrames class, which is useless here.

    I do not have OpenCV installed and do not really know the package nor do I have your video file, so consider this a starting point for your further investigation.

    from multiprocessing.pool import Pool
    import sys
    
    import videoPlayerThreading as vpt
    from objDect import objDect as od
    
    def read_frames(videoSource:Union[int,str]=0):
        try:
            stream = cv2.VideoCapture(videoSource)
        except Exception as e:
            raise Exception(f"Video source error: {e}")
        while True:
            hasFrame, frame = stream.read()
            if not hasFrame:
                break
            yield frame
    
    
    def main(videoSource):
        obd = od( videoSources = videoSource )
        showFrame = vpt.showFrames(videoSource).start()
        with Pool() as pool:
            for frame in pool.imap(obd.predictYolo, read_frames(videoSource)):
                showFrame.frame = frame
        
                if showFrame.doVideo is False:
                    showFrame.stop()
                break
    
    if __name__=="__main__":
       main(0)