Live555 — Правильное завершение работы клиента с помощью watchVariable

#c #multithreading #rtsp #live555

#c #многопоточность #rtsp #live555

Вопрос:

В настоящее время я сталкиваюсь с проблемой с live555.

Я написал Windows DLL для своего проекта, эта DLL предоставляет очень простой API для легкого запуска RTSP-клиента. Программа Unity загружает DLL, а затем использует API для получения фреймов.

представлены две основные функции :

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

Из-за особенностей библиотеки Live555 я не могу запустить RTSP в потоке unity. Итак, я создал новый поток при вызове startRTSP , и с некоторыми обратными вызовами фреймы отправляются в unity.

Однако, чтобы иметь возможность остановить RTSP из внешнего потока (поток unity, вызывающий stopRTSP), я использую eventLoopWatchVariable . Например, так запускается цикл событий RTSP :

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

Когда вызывается функция stop , переменной eventLoopWatchVariable присваивается значение 1 из потока unity.
Завершение цикла событий.

Сразу после завершения этого цикла событий вызываются функции очистки :

 delete scheduler;
env->reclaim();
 

Я ожидал, что эта функция пройдет через RTSP-клиент и отключит их. (Например, отправка команды ДЕМОНТАЖА на сервер)

Но они явно этого не делают, и клиенты никогда не уничтожаются!

Я подозреваю, что это вызовет проблему повторного подключения к тому же потоку. (команды SETUP , DESCRIBE и PLAY отправляются, и ответы получены, но данные не поступают) Используя VLC или mplayer, я вижу, что сервер все еще работает в потоковом режиме, так что это не проблема сервера.

Как я могу попросить live555 закрыть RTSPClient и их дочерние элементы, когда eventLoopWatchVariable имеет значение 1?

Я не могу отправить команду ДЕМОНТАЖА на сервер, если eventLoop больше не выполняется. Так что я сейчас немного растерялся в отношении наилучшего способа сделать это.

Если у кого-нибудь есть идея по этому поводу, я хотел бы ее услышать!

Заранее спасибо.

Ответ №1:

Я не могу отправить команду ДЕМОНТАЖА на сервер, если eventLoop больше не выполняется.

Это неточно, основной цикл необходим для получения сообщений, а не для отправки сообщений.

Чтобы правильно закрыть клиентское соединение RTSP после основного цикла и перед выпуском среды, вы могли бы поступить следующим образом :

 // wait for stop event
env->taskScheduler().doEventLoop(amp;eventLoopWatchVariable);

// send tear TEARDOWN
client->sendTeardownCommand(session, NULL);

// close subsession amp; session
Medium::close(session);

// close RTSP client
Medium::close(client);

// free environment amp; scheduler
env->reclaim();
delete scheduler;
 

Вы также можете дождаться ответа на удаление, выполнив обратный вызов sendTeardownCommand и снова запустив doEventLoop.

Комментарии:

1. Откуда берется переменная «session»? В частности, из main() из testProgs/testRTSPClient.cpp . Нужно ли мне создавать глобальную переменную для доступа к ней?

Ответ №2:

Вот правильный способ полного завершения работы rtsp-клиента. В этом ответе предполагается, что вы используете следующую программу в качестве основы для вашего клиента rtsp: testProgs/testRTSPClient.cpp (в комплекте с live555).

Сначала измените openURL(), чтобы каким-то образом вернуть «RTSPClient* rtspClient» обратно вызывающему. Затем используйте этот пример (продолжая с main() внутри testRTSPClient.cpp ):

 RTSPClient* rtspClient = openURL(*env, argv[0], argv[1]);

// All subsequent activity takes place within the event loop:
env->taskScheduler().doEventLoop(amp;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
StreamClientStateamp; scs = ((ourRTSPClient*)rtspClient)->scs;

rtspClient->sendTeardownCommand(*scs.session, NULL);

Medium::close(client->rtspClient);
//end code segment

env->reclaim();
env = NULL;
delete scheduler;
scheduler = NULL;