GStreamer Python:gi.repository.GLib.GError:gst_parse_error:OSX 上没有元素“appsrc”

问题描述 投票:0回答:0

我正在尝试使用 OpenCV 在 Python 中设置 RTSP 流。我找到了this repository,我以此作为例子开始。我很确定那里的代码不完全是那个人写的,因为我发现了一些具有相同代码的旧源。 但是,我以此为基础来熟悉一切。

这是我尝试运行的完整(略有改动的)Python 脚本:

import gi
import cv2 as cv
import argparse

gi.require_versions({
  # 'Gtk': '3.0',
  'Gst': '1.0',
  'GstRtspServer': '1.0',
  'GLib': '2.0'
})
from gi.repository import Gst, GstRtspServer, GLib

class StreamFactory(GstRtspServer.RTSPMediaFactory):
  def __init__(self, **properties):
    super(StreamFactory, self).__init__(**properties)
    self.cap = cv.VideoCapture(0) # 0 is the default camera
    self.number_frames = 0
    self.fps = opt.fps
    self.duration = 1 / self.fps * Gst.SECOND # duration of a frame in nanoseconds
    self.launch_string = 'appsrc name=source is-live=true block=true format=GST_FORMAT_TIME ' \
                      'caps=video/x-raw,format=BGR,width={},height={},framerate={}/1 ' \
                      '! videoconvert ! video/x-raw,format=I420 ' \
                      '! x264enc speed-preset=ultrafast tune=zerolatency ' \
                      '! rtph264pay config-interval=1 name=pay0 pt=96' \
                      .format(opt.image_width, opt.image_height, self.fps)

  def on_need_data(self, src, length):
    if self.cap.isOpened():
      ret, frame = self.cap.read()
      if ret:
        frame = cv.resize(frame, (640, 480))
        data = frame.tostring()
        buf = Gst.Buffer.new_allocate(None, len(data), None)
        buf.fill(0, data)
        timestamp = self.number_frames * self.duration
        buf.pts = int(timestamp)
        buf.dts = int(timestamp)
        buf.offset = timestamp
        self.number_frames += 1
        retval = src.emit('push-buffer', buf)

        if retval != Gst.FlowReturn.OK:
          print(retval)

  def do_create_element(self, url):
    return Gst.parse_launch(self.launch_string)

  def do_configure(self, rtsp_media):
    self.number_frames = 0
    appsrc = rtsp_media.get_element().get_child_by_name('source')
    appsrc.connect('need-data', self.on_need_data)

class GstServer(GstRtspServer.RTSPServer):
  def __init__(self, **properties):
    super(GstServer, self).__init__(**properties)
    self.factory = StreamFactory()
    self.factory.set_shared(True)
    self.get_mount_points().add_factory(opt.stream_uri, self.factory)
    self.attach(None)


parser = argparse.ArgumentParser()
parser.add_argument("--device_id", required=True, help="device id for the video device or video file location")
parser.add_argument("--fps", required=True, help="fps of the camera", type = int)
parser.add_argument("--image_width", required=True, help="video frame width", type = int)
parser.add_argument("--image_height", required=True, help="video frame height", type = int)
parser.add_argument("--port", default=8554, help="port to stream video", type = int)
parser.add_argument("--stream_uri", default = "/video_stream", help="rtsp video stream uri")
opt = parser.parse_args()

# GObject.threads_init()
Gst.init(None)
server = GstServer()
loop = GLib.MainLoop()
loop.run()

运行这个的结果是启动了,但是我一连接上服务器就抛出如下异常:

目前我只能使用M1 Mac,所以我自己无法确认,但根据我发现的一些问题(比如这个),可能与架构相关,虽然我对此并不完全肯定,因为我也看到了this issue,看起来它确实已经过时并且不相关,因为如果我运行

gst-launch-1.0 videotestsrc ! videoconvert ! autovideosink
它工作得很好,不像那个问题中所说的那样。

我通过 HomeBrew 安装了

gstreamer
+ 所有依赖项,但我也验证了我在没有 HomeBrew 的情况下从头开始构建相同的结果。

到目前为止我用自制软件安装的所有库(我将在此处发布完整列表,但请记住并非所有依赖项都与此问题相关):

这也是我的 Python 依赖列表:

✖ pip3 freeze
docutils==0.19
numpy==1.24.2
opencv-python==4.7.0.72
pycairo==1.23.0
PyGObject==3.42.2
six==1.16.0

在python版本上:

3.9.16.final.0
,也尝试了最新的
3.11
版本。 OSX 版本:
13.0.1 (22A400)

我还使用

appsrc
命令验证了
gst-inspect
插件可用于 gst,它看起来是:

✖ gst-inspect-1.0 appsrc
Factory Details:
  Rank                     none (0)
  Long-name                AppSrc
  Klass                    Generic/Source
  Description              Allow the application to feed buffers to a pipeline
  Author                   David Schleef <[email protected]>, Wim Taymans <[email protected]>
  Documentation            https://gstreamer.freedesktop.org/documentation/app/appsrc.html

Plugin Details:
  Name                     app
  Description              Elements used to communicate with applications
  Filename                 /opt/homebrew/lib/gstreamer-1.0/libgstapp.dylib
  Version                  1.22.0
  License                  LGPL
  Source module            gst-plugins-base
  Documentation            https://gstreamer.freedesktop.org/documentation/app/
  Source release date      2023-01-23
  Binary package           GStreamer Base Plug-ins source release
  Origin URL               Unknown package origin

GObject
 +----GInitiallyUnowned
       +----GstObject
             +----GstElement
                   +----GstBaseSrc
                         +----GstAppSrc

Implemented Interfaces:
  GstURIHandler

Pad Templates:
  SRC template: 'src'
    Availability: Always
    Capabilities:
      ANY

Element has no clocking capabilities.

URI handling capabilities:
  Element can act as source.
  Supported URI protocols:
    appsrc

Pads:
  SRC: 'src'
    Pad Template: 'src'

Element Properties:
  block               : Block push-buffer when max-bytes are queued
                        flags: readable, writable
                        Boolean. Default: false
  blocksize           : Size in bytes to read per buffer (-1 = default)
                        flags: readable, writable
                        Unsigned Integer. Range: 0 - 4294967295 Default: 4096
  caps                : The allowed caps for the src pad
                        flags: readable, writable
                        Caps (NULL)
  current-level-buffers: The number of currently queued buffers
                        flags: readable
                        Unsigned Integer64. Range: 0 - 18446744073709551615 Default: 0
  current-level-bytes : The number of currently queued bytes
                        flags: readable
                        Unsigned Integer64. Range: 0 - 18446744073709551615 Default: 0
  current-level-time  : The amount of currently queued time
                        flags: readable
                        Unsigned Integer64. Range: 0 - 18446744073709551615 Default: 0
  do-timestamp        : Apply current stream time to buffers
                        flags: readable, writable
                        Boolean. Default: false
  duration            : The duration of the data stream in nanoseconds (GST_CLOCK_TIME_NONE if unknown)
                        flags: readable, writable
                        Unsigned Integer64. Range: 0 - 18446744073709551615 Default: 18446744073709551615
  emit-signals        : Emit need-data, enough-data and seek-data signals
                        flags: readable, writable
                        Boolean. Default: true
  format              : The format of the segment events and seek
                        flags: readable, writable
                        Enum "GstFormat" Default: 2, "bytes"
                           (0): undefined        - GST_FORMAT_UNDEFINED
                           (1): default          - GST_FORMAT_DEFAULT
                           (2): bytes            - GST_FORMAT_BYTES
                           (3): time             - GST_FORMAT_TIME
                           (4): buffers          - GST_FORMAT_BUFFERS
                           (5): percent          - GST_FORMAT_PERCENT
  handle-segment-change: Whether to detect and handle changed time format GstSegment in GstSample. User should set valid GstSegment in GstSample. Must set format property as "time" to enable this property
                        flags: readable, writable, changeable only in NULL or READY state
                        Boolean. Default: false
  is-live             : Whether to act as a live source
                        flags: readable, writable
                        Boolean. Default: false
  leaky-type          : Whether to drop buffers once the internal queue is full
                        flags: readable, writable, changeable only in NULL or READY state
                        Enum "GstAppLeakyType" Default: 0, "none"
                           (0): none             - GST_APP_LEAKY_TYPE_NONE
                           (1): upstream         - GST_APP_LEAKY_TYPE_UPSTREAM
                           (2): downstream       - GST_APP_LEAKY_TYPE_DOWNSTREAM
  max-buffers         : The maximum number of buffers to queue internally (0 = unlimited)
                        flags: readable, writable
                        Unsigned Integer64. Range: 0 - 18446744073709551615 Default: 0
  max-bytes           : The maximum number of bytes to queue internally (0 = unlimited)
                        flags: readable, writable
                        Unsigned Integer64. Range: 0 - 18446744073709551615 Default: 200000
  max-latency         : The maximum latency (-1 = unlimited)
                        flags: readable, writable
                        Integer64. Range: -1 - 9223372036854775807 Default: -1
  max-time            : The maximum amount of time to queue internally (0 = unlimited)
                        flags: readable, writable
                        Unsigned Integer64. Range: 0 - 18446744073709551615 Default: 0
  min-latency         : The minimum latency (-1 = default)
                        flags: readable, writable
                        Integer64. Range: -1 - 9223372036854775807 Default: -1
  min-percent         : Emit need-data when queued bytes drops below this percent of max-bytes
                        flags: readable, writable
                        Unsigned Integer. Range: 0 - 100 Default: 0
  name                : The name of the object
                        flags: readable, writable
                        String. Default: "appsrc0"
  num-buffers         : Number of buffers to output before sending EOS (-1 = unlimited)
                        flags: readable, writable
                        Integer. Range: -1 - 2147483647 Default: -1
  parent              : The parent of the object
                        flags: readable, writable
                        Object of type "GstObject"
  size                : The size of the data stream in bytes (-1 if unknown)
                        flags: readable, writable
                        Integer64. Range: -1 - 9223372036854775807 Default: -1
  stream-type         : the type of the stream
                        flags: readable, writable
                        Enum "GstAppStreamType" Default: 0, "stream"
                           (0): stream           - GST_APP_STREAM_TYPE_STREAM
                           (1): seekable         - GST_APP_STREAM_TYPE_SEEKABLE
                           (2): random-access    - GST_APP_STREAM_TYPE_RANDOM_ACCESS
  typefind            : Run typefind before negotiating (deprecated, non-functional)
                        flags: readable, writable, deprecated
                        Boolean. Default: false

Element Signals:
  "need-data" :  void user_function (GstElement* object,
                                     guint arg0,
                                     gpointer user_data);
  "enough-data" :  void user_function (GstElement* object,
                                       gpointer user_data);
  "seek-data" :  gboolean user_function (GstElement* object,
                                         guint64 arg0,
                                         gpointer user_data);

Element Actions:
  "push-buffer" :  GstFlowReturn user_function (GstElement* object,
                                                GstBuffer* arg0);
  "push-buffer-list" :  GstFlowReturn user_function (GstElement* object,
                                                     GstBufferList* arg0);
  "push-sample" :  GstFlowReturn user_function (GstElement* object,
                                                GstSample* arg0);
  "end-of-stream" :  GstFlowReturn user_function (GstElement* object);

我尝试的最后一件事是直接从 CLI 运行命令而不是通过 Python 调用它,看起来它运行时没有崩溃:

❯ gst-launch-1.0 appsrc name=source is-live=true block=true format=GST_FORMAT_TIME caps=video/x-raw,format=BGR,width=1920,height=1080,framerate=30/1 ! videoconvert ! video/x-raw,format=I420 ! x264enc speed-preset=ultrafast tune=zerolatency ! rtph264pay config-interval=1 name=pay0 pt=96
Setting pipeline to PAUSED ...
Pipeline is live and does not need PREROLL ...
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
Redistribute latency...
^Chandling interrupt.
Interrupt: Stopping pipeline ...
Execution ended after 0:00:46.577237000
Setting pipeline to NULL ...
Freeing pipeline ...

有没有人解决了这个问题或者在这方面取得了更多进展?我真的不知道还有什么地方可以打开与此相关的问题,因为我从中获得示例脚本的原始回购所有者似乎不知道代码实际发生了什么。在自制软件回购中打开另一个问题似乎也是错误的,因为它看起来不像是自制软件问题(不再),并且当前问题已关闭且无法发表评论。 GStreamer 回购也不允许打开问题。

有机会时,我将尝试验证它是否发生在 intel mac 和/或 x86_64 ubuntu 系统上,但与此同时,欢迎所有指点:)

python macos homebrew gstreamer
© www.soinside.com 2019 - 2024. All rights reserved.