在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