[Live-devel] How to receive multicast MP4V-ES stream and send it by unicast

qiek at 163.com qiek at 163.com
Fri Apr 21 00:04:47 PDT 2006


I try to receive m4v stream(rtpmap:96 MP4V-ES/90000 ) from 224.1.1.1:11110
(multicast), 
and then like testOnDemandRTSPServer send it (unicast).
 
But it seem to not work. The below  is my code.
I greatly appreciate your timely help.



###############################mp4live.cpp#################################

#include "liveMedia.hh"
#include "BasicUsageEnvironment.hh"
#include "GroupsockHelper.hh"
#include "MPEG4VideoRelayMediaSubsession.h"
UsageEnvironment* env;
 
// To make the second and subsequent client for each stream reuse the same
// input stream as the first client (rather than playing the file from the
// start for each client), change the following "False" to "True":
Boolean reuseFirstSource = False;
int videoBitrate = 1000000;
 
int main(int argc, char** argv) {
  // Begin by setting up our usage environment:
  TaskScheduler* scheduler = BasicTaskScheduler::createNew();
  env = BasicUsageEnvironment::createNew(*scheduler);
 
 // Create a 'groupsock' for the input multicast group,port:
  char* inputAddressStr  = "224.1.1.1";
  struct in_addr inputAddress;
  inputAddress.s_addr = our_inet_addr(inputAddressStr);
  Port const inputPort(11110);
  unsigned char const inputTTL = 255; // we're only reading from this mcast
group
  Groupsock inputGroupsock(*env, inputAddress, inputPort, inputTTL);
  // Then create a liveMedia 'source' object, encapsulating this groupsock:
  MPEG4ESVideoRTPSource* source = MPEG4ESVideoRTPSource::createNew(*env,
&inputGroupsock, 96, 90000);
 
  UserAuthenticationDatabase* authDB = NULL;
    // Create the RTSP server:
  RTSPServer* rtspServer = RTSPServer::createNew(*env, 8554, authDB);
  if (rtspServer == NULL) {
    *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";
    exit(1);
  }
 
  char const* descriptionString
    = "Session streamed by \"testOnDemandRTSPServer\"";
  {
    char const* streamName = "testStream";
    
    ServerMediaSession* sms
      = ServerMediaSession::createNew(*env, streamName, streamName,
          descriptionString);
              
    sms->addSubsession(MPEG4VideoRelayMediaSubsession::createNew(*env,
source, videoBitrate));
    
    rtspServer->addServerMediaSession(sms);
 char* url = rtspServer->rtspURL(sms);  
 *env << "Play this stream using the URL \"" << url << "\"\n";
 delete[] url;
     
  }
  
  env->taskScheduler().doEventLoop(); // does not return
  
  return 0; // only to prevent compiler warning
}
 


 ###############################MPEG4VideoRelayMediaSubsession
h#################################
 
#ifndef MPEG4VIDEORELAYMEDIASUBSESSION_H_
#define MPEG4VIDEORELAYMEDIASUBSESSION_H_

#include <OnDemandServerMediaSubsession.hh>
#include <MPEG4ESVideoRTPSource.hh>

class MPEG4VideoRelayMediaSubsession: public OnDemandServerMediaSubsession {
public:
  static MPEG4VideoRelayMediaSubsession*
  createNew(UsageEnvironment& env, MPEG4ESVideoRTPSource* mp4source,
unsigned estimatedBitrate);

  void setDoneFlag() { fDoneFlag = ~0; }
  void checkForAuxSDPLine1();

private:
  MPEG4VideoRelayMediaSubsession(UsageEnvironment& env,
MPEG4ESVideoRTPSource* mp4source,
         unsigned estimatedBitrate);
      // called only by createNew()
  virtual ~MPEG4VideoRelayMediaSubsession();

private: // redefined virtual functions
  virtual char const* getAuxSDPLine(RTPSink* rtpSink,
        FramedSource* inputSource);
  virtual FramedSource* createNewStreamSource(unsigned clientSessionId,
           unsigned& estBitrate);
  virtual RTPSink* createNewRTPSink(Groupsock* rtpGroupsock,
                                    unsigned char rtpPayloadTypeIfDynamic,
        FramedSource* inputSource);

private:
  char fDoneFlag; // used when setting up 'SDPlines'
  RTPSink* fDummyRTPSink; // ditto
  unsigned fEstimatedKbps;
  MPEG4ESVideoRTPSource* fInput;
  
};
#define VIDEO_MAX_FRAME_SIZE 150000
inline void setVideoRTPSinkBufferSize() { OutPacketBuffer::maxSize =
VIDEO_MAX_FRAME_SIZE; }
#endif /*MPEG4VIDEORELAYMEDIASUBSESSION_H_*/



###############################MPEG4VideoRelayMediaSubsession
cpp#################################
#include "MPEG4VideoRelayMediaSubsession.h"
#include <MPEG4ESVideoRTPSink.hh>
#include <MPEG4VideoStreamDiscreteFramer.hh>

MPEG4VideoRelayMediaSubsession* MPEG4VideoRelayMediaSubsession
::createNew(UsageEnvironment& env, MPEG4ESVideoRTPSource* mp4source,
unsigned estimatedBitrate) {
  return new MPEG4VideoRelayMediaSubsession(env, mp4source,
estimatedBitrate);
}

MPEG4VideoRelayMediaSubsession
::MPEG4VideoRelayMediaSubsession(UsageEnvironment& env,
MPEG4ESVideoRTPSource* mp4source,
         unsigned estimatedBitrate)
  : OnDemandServerMediaSubsession(env, True) {
   fInput = mp4source;
   fEstimatedKbps = (estimatedBitrate + 500)/1000;
   
}

MPEG4VideoRelayMediaSubsession::~MPEG4VideoRelayMediaSubsession() {
}

static void afterPlayingDummy(void* clientData) {
  MPEG4VideoRelayMediaSubsession* subsess
    = (MPEG4VideoRelayMediaSubsession*)clientData;
  // Signal the event loop that we're done:
  subsess->setDoneFlag();
}

static void checkForAuxSDPLine(void* clientData) {
  MPEG4VideoRelayMediaSubsession* subsess
    = (MPEG4VideoRelayMediaSubsession*)clientData;
  subsess->checkForAuxSDPLine1();
}

void MPEG4VideoRelayMediaSubsession::checkForAuxSDPLine1() { 
  if (fDummyRTPSink->auxSDPLine() != NULL) {
   printf("MPEG4VideoRelayMediaSubsession::checkForAuxSDPLine1
fDummyRTPSink->auxSDPLine() != NULL\n");
    // Signal the event loop that we're done:
    setDoneFlag();
  } else {
   printf("MPEG4VideoRelayMediaSubsession::checkForAuxSDPLine1
fDummyRTPSink->auxSDPLine() == NULL\n");
    // try again after a brief delay:
    int uSecsToDelay = 100000; // 100 ms
    nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecsToDelay,
         (TaskFunc*)checkForAuxSDPLine, this);
  }
}

char const* MPEG4VideoRelayMediaSubsession
::getAuxSDPLine(RTPSink* rtpSink, FramedSource* inputSource) {
  // Note: For MPEG-4 video buffer, the 'config' information isn't known
  // until we start reading the Buffer.  This means that "rtpSink"s
  // "auxSDPLine()" will be NULL initially, and we need to start reading
  // data from our buffer until this changes.
  fDummyRTPSink = rtpSink;
    
  // Start reading the buffer:
  fDummyRTPSink->startPlaying(*inputSource, afterPlayingDummy, this);
  
  // Check whether the sink's 'auxSDPLine()' is ready:
  checkForAuxSDPLine(this);
  
  fDoneFlag = 0;
      
  envir().taskScheduler().doEventLoop(&fDoneFlag);
    
  char const* auxSDPLine = fDummyRTPSink->auxSDPLine();
  
  return auxSDPLine;
  //return NULL;
}

FramedSource* MPEG4VideoRelayMediaSubsession
::createNewStreamSource(unsigned /*clientSessionId*/, unsigned& estBitrate)
{
  estBitrate = fEstimatedKbps;
  // Create a framer for the Video Elementary Stream:
  return MPEG4VideoStreamFramer::createNew(envir(), fInput);
}

RTPSink* MPEG4VideoRelayMediaSubsession
::createNewRTPSink(Groupsock* rtpGroupsock,
     unsigned char rtpPayloadTypeIfDynamic,
     FramedSource* /*inputSource*/) {
  return MPEG4ESVideoRTPSink::createNew(envir(), rtpGroupsock,
rtpPayloadTypeIfDynamic);
}

 #############################Makefile (redhat)##########################
INCLUDES = -I../UsageEnvironment/include -I../groupsock/include -I.
/liveMedia/include -I../BasicUsageEnvironment/include
##### Change the following for your environment: 
COMPILE_OPTS =  $(INCLUDES) -I. -O2 -DSOCKLEN_T=socklen_t
-D_LARGEFILE_SOURCE=1
C =   c
C_COMPILER =  cc
C_FLAGS =  $(COMPILE_OPTS)
CPP =   cpp
CPLUSPLUS_COMPILER = c++
CPLUSPLUS_FLAGS = $(COMPILE_OPTS) -Wall -DBSD=1
OBJ =   o
LINK =   c++ -o
LINK_OPTS =  -L.
CONSOLE_LINK_OPTS = $(LINK_OPTS)
LIBRARY_LINK =  ld -o
LIBRARY_LINK_OPTS = $(LINK_OPTS) -r -Bstatic
LIB_SUFFIX =   a
LIBS_FOR_CONSOLE_APPLICATION =
LIBS_FOR_GUI_APPLICATION =
EXE =
##### End of variables to change

UNICAST_APPS = mp4live$(EXE)


ALL = $(UNICAST_APPS)
all: $(ALL)


.$(C).$(OBJ):
 $(C_COMPILER) -c $(C_FLAGS) $<       

.$(CPP).$(OBJ):
 $(CPLUSPLUS_COMPILER) -c $(CPLUSPLUS_FLAGS) $<

MPEG4_VIDEO_STREAMER_OBJS = MPEG4VideoRelayMediaSubsession.$(OBJ)
MP4LIVE_OBJS = mp4live.$(OBJ) 

MPEG4VideoRelayMediaSubsession.$(CPP): MPEG4VideoRelayMediaSubsession.h

USAGE_ENVIRONMENT_DIR = ../UsageEnvironment
USAGE_ENVIRONMENT_LIB = $(USAGE_ENVIRONMENT_DIR)/libUsageEnvironment
$(LIB_SUFFIX)
BASIC_USAGE_ENVIRONMENT_DIR = ../BasicUsageEnvironment
BASIC_USAGE_ENVIRONMENT_LIB =
$(BASIC_USAGE_ENVIRONMENT_DIR)/libBasicUsageEnvironment.$(LIB_SUFFIX)
LIVEMEDIA_DIR = ../liveMedia
LIVEMEDIA_LIB = $(LIVEMEDIA_DIR)/libliveMedia.$(LIB_SUFFIX)
GROUPSOCK_DIR = ../groupsock
GROUPSOCK_LIB = $(GROUPSOCK_DIR)/libgroupsock.$(LIB_SUFFIX)
LOCAL_LIBS = $(LIVEMEDIA_LIB) $(GROUPSOCK_LIB) \
  $(USAGE_ENVIRONMENT_LIB) $(BASIC_USAGE_ENVIRONMENT_LIB)
LIBS =   $(LOCAL_LIBS) $(LIBS_FOR_CONSOLE_APPLICATION)

mp4live$(EXE): $(MP4LIVE_OBJS) $(MPEG4_VIDEO_STREAMER_OBJS) $(LOCAL_LIBS)
 $(LINK)$@ $(CONSOLE_LINK_OPTS) $(MP4LIVE_OBJS) $(MPEG4_VIDEO_STREAMER_OBJS)
 $(LIBS)

clean:
 -rm -rf *.$(OBJ) $(ALL) core *.core *~ include/*~
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.live555.com/pipermail/live-devel/attachments/20060421/4be2d76c/attachment.html 


More information about the live-devel mailing list