为了账号安全,请及时绑定邮箱和手机立即绑定

使用 gst-rtsp-server Python 绑定处理错误

使用 gst-rtsp-server Python 绑定处理错误

长风秋雁 2021-10-12 17:59:11
我有一个简单的 Python 程序使用 gst-rtsp-server 创建一个 RTSP 流。它有效,但按原样没有错误处理。如果管道有拼写错误或连接到视频源时出现问题,我将看不到堆栈跟踪或任何日志记录。我应该在哪里挂钩代码来处理这样的问题?我应该提一下,我是 GObject 世界的完全初学者。我怀疑这些库有一种标准的方法来报告错误,但我无法在我读过的文档中找到任何关于它是如何完成的。如果它有帮助,这是我现在拥有的代码:from threading import Threadfrom time import sleepimport signalimport gigi.require_version("Gst", "1.0")gi.require_version("GstRtsp", "1.0")gi.require_version("GstRtspServer", "1.0")from gi.repository import GLib, GObject, Gst, GstRtsp, GstRtspServerPIPELINE = (    "( videotestsrc ! vp8enc ! rtpvp8pay name=pay0 pt=96 )")def main():    GObject.threads_init()    Gst.init(None)    server = GstRtspServer.RTSPServer.new()    server.props.service = "3000"    server.attach(None)    loop = GLib.MainLoop.new(None, False)    def on_sigint(_sig, _frame):        print("Got a SIGINT, closing...")        loop.quit()    signal.signal(signal.SIGINT, on_sigint)    def run_main_loop():        loop.run()    main_loop_thread = Thread(target=run_main_loop)    main_loop_thread.start()    media_factory = GstRtspServer.RTSPMediaFactory.new()    media_factory.set_launch(PIPELINE)    media_factory.set_shared(True)    server.get_mount_points().add_factory("/test", media_factory)    print("Stream ready at rtsp://127.0.0.1:3000/test")    while loop.is_running():        sleep(0.1)if __name__ == "__main__":    main()
查看完整描述

2 回答

?
泛舟湖上清波郎朗

TA贡献1818条经验 获得超3个赞

所以,你可以覆盖do_handle_message在Gst.Bin下面的方法:


import gi

gi.require_version("Gst", "1.0")

from gi.repository import Gst, GLib

Gst.init(None)


class SubclassBin(Gst.Bin):

    def do_handle_message(self, message):

        if message.type == Gst.MessageType.ERROR:

            error, message = message.parse_error()

            # TODO: Do something with the error

        # Call the base Gst.Bin do_handle_message

        super().do_handle_message(self, message)


subclass_bin = SubclassBin("mybin")

也就是说,我不确定如何GstRtspServer.RTSPMediaFactory使用SubclassBin而不是Gst.Bin因为据我所知,将任何 Bin 连接到的唯一方法RTSPMediaFactory是通过set_launch需要管道字符串而不是预构建 bin 的方法。如果有一种方法可以将预构建的 bin 添加到RTSPMediaFactory,这将是一个完整的答案......但不幸的是,这是我所能得到的。


查看完整回答
反对 回复 2021-10-12
?
慕村9548890

TA贡献1884条经验 获得超4个赞

我建议使用 bkanuka 的解决方案 (Subclassing Gst.Bin) 而不是下面的解决方案,它有很多缺点。


对 GStreamer 和 RTSP 服务器库进行了一些更多的实验后,错误处理情况很复杂。


正常方式

查看 GStreamer 管道上的错误的规范方法是向管道的总线添加观察者并侦听错误消息。


def watcher(bus, message, *user_data);

    if message.type == Gst.MessageType.ERROR:

        error, message = message.parse_error()

        # TODO: Do something with the error


my_pipeline.get_bus().add_watch(

    GLib.PRIORITY_DEFAULT,

    watcher,

    None)

但是,您不能使用提供给 GstRtspServer 的管道执行此操作。这是因为 GstRtspServer 期望能够在管道的总线上安装自己的观察器,并且一次只能将一个观察器连接到总线。这尤其令人遗憾,因为这会阻止我们侦听管道上的任何事件,而不仅仅是错误。


我的解决方法

我们可以将管道分成两部分:一部分负责连接到源和解码帧的容易出错的过程,另一部分负责对结果帧进行编码并将它们加载到 GstRtspServer。然后我们可以使用视频间插件在两者之间进行通信。


例如,假设您尝试从 VP8 格式的文件进行流式传输。我们负责读取和解码帧的第一个管道如下所示:


filesrc location="{filepath}" ! decodebin ! intervideosink channel="file-channel"

...我们负责编码和加载帧的第二条管道将如下所示:


intervideosrc channel="file-channel" ! videoconvert ! vp8enc deadline=1 ! rtpvp8pay name=pay0 pt=96

这里的关键是只有第二个管道必须由 GstRtspServer 管理,因为它是提供有效负载数据的管道。第一个由我们管理,我们可以将我们自己的观察者附加到它上面,它可以智能地响应错误并做我们需要的任何其他事情。这当然不是一个完美的解决方案,因为我们无法响应与编码和负载相关的错误,但我们已经获得了接收与读取文件和解码文件相关的错误的能力。我们现在还能够执行其他与消息相关的任务,例如拦截流结束消息以循环播放视频文件。


查看完整回答
反对 回复 2021-10-12
  • 2 回答
  • 0 关注
  • 589 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号