[Live-devel] Streaming Relay

wissam.l at free.fr wissam.l at free.fr
Thu Oct 6 15:32:03 PDT 2005


Hi,

I would like to create a unicast streaming relay called Relay that launches 2
threads: one thread for a relayClient and another one for a relayServer.

I do have an streamer (a testOnDemandRTSPServer) that streams m4v files on
demand. My relayClient would be the equivalent of the openRTSP client and the
playcommon merged , and my relayServer would be the testOnDemandRTSPServer
modified in a way to support live streaming; my purpose is to get the live
stream from the streamer with my relayClient and stream it again with my
relayServer:

So basically what I do in my client is that I get the reference to freadSource
defined in the object MediaSession in this way:

***********************MediaSession**********************************
 } else if (strcmp(fCodecName, "MP4V-ES") == 0) {
        fReadSource = fRTPSource
          = MPEG4ESVideoRTPSource::createNew(env(), fRTPSocket,
                                             fRTPPayloadFormat,
                                             fRTPTimestampFrequency);
***********************MediaSession**********************************

***********************relayClient start **********************************
setupStreams();
iter.reset();
      madeProgress = False;
      while ((subsession = iter.next()) != NULL) {
        if (subsession->readSource() == NULL) continue;

          setVideoSource(subsession->readSource());
//to pass the reference to the relayserver.

          madeProgress = True;
          break;
      }
      if (!madeProgress) shutdown();
//Note that for the moment I have only one video subsession.

void * relayClient::setVideoSource(FramedSource * source){
fVideoSource=source;
}

FramedSource * relayClient::getVideoSource(){
return fVideoSource;
}
***********************relayClient end **********************************


In Relay:
-	Client is relayClient.
-	Server is relayServer.

Launch the thread relayClient  then I pass the reference freadSource to the
relayServer server:


server->setVideoSource(shr->client->getVideoSource());
server->launchServer(shr->env_server);
And I launch the thread of the serve later on.

So definetly I do have the fVideoSource reference in my relayServer as following

  {
    char const* streamName = "x";

    ServerMediaSession* sms
      = ServerMediaSession::createNew(*env1, streamName, streamName,
                                      descriptionString);

   *env1 << sms->addSubsession(MPEG4ESVideoServerMediaSubsession
                       ::createNew(*env1, reuseFirstSource,fVideoSource));
    rtspServer->addServerMediaSession(sms);
*env1 << "running...";

    announceStream(rtspServer, sms, streamName);
  }

env1->taskScheduler().doEventLoop(); // does not return
}

So then I defined my own ServerSubsession called
MPEG4ESVideoServerMediaSubsession where I can inject the  fVideoSource unstead
of the filename... (I got inspired from what have been done in 
MPEG4ESVideoFileServerMediaSubsession.)

Later on in the method createNewStreamSource I used the same reference to the
fVideoSource unstead of creating a ByteStreamFileSource* fileSource


FramedSource* MPEG4ESVideoServerMediaSubsession
::createNewStreamSource(unsigned /*clientSessionId*/, unsigned& estBitrate)
{
 estBitrate = 500;
 return MPEG4VideoStreamFramer::createNew(envir(), fVideoSource);
}

At the end when I requested the stream in question on the appropriate announced
address and port, the framed source blocks and says your are trying to read
twice on the same source
 I guess this comes from the method getNextframe in
FramedSource:

if (fIsCurrentlyAwaitingData) {
    envir() << "FramedSource[" << this << "]::getNextFrame(): attempting to read
more than once at the same time!\n";
    exit(1);
  }

But what would that mean ?

The curious thing is that the dummy source is played by the dummy sink and I can
 get the SDP lines correctly .

Knowing that if I pass the same reference fVideoSource to the code of the
testMPEG4VideoStreamer as a relayServer in the method play:

void play() {

debug(">> relayServer::setVideoSource(%p)\n",fVideoSource);
  videoSource = MPEG4VideoStreamFramer::createNew(*env1, fVideoSource);
  *env1 << "Beginning to play...\n";
  videoSink->startPlaying(*videoSource, afterPlaying, videoSink);
}

I don’t have any problem playing it except that the PassiveServerMediaSubsession
is not a good solution for me.

I would like to know if I need really in this case to write a DeviceSource class
?

Do I miss something in the method createNewStreamSource?

Any help is welcome.

Best regards.



More information about the live-devel mailing list