在Linux裡,我們可以透過signal()於程式中設立處理常式(signal handler),於對應之處理常式中,我們將可正確地停止RTSP伺服器。
在live55裡,<RTSPServer>、<ServerMediaSession>、<ServerMediaSubSession>都是<Medium>的子類別。由於Medium類別之解構子被宣告為protected,所以Medium物件之回收無法直接由delete運算子處理,必須經由Medium類別提供之close()釋放。這樣的手法,在live555裡隨處可見。
class Medium {
public:
static Boolean lookupByName(UsageEnvironment& env,
char const* mediumName,
Medium*& resultMedium);
static void close(UsageEnvironment& env, char const* mediumName);
static void close(Medium* medium); // alternative close() method using ptrs
// (has no effect if medium == NULL)
UsageEnvironment& envir() const {return fEnviron;}
char const* name() const {return fMediumName;}
// Test for specific types of media:
virtual Boolean isSource() const;
virtual Boolean isSink() const;
virtual Boolean isRTCPInstance() const;
virtual Boolean isRTSPClient() const;
virtual Boolean isRTSPServer() const;
virtual Boolean isMediaSession() const;
virtual Boolean isServerMediaSession() const;
virtual Boolean isDarwinInjector() const;
protected:
Medium(UsageEnvironment& env); // abstract base class
virtual ~Medium(); // instances are deleted using close() only
TaskToken& nextTask() {
return fNextTask;
}
private:
friend class MediaLookupTable;
UsageEnvironment& fEnviron;
char fMediumName[mediumNameMaxLen];
TaskToken fNextTask;
};
目前live55採取event loop驅動的模式。當程式初始化完畢,進入event loop開始運作時,除非發生例外事件,否則將不會輕易離開event loop。若要取得event loop控制權,必須在進入迴圈時就設立變數,並透過該變數中斷event loop。
class TaskScheduler {
... ... ...
virtual void doEventLoop(char* watchVariable = NULL) = 0;
// Causes further execution to take place within the event loop.
// Delayed tasks, background I/O handling,
// and other events are handled, sequentially (as a single thread of control).
// (If "watchVariable" is not NULL,
// then we return from this routine when *watchVariable != 0)
... ... ...
};
程式範例:
#include <signal.h>
#include <livemedia.hh>
#include <basicusageenvironment.hh>
static char stopEventLoop = 0;
static RTSPServer* rtspServer = NULL;
static UsageEnvironment* env = NULL;
static void announceStream(RTSPServer* rtspServer, ServerMediaSession* sms,
char const* streamName, char const* inputFileName);
static void handleSignal(int);
int main(int argc, char** argv)
{
TaskScheduler* scheduler = BasicTaskScheduler::createNew();
env = BasicUsageEnvironment::createNew(*scheduler);
// 1. Create the RTSP server:
rtspServer = RTSPServer::createNew(*env, 8554, NULL);
if (rtspServer == NULL) {
*env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";
exit(1);
}
// 2. Add a H.264 video elementary stream to RTSP server
{
char const* streamName = "h264";
char const* inputFileName = "test.h264";
ServerMediaSession* sms =
ServerMediaSession::createNew(*env,
streamName, streamName,
"H.264 video");
sms->addSubsession(
H264VideoFileServerMediaSubsession::createNew(*env,
inputFileName, False));
rtspServer->addServerMediaSession(sms);
announceStream(rtspServer, sms, streamName, inputFileName);
}
signal(SIGINT, handleSignal);
*env << "Press Ctrl+C to stop RTSP server\n";
// 3. Kick-off the server
env->taskScheduler().doEventLoop(&stopEventLoop);
*env << "RTSP server stops\n";
env->reclaim();
delete scheduler;
return 0;
}
static void announceStream(RTSPServer* rtspServer, ServerMediaSession* sms,
char const* streamName, char const* inputFileName)
{
char* url = rtspServer->rtspURL(sms);
*env << "\n\"" << streamName << "\" stream, from the file \""
<< inputFileName << "\"\n";
*env << "Play this stream using the URL \"" << url << "\"\n";
delete[] url;
}
static void handleSignal(int)
{
*env << "SIGINT received\n";
Medium::close(rtspServer);
stopEventLoop = 1;
}
執行結果:$ ./h264RtspServer "h264" stream, from the file "test.h264" Play this stream using the URL "rtsp://192.168.11.111:8554/h264" Press Ctrl+C to stop RTSP server ^CSIGINT received RTSP server stops $有時妥善的管理程式資源需要多花費一些心力,但是可以確保伺服器長久運行無誤。live555是一個優秀的開放原始碼專案,可惜文件有限,所以有時需要追蹤其原始碼,整這個過程可以讓我們更加瞭解其設計架構及理念。
Hello sir,
ReplyDeleteI used your idea but my server crashes at the line Medium::close(rtspServer);,some heap corrouption message is displayed
you can check my code here http://stackoverflow.com/questions/14337755/how-to-create-and-destroy-rtsp-server-again-and-again-live-555
ReplyDeleteHi if i wan to pass live stream as an input where you have pass test.h264 as input filename then what i have to do ? Can u plz guide me ?
ReplyDelete