On 17.12.2015 17:46, Ross Finlayson wrote:
I have an application that has its own event loop when manipulating/reading 
sockets, however, I'd like to use live555 to do the rtsp negotiation process 
with the cameras.
Unfortunately, I’m not quite sure what you mean when you say that your 
application “has its own event loop when manipulating/reading sockets”, because 
the LIVE555 code - when it implements RTSP/RTP/RTCP - does so by ‘reading and 
writing sockets’.  Therefore, if you want to implement RTSP/RTP/RTCP using the 
“LIVE555 Streaming Media” code, then you *must* do so using the LIVE555 event 
loop, which you will enter by calling “doEventLoop()” within your application.

Perhaps your application already has its own event loop (e.g., to implement a 
GUI)?  In that case, you *could* try to arrange for these other ‘GUI’ events to 
be handled as part of the LIVE555 event loop - i.e., so that your application 
has just a single event loop.  Most people, however, find it simpler to run all 
of the LIVE555 code (including its event loop) in a separate thread, with the 
other ‘main’ event loop thread communicating with the LIVE555 event loop thread 
via shared variables (e.g. event loop ‘watch variables’) or by calling 
“triggerEvent()” (the *only* LIVE555 function that you may call from the 
non-LIVE555 event loop thread).


I also need my own step-to-step control over the rtsp negotiation process, i.e.

1) describe+setup => port numbers
(do something within my own event loop)
2) play
(do something within my own event loop)
3) teardown
(do something within my own event loop)
This is easy to do - except that instead of doing ‘something’ within your ‘own' 
event loop, you will do it within the LIVE555 event loop.  Note that each 
LIVE555 function that implements the sending of a RTSP command - i.e., 
“sendDescribeCommand()”, “sendSetupCommand()”, “sendPlayCommand()” etc. - 
takes, as a parameter, a function that will get called, automatically (by the 
LIVE555 event loop), after the RTSP command has completed.  It is within this 
function that you would do your ‘something’ in each case.

Dear Ross,

Thank you for your reply. The long story is, that I have my own program having its own event loop, with simultaneous select calls on sockets, multiprocessing pipes, etc.

In the future, I will migrate my code into using live555, but I can't do it in one shot..! (always been a bit slow learner..)

At the moment I'd like to use the live555 rtsp implementation to do the authentication and negotiation part.. after getting the port numbers, I will open the sockets for udp streaming myself and use my own existing code..

.. yes, sounds stupid, but that is the fix for the moment (my own rtsp negotiation code fails with some cameras needing stronger authentication methods.. and I don't want to reinvent the wheel (once) again).. as I'll learn more live555, I'll do the (semi/complete) migration to it.

1) I understand that in the rtsp "response handlers" and in the callbacks within them, we 
create the necessary logic, but how does the program actually run?  .. does the event loop 
explicitly execute the "response handlers"..? where in the code this takes place?
All of this (the LIVE555 event loop) takes place inside the call to 
“doEventLoop()”; see
        http://live555.com/liveMedia/faq.html#control-flow
The LIVE555 code handles each RTSP response by handling a ‘new data is 
available’ event on the RTSP command socket.  In doing so, it will read and 
parse the RTSP response, and call the appropriate ‘response handler’.  It does 
all of this automatically (within the LIVE555 event loop), and you don’t need 
to concern yourself with how this is implemented (i.e., you should treat the 
LIVE555 libraries as being a ‘black box’).

Thanks for the explanation..! Let's see if I have understood correctly by looking at the "testRTSPClient.cpp:" intendation means entering a function/method

main:

  => openURL

    => rtspClient->sendDescribeCommand(continueAfterDESCRIBE) [1]
=> continueAfterDESCRIBE(rtspClient,..): setupNextSubSession(rtspClient) [2] => rtspClient->sendSetupCommand(*scs.subsession, continueAfterSETUP, ..) [3]
          => continueAfterSETUP(rtspClient,..): [4]
=> scs.subsession->sink = DummySink::createNew(env, *scs.subsession, rtspClient->url()); => scs.subsession->sink->startPlaying(*(scs.subsession->readSource()), subsessionAfterPlaying, scs.subsession); => rtspClient->sendPlayCommand(*scs.session, continueAfterPLAY, ..) [5]

  => start the event loop [6]

Also, let's keep in mind:

rtspClient->envir() gives the UsageEnvironment
rtspClient->envir()->taskScheduler() gives the taskScheduler

[1] registers a command to the event loop. The method is found in "RTSPClient.cpp":

sendDescribeCommand(responseHandler* responseHandler, Authenticator* authenticator) return sendRequest(new RequestRecord(++fCSeq, "DESCRIBE", responseHandler));

[2] does not register anything to the event loop, but simply sets up a logic with the callback functions

etc.

[6] event loop executes the first command that has been registered (somehow.. with "RequestRecord" ?) into it .. which results in a cascade execution of the callback functions, i.e. "continueAfterDESCRIBE", etc.

The next thing the event loop handles, is "sendSetupCommand"

In general, all of these "send*Command"s are registered into, and executed one by one by the event loop, while each execution goes into a cascade of callbacks.

.. ummm, right?

Could you maybe give me a clue, where in the code is the registration of events to the event loop implemented..?



3) Is there any better way to access the subsession data, other than always creating a *new* MediaSubsessionIterator 
and then using the "next()" method ?  .. iterators should have also "begin()", 
"previous()", etc. methods, but these seem to me missing in the code..?  i.e. one must create a new object 
and then, after using "next" couple of times, the object becomes useless and throwing segfaults if you try to 
access data, for example, clientPortNums.
I don’t really understand what you’re asking here, but I don’t think you 
understand how the “testRTSPClient” code (for example) works.  Note, in 
particular, how this code defines a class “StreamClientState”, which includes a 
“MediaSubsessionIterator” and a pointer to a “MediaSubsession”.  An object of 
this class is used to represent the current state of the RTSP client.  Note 
that a “MediaSubsessionIterator” is created only once (for each RTSP client).

After the rtsp negotiation, the data about the media subsessions is available .. I just wanted a way to access that data in a convenient way (and to use it outside the event loop).

Thanks for the great code.. and for your patience..!  ;)

Regards,

Sampsa



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


_______________________________________________
live-devel mailing list
live-devel@lists.live555.com
http://lists.live555.com/mailman/listinfo/live-devel

_______________________________________________
live-devel mailing list
live-devel@lists.live555.com
http://lists.live555.com/mailman/listinfo/live-devel

Reply via email to