[Live-devel] problems moving to asynchronous rtsp interface

Ross Finlayson finlayson at live555.com
Sat Nov 26 11:34:56 PST 2011


> 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.


> 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.


> 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.

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/284f74e0/attachment.html>


More information about the live-devel mailing list