<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=us-ascii"><meta name=Generator content="Microsoft Word 14 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
{font-family:Helvetica;
panose-1:2 11 6 4 2 2 2 2 2 4;}
@font-face
{font-family:Helvetica;
panose-1:2 11 6 4 2 2 2 2 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:Tahoma;
panose-1:2 11 6 4 3 5 4 4 2 4;}
@font-face
{font-family:Consolas;
panose-1:2 11 6 9 2 2 4 3 2 4;}
@font-face
{font-family:"Trebuchet MS";
panose-1:2 11 6 3 2 2 2 2 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
margin-bottom:.0001pt;
font-size:12.0pt;
font-family:"Times New Roman","serif";}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:purple;
text-decoration:underline;}
span.apple-tab-span
{mso-style-name:apple-tab-span;}
span.apple-style-span
{mso-style-name:apple-style-span;}
span.EmailStyle19
{mso-style-type:personal-reply;
font-family:"Calibri","sans-serif";
color:#1F497D;}
.MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]--></head><body lang=EN-US link=blue vlink=purple><div class=WordSection1><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>I happen to use the following data class because I want to hang onto a few items.<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas;color:green'> //Call back instance and session pointer container.</span><span style='font-size:9.5pt;font-family:Consolas'><o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> <span style='color:blue'>class</span> MVSRTSPClient;<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> <span style='color:blue'>class</span> MVSClientData<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> {<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> <span style='color:blue'>public</span>:<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> MVSClientData(MVSRTSPClient* instancePtr, MediaSubsession* subsessionPtr) <o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> : instancePtr_(instancePtr),<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> subsessionPtr_(subsessionPtr){}<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> MVSRTSPClient* instancePtr_;<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> MediaSubsession* subsessionPtr_;<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> };<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'>Then I just cast it when I get called back<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'>Ie<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas;color:blue'>void</span><span style='font-size:9.5pt;font-family:Consolas'> callbackSubsessionAfterPLAYING(<span style='color:blue'>void</span>* vclient)<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> {<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> boost::mutex::scoped_lock lock(MVS::CMVSRTSPClient::AFTERPlayMutex_);<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> <span style='color:green'>// Begin by closing this media subsession's stream:</span><o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> MVSClientData* client = (MVSClientData*) vclient;<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> MediaSubsession* subsession = (MediaSubsession*)client->subsessionPtr_;<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> Medium::close(subsession->sink);<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> subsession->sink = NULL;<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> <span style='color:green'>// Next, check whether *all* subsessions' streams have now been closed:</span><o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> MediaSession& session = subsession->parentSession();<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> MediaSubsessionIterator iter(session);<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> <span style='color:blue'>while</span> ((subsession = iter.next()) != NULL) {<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> <span style='color:blue'>if</span> (subsession->sink != NULL) <span style='color:blue'>return</span>; <span style='color:green'>// this subsession is still active</span><o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> }<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> <span style='color:green'>// All subsessions' streams have now been closed</span><o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> MVSRTSPClient* mySelf = (MVSRTSPClient*) client->instancePtr_;<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> mySelf->sessionAfterPlaying();<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'> }<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'>The locking is because I have many instances and many threads<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.5pt;font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><div><div style='border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in'><p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Tahoma","sans-serif"'>From:</span></b><span style='font-size:10.0pt;font-family:"Tahoma","sans-serif"'> live-devel-bounces@ns.live555.com [mailto:live-devel-bounces@ns.live555.com] <b>On Behalf Of </b>Ross Finlayson<br><b>Sent:</b> Friday, December 09, 2011 10:41 AM<br><b>To:</b> LIVE555 Streaming Media - development & use<br><b>Subject:</b> Re: [Live-devel] Stop specific streams.<o:p></o:p></span></p></div></div><p class=MsoNormal><o:p> </o:p></p><div><blockquote style='margin-top:5.0pt;margin-bottom:5.0pt'><div><p class=MsoNormal><span style='font-family:"Trebuchet MS","sans-serif";color:#005080'>So I am trying to create a event trigger, but I am unsure on how to proceed. The taskScheduler->createEventTrigger() function expects a taskFunc object and I am not sure what this is.</span><o:p></o:p></p></div></blockquote><div><p class=MsoNormal><o:p> </o:p></p></div><p class=MsoNormal>It's quite simple. It's this:<o:p></o:p></p></div><div><p class=MsoNormal><span class=apple-tab-span> </span>typedef void TaskFunc(void* clientData); <o:p></o:p></p></div><div><p class=MsoNormal>I.e., it's a void function that takes a "void*" as argument.<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><blockquote style='margin-top:5.0pt;margin-bottom:5.0pt'><div><p class=MsoNormal><span style='color:black'> </span><span style='font-family:"Trebuchet MS","sans-serif";color:#005080'>Is it similar to a callback?</span><o:p></o:p></p></div></blockquote><div><p class=MsoNormal><o:p> </o:p></p></div><p class=MsoNormal>Yes, but it's 'called back' from within the event loop, when the event is 'triggered'.<o:p></o:p></p></div><div><p class=MsoNormal><br><br><o:p></o:p></p><div><p class=MsoNormal><span style='font-family:"Trebuchet MS","sans-serif";color:#005080'>If so, how do I cast my function do a taskFunc object? I currently having something like this, which is way off:</span><o:p></o:p></p><p class=MsoNormal> <o:p></o:p></p><p class=MsoNormal><span style='font-family:"Trebuchet MS","sans-serif";color:#005080'>void killStream() {};</span><o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><p class=MsoNormal>"kilStream()" needs a single void* parameter. Don't you want to specify a specific stream that you want to 'kill'? If so, then you can use that as your parameter (cast it to a void*) when you later call "triggerEvent()".<o:p></o:p></p></div><div><p class=MsoNormal> <br><br><o:p></o:p></p><div><p class=MsoNormal><span style='font-family:"Trebuchet MS","sans-serif";color:#005080'>taskSched->createEventTrigger(&killstream);</span><o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><p class=MsoNormal>Yes, but you'll need to remember the result "EventTriggerId" of this call, so you can later use it in your call to "triggerEvent()".<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>If you're still unsure about how to use event triggers, then you can see an example in "liveMedia/DeviceSource.cpp".<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal><br><br><o:p></o:p></p><div><p class=MsoNormal> <span class=apple-style-span><span style='font-family:"Trebuchet MS","sans-serif";color:#005080'>I am also still unsure about the mechanisms for actually stopping the streams.</span></span><o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><p class=MsoNormal>OK, this is a completely different question.<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>To remove (and delete) a "ServerMediaSession" object from the server, simply call <o:p></o:p></p></div><div><p class=MsoNormal><span class=apple-tab-span> </span>RTSPServer::removeServerMediaSession()<o:p></o:p></p></div><div><p class=MsoNormal>***Do not*** call "Medium::close()" on the "ServerMediaSession" object; that is done automatically by "removeServerMediaSession()". Note, however, that although this will prevent any future clients from accessing this stream, it will not stop any streaming that's current ongoing for this "ServerMediaSession". If you want to do that, you would need to delete the "RTSPServer::RTSPClientSession" object for each currently active client. (This has the same effect as the client having done a RTSP "TEARDOWN".)<o:p></o:p></p></div><p class=MsoNormal style='margin-bottom:12.0pt'><o:p> </o:p></p><div><p class=MsoNormal><span class=apple-style-span><span style='font-size:13.5pt;font-family:"Helvetica","sans-serif";color:black'>Ross Finlayson</span></span><span style='font-size:13.5pt;font-family:"Helvetica","sans-serif";color:black'><br><span class=apple-style-span>Live Networks, Inc.</span><br><span class=apple-style-span><a href="http://www.live555.com/">http://www.live555.com/</a></span></span> <o:p></o:p></p></div><p class=MsoNormal><o:p> </o:p></p></div></body></html>