[Live-devel] Remove a session...
Raphaël KINDT
raphael.kindt at seldes.com
Fri Apr 11 07:06:07 PDT 2008
Hello Ross,
What are the situations where DynamicRTSPServer is usefull to use?
How to wake up env->taskScheduler().doEventLoop(&watch_scheduler) when
no server media session is added?
The loop is waiting at a 'select()' call and thus doesn't check my
watch_scheduler.
To do that I must be able to wake this 'select()' instruction...
In short, how to stop the server gracefully when no streaming has been
performed?
I've some difficulty to add and remove session properly. Sometimes the
server crashes because I've a memory violation.
I can show remote video with VLC. But when I remove a session, the server
crashes (sometimes, with or without a connected VLC client)...
I do my best to understand the LIVE library but it's not very easy...
Below I send you a part of my test code.
The class SeldesJPEGVideoSource is derived from JPEGVideoSource.
This class reads some JPEG files to simulate video (all JPEG files are saved
into the RAM for the video simulation).
The struct I used for my test:
typedef struct _sessionState_t
{
FramedSource* source;
RTPSink* sink;
RTCPInstance* rtcpInstance;
Groupsock* rtpGroupsock;
Groupsock* rtcpGroupsock;
ServerMediaSession * sms;
} sessionState_t;
typedef std::map<std::string, sessionState_t> sessions_map_t;
typedef sessions_map_t::iterator sessions_map_it;
sessions_map_t sessionMap;
... and some other global variable ...
The thread that executes the scheduler:
DWORD WINAPI Scheduler(LPVOID pParam)
{
// Begin by setting up our usage environment:
TaskScheduler* scheduler = BasicTaskScheduler::createNew();
env = BasicUsageEnvironment::createNew(*scheduler);
// Allow for up to 100 RTP packets per JPEG frame
//OutPacketBuffer::numPacketsLimit = 100;
OutPacketBuffer::maxSize = MAX_BUFFER_SIZE;
timePerFrame = 1000000 / fps; // microseconds
averageFrameSizeInBytes = 35000; // estimate
totalSessionBandwidth = (8 * 1000 * averageFrameSizeInBytes) /
timePerFrame; // in kbps
//gethostname((char*)CNAME, maxCNAMElen);
sprintf((char*)CNAME, "Seldes camera"); // "gethostname()" isn't
supported
CNAME[maxCNAMElen] = '\0'; // just in case
rtpPortNum = 2222;
rtcpPortNum = rtpPortNum+1;
ttl = 255; // time to live (for client buffer)
// Create and start a RTSP server to serve this stream:
UserAuthenticationDatabase* authDB = NULL;
rtspServer = RTSPServer::createNew(*env, 7070, authDB);
if (rtspServer == NULL)
{
*env << "Failed to create RTSP server: " << env->getResultMsg() <<
"\n";
exit(1);
}
//---------------------------------------------------
env->taskScheduler().doEventLoop(&watch_scheduler);
//---------------------------------------------------
sessions_map_it it;
for(it = sessionMap.begin(); it != sessionMap.end(); ++it)
{
RemoveSession(it->first);
sessionMap.erase(it++);
}
Medium::close(rtspServer);
delete scheduler;
env->reclaim();
return true;
}
To add a session (called by another thread):
bool AddSession(const std::string & _session_name)
{
// verifie si la session existe deja
sessions_map_it it;
for(it = sessionMap.begin(); it != sessionMap.end(); ++it)
{
if(it->first == _session_name)
{
std::cout << "This session already exist...\n";
return false;
}
}
// Create 'groupsocks' for RTP and RTCP:
struct in_addr destinationAddress;
destinationAddress.s_addr = chooseRandomIPv4SSMAddress(*env);
const Port rtpPort(rtpPortNum);
const Port rtcpPort(rtcpPortNum);
sessionMap[_session_name].rtpGroupsock = new Groupsock(*env,
destinationAddress, rtpPort, ttl);
sessionMap[_session_name].rtpGroupsock->multicastSendOnly();
sessionMap[_session_name].rtcpGroupsock = new Groupsock(*env,
destinationAddress, rtcpPort, ttl);
sessionMap[_session_name].rtcpGroupsock->multicastSendOnly();
// Create an appropriate RTP sink from the RTP 'groupsock':
sessionMap[_session_name].sink = JPEGVideoRTPSink::createNew(*env,
sessionMap[_session_name].rtpGroupsock);
// Create (and start) a 'RTCP instance' for this RTP sink:
sessionMap[_session_name].rtcpInstance = RTCPInstance::createNew(
*env,
sessionMap[_session_name].rtcpGroupsock,
totalSessionBandwidth,
CNAME,
sessionMap[_session_name].sink,
NULL /* we're a server */,
True /* we're a SSM source*/);
// Note: This starts RTCP running automatically
sessionMap[_session_name].sms = ServerMediaSession::createNew(
*env,
_session_name.c_str(),
progName,
"Session streamed by the Seldes camera 1",
True/*SSM*/);
sessionMap[_session_name].sms->addSubsession(PassiveServerMediaSubsession::c
reateNew(*sessionMap[_session_name].sink,
sessionMap[_session_name].rtcpInstance));
rtspServer->addServerMediaSession(sessionMap[_session_name].sms);
announceStream(rtspServer, sessionMap[_session_name].sms,
_session_name.c_str());
// Open the Seldes camera:
sessionMap[_session_name].source =
SeldesJPEGVideoSource::createNew(*env, timePerFrame, _session_name);
if (sessionMap[_session_name].source == NULL)
{
*env << "Unable to open Seldes camera: " << env->getResultMsg() <<
"\n";
exit(1);
}
// Finally, start the streaming:
*env << "\nBeginning streaming...\n";
sessionMap[_session_name].sink->startPlaying(*sessionMap[_session_name].sour
ce, afterPlaying, &sessionMap[_session_name]);
return true;
}
To close a session (called by another thread):
bool RemoveSession(const std::string & _session_name)
{
sessionMap[_session_name].sink->stopPlaying();// important sinon bug
dans startplaying au reboot du server
sessionMap[_session_name].source->stopGettingFrames();
rtspServer->removeServerMediaSession(sessionMap[_session_name].sms);
Medium::close(sessionMap[_session_name].sink);
Medium::close(sessionMap[_session_name].source);
Medium::close(sessionMap[_session_name].rtcpInstance);
delete sessionMap[_session_name].rtpGroupsock;
delete sessionMap[_session_name].rtcpGroupsock;
std::cout << "Session \"" << _session_name << "\" removed...\n";
return true;
}
Quickly... Do you found mistakes?
Sorry for this long mail.
Thanks for your help.
------------------------------
Ing. KINDT Raphaël Software R&D Manager
Rue des Bleuets, 1b E-Mail : raphael.kindt at seldes.com
B-7000 Mons (Belgium) Phone : +32 (0)65 352 252
Web site: www.seldes.com Fax : +32 (0)65 352 253
More information about the live-devel
mailing list