【问题标题】:Live555 - Proper client shutdown with watchVariableLive555 - 使用 watchVariable 正确关闭客户端
【发布时间】:2016-10-15 16:25:37
【问题描述】:

我目前面临 live555 的问题。

我为我的项目编写了一个 Windows DLL,这个 DLL 公开了一个非常简单的 API 来轻松启动一个 RTSP 客户端。统一程序加载 DLL,然后使用 API 接收帧。

公开的两个主要功能是:

bool startRTSP(bool isTCP);
bool stopRTSP();

由于 Live555 库的性质,我无法在统一线程中启动 RTSP。所以我在调用 startRTSP 时创建了一个新线程,并通过一些回调将帧发送到统一。

但是,为了能够从外部线程(调用 stopRTSP 的统一线程)停止 RTSP,我正在使用 eventLoopWatchVariable。例如,这是 RTSP 事件循环的启动方式:

env->taskScheduler().doEventLoop(&eventLoopWatchVariable);

当调用停止函数时,eventLoopWatchVariable 从统一线程设置为 1。 关闭事件循环。

在此事件循环退出后立即调用清理函数:

delete scheduler;
env->reclaim();

我期待这些功能通过 RTSP 客户端并关闭它们。 (例如向服务器发送 TEARDOWN 命令)

但他们显然没有,而且客户端永远不会被破坏!

我怀疑它会导致同一流出现重新连接问题。 (发送 SETUP 、 DESCRIBE 和 PLAY 命令并收到响应,但没有数据到来)使用 VLC 或 mplayer 我可以看到服务器仍在流式传输,所以这不是服务器问题。

当 eventLoopWatchVariable 设置为 1 时,我如何要求 live555 关闭 RTSPClient 及其子会话?

如果 eventLoop 不再运行,我无法将 TEARDOWN 命令发送到服务器。所以我现在对最好的方法有点迷茫。

如果有人对此有任何想法,我很想听听!

提前致谢。

【问题讨论】:

    标签: c++ multithreading rtsp live555


    【解决方案1】:

    如果 eventLoop 是,我无法将 TEARDOWN 命令发送到服务器 不再运行。

    这是不准确的,需要主循环来接收消息而不是发送消息。

    为了在主循环之后和释放环境之前正确关闭 RTSP 客户端连接,您可以这样进行:

    // wait for stop event
    env->taskScheduler().doEventLoop(&eventLoopWatchVariable);
    
    // send tear TEARDOWN
    client->sendTeardownCommand(session, NULL);
    
    // close subsession & session
    Medium::close(session);
    
    // close RTSP client
    Medium::close(client);
    
    // free environment & scheduler
    env->reclaim();
    delete scheduler;
    

    您也可以等待 TEARDOWN 应答,给 sendTeardownCommand 一个回调并再次运行 doEventLoop。

    【讨论】:

    • 从哪里获得“会话”变量?具体来自 testProgs/testRTSPClient.cpp 的 main()。我需要创建一个全局变量来访问它吗?
    【解决方案2】:

    这是完全关闭 rtsp 客户端的正确方法。此答案假定您使用以下程序作为 rtsp 客户端的基础:testProgs/testRTSPClient.cpp(与 live555 捆绑)。

    首先将 openURL() 修改为如何将“RTSPClient* rtspClient”返回给调用者。然后使用此示例(从 testRTSPClient.cpp 中的 main() 继续):

    RTSPClient* rtspClient = openURL(*env, argv[0], argv[1]);
    
    // All subsequent activity takes place within the event loop:
    env->taskScheduler().doEventLoop(&eventLoopWatchVariable);
    
    //... do whatever stuff you want to do in the background...
    
    //start this code when you want to stop the rtsp client
    eventLoopWatchVariable = 1;
    
    //run this code for each rtspClient that exists
    StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs;
    
    rtspClient->sendTeardownCommand(*scs.session, NULL);
    
    Medium::close(client->rtspClient);
    //end code segment
    
    env->reclaim();
    env = NULL;
    delete scheduler;
    scheduler = NULL;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-03
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-23
      相关资源
      最近更新 更多