Ahmad Alhilal
Ahmad Alhilal

Reputation: 454

Why does reading from a video block when using multiprocessing?

I'm trying to read a video file using cv2 within a process as shown below. Reading blocks at the beginning without displaying any frame!!!

I ensured opening the video file using reader_1920_1080.isOpened()!! It blocks at self.reader_1920_1080.read() and doesn't continue to next line of code, which doesn't help me to check success.

When I tried running without multiprocessing, it works perfectly!!

As such, the problem is in reading within a process!!

Any solution?

import cv2
from multiprocessing import Process

class ComputePSNRProcess(Process):
    def __init__(self):
        super(ComputePSNRProcess, self).__init__()
        self.reader_1920_1080 = cv2.VideoCapture('res_1920_1080.ivf')


    def run(self):
        while True:
            success, original_1920_1080 = self.reader_1920_1080.read()
            cv2.imshow('original', original_1920_1080)
            cv2.waitKey(25)


computePSNR = ComputePSNRProcess()
computePSNR.start()

Upvotes: 1

Views: 481

Answers (1)

Rotem
Rotem

Reputation: 32124

You can't execute cv2.VideoCapture in the master process and use it in the child process.

I am not sure, but I think the reason is that cv2.VideoCapture locks an OS resource, that cannot be passed to other process.

Running your code in Windows 10, I am getting an exception:

can't pickle cv2.VideoCapture objects

In the following post, Dan Mašek recommends to create the VideoCapture instance in run method.


Other issues:

  • When working with processes, you must use if __name__ == '__main__': ...
  • For clean finish, you need to break the loop when success is False.

The following code sample supposed to work:

import cv2
from multiprocessing import Process

class ComputePSNRProcess(Process):
    def __init__(self):
        super(ComputePSNRProcess, self).__init__()

    def run(self):
        self.reader_1920_1080 = cv2.VideoCapture('res_1920_1080.ivf')

        while True:
            success, original_1920_1080 = self.reader_1920_1080.read()

            if not success:
                break

            cv2.imshow('original', original_1920_1080)
            cv2.waitKey(25)

        self.reader_1920_1080.release()
        cv2.destroyAllWindows()

if __name__ == '__main__':
    computePSNR = ComputePSNRProcess()
    computePSNR.start()

Upvotes: 1

Related Questions