[Live-devel] Problem with serverMediaSubsession::createNewRTSPink method

Andrea Beoldo andrea.beoldo at technoaware.com
Thu Apr 3 08:25:39 PDT 2014


Dear support,

I have implemented a RTSP live streaming server with multiple stream 
that is used in our ONVIF server. In this server we create several 
profiles, every profile set up a live555  streaming server on different 
port (h264).
I use latest Live555 (25 march 2014).

The problem occurs in the release version when from the client switch 
from a stream to another. I don't identify exactly where the system 
crash, but it seem block after a call of 
serverMediaSubsession::createNewRTPSink. I add some log to understand 
better and I find to sometimes the system crash in the doGetNextFrame 
method.
This problem is not present in the debug version.

I tried to insert different passive wait (before calling 
createNewStreamSource(), createNewRTPSink() and deleteStream()) and the 
problem occurs far less times.

Do you have any idea of the problem?


Thanks in advance for your help.

Bets regards

Andrea

Here there is the code of my serverMediaSubsession and of the functions 
doGetNextFrame() and  deliverFrame() of our framedSource :


class serverMediaSubsession: public OnDemandServerMediaSubsession
         {

         public :
             static serverMediaSubsession* createNew(UsageEnvironment 
&env, Boolean reuseFirstSource, rtspVideoStreamer::parameters params, 
rtspVideoStreamer* parent);


             void checkForAuxSDPLine1();
             void afterPlayingDummy1();

         protected:
             serverMediaSubsession(UsageEnvironment &env, Boolean 
reuseFirstSource, rtspVideoStreamer::parameters params, 
rtspVideoStreamer* parent);
             virtual ~serverMediaSubsession();

             void setDoneFlag() { fDoneFlag = ~0; }

         protected:

             //redefined virtual functions
             virtual char const* getAuxSDPLine(RTPSink* rtpSink, 
FramedSource* inputSource);
             virtual FramedSource* createNewStreamSource(unsigned 
clientSessionId, unsigned& estBitrate);
             // "estBitrate" is the stream's estimated bitrate, in kbps
             virtual RTPSink* createNewRTPSink(Groupsock* rtpGroupsock, 
unsigned char rtpPayloadTypeIfDynamic, FramedSource* inputSource);

             virtual void deleteStream(unsigned clientSessionId, void*& 
streamToken);
         private:

             UsageEnvironment* m_pEnvironment;

             rtspVideoStreamer * m_pParent;
             rtspVideoStreamer::parameters  fParam;

             char* fAuxSDPLine;
             char fDoneFlag; // used when setting up "fAuxSDPLine"
             RTPSink* fDummyRTPSink;
         };

/*--------------------------------------------------------------------*/
     rtspVideoStreamer::serverMediaSubsession* 
rtspVideoStreamer::serverMediaSubsession::createNew(UsageEnvironment& 
env, Boolean reuseFirstSource, rtspVideoStreamer::parameters params, 
rtspVideoStreamer* parent)
     {

         return new serverMediaSubsession(env, 
reuseFirstSource,params,parent);
     }

/*--------------------------------------------------------------------*/
     rtspVideoStreamer::serverMediaSubsession 
::serverMediaSubsession(UsageEnvironment& env, Boolean reuseFirstSource, 
rtspVideoStreamer::parameters params, rtspVideoStreamer* parent)
         : OnDemandServerMediaSubsession(env, reuseFirstSource), 
fParam(params), m_pParent(parent)
     {
         m_pEnvironment = &env;
         fAuxSDPLine = NULL;
         fDoneFlag = 0;
         fDummyRTPSink = NULL;
     }

/*--------------------------------------------------------------------*/
rtspVideoStreamer::serverMediaSubsession::~serverMediaSubsession()
     {
         envir().taskScheduler().unscheduleDelayedTask(nextTask());
         delete[] fAuxSDPLine;
     }

/*--------------------------------------------------------------------*/
     static void afterPlayingDummy(void* clientData)
     {
         rtspVideoStreamer::serverMediaSubsession* subsess = 
(rtspVideoStreamer::serverMediaSubsession*)clientData;
         subsess->afterPlayingDummy1();
     }
/*--------------------------------------------------------------------*/
     void rtspVideoStreamer::serverMediaSubsession::afterPlayingDummy1()
     {
         envir().taskScheduler().unscheduleDelayedTask(nextTask());
         setDoneFlag();
     }

/*--------------------------------------------------------------------*/
     static void checkForAuxSDPLine(void* clientData)
     {
         rtspVideoStreamer::serverMediaSubsession* subsess = 
(rtspVideoStreamer::serverMediaSubsession*)clientData;
         subsess->checkForAuxSDPLine1();
     }

/*--------------------------------------------------------------------*/
     void rtspVideoStreamer::serverMediaSubsession::checkForAuxSDPLine1()
     {
         char const* dasl;
         if (fAuxSDPLine != NULL) {
             setDoneFlag();
         } else if (fDummyRTPSink != NULL && (dasl = 
fDummyRTPSink->auxSDPLine()) != NULL) {
             fAuxSDPLine = strDup(dasl);
             fDummyRTPSink = NULL;

             setDoneFlag();
         } else {
             int uSecsToDelay = 100000; // 100 ms
             nextTask() = 
envir().taskScheduler().scheduleDelayedTask(uSecsToDelay, 
(TaskFunc*)checkForAuxSDPLine, this);
         }
     }

/*--------------------------------------------------------------------*/
     char const* 
rtspVideoStreamer::serverMediaSubsession::getAuxSDPLine(RTPSink* 
rtpSink, FramedSource* inputSource)
     {
         if (fAuxSDPLine != NULL) return fAuxSDPLine;

         if (fDummyRTPSink == NULL) {
             fDummyRTPSink = rtpSink;

             fDummyRTPSink->startPlaying(*inputSource, 
afterPlayingDummy, this);

             checkForAuxSDPLine(this);
         }

         envir().taskScheduler().doEventLoop(&fDoneFlag);

         return fAuxSDPLine;
     }

/*--------------------------------------------------------------------*/
     FramedSource* 
rtspVideoStreamer::serverMediaSubsession::createNewStreamSource(unsigned 
clientSessionId, unsigned& estBitrate)
     {
        passiveWait(1000*1000);

         estBitrate = 500;
         m_pParent->lockSource();
         FramedSource* mysource = NULL;

         if (fParam.m_encoderParams.m_videoCodec != mjpeg)
         {
             mysource = genericSource::createNew(*m_pEnvironment, 
fParam, m_pParent);
         }
         else
         {
             mysource =  new myJPEGVideoSource(*m_pEnvironment, fParam, 
m_pParent);
         }

         m_pParent->m_bClientConnected = true;
         m_pParent->unlockSource();

         FramedSource* videoES = mysource;

         switch(fParam.m_encoderParams.m_videoCodec)
         {
         case mpeg4:
             return MPEG4VideoStreamFramer::createNew(*m_pEnvironment, 
videoES);
             break;
         case h263p:
             return 
H263plusVideoStreamFramer::createNew(*m_pEnvironment, videoES);
             break;
         case h264:
             return H264VideoStreamFramer::createNew(*m_pEnvironment, 
videoES);
             break;
         case mpeg2:
         case mpeg1:
             return 
MPEG1or2VideoStreamFramer::createNew(*m_pEnvironment, videoES);
             break;
         case mjpeg:
             return mysource;
             break;
         default:
             return NULL;
             break;
         }

     }

/*--------------------------------------------------------------------*/
     RTPSink* 
rtspVideoStreamer::serverMediaSubsession::createNewRTPSink(Groupsock* 
rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, FramedSource* 
inputSource)
     {
         passiveWait(1000*1000);
         switch(fParam.m_encoderParams.m_videoCodec)
         {
         case mpeg4:
             return MPEG4ESVideoRTPSink::createNew(*m_pEnvironment, 
rtpGroupsock, 96);
             break;
         case h263p:
             return H263plusVideoRTPSink::createNew(*m_pEnvironment, 
rtpGroupsock, 96);
             break;
         case h264:
             return  H264VideoRTPSink::createNew(*m_pEnvironment, 
rtpGroupsock, rtpPayloadTypeIfDynamic/*96*/);
             break;
         case mpeg2:
         case mpeg1:
             return MPEG1or2VideoRTPSink::createNew(*m_pEnvironment, 
rtpGroupsock);
             break;
         case mjpeg:
             return JPEGVideoRTPSink::createNew(*m_pEnvironment, 
rtpGroupsock);
             break;
         default:
             return NULL;
             break;
         }
     }

/*--------------------------------------------------------------------*/
     void 
rtspVideoStreamer::serverMediaSubsession::deleteStream(unsigned 
clientSessionId, void*& streamToken)
     {
OnDemandServerMediaSubsession::deleteStream(clientSessionId, streamToken);
        passiveWait(1500*1000);

         StreamState* streamState = (StreamState*)streamToken;
         if (streamState != NULL)
             m_pParent->m_bClientConnected = true;
         else
             m_pParent->m_bClientConnected = false;
     }

/*--------------------------------------------------------------------*/
     void rtspVideoStreamer::genericSource::doGetNextFrame()
     {
         bool ret;
         ucImage img;
         m_pParent->getImage(img);
         if (img.isValid())
         {
             if ((m_imgSize.width()!=img.getWidth()) || 
(m_imgSize.height()!=img.getHeight()))
             {
                 imgResizer imgres;
                 imgResizer::parameters resizeparam;
                 resizeparam.m_width = m_imgSize.width();
                 resizeparam.m_height = m_imgSize.height();
                 imgres.setParameters(resizeparam);
                 imgres.apply(img);
             }
             try
             {
                 ret = m_enc.apply(img, m_pBufferCompressed, 
m_iCompressedSize);
             }
             catch (...)
             {

             }


         }

         try
         {
             deliverFrame();
         }
         catch (...)
         {
LOG_DBG("rtspVideoStreamer::genericSource::doGetNextFrame()::deliverFrame() 
ecception");
         }
         if (0 /* the source stops being readable */)
         {
             handleClosure(this);
             return;
         }
     }

/*--------------------------------------------------------------------*/
     void rtspVideoStreamer::genericSource::deliverFrame()
     {
         if ((unsigned)m_iCompressedSize > fMaxSize)
         {
             fNumTruncatedBytes = m_iCompressedSize - fMaxSize;
             fFrameSize = fMaxSize;
             memcpy(fTo, m_pBufferCompressed, fMaxSize);
         }
         else
         {
             memcpy(fTo, m_pBufferCompressed, m_iCompressedSize);
             fFrameSize = m_iCompressedSize;
         }

         gettimeofday(&fPresentationTime, NULL);

         if (!isCurrentlyAwaitingData()) return; // we're not ready for 
the data yet

         FramedSource::afterGetting(this);
     }

-- 
*Andrea Beoldo*
Project Manager/R&D
Technoaware Srl
Corso Buenos Aires 18/11, 16129 Genova (GE)
Ph. +39 010 5539239 Fax. +39 0105539240
Email: andrea.beoldo at technoaware.com
Web: www.technoaware.com

------------------------------------------------------------------------
*Privacy*

Le informazioni contenute in questo messaggio sono riservate e confidenziali. Il loro utilizzo è consentito esclusivamente al destinatario del messaggio, per le finalità indicate nel messaggio stesso. Qualora Lei non fosse la persona a cui il presente messaggio è destinato, La invitiamo ad eliminarlo dal Suo sistema ed a distruggere le varie copie o stampe, dandocene gentilmente comunicazione. Ogni utilizzo improprio è contrario ai principi del D.lgs 196/03 e alla legislazione europea (Direttiva 2002/58/CE). TechnoAware opera in conformità al D.lgs 196/2003 e alla legislazione europea.

The information contained in this message as well as the attached file(s)is confidential/privileged and is only intended for the person to whom it is addressed. If the reader of this message is not the intended recipient or the employee or agent responsible for delivering the message to the intended recipient, or you have received this communication in error, please be aware that any dissemination, distribution or duplication is strictly prohibited and can be illegal. Please notify us immediately and delete all copies from your mailbox and other archives. Thank you.

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


More information about the live-devel mailing list