[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