[Live-devel] problems moving to asynchronous rtsp interface

Jeff Shanab jshanab at smartwire.com
Sat Nov 26 12:26:44 PST 2011



From: live-devel-bounces at ns.live555.com [mailto:live-devel-bounces at ns.live555.com] On Behalf Of Ross Finlayson
Sent: Saturday, November 26, 2011 1:35 PM
To: LIVE555 Streaming Media - development & use
Subject: Re: [Live-devel] problems moving to asynchronous rtsp interface

I just started trying to upgrade our code to use the asynchronous interface and I am a bit perplexed at the mix of C and C++.  In other libraries the callbacks generally have a void pointer to clientData or 'instance' or something like that which allows me to pass the 'this' pointer, cast it, to the class and access all the particular instances' members.  In the openRTSP and PlayCommon code I see the signatures for the callbacks are hard coded to foo(RTSPClient::responsehandler*,int,char*).

The "openRTSP.cpp"/"playCommon.cpp" code, unfortunately, does not provide the greatest example of how to use the asynchronous "RTSPClient" interface, precisely because it uses a single, global "RTSPClient*" variable (called "ourRTSPClient").  (Also, because "playCommon.cpp" shares code with a separate application called "playSIP".)

The key thing to note is that the "RTSPClient:responseHandler()" functions all have a "RTSPClient*" as their first parameter.  When the response handler gets called, its first parameter will be (a pointer to) the "RTSPClient" object that made the request.  In our "playCommon.cpp" code, the first parameter to our response handler functions ends up not being needed, because its value will - in this case - be the same as our global variable "ourRTSPClient".  In your case, however, you will want to use this first parameter, because it will tell you which particular "RTSPClient" object made the request.

>> I realized that and am working on the subclass from RTSPClient idea. Because there is a LOT of other instance data, just like in the openRTSP example, thre is a LOT of global information.  But I am finding that the RTSPClient was not really designed to be subclassed. The gotcha I have now is, although it does nothing but set values in it's constructor, I cannot instanitiate my subclass without an initializer for the RTSPClient base class, but then I cannot call setBaseURL() for example, later when I know all the info.


For example. This is what causes the ourRTSPClient in the example to be a Global variable. I need to have this as a class member variable, and perhaps do something like this....

getOptions(RTSPClient::responseHandler* afterFunc, void* clientData) {
       myClass * instancePTR = (myClass *) clientData;
              instancePTR->ourClient_->sendOptionsCommand(instancePTR, ourAuthenticator, clientData);
        }

No, this won't work, because the signature of your call to "RTSPClient::sendOptionsCommand()" is all wrong.

Instead, don't define or call a "getOptions()" function at all.  Instead just call:
            instancePTR->ourClient->sendOptionsCommand(continueAfterOPTIONS, ourAuthenticator);

And then, when the "continueAfterOPTIONS()" response handler later gets called, its first parameter will be "instancePTR->ourClient" - i.e., a "RTSPClient*".

If you need more information from this "RTSPClient*" pointer (e.g., in your case, to identify it's "myClass*" parent), then you can do so by subclassing "RTSPClient", and putting the information that you want in a subclass member field.

See above why this is difficult.



What is the best way to use these callbacks in a multi threaded (multiple UsageEnvironments) c++ program.?

You do realize, I hope, that the use of the asynchronous "RTSPClient" interface makes it even less necessary to use multiple threads.  (If you use the asynchronous interface, you can access multiple RTSP streams concurrently from a single thread (running a single event loop).)  But if you insist on using multiple threads (something that I still don't recommend, even though it's possible), you can do so provided that you use a separate "TaskScheduler" and "UsageEnvironment" for each.  Note that - if you wish - you can call "->envir()" on your response handlers' "RTSPClient*" first parameter, if you need to find out which "UsageEnvironment" - and thus which thread - it is using.

Yes but I am trying to upgrade to the newer interface without breaking everthing all at once.  Especially under the threat of impending removal!

Ross Finlayson
Live Networks, Inc.
http://www.live555.com/

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.live555.com/pipermail/live-devel/attachments/20111126/eded9e95/attachment-0001.html>


More information about the live-devel mailing list