<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=gb2312">
<META content="IncrediMail 1.0" name=GENERATOR>
<!--IncrdiXMLRemarkStart>
<IncrdiX-Info>
<X-FID>FLAVOR00-NONE-0000-0000-000000000000</X-FID>
<X-FVER>4.0</X-FVER>
<X-CNT>;</X-CNT>
</IncrdiX-Info>
<IncrdiXMLRemarkEnd-->
</HEAD>
<BODY style="BACKGROUND-POSITION: 0px 0px; SCROLLBAR-FACE-COLOR: #c6d7ff; FONT-SIZE: 12pt; MARGIN: 5px 10px 10px; SCROLLBAR-HIGHLIGHT-COLOR: #ffffff; SCROLLBAR-SHADOW-COLOR: #ffffff; SCROLLBAR-3DLIGHT-COLOR: #7b9ed6; SCROLLBAR-ARROW-COLOR: #4a6184; FONT-FAMILY: Arial; SCROLLBAR-DARKSHADOW-COLOR: #bebebe" bgColor=#ffffff background="" scroll=yes ORGYPOS="0">
<TABLE id=INCREDIMAINTABLE cellSpacing=0 cellPadding=2 width="100%" border=0>
<TBODY>
<TR>
<TD id=INCREDITEXTREGION style="FONT-SIZE: 12pt; CURSOR: auto; FONT-FAMILY: Arial" width="100%">
<DIV>&nbsp;</DIV>
<DIV>I try to receive m4v stream(rtpmap:96 MP4V-ES/90000 ) from 224.1.1.1:11110 (multicast), <BR>and then like testOnDemandRTSPServer send it (unicast).<BR> <BR>But it seem to not work. The&nbsp;below&nbsp; is my&nbsp;code.<BR>I greatly appreciate your timely help.<BR></DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;</DIV>
<DIV>###############################mp4live.cpp#################################</DIV>
<DIV>&nbsp;</DIV>
<DIV>#include "liveMedia.hh"<BR>#include "BasicUsageEnvironment.hh"<BR>#include "GroupsockHelper.hh"<BR>#include "MPEG4VideoRelayMediaSubsession.h"<BR>UsageEnvironment* env;</DIV>
<DIV>&nbsp;</DIV>
<DIV>// To make the second and subsequent client for each stream reuse the same<BR>// input stream as the first client (rather than playing the file from the<BR>// start for each client), change the following "False" to "True":<BR>Boolean reuseFirstSource = False;<BR>int videoBitrate = 1000000;</DIV>
<DIV>&nbsp;</DIV>
<DIV>int main(int argc, char** argv) {<BR>&nbsp; // Begin by setting up our usage environment:<BR>&nbsp; TaskScheduler* scheduler = BasicTaskScheduler::createNew();<BR>&nbsp; env = BasicUsageEnvironment::createNew(*scheduler);</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;// Create a 'groupsock' for the input multicast group,port:<BR>&nbsp; char* inputAddressStr&nbsp; = "224.1.1.1";<BR>&nbsp; struct in_addr inputAddress;<BR>&nbsp; inputAddress.s_addr = our_inet_addr(inputAddressStr);<BR>&nbsp; Port const inputPort(11110);<BR>&nbsp; unsigned char const inputTTL = 255; // we're only reading from this mcast group<BR>&nbsp; Groupsock inputGroupsock(*env, inputAddress, inputPort, inputTTL);<BR>&nbsp; // Then create a liveMedia 'source' object, encapsulating this groupsock:<BR>&nbsp; MPEG4ESVideoRTPSource* source = MPEG4ESVideoRTPSource::createNew(*env, &amp;inputGroupsock, 96, 90000);</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; UserAuthenticationDatabase* authDB = NULL;<BR>&nbsp;&nbsp;&nbsp; // Create the RTSP server:<BR>&nbsp; RTSPServer* rtspServer = RTSPServer::createNew(*env, 8554, authDB);<BR>&nbsp; if (rtspServer == NULL) {<BR>&nbsp;&nbsp;&nbsp; *env &lt;&lt; "Failed to create RTSP server: " &lt;&lt; env-&gt;getResultMsg() &lt;&lt; "\n";<BR>&nbsp;&nbsp;&nbsp; exit(1);<BR>&nbsp; }</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; char const* descriptionString<BR>&nbsp;&nbsp;&nbsp; = "Session streamed by \"testOnDemandRTSPServer\"";<BR>&nbsp; {<BR>&nbsp;&nbsp;&nbsp; char const* streamName = "testStream";<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; ServerMediaSession* sms<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = ServerMediaSession::createNew(*env, streamName, streamName,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; descriptionString);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; sms-&gt;addSubsession(MPEG4VideoRelayMediaSubsession::createNew(*env, source, videoBitrate));<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; rtspServer-&gt;addServerMediaSession(sms);<BR>&nbsp;char* url = rtspServer-&gt;rtspURL(sms);&nbsp; <BR>&nbsp;*env &lt;&lt; "Play this stream using the URL \"" &lt;&lt; url &lt;&lt; "\"\n";<BR>&nbsp;delete[] url;<BR>&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp; }<BR>&nbsp; <BR>&nbsp; env-&gt;taskScheduler().doEventLoop(); // does not return<BR>&nbsp; <BR>&nbsp; return 0; // only to prevent compiler warning<BR>}</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;###############################MPEG4VideoRelayMediaSubsession.h#################################</DIV>
<DIV>&nbsp;</DIV>
<DIV>#ifndef MPEG4VIDEORELAYMEDIASUBSESSION_H_<BR>#define MPEG4VIDEORELAYMEDIASUBSESSION_H_</DIV>
<DIV>&nbsp;</DIV>
<DIV>#include &lt;OnDemandServerMediaSubsession.hh&gt;<BR>#include &lt;MPEG4ESVideoRTPSource.hh&gt;</DIV>
<DIV>&nbsp;</DIV>
<DIV>class MPEG4VideoRelayMediaSubsession: public OnDemandServerMediaSubsession {<BR>public:<BR>&nbsp; static MPEG4VideoRelayMediaSubsession*<BR>&nbsp; createNew(UsageEnvironment&amp; env, MPEG4ESVideoRTPSource* mp4source, unsigned estimatedBitrate);</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; void setDoneFlag() { fDoneFlag = ~0; }<BR>&nbsp; void checkForAuxSDPLine1();</DIV>
<DIV>&nbsp;</DIV>
<DIV>private:<BR>&nbsp; MPEG4VideoRelayMediaSubsession(UsageEnvironment&amp; env, MPEG4ESVideoRTPSource* mp4source,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned estimatedBitrate);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // called only by createNew()<BR>&nbsp; virtual ~MPEG4VideoRelayMediaSubsession();</DIV>
<DIV>&nbsp;</DIV>
<DIV>private: // redefined virtual functions<BR>&nbsp; virtual char const* getAuxSDPLine(RTPSink* rtpSink,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FramedSource* inputSource);<BR>&nbsp; virtual FramedSource* createNewStreamSource(unsigned clientSessionId,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned&amp; estBitrate);<BR>&nbsp; virtual RTPSink* createNewRTPSink(Groupsock* rtpGroupsock,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned char rtpPayloadTypeIfDynamic,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FramedSource* inputSource);</DIV>
<DIV>&nbsp;</DIV>
<DIV>private:<BR>&nbsp; char fDoneFlag; // used when setting up 'SDPlines'<BR>&nbsp; RTPSink* fDummyRTPSink; // ditto<BR>&nbsp; unsigned fEstimatedKbps;<BR>&nbsp; MPEG4ESVideoRTPSource* fInput;<BR>&nbsp; <BR>};<BR>#define VIDEO_MAX_FRAME_SIZE 150000<BR>inline void setVideoRTPSinkBufferSize() { OutPacketBuffer::maxSize = VIDEO_MAX_FRAME_SIZE; }<BR>#endif /*MPEG4VIDEORELAYMEDIASUBSESSION_H_*/<BR></DIV>
<DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;</DIV>
<DIV>###############################MPEG4VideoRelayMediaSubsession.cpp#################################</DIV></DIV>
<DIV>#include "MPEG4VideoRelayMediaSubsession.h"<BR>#include &lt;MPEG4ESVideoRTPSink.hh&gt;<BR>#include &lt;MPEG4VideoStreamDiscreteFramer.hh&gt;</DIV>
<DIV>&nbsp;</DIV>
<DIV>MPEG4VideoRelayMediaSubsession* MPEG4VideoRelayMediaSubsession<BR>::createNew(UsageEnvironment&amp; env, MPEG4ESVideoRTPSource* mp4source, unsigned estimatedBitrate) {<BR>&nbsp; return new MPEG4VideoRelayMediaSubsession(env, mp4source, estimatedBitrate);<BR>}</DIV>
<DIV>&nbsp;</DIV>
<DIV>MPEG4VideoRelayMediaSubsession<BR>::MPEG4VideoRelayMediaSubsession(UsageEnvironment&amp; env, MPEG4ESVideoRTPSource* mp4source,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned estimatedBitrate)<BR>&nbsp; : OnDemandServerMediaSubsession(env, True) {<BR>&nbsp; &nbsp;fInput = mp4source;<BR>&nbsp; &nbsp;fEstimatedKbps = (estimatedBitrate + 500)/1000;<BR>&nbsp; &nbsp;<BR>}</DIV>
<DIV>&nbsp;</DIV>
<DIV>MPEG4VideoRelayMediaSubsession::~MPEG4VideoRelayMediaSubsession() {<BR>}</DIV>
<DIV>&nbsp;</DIV>
<DIV>static void afterPlayingDummy(void* clientData) {<BR>&nbsp; MPEG4VideoRelayMediaSubsession* subsess<BR>&nbsp;&nbsp;&nbsp; = (MPEG4VideoRelayMediaSubsession*)clientData;<BR>&nbsp; // Signal the event loop that we're done:<BR>&nbsp; subsess-&gt;setDoneFlag();<BR>}</DIV>
<DIV>&nbsp;</DIV>
<DIV>static void checkForAuxSDPLine(void* clientData) {<BR>&nbsp; MPEG4VideoRelayMediaSubsession* subsess<BR>&nbsp;&nbsp;&nbsp; = (MPEG4VideoRelayMediaSubsession*)clientData;<BR>&nbsp; subsess-&gt;checkForAuxSDPLine1();<BR>}</DIV>
<DIV>&nbsp;</DIV>
<DIV>void MPEG4VideoRelayMediaSubsession::checkForAuxSDPLine1() {&nbsp;<BR>&nbsp; if (fDummyRTPSink-&gt;auxSDPLine() != NULL) {<BR>&nbsp; &nbsp;printf("MPEG4VideoRelayMediaSubsession::checkForAuxSDPLine1 fDummyRTPSink-&gt;auxSDPLine() != NULL\n");<BR>&nbsp;&nbsp;&nbsp; // Signal the event loop that we're done:<BR>&nbsp;&nbsp;&nbsp; setDoneFlag();<BR>&nbsp; } else {<BR>&nbsp; &nbsp;printf("MPEG4VideoRelayMediaSubsession::checkForAuxSDPLine1 fDummyRTPSink-&gt;auxSDPLine() == NULL\n");<BR>&nbsp;&nbsp;&nbsp; // try again after a brief delay:<BR>&nbsp;&nbsp;&nbsp; int uSecsToDelay = 100000; // 100 ms<BR>&nbsp;&nbsp;&nbsp; nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecsToDelay,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (TaskFunc*)checkForAuxSDPLine, this);<BR>&nbsp; }<BR>}</DIV>
<DIV>&nbsp;</DIV>
<DIV>char const* MPEG4VideoRelayMediaSubsession<BR>::getAuxSDPLine(RTPSink* rtpSink, FramedSource* inputSource) {<BR>&nbsp; // Note: For MPEG-4 video buffer, the 'config' information isn't known<BR>&nbsp; // until we start reading the Buffer.&nbsp; This means that "rtpSink"s<BR>&nbsp; // "auxSDPLine()" will be NULL initially, and we need to start reading<BR>&nbsp; // data from our buffer until this changes.<BR>&nbsp; fDummyRTPSink = rtpSink;<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp; // Start reading the buffer:<BR>&nbsp; fDummyRTPSink-&gt;startPlaying(*inputSource, afterPlayingDummy, this);<BR>&nbsp; <BR>&nbsp; // Check whether the sink's 'auxSDPLine()' is ready:<BR>&nbsp; checkForAuxSDPLine(this);<BR>&nbsp; <BR>&nbsp; fDoneFlag = 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp; envir().taskScheduler().doEventLoop(&amp;fDoneFlag);<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp; char const* auxSDPLine = fDummyRTPSink-&gt;auxSDPLine();<BR>&nbsp; <BR>&nbsp; return auxSDPLine;<BR>&nbsp; //return NULL;<BR>}</DIV>
<DIV>&nbsp;</DIV>
<DIV>FramedSource* MPEG4VideoRelayMediaSubsession<BR>::createNewStreamSource(unsigned /*clientSessionId*/, unsigned&amp; estBitrate) {<BR>&nbsp; estBitrate = fEstimatedKbps;<BR>&nbsp; // Create a framer for the Video Elementary Stream:<BR>&nbsp; return MPEG4VideoStreamFramer::createNew(envir(), fInput);<BR>}</DIV>
<DIV>&nbsp;</DIV>
<DIV>RTPSink* MPEG4VideoRelayMediaSubsession<BR>::createNewRTPSink(Groupsock* rtpGroupsock,<BR>&nbsp;&nbsp;&nbsp;&nbsp; unsigned char rtpPayloadTypeIfDynamic,<BR>&nbsp;&nbsp;&nbsp;&nbsp; FramedSource* /*inputSource*/) {<BR>&nbsp; return MPEG4ESVideoRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic);<BR>}<BR></DIV>
<DIV>&nbsp;#############################Makefile (redhat)##########################</DIV>
<DIV>INCLUDES = -I../UsageEnvironment/include -I../groupsock/include -I../liveMedia/include -I../BasicUsageEnvironment/include<BR>##### Change the following for your environment: <BR>COMPILE_OPTS =&nbsp;&nbsp;$(INCLUDES) -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1<BR>C =&nbsp;&nbsp;&nbsp;c<BR>C_COMPILER =&nbsp;&nbsp;cc<BR>C_FLAGS =&nbsp;&nbsp;$(COMPILE_OPTS)<BR>CPP =&nbsp;&nbsp;&nbsp;cpp<BR>CPLUSPLUS_COMPILER =&nbsp;c++<BR>CPLUSPLUS_FLAGS =&nbsp;$(COMPILE_OPTS) -Wall -DBSD=1<BR>OBJ =&nbsp;&nbsp;&nbsp;o<BR>LINK =&nbsp;&nbsp;&nbsp;c++ -o<BR>LINK_OPTS =&nbsp;&nbsp;-L.<BR>CONSOLE_LINK_OPTS =&nbsp;$(LINK_OPTS)<BR>LIBRARY_LINK =&nbsp;&nbsp;ld -o<BR>LIBRARY_LINK_OPTS =&nbsp;$(LINK_OPTS) -r -Bstatic<BR>LIB_SUFFIX =&nbsp;&nbsp;&nbsp;a<BR>LIBS_FOR_CONSOLE_APPLICATION =<BR>LIBS_FOR_GUI_APPLICATION =<BR>EXE =<BR>##### End of variables to change</DIV>
<DIV>&nbsp;</DIV>
<DIV>UNICAST_APPS = mp4live$(EXE)</DIV>
<DIV>&nbsp;</DIV>
<DIV><BR>ALL = $(UNICAST_APPS)<BR>all: $(ALL)</DIV>
<DIV>&nbsp;</DIV>
<DIV><BR>.$(C).$(OBJ):<BR>&nbsp;$(C_COMPILER) -c $(C_FLAGS) $&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </DIV>
<DIV>&nbsp;</DIV>
<DIV>.$(CPP).$(OBJ):<BR>&nbsp;$(CPLUSPLUS_COMPILER) -c $(CPLUSPLUS_FLAGS) $&lt;</DIV>
<DIV>&nbsp;</DIV>
<DIV>MPEG4_VIDEO_STREAMER_OBJS = MPEG4VideoRelayMediaSubsession.$(OBJ)<BR>MP4LIVE_OBJS = mp4live.$(OBJ) </DIV>
<DIV>&nbsp;</DIV>
<DIV>MPEG4VideoRelayMediaSubsession.$(CPP):&nbsp;MPEG4VideoRelayMediaSubsession.h</DIV>
<DIV>&nbsp;</DIV>
<DIV>USAGE_ENVIRONMENT_DIR = ../UsageEnvironment<BR>USAGE_ENVIRONMENT_LIB = $(USAGE_ENVIRONMENT_DIR)/libUsageEnvironment.$(LIB_SUFFIX)<BR>BASIC_USAGE_ENVIRONMENT_DIR = ../BasicUsageEnvironment<BR>BASIC_USAGE_ENVIRONMENT_LIB = $(BASIC_USAGE_ENVIRONMENT_DIR)/libBasicUsageEnvironment.$(LIB_SUFFIX)<BR>LIVEMEDIA_DIR = ../liveMedia<BR>LIVEMEDIA_LIB = $(LIVEMEDIA_DIR)/libliveMedia.$(LIB_SUFFIX)<BR>GROUPSOCK_DIR = ../groupsock<BR>GROUPSOCK_LIB = $(GROUPSOCK_DIR)/libgroupsock.$(LIB_SUFFIX)<BR>LOCAL_LIBS =&nbsp;$(LIVEMEDIA_LIB) $(GROUPSOCK_LIB) \<BR>&nbsp;&nbsp;$(USAGE_ENVIRONMENT_LIB) $(BASIC_USAGE_ENVIRONMENT_LIB)<BR>LIBS =&nbsp;&nbsp;&nbsp;$(LOCAL_LIBS) $(LIBS_FOR_CONSOLE_APPLICATION)</DIV>
<DIV>&nbsp;</DIV>
<DIV>mp4live$(EXE):&nbsp;$(MP4LIVE_OBJS) $(MPEG4_VIDEO_STREAMER_OBJS) $(LOCAL_LIBS)<BR>&nbsp;$(LINK)$@ $(CONSOLE_LINK_OPTS) $(MP4LIVE_OBJS) $(MPEG4_VIDEO_STREAMER_OBJS)&nbsp; $(LIBS)</DIV>
<DIV>&nbsp;</DIV>
<DIV>clean:<BR>&nbsp;-rm -rf *.$(OBJ) $(ALL) core *.core *~ include/*~</DIV>
<DIV>&nbsp;</DIV>
<DIV><BR>&nbsp;</DIV></TD></TR>
<TR>
<TD id=INCREDIFOOTER width="100%">
<TABLE cellSpacing=0 cellPadding=0 width="100%">
<TBODY>
<TR>
<TD width="100%"></TD>
<TD id=INCREDISOUND vAlign=bottom align=middle></TD>
<TD id=INCREDIANIM vAlign=bottom align=middle></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></BODY></HTML>