gst-rtsp-server 开源包提供了一份 readme 文件,以下是相关内容的整理:
说明:相关内容更新于2013年7月15日(周一),版本0.11.90.1
本 HOWTO 介绍 GStreamer RTSP 库的基本用法以及如何可以用它构建简单的服务器应用程序。
0. 概述
服务器严重依赖 GStreamer 的 RTSP 基础设施。这包括所有的媒体采集、解码、编码、付费和 UDP/TCP 流。我们将 rtpbin 元素用于所有会话管理。服务器中的大多数 RTSP 消息解析和构造都是使用gst插件库附带的 RTSP 库完成的。
结果是服务器非常小(只有11000行代码),并且易于理解和扩展。在它目前的发展状态下,事物变化很快,API 和 ABI 都是不稳定的。我们鼓励人们将其用于各种用例,并通过建议更改/特性来参与。
大多数服务器构建为一个库,其中包含一堆 GObject 对象,这些对象提供合理的默认功能,但有相当数量的钩子来覆盖默认行为。
服务器目前与 glib mainloop 很好地集成。它目前不打算在高负载场景中使用,因为还没有进行安全审计,所以您可能不应该将它放在公共 IP 地址上。
1. 初始化
在使用任何RTSP服务器函数之前,需要初始化 GStreamer。
#include <gst/gst.h>
int
main (int argc, char *argv[])
{
gst_init (&argc, &argv);
...
}
服务器本身目前没有任何特定的初始化功能,但将来可能会发生变化。
2. 创建服务器
您要做的第一件事是创建一个新的GstRTSPServer对象。一旦这个对象被添加到GMainLoop中,它将处理到服务器的所有新客户端连接。您可以创建如下所示的新服务器对象:
#include <gst/rtsp-server/rtsp-server.h>
GstRTSPServer *server;
server = gst_rtsp_server_new ();
默认情况下,服务器将在端口8554上侦听新连接。这可以通过调用 gst_rtsp_server_set_service()
或使用 'service' GObject
属性来更改。这使得在一台机器上运行多个服务器实例监听多个端口成为可能。
我们可以通过将服务器连接到一个 mainloop,使其开始侦听其默认端口。下面的示例显示了如何执行此操作,并将在默认8554端口上启动服务器。对于我们发出的任何请求,我们都会得到一个未找到的错误代码,因为我们需要在服务器变得有用之前配置更多的东西。
#include <gst/gst.h>
#include <gst/rtsp-server/rtsp-server.h>
int
main (int argc, char *argv[])
{
GstRTSPServer *server;
GMainLoop *loop;
gst_init (&argc, &argv);
server = gst_rtsp_server_new ();
/* make a mainloop for the default context */
loop = g_main_loop_new (NULL, FALSE);
/* attach the server to the default maincontext */
gst_rtsp_server_attach (server, NULL);
/* start serving */
g_main_loop_run (loop);
}
服务器管理另外四个对象: GstRTSPSessionPool
、GstRTSPMountPoints
、 GstRTSPAuth
和 GstRTSPThreadPool
。
GstRTSPSessionPool
是一个跟踪服务器中所有活动会话的对象。通常会为每个为某个媒体流执行设置请求的客户机保留一个会话。它包含客户端与服务器协商以接收特定流的配置,即UDP使用的传输和端口对以及流的状态。会话池的默认实现通常就足够了,但服务器可以使用替代实现。
GstRTSPMountPoints
对象更有趣,在服务器对象有用之前需要更多的配置。此对象管理从请求URL到特定流的映射及其配置。我们将在下一个主题中解释如何配置此对象。
GstRTSPAuth
是对用户进行身份验证并授权用户执行的操作的对象。默认情况下,服务器没有 GstRTSPAuth
对象,因此不会尝试执行任何身份验证或授权。
GstRTSPThreadPool
管理用于客户端连接和媒体管道的线程。服务器有一个线程池的默认实现,在大多数情况下应该足够了。
3. 创建 url 装载点
接下来,我们需要定义什么媒体附加到特定的URL。我们想要实现的是,当用户向我们的服务器请求一个特定的URL时,比如说/test,我们就创建(或重用)一个GStreamer管道来生成一个或多个RTP流。
可以创建此类管道的对象称为 GstRTSPMediaFactory
对象。GstRTSPMediaFactory
的默认实现允许您使用 gst-launch
语法轻松创建 GStreamer 管道。可以创建使用不同方法构造管道的 GstRTSPMediaFactory
子类。
默认的 GstRTSPMediaFactory
可以配置一个生成顶级 bin 的 gst-launch 命令行( “(”和“)” 括住管道描述强制使用顶级 GstBin
,而不是默认的 GstPipeline
顶级元素)。管道描述应该包含名为 payN
的元素,每个流对应一个元素(例如 pay0
、pay1
、…)。另外,为了增加兼容性,每个流应该有不同的负载类型,可以在payloader上配置。
下面的代码片段演示了如何创建一个媒体工厂,该工厂创建H264编码的测试视频信号的RTP提要。
GstRTSPMediaFactory *factory;
factory = gst_rtsp_media_factory_new ();
gst_rtsp_media_factory_set_launch (factory,
"( videotestsrc ! x264enc ! rtph264pay pt=96 name=pay0 )");
现在我们已经有了媒体工厂,我们可以将它附加到一个特定的 url。为此,我们从服务器获取默认GSTRTSPMootPoints
,并将 url 添加到工厂装载点,如下所示:
GstRTSPMountPoints *mounts;
...create server..create factory..
/* get the default mount points from the server */
mounts = gst_rtsp_server_get_mount_points (server);
/* attach the video test signal to the "/test" URL */
gst_rtsp_mount_points_add_factory (mounts, "/test", factory);
g_object_unref (mounts);
现在启动服务器并将RTP客户端定向到URL时(与vlc、mplayer 或 gstreamer 类似):
rtsp://localhost:8554/test
测试信号将流式传输到客户端。完整的示例代码可以在 examples/test-readme.c
文件中找到。
请注意,默认情况下,工厂将为每个客户机创建一个新管道。如果要在客户端之间共享管道,请使用 gst_rtsp_media_factory_set_shared()
。
4. 更多关于 GstRTSPMediaFactory 的信息
GstRTSPMediaFactory
负责创建和缓存 GstRTSPMedia
对象。
刚从工厂创建的 GstRTSPMedia
对象最初只包含一个 GstElement
,其中包含了一个元素用于产生媒体的 RTP 流和描述 payloader 和它的 source pad 的 GstRTSPStream 对象的一个 GPtrArray
通常,url将决定应该创建哪种管道。例如,您可以使用查询参数来配置管道的某些部分,或者基于某些url模式选择编码器和付费加载程序。
当处理来自例如网络摄像头的实时流时,与多个客户机共享管道可能会很有趣。当一次只能使用一个视频捕获元素实例时,必须执行此操作。在这种情况下,必须使用 GstRTSPMedia
的 shared
属性来指示默认的 GstRTSPMediaFactory
实现缓存媒体。
当从工厂创建的所有对象都可以共享时,可以直接在工厂上设置共享特性。
5. 更多关于 GstRTSPMedia 的信息
从工厂创建 GstRTSPMedia
对象后,可以使用 gst_rtsp_media_prepare()
进行准备。此方法将把这些对象放在 GstPipeline
中,并构造和链接流元素和rtpbin会话管理器对象。
然后,_prepare()
方法将预滚管道,以计算付费加载程序的上限。在 GstRTSPMedia
预滚之后,它将处于 prepared
状态,可以用于创建 SDP 文件或流式传输到客户端。
prepare
方法还将为每个流创建2个UDP端口,用于从客户端发送和接收 RTP/RTCP。这些端口号必须在安装请求中与客户端协商。
在准备 GstRTSPMedia
时,还会构造一个 appsink
和 asppsrc
,以便在请求时通过 TCP 流传输流。
当从客户机接收到描述或设置请求时,服务器准备介质。
6. GstRTSPClient 对象
当服务器在其端口上检测到新的客户端连接时,它将接受该连接,检查是否允许该连接,然后调用 vmethod(注:虚方法) create_client
。此函数的默认实现将创建一个新的 GstRTCPClient
对象,并在其中配置会话池、装入点、身份验证和线程池对象。
然后,服务器将把新的客户机连接到服务器主循环,让它处理与客户机的进一步通信。在RTSP中,通常在多个RTSP请求之间保持连接打开。当接收到新的GstRTSPMessage
时,服务器 mainloop 将调度客户机监视,然后处理该消息并发送响应。
只要客户机与服务器的 TCP 连接打开,GstRTSPClient
对象就会保持活动状态。由于客户端可以打开和关闭请求之间的 TCP 连接,因此无法将与已配置的 RTSP 会话相关的状态存储在 GstRTSPClient
对象中。此服务器状态存储在 GstRTSPSession
对象中,由会话 id 标识。
7. GstRTSPSession
此对象包含有关用会话 id 标识的特定 RTSP 会话的状态。此状态包含已配置的流及其关联的传输。
当 GstRTSPClient
执行安装请求时,服务器将从 GstRTSPSessionPool
中分配一个具有唯一会话 id 的新GstRTSPSession
。池维护所有现有会话的列表,并确保没有会话id被多次使用。会话id被发送到客户端,以便客户端可以通过在进一步请求中发送会话id来引用其先前配置的状态。
然后,客户机将使用会话id来配置一个或多个 GstRTSPSessionMedia
对象,由它们的url标识。此SessionMedia对象包含GstRTSPMedia及其配置的GstRTSPStreamTransport的配置。
8. GstRTSPSessionMedia 和 GstRTSPStreamTransport
GstRTSPSession
媒体由 URL 标识,并由 GstRTSPSession
引用。一旦客户机对特定URL执行设置操作,就会创建该 URL。它将包含一个指向与 URL关联的GstRTSPMedia
对象的链接,以及媒体的状态和为媒体中的每个流配置的传输。
客户端执行的每个设置请求都将配置一个由 GstRTSPSessionMedia
结构链接到的 GstRTSPStreamTransport
对象。它将包含将此流发送到客户端所需的传输信息。GstRTSPStream
传输还包含到 GstRTSPStream
对象的链接,该对象生成要流式传输到客户端的实际数据。
注意 GstRTSPMedia
和 GstRTSPStream
(数据流的提供者)是如何与 GstRTSPSessionMedia
和GstRTSPStreamTransport
(如何将此流发送到客户端的配置)分离的,以便能够将一个 GstRTSPMedia
的数据发送到多个客户端。
9. 媒体控制
在客户机为 GstRTSPMedia
及其 gstrtsp
流配置传输之后,客户机可以播放/暂停/停止流。
GstRTSPMedia
对象是在 DESCRIBE
调用中准备的(或者在安装过程中,当客户端跳过 DESCRIBE
请求时)。如前所述,这配置了两个 udpsink 和 udpsrc 元素,分别向客户端发送和接收媒体。
当客户端执行播放请求时,其配置的目标 UDP 端口将添加到 GstRTSPStream
目标目标,此时数据将发送到客户端。如果尚未将相应的 GstRTSPMedia
对象设置为播放状态,则该对象将被设置为播放状态,以便将数据发送到目的地。
服务器需要在播放响应中准备一个 RTP-Info header
字段,该字段由下一个 RTP 包的序列号和 RTP 时间戳组成。为了实现这一点,服务器在预卷管道时向付费加载程序查询此信息。
当客户端执行暂停请求时,将从 GstRTSPStream
对象中删除目标 UDP 端口,并且如果不再配置其他目标,则将 GstRTSPMedia
对象设置为暂停。
10. 查找(seek)
当客户端在播放请求中发送范围报头时,执行查找。这只适用于不处理共享(实时)流的情况。
服务器在媒体上执行 GStreamer 刷新查找,等待管道再次预卷(preroll),然后在从付费加载程序收集新的 RTP 序列号和时间戳后响应客户端。
11. 会话管理
服务器必须对由于网络问题或其他原因而突然消失的客户机做出反应。它需要确保当客户端似乎不在时,它可以合理地释放用于流式处理的各种对象所使用的资源。
因此,由 GstRTSPSession
池管理的每个 GstRTSPSession
对象都有一个 last_access
字段,其中包含上次记录客户端活动的时间戳。
检测来自客户端的活动有多种方法:
- RTSP keepalive 请求。当客户端接收到 RTP 数据时,RTSP-TCP 连接基本上没有使用。客户机负责通过 TCP 通道定期发送 keep-alive 请求。
每当服务器收到 keep-alive 请求(任何包含会话id的请求,通常是OPTION
或GET_PARAMETER
请求)时会话的最后一次访问已更新。 - 由于流式传输时客户端不需要保持 RTSP TCP 连接打开,因此
gst-rtsp-server
还通过查看接收到的 RTCP 消息来检测来自客户端的活动。
当从客户机接收到 RTCP 消息时,如果此消息源于GstRTSPSession
中当前处于活动状态的已知主机/端口对,则服务器将查找其活动端口列表。如果是这种情况,会话将保持活动状态。
由于服务器不知道客户端将用来发送RTCP的端口号,因此此方法并不总是有效的。稍后的 RTSP RFCs 将支持与服务器协商此端口号。然而,大多数客户端使用相同的端口号来发送和接收 RTCP 正是出于这个原因。
如果某个会话长时间没有活动(默认为60秒),应用程序应该从池中删除该会话。为此,应用程序应该定期(比如每2秒)检查是否没有会话过期,并调用 gst_rtsp_session_pool_cleanup()
来删除它们。
当会话从 sessionpool 中删除并且其最后一个引用未被恢复时,所有相关的对象和媒体都会被销毁,就好像从客户端发生了一次拆卸一样。
12. 拆卸
拆卸请求将首先找到 URL 的 GstRTSPSessionMedia
。然后,它将从流中删除所有传输,确保流停止到客户端。然后它将删除 GstRTSPSessionMedia
和 GstRTSPStreamTransport
对象。最后,GstRTSPSession
被释放回池中。
当不再有对 GstRTSPMedia
的引用时,媒体管道将被关闭(处于_unprepare 状态)并销毁。这也会破坏 GstRTSPStream
对象。
13. 安全
服务器和策略的安全性在 GstRTSPAuth
对象中实现。该对象负责:
- 验证服务器的用户。
- 检查当前用户是否有权执行操作。
对于关键操作,服务器将使用描述应验证的操作的字符串调用 gst_rtsp_auth_check()
。然后,安装的 GstRTSPAuth
对象负责检查是否允许该操作。
GstRTSPAuth
对象的实现可以使用 rtsp 服务器的以下基础结构位来实现这些检查:
GstRTSPToken
:描述授予用户的角色和权限的通用结构。GstRTSPPermissions
:角色和匹配权限的通用列表。这些可以连接到媒体和工厂目前。
Auth 实现通常会使用诸如基本身份验证或客户机证书之类的方法对用户进行身份验证,或者可能只是简单地使用 IP 地址。用户身份验证的结果将是一个 GstRTSPToken
,该 GstRTSPToken
在当前请求的上下文中成为当前的。
然后,auth 模块可以通过查看当前令牌来实现服务器中的各种检查,如果需要,还可以将其与当前对象所需的 GstRTSPPermissions
进行比较。
通过 GstRTSPAuth
对象的默认实现故意将安全性保持为通用的,提供了一个可用且简单的实现。为了创建更复杂的安全模块,应该对 auth 对象进行子类化,并且需要为检查执行新的实现。
14. 对象
对象 | 说明 |
---|---|
GstRTSPServer | 顶级对象侦听连接并创建新的GstRTSPClient对象。 |
GstRTSPClient | 处理来自已连接客户端的RTSP请求。所有其他对象被这个对象调用。 |
GstRTSPContext | 包含请求当前状态的Helper结构由客户处理。 |
GstRTSPMountPoints | 将 url 映射到GstRTSPMediaFactory实现。默认值实现使用一个简单的哈希表将 url 映射到工厂。 |
GstRTSPMediaFactory | 创建和缓存GstRTSPMedia对象。默认实现可以基于gst启动语法创建GstRTSPMedia对象。 |
GstRTSPMediaFactoryURI | 专门的GstRTSPMediaFactory,可以流式传输任何 URI。 |
GstRTSPMedia | 包含媒体管道和各种GstRTSPStream的对象生成RTP数据包的对象。 |
GstRTSPStream | 管理元素以将GstRTSPMedia流传输到一个或多个更多的gstrtsp流传输。 |
GstRTSPSessionPool | 创建和管理由id标识的GstRTSPSession对象。 |
GstRTSPSession | 包含所管理的各种GstRTSPSessionMedia对象的对象在这次会议之前。 |
GstRTSPSessionMedia | gstrtsp媒体的状态和gstrtsp流的配置物体。GstRTSPStream的配置存储在GstRTSPStreamTransport对象。 |
GstRTSPStreamTransport | 如何将GstRTSPStream发送到特定客户端的配置。它包含在安装程序中与客户端协商的传输请求。 |
GstRTSPSDP | 用于从gstRTSPMedia创建SDP消息的帮助程序函数。 |
GstRTSPAddressPool | 流媒体中使用的多播和单播地址池。 |
GstRTSPThreadPool | 用于各种服务器任务的线程池,例如处理客户端和管理媒体管道。 |
GstRTSPAuth | 用于检查授权的钩子,所有客户端活动都将调用此钩子具有GstRTSPContext结构的对象。默认情况下,它支持基本身份验证。 |
GstRTSPToken | 用户的凭据。这与允许用户的角色相反承担用户的权限或能力。 |
GstRTSPPermissions | -每个角色的权限列表。权限通常是附加的以对象来描述哪些角色具有哪些权限。 |
GstRTSPParams | 对象来处理获取和设置参数请求。 |