Possible memory leak using opencv VideoCapture with gstreamer backend

**• Hardware Platform **
Jetson Nano Developer Kit
• Gstreamer Version
1.14.5
• Opencv Version
4.7.0
• Python Version
3.6.9

Minimal python script:

def mem_available_mb():
    with open('/proc/meminfo') as file:
        mem_available_in_kb = None
        mem_total_in_kb = None
        for line in file:
            if 'MemTotal' in line:
                mem_total_in_kb = int(line.split()[1])
                if mem_available_in_kb is not None:
                    print("used:", mem_total_in_kb / 1024)
            elif 'MemAvailable' in line:
                mem_available_in_kb = int(line.split()[1])
                break
            if mem_available_in_kb is None or mem_total_in_kb is None:
                continue

    return mem_available_in_kb / 1024

def init_cam_streams():
    cams = []
    for i in range(2):
        cams.append(cv2.VideoCapture(i, cv2.CAP_GSTREAMER))
    return cams

if __name__ == "__main__":
    file_name = "test gstreamer minimal.txt"
    cams = init_cam_streams()
    while True:
        try:
            a = mem_available_mb()
            with open(file_name, "a") as f:
                f.write(str(a) + "\n")
            time.sleep(10)
            print(len(cams))
        except KeyboardInterrupt:
            break

While running this script, available memory decreases with ± 1MB/min. Switching to FFMPEG backend causes the problem to disappear. Any suggestions?

welcome.

“possible” memory leaks receive no attention until the existence of a leak is proven.

often, people aren’t clear on what a “memory leak” is, and what is not a memory leak. this here is not a memory leak.

your code opens various camera devices without actually reading frames from any of them. that is not proper.

if you don’t read those frames, they are buffered and waiting for you to be read. that is what is “leaking”. it’s intentional. it’s not a leak.

Hi, thanks for the clarification. However, even if I read out the frames with a very basic program like this

if __name__ == "__main__":
    cap = cv2.VideoCapture(0, cv2.CAP_V4L2)
    while True:
        try:
            success, frame = cap.read()
        except KeyboardInterrupt:
            break

using htop I still see the memory used by this process increasing gradually.

that’s the whole program, except for the cv2 import? nothing more? okay, that would be a valid program to demonstrate a leak.

can you record memory usage of this process and plot it over time, until the system crashes, programs are killed due to lack of free memory, or a significant amount of memory is allocated?

Hi, yes this is the whole program. When plotting the memory usage (using process.memory_info().rss) over a longer time it looks like this:

memory_use

BTW I noticed that I made a mistake in my previous post CAP_V4L2 should of course be CAP_GSTREAMER.

hm ok that looks like enough evidence to conclude a memory leak.

if you use CAP_V4L2, can you read frames from the video device, i.e. cap.isOpened() and success? when using V4L2, does memory consumption grow similarly, or does it level out?

that test would tell whether the leak is in a specific backend or in common code.

Hi, yes I can open the camera with V4L2. When running the exact same program with V4L2 backend, the process memory stays perfectly stable, so the leak is probably located in the GSTREAMER backend.

Great. I believe you’ve got all the evidence for a bug report: simple reproducer, works ok with other backends, very obvious memory growth…

your plot shows an increase of about 750 bytes per frame. that isn’t much so I’m not surprised that wasn’t noticed before. that should also help narrow down the source of the leak.