使用gsteramer appsink的内存泄漏(Python绑定)

时间:2018-07-04 16:14:30

标签: python memory-leaks gstreamer pygobject

我正在尝试使用appsink构建管道,它占用了大量内存:

#!/usr/bin/env python

import sys

import gi


gi.require_version('Gst', '1.0')
from gi.repository import GObject, Gst


def main():
    GObject.threads_init()
    Gst.init(None)
    # pipeline = Gst.parse_launch('fakesrc ! fakesink')
    pipeline = Gst.parse_launch('fakesrc ! appsink')

    loop = GObject.MainLoop()

    pipeline.set_state(Gst.State.PLAYING)
    try:
        loop.run()
    except:
        pass

    pipeline.set_state(Gst.State.NULL)


if __name__ == '__main__':
    sys.exit(main())

即使没有设置连接,内存也在不断增加。我试图使用sink.connect("new-sample", handler, sink)连接一个函数-它也会泄漏内存。还尝试将处理程序添加到总线(读取gst可能会使未传递到python的消息排队,并使其永久保存的地方)-也不起作用。

我需要在某个地方释放内存吗?我在C代码中找到了对gst_object_unref的调用,但是我不确定是否应该在python代码中使用unref。

此外,简单的管道'fakesrc ! fakesink'不会泄漏内存。

该脚本在Docker内部运行(不确定是否很重要,不幸的是,我无法在Docker外部进行测试)

FROM python:3.6
ENV PYTHONUNBUFFERED 1
RUN mkdir -p /code
WORKDIR /code
ADD Pipfile Pipfile.lock /code/
RUN apt-get update && apt-get install -y software-properties-common cmake \
    gobject-introspection libgirepository1.0-dev libcairo2-dev \
    libgstreamer1.0-0 gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad \
    gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-doc gstreamer1.0-tools \
    python-gst-1.0
RUN pip install pipenv && pipenv install --system
ADD . /code/
WORKDIR /code/src
EXPOSE 8181
CMD python main.py

2 个答案:

答案 0 :(得分:2)

Appsink有一个队列,用于存储传入的样本。默认情况下,此大小是无限的。您可以通过appsink的max-buffersdrop属性进行控制,这样它就不会无限增长。

但是您实际要做的是主动将这些样本从appink中拉出并进行处理-或至少将它们丢弃。

new-sample信号是一个好的开始。如果触发了该信号,则新样品已到达并准备进行处理。我在这里记不清Python,但是您想调用appsink对象的pull_sample方法以将样品所有权从appsink转移到您自己。一旦超出范围,该样本应正确发布-我想。

编辑:确保发出信号。有一个appsink属性emit-signals,默认情况下处于关闭状态。但是我通常会做C东西,所以我不确定Python确实会翻转某些开关,所以它开箱即用。.

答案 1 :(得分:0)

嗯,解决方案(至少是修补程序)很简单:手动调用gc.collect()

我不确定为什么不自动调用(或释放),但是只需在每个gc.collect()处理程序上调用sink即可解决问题。在每个帧上调用gc并不是超级有效,我一定会在有空闲时间时对此进行一些研究。

该解决方案是通过改写Java来发现的(它也占用大量内存),但是在Java中,您可以指定-Xmx来减少JVM可用的内存量