1

I'm running a python script which uses OpenCV an ffmpeg for video streaming on RPI 2 (os is raspbian Jessie). The script is

    camera = cv2.VideoCapture(self.camera_id)

    command = "ffmpeg -re -f rawvideo -vcodec rawvideo -s 640x480 -i - -vcodec libx264 -preset ultrafast -tune zerolatency -an -f flv -metadata streamName=myStream tcp://0.0.0.0:6666"

    proc = sp.Popen(command, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE, shell=True)
    print("the commandline is: {}".format(command))

    start_time = time.time()

    while self.running:

        time.sleep(0.01)  # sane sleep time of 0.01 seconds
        ret, image = camera.read()
        if not ret:
            break

        # processing
        if (time.time() - start_time) >= self.time_interval:
            do_some_process(image)
            continue

        timestamp = datetime.datetime.now()
        ts = timestamp.strftime("%A %d %B %Y %I:%M:%S%p")
        cv2.putText(image, ts, (10, image.shape[0] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 2)


        img_out = cv2.cvtColor(image, cv2.COLOR_BGR2YUV_I420)
        proc.stdin.write(img_out.tostring())
        # sys.stdout.write( img_out.tostring())

It has a high cpu usage (average is 4*70% every time), I have limited its cpu usage by using nice command (nice -n 19) and time.sleep(0.01) up to the main loop.

The problem is that, this program doesn't run for a long time and then got suspended by the os, I don't know why, maybe it is due to resource being used up.

At the startup of the program

At the startup of the program

At the moment when the program is suspended

At the moment when the program is suspended

Please how can I solve this, any help?

7
  • "then got suspended by the os" -> Suspended as in it stopped but then mysteriously started again, or suspended as in permanently, like, dead? Have you monitored the RAM usage while you were watching the CPU usage? What was the responsiveness of the system generally about the time this happened?
    – goldilocks
    Sep 7, 2016 at 7:47
  • Thanks @goldilocks, I edit my question to add some screenshot of htop. The startup of the program and the moment when the program was suspended.
    – Erman
    Sep 7, 2016 at 8:41
  • Okay, but that's not quite what I was trying to get at. What could be happening is you are running out of RAM, but this won't be apparent in those screenshots because you are forking a lot of subprocessess, and only one of them will be killed, and if killing one of them "suspends" the execution of the whole, then the after picture here will show things after the its RAM has been freed. You should be able to tell if that's going on by watching htop throughout though. Also check sudo grep -i "oom.killer" /var/log/syslog afterward; if there is nothing this is not the issue.
    – goldilocks
    Sep 7, 2016 at 8:54
  • I run this command sudo grep -i "oom.killer" /var/log/syslog and the result is empty.
    – Erman
    Sep 7, 2016 at 9:15
  • Okay I don't think that's the problem then (OOM = "out of memory"; the OOM killer is something the kernel invokes when this happens to kill a process and free up some memory, but it is well indicated in the system log). You may have to add a lot of logging to your own code to get a better clue of at what point it happens.
    – goldilocks
    Sep 7, 2016 at 9:18

1 Answer 1

1

You are setting up stdout and stderr as pipes for the ffmpeg process, but never read them. If ffmpeg is producing any output at all then it will start to fill up the stdout and stderr buffers. The kernel buffers input/output to programs to stop them blocking for any read/write but they are of limited size. This is not normally an issue but in your case you never actually read from them.

Once the i/o buffers are full any writes to them will block, this will stop ffmpeg from processing any more of its stdin, which your process will continue to write to. Once the stdin buffer fills up your process will block creating a deadlock.

Instead you should either pass stdout and stderr of ffmpeg to the terminal (this is the default when you do not specify stdout=sp.PIPE or stderr=sp.PIPE) or throw them away entirely (by setting them to stdout=sp.DEVNULL and stderr=sp.DEVNULL) or read and handle them yourself inside your loop.

2
  • Thanks so much Michael, It's work very well. After change those pipe to sp.DEVNULL the problem disappeared. The proc now is proc = sp.Popen(command, stdin=sp.PIPE, stdout=sp.DEVNULL, stderr=sp.DEVNULL, shell=True)
    – Erman
    Sep 7, 2016 at 15:40
  • 1
    You may want to try setting them to null to see what ffmpeg is printing out - might be of interest. Especially stderr if it has any problems you are currently throwing them away. Sep 7, 2016 at 15:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.