1010#include " MPEG2TransportStreamParser.hh" // internal header for PIDState_STREAM and StreamType
1111#include " H264VideoStreamFramer.hh"
1212#include " H265VideoStreamFramer.hh"
13+ #include " Base64.hh"
1314#include " StreamSink.h"
1415
1516#ifdef _DEBUG
@@ -170,6 +171,8 @@ void StreamPuller::start()
170171 exit = 0 ;
171172 if (protocol == CRP_RTSP)
172173 thread = std::thread (&StreamPuller::runRTSP, this );
174+ else if (protocol == CRP_SDP)
175+ thread = std::thread (&StreamPuller::runSDP, this );
173176 else if (protocol == CRP_RTP)
174177 thread = std::thread (&StreamPuller::runRTP, this );
175178 else if (protocol == CRP_HTTP)
@@ -199,11 +202,61 @@ void StreamPuller::runRTSP()
199202 delete scheduler;
200203}
201204
205+ static bool parseSDP (const std::string& url, std::string& sdp)
206+ {
207+ static const std::regex regex (R"( ([a-z\d\+]+):\/\/(.+))" );
208+ std::smatch match;
209+ if (std::regex_match (url, match, regex))
210+ {
211+ std::string schema = match[1 ].str ();
212+ sdp = match[2 ].str ();
213+ if (schema == " sdp+base64" )
214+ {
215+ unsigned dataSize = 0 ;
216+ unsigned char * data = base64Decode (sdp.c_str (), sdp.length (), dataSize, true );
217+ sdp = std::string ((char *) data, dataSize);
218+ }
219+ else if (schema != " sdp" )
220+ {
221+ sdp = " " ;
222+ return false ;
223+ }
224+ return !sdp.empty ();
225+ }
226+ return false ;
227+ }
228+
229+ void StreamPuller::runSDP ()
230+ {
231+ std::string sdp;
232+ if (!parseSDP (url, sdp))
233+ {
234+ fprintf (stderr, " Invalid SDP description: %s\n " , url.c_str ());
235+ callback.invokeSync (CRP_EV_ERROR, (void *) 0 , userData);
236+ return ;
237+ }
238+
239+ scheduler = BasicTaskScheduler::createNew ();
240+ environment = BasicUsageEnvironment::createNew (*scheduler);
241+ rtspClient = NULL ;
242+ session = NULL ;
243+ demuxer = NULL ;
244+ livenessCheckTask = NULL ;
245+
246+ callback.invokeSync (CRP_EV_START, nullptr , userData);
247+ continueAfterDESCRIBE (NULL , 0 , sdp.c_str ());
248+ environment->taskScheduler ().doEventLoop (&exit);
249+
250+ shutdownStream (NULL );
251+ delete scheduler;
252+ }
253+
202254static bool parseRTPUrl (const std::string& url, std::string& host, int & port)
203255{
204- std::regex regex (R"( rtp://([^:]+):(\d+))" );
256+ static const std::regex regex (R"( rtp://([^:]+):(\d+))" );
205257 std::smatch match;
206- if (std::regex_match (url, match, regex)) {
258+ if (std::regex_match (url, match, regex))
259+ {
207260 host = match[1 ].str ();
208261 port = std::stoi (match[2 ].str ());
209262 return true ;
@@ -420,7 +473,7 @@ void StreamPuller::runHTTP()
420473
421474void StreamPuller::shutdownStream (RTSPClient* rtspClient)
422475{
423- UsageEnvironment& env = rtspClient-> envir () ;
476+ UsageEnvironment& env = *environment ;
424477
425478 if (session != NULL )
426479 {
@@ -442,7 +495,7 @@ void StreamPuller::shutdownStream(RTSPClient* rtspClient)
442495 }
443496 }
444497
445- if (someSubsessionsWereActive)
498+ if (rtspClient != NULL && someSubsessionsWereActive)
446499 {
447500 rtspClient->sendTeardownCommand (*session, NULL );
448501 }
@@ -453,9 +506,9 @@ void StreamPuller::shutdownStream(RTSPClient* rtspClient)
453506 this ->rtspClient = NULL ;
454507}
455508
456- void StreamPuller::continueAfterDESCRIBE (RTSPClient* rtspClient, int resultCode, char * resultString)
509+ void StreamPuller::continueAfterDESCRIBE (RTSPClient* rtspClient, int resultCode, const char * resultString)
457510{
458- UsageEnvironment& env = rtspClient-> envir () ;
511+ UsageEnvironment& env = *environment ;
459512
460513 if (resultCode != 0 )
461514 {
@@ -490,7 +543,7 @@ void StreamPuller::continueAfterDESCRIBE(RTSPClient* rtspClient, int resultCode,
490543
491544void StreamPuller::continueAfterSETUP (RTSPClient* rtspClient, int resultCode, char * resultString)
492545{
493- UsageEnvironment& env = rtspClient-> envir () ;
546+ UsageEnvironment& env = *environment ;
494547 const char * mediumName;
495548 const char * codecName;
496549
@@ -630,22 +683,22 @@ void StreamPuller::continueAfterSETUP(RTSPClient* rtspClient, int resultCode, ch
630683 goto end;
631684 }
632685
633- subsession->miscPtr = rtspClient ;
686+ subsession->miscPtr = this ;
634687 if (subsession->sink != NULL )
635688 {
636689 env << " Created a " << mediumName << " data sink for the subsession\n " ;
637690 subsession->sink ->startPlaying (*(subsession->readSource ()), [](void * clientData)
638691 {
639692 MediaSubsession* subsession = (MediaSubsession*) clientData;
640- ((OurRTSPClient *) subsession->miscPtr )-> parent ->subsessionAfterPlaying (subsession);
693+ ((StreamPuller *) subsession->miscPtr )->subsessionAfterPlaying (subsession);
641694 }, subsession);
642695 }
643696 if (subsession->rtcpInstance () != NULL )
644697 {
645698 subsession->rtcpInstance ()->setByeWithReasonHandler ([](void * clientData, char const * reason)
646699 {
647700 MediaSubsession* subsession = (MediaSubsession*) clientData;
648- ((OurRTSPClient *) subsession->miscPtr )-> parent ->subsessionByeHandler (subsession, reason);
701+ ((StreamPuller *) subsession->miscPtr )->subsessionByeHandler (subsession, reason);
649702 delete[] reason;
650703 }, subsession);
651704 }
@@ -656,7 +709,7 @@ void StreamPuller::continueAfterSETUP(RTSPClient* rtspClient, int resultCode, ch
656709
657710void StreamPuller::continueAfterPLAY (RTSPClient* rtspClient, int resultCode, char * resultString)
658711{
659- UsageEnvironment& env = rtspClient-> envir () ;
712+ UsageEnvironment& env = *environment ;
660713
661714 if (resultCode != 0 )
662715 {
@@ -676,7 +729,7 @@ void StreamPuller::continueAfterPLAY(RTSPClient* rtspClient, int resultCode, cha
676729
677730void StreamPuller::setupNextSubsession (RTSPClient* rtspClient)
678731{
679- UsageEnvironment& env = rtspClient-> envir () ;
732+ UsageEnvironment& env = *environment ;
680733
681734 subsession = iter->next ();
682735 if (subsession != NULL )
@@ -695,20 +748,34 @@ void StreamPuller::setupNextSubsession(RTSPClient* rtspClient)
695748 else
696749 env << " client ports " << subsession->clientPortNum () << " -" << subsession->clientPortNum () + 1 ;
697750 env << " )\n " ;
698- rtspClient->sendSetupCommand (*subsession, [](RTSPClient * rtspClient, int resultCode, char * resultString)
699- {
700- ((OurRTSPClient*) rtspClient)->parent ->continueAfterSETUP (rtspClient, resultCode, resultString);
701- delete[] resultString;
702- }, False, option.transport == CRP_TCP);
751+ if (rtspClient != NULL )
752+ {
753+ rtspClient->sendSetupCommand (*subsession, [](RTSPClient* rtspClient, int resultCode, char * resultString)
754+ {
755+ ((OurRTSPClient*) rtspClient)->parent ->continueAfterSETUP (rtspClient, resultCode, resultString);
756+ delete[] resultString;
757+ }, False, option.transport == CRP_TCP);
758+ }
759+ else
760+ {
761+ continueAfterSETUP (NULL , 0 , NULL );
762+ }
703763 }
704764 return ;
705765 }
706766
707- rtspClient->sendPlayCommand (*session, [](RTSPClient * rtspClient, int resultCode, char * resultString)
708- {
709- ((OurRTSPClient*) rtspClient)->parent ->continueAfterPLAY (rtspClient, resultCode, resultString);
710- delete[] resultString;
711- });
767+ if (rtspClient != NULL )
768+ {
769+ rtspClient->sendPlayCommand (*session, [](RTSPClient* rtspClient, int resultCode, char * resultString)
770+ {
771+ ((OurRTSPClient*) rtspClient)->parent ->continueAfterPLAY (rtspClient, resultCode, resultString);
772+ delete[] resultString;
773+ });
774+ }
775+ else
776+ {
777+ continueAfterPLAY (NULL , 0 , NULL );
778+ }
712779}
713780
714781void StreamPuller::subsessionAfterPlaying (MediaSubsession* subsession)
@@ -730,7 +797,7 @@ void StreamPuller::subsessionAfterPlaying(MediaSubsession* subsession)
730797
731798void StreamPuller::subsessionByeHandler (MediaSubsession* subsession, char const * reason)
732799{
733- UsageEnvironment& env = rtspClient-> envir () ;
800+ UsageEnvironment& env = *environment ;
734801
735802 env << " Received RTCP \" BYE\" " ;
736803 if (reason != NULL )
@@ -817,6 +884,8 @@ StreamPuller::Protocol StreamPuller::parseUrl(const std::string& url)
817884{
818885 if (url.starts_with (" rtsp" ))
819886 return CRP_RTSP;
887+ else if (url.starts_with (" sdp" ))
888+ return CRP_SDP;
820889 else if (url.starts_with (" rtp" ))
821890 return CRP_RTP;
822891 else if (url.starts_with (" http" ))
0 commit comments