<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> </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 below is my code.<BR>I greatly appreciate your timely help.<BR></DIV>
<DIV> </DIV>
<DIV> </DIV>
<DIV>###############################mp4live.cpp#################################</DIV>
<DIV> </DIV>
<DIV>#include "liveMedia.hh"<BR>#include "BasicUsageEnvironment.hh"<BR>#include "GroupsockHelper.hh"<BR>#include "MPEG4VideoRelayMediaSubsession.h"<BR>UsageEnvironment* env;</DIV>
<DIV> </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> </DIV>
<DIV>int main(int argc, char** argv) {<BR> // Begin by setting up our usage environment:<BR> TaskScheduler* scheduler = BasicTaskScheduler::createNew();<BR> env = BasicUsageEnvironment::createNew(*scheduler);</DIV>
<DIV> </DIV>
<DIV> // Create a 'groupsock' for the input multicast group,port:<BR> char* inputAddressStr = "224.1.1.1";<BR> struct in_addr inputAddress;<BR> inputAddress.s_addr = our_inet_addr(inputAddressStr);<BR> Port const inputPort(11110);<BR> unsigned char const inputTTL = 255; // we're only reading from this mcast group<BR> Groupsock inputGroupsock(*env, inputAddress, inputPort, inputTTL);<BR> // Then create a liveMedia 'source' object, encapsulating this groupsock:<BR> MPEG4ESVideoRTPSource* source = MPEG4ESVideoRTPSource::createNew(*env, &inputGroupsock, 96, 90000);</DIV>
<DIV> </DIV>
<DIV> UserAuthenticationDatabase* authDB = NULL;<BR> // Create the RTSP server:<BR> RTSPServer* rtspServer = RTSPServer::createNew(*env, 8554, authDB);<BR> if (rtspServer == NULL) {<BR> *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";<BR> exit(1);<BR> }</DIV>
<DIV> </DIV>
<DIV> char const* descriptionString<BR> = "Session streamed by \"testOnDemandRTSPServer\"";<BR> {<BR> char const* streamName = "testStream";<BR> <BR> ServerMediaSession* sms<BR> = ServerMediaSession::createNew(*env, streamName, streamName,<BR> descriptionString);<BR> <BR> sms->addSubsession(MPEG4VideoRelayMediaSubsession::createNew(*env, source, videoBitrate));<BR> <BR> rtspServer->addServerMediaSession(sms);<BR> char* url = rtspServer->rtspURL(sms); <BR> *env << "Play this stream using the URL \"" << url << "\"\n";<BR> delete[] url;<BR> <BR> }<BR> <BR> env->taskScheduler().doEventLoop(); // does not return<BR> <BR> return 0; // only to prevent compiler warning<BR>}</DIV>
<DIV> </DIV>
<DIV> </DIV>
<DIV> </DIV>
<DIV> ###############################MPEG4VideoRelayMediaSubsession.h#################################</DIV>
<DIV> </DIV>
<DIV>#ifndef MPEG4VIDEORELAYMEDIASUBSESSION_H_<BR>#define MPEG4VIDEORELAYMEDIASUBSESSION_H_</DIV>
<DIV> </DIV>
<DIV>#include <OnDemandServerMediaSubsession.hh><BR>#include <MPEG4ESVideoRTPSource.hh></DIV>
<DIV> </DIV>
<DIV>class MPEG4VideoRelayMediaSubsession: public OnDemandServerMediaSubsession {<BR>public:<BR> static MPEG4VideoRelayMediaSubsession*<BR> createNew(UsageEnvironment& env, MPEG4ESVideoRTPSource* mp4source, unsigned estimatedBitrate);</DIV>
<DIV> </DIV>
<DIV> void setDoneFlag() { fDoneFlag = ~0; }<BR> void checkForAuxSDPLine1();</DIV>
<DIV> </DIV>
<DIV>private:<BR> MPEG4VideoRelayMediaSubsession(UsageEnvironment& env, MPEG4ESVideoRTPSource* mp4source,<BR> unsigned estimatedBitrate);<BR> // called only by createNew()<BR> virtual ~MPEG4VideoRelayMediaSubsession();</DIV>
<DIV> </DIV>
<DIV>private: // redefined virtual functions<BR> virtual char const* getAuxSDPLine(RTPSink* rtpSink,<BR> FramedSource* inputSource);<BR> virtual FramedSource* createNewStreamSource(unsigned clientSessionId,<BR> unsigned& estBitrate);<BR> virtual RTPSink* createNewRTPSink(Groupsock* rtpGroupsock,<BR> unsigned char rtpPayloadTypeIfDynamic,<BR> FramedSource* inputSource);</DIV>
<DIV> </DIV>
<DIV>private:<BR> char fDoneFlag; // used when setting up 'SDPlines'<BR> RTPSink* fDummyRTPSink; // ditto<BR> unsigned fEstimatedKbps;<BR> MPEG4ESVideoRTPSource* fInput;<BR> <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> </DIV>
<DIV> </DIV>
<DIV>###############################MPEG4VideoRelayMediaSubsession.cpp#################################</DIV></DIV>
<DIV>#include "MPEG4VideoRelayMediaSubsession.h"<BR>#include <MPEG4ESVideoRTPSink.hh><BR>#include <MPEG4VideoStreamDiscreteFramer.hh></DIV>
<DIV> </DIV>
<DIV>MPEG4VideoRelayMediaSubsession* MPEG4VideoRelayMediaSubsession<BR>::createNew(UsageEnvironment& env, MPEG4ESVideoRTPSource* mp4source, unsigned estimatedBitrate) {<BR> return new MPEG4VideoRelayMediaSubsession(env, mp4source, estimatedBitrate);<BR>}</DIV>
<DIV> </DIV>
<DIV>MPEG4VideoRelayMediaSubsession<BR>::MPEG4VideoRelayMediaSubsession(UsageEnvironment& env, MPEG4ESVideoRTPSource* mp4source,<BR> unsigned estimatedBitrate)<BR> : OnDemandServerMediaSubsession(env, True) {<BR> fInput = mp4source;<BR> fEstimatedKbps = (estimatedBitrate + 500)/1000;<BR> <BR>}</DIV>
<DIV> </DIV>
<DIV>MPEG4VideoRelayMediaSubsession::~MPEG4VideoRelayMediaSubsession() {<BR>}</DIV>
<DIV> </DIV>
<DIV>static void afterPlayingDummy(void* clientData) {<BR> MPEG4VideoRelayMediaSubsession* subsess<BR> = (MPEG4VideoRelayMediaSubsession*)clientData;<BR> // Signal the event loop that we're done:<BR> subsess->setDoneFlag();<BR>}</DIV>
<DIV> </DIV>
<DIV>static void checkForAuxSDPLine(void* clientData) {<BR> MPEG4VideoRelayMediaSubsession* subsess<BR> = (MPEG4VideoRelayMediaSubsession*)clientData;<BR> subsess->checkForAuxSDPLine1();<BR>}</DIV>
<DIV> </DIV>
<DIV>void MPEG4VideoRelayMediaSubsession::checkForAuxSDPLine1() { <BR> if (fDummyRTPSink->auxSDPLine() != NULL) {<BR> printf("MPEG4VideoRelayMediaSubsession::checkForAuxSDPLine1 fDummyRTPSink->auxSDPLine() != NULL\n");<BR> // Signal the event loop that we're done:<BR> setDoneFlag();<BR> } else {<BR> printf("MPEG4VideoRelayMediaSubsession::checkForAuxSDPLine1 fDummyRTPSink->auxSDPLine() == NULL\n");<BR> // try again after a brief delay:<BR> int uSecsToDelay = 100000; // 100 ms<BR> nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecsToDelay,<BR> (TaskFunc*)checkForAuxSDPLine, this);<BR> }<BR>}</DIV>
<DIV> </DIV>
<DIV>char const* MPEG4VideoRelayMediaSubsession<BR>::getAuxSDPLine(RTPSink* rtpSink, FramedSource* inputSource) {<BR> // Note: For MPEG-4 video buffer, the 'config' information isn't known<BR> // until we start reading the Buffer. This means that "rtpSink"s<BR> // "auxSDPLine()" will be NULL initially, and we need to start reading<BR> // data from our buffer until this changes.<BR> fDummyRTPSink = rtpSink;<BR> <BR> // Start reading the buffer:<BR> fDummyRTPSink->startPlaying(*inputSource, afterPlayingDummy, this);<BR> <BR> // Check whether the sink's 'auxSDPLine()' is ready:<BR> checkForAuxSDPLine(this);<BR> <BR> fDoneFlag = 0;<BR> <BR> envir().taskScheduler().doEventLoop(&fDoneFlag);<BR> <BR> char const* auxSDPLine = fDummyRTPSink->auxSDPLine();<BR> <BR> return auxSDPLine;<BR> //return NULL;<BR>}</DIV>
<DIV> </DIV>
<DIV>FramedSource* MPEG4VideoRelayMediaSubsession<BR>::createNewStreamSource(unsigned /*clientSessionId*/, unsigned& estBitrate) {<BR> estBitrate = fEstimatedKbps;<BR> // Create a framer for the Video Elementary Stream:<BR> return MPEG4VideoStreamFramer::createNew(envir(), fInput);<BR>}</DIV>
<DIV> </DIV>
<DIV>RTPSink* MPEG4VideoRelayMediaSubsession<BR>::createNewRTPSink(Groupsock* rtpGroupsock,<BR> unsigned char rtpPayloadTypeIfDynamic,<BR> FramedSource* /*inputSource*/) {<BR> return MPEG4ESVideoRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic);<BR>}<BR></DIV>
<DIV> #############################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 = $(INCLUDES) -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1<BR>C = c<BR>C_COMPILER = cc<BR>C_FLAGS = $(COMPILE_OPTS)<BR>CPP = cpp<BR>CPLUSPLUS_COMPILER = c++<BR>CPLUSPLUS_FLAGS = $(COMPILE_OPTS) -Wall -DBSD=1<BR>OBJ = o<BR>LINK = c++ -o<BR>LINK_OPTS = -L.<BR>CONSOLE_LINK_OPTS = $(LINK_OPTS)<BR>LIBRARY_LINK = ld -o<BR>LIBRARY_LINK_OPTS = $(LINK_OPTS) -r -Bstatic<BR>LIB_SUFFIX = a<BR>LIBS_FOR_CONSOLE_APPLICATION =<BR>LIBS_FOR_GUI_APPLICATION =<BR>EXE =<BR>##### End of variables to change</DIV>
<DIV> </DIV>
<DIV>UNICAST_APPS = mp4live$(EXE)</DIV>
<DIV> </DIV>
<DIV><BR>ALL = $(UNICAST_APPS)<BR>all: $(ALL)</DIV>
<DIV> </DIV>
<DIV><BR>.$(C).$(OBJ):<BR> $(C_COMPILER) -c $(C_FLAGS) $< </DIV>
<DIV> </DIV>
<DIV>.$(CPP).$(OBJ):<BR> $(CPLUSPLUS_COMPILER) -c $(CPLUSPLUS_FLAGS) $<</DIV>
<DIV> </DIV>
<DIV>MPEG4_VIDEO_STREAMER_OBJS = MPEG4VideoRelayMediaSubsession.$(OBJ)<BR>MP4LIVE_OBJS = mp4live.$(OBJ) </DIV>
<DIV> </DIV>
<DIV>MPEG4VideoRelayMediaSubsession.$(CPP): MPEG4VideoRelayMediaSubsession.h</DIV>
<DIV> </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 = $(LIVEMEDIA_LIB) $(GROUPSOCK_LIB) \<BR> $(USAGE_ENVIRONMENT_LIB) $(BASIC_USAGE_ENVIRONMENT_LIB)<BR>LIBS = $(LOCAL_LIBS) $(LIBS_FOR_CONSOLE_APPLICATION)</DIV>
<DIV> </DIV>
<DIV>mp4live$(EXE): $(MP4LIVE_OBJS) $(MPEG4_VIDEO_STREAMER_OBJS) $(LOCAL_LIBS)<BR> $(LINK)$@ $(CONSOLE_LINK_OPTS) $(MP4LIVE_OBJS) $(MPEG4_VIDEO_STREAMER_OBJS) $(LIBS)</DIV>
<DIV> </DIV>
<DIV>clean:<BR> -rm -rf *.$(OBJ) $(ALL) core *.core *~ include/*~</DIV>
<DIV> </DIV>
<DIV><BR> </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>