本文整理汇总了C++中MediaSubsession::rtcpInstance方法的典型用法代码示例。如果您正苦于以下问题:C++ MediaSubsession::rtcpInstance方法的具体用法?C++ MediaSubsession::rtcpInstance怎么用?C++ MediaSubsession::rtcpInstance使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类MediaSubsession
的用法示例。
在下文中一共展示了MediaSubsession::rtcpInstance方法的11个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: shutdownStream
void shutdownStream(RTSPClient* rtspClient, int exitCode) {
(void)exitCode;
// UsageEnvironment& env = rtspClient->envir(); // alias
StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias
int channel = ((ourRTSPClient*)rtspClient)->_channel;
while(pthread_mutex_lock(&g_context[channel].mutex) != 0 && errno == EINTR){};
// First, check whether any subsessions have still to be closed:
if (scs.session != NULL) {
Boolean someSubsessionsWereActive = False;
MediaSubsessionIterator iter(*scs.session);
MediaSubsession* subsession;
while ((subsession = iter.next()) != NULL) {
if (subsession->sink != NULL) {
Medium::close(subsession->sink);
subsession->sink = NULL;
if (subsession->rtcpInstance() != NULL) {
subsession->rtcpInstance()->setByeHandler(NULL, NULL); // in case the server sends a RTCP "BYE" while handling "TEARDOWN"
}
someSubsessionsWereActive = True;
}
}
if (someSubsessionsWereActive) {
// Send a RTSP "TEARDOWN" command, to tell the server to shutdown the stream.
// Don't bother handling the response to the "TEARDOWN".
rtspClient->sendTeardownCommand(*scs.session, NULL);
}
}
// env << *rtspClient << "Closing the stream.\n";
Medium::close(rtspClient);
// Note that this will also cause this stream's "StreamClientState" structure to get reclaimed.
//if (--rtspClientCount == 0)
{
// The final stream has ended, so exit the application now.
// (Of course, if you're embedding this code into your own application, you might want to comment this out,
// and replace it with "eventLoopWatchVariable = 1;", so that we leave the LIVE555 event loop, and continue running "main()".)
// exit(exitCode);
g_context[channel].shutdown = true;
g_context[channel].eventLoopVar = 1;
}
while(pthread_mutex_unlock(&g_context[channel].mutex) != 0 && errno == EINTR){};
}
示例2: iter
AVIFileSink::AVIFileSink(UsageEnvironment& env,
MediaSession& inputSession,
char const* outputFileName,
unsigned bufferSize,
unsigned short movieWidth, unsigned short movieHeight,
unsigned movieFPS, Boolean packetLossCompensate)
: Medium(env), fInputSession(inputSession),
fIndexRecordsHead(NULL), fIndexRecordsTail(NULL), fNumIndexRecords(0),
fBufferSize(bufferSize), fPacketLossCompensate(packetLossCompensate),
fAreCurrentlyBeingPlayed(False), fNumSubsessions(0), fNumBytesWritten(0),
fHaveCompletedOutputFile(False),
fMovieWidth(movieWidth), fMovieHeight(movieHeight), fMovieFPS(movieFPS) {
fOutFid = OpenOutputFile(env, outputFileName);
if (fOutFid == NULL) return;
// Set up I/O state for each input subsession:
MediaSubsessionIterator iter(fInputSession);
MediaSubsession* subsession;
while ((subsession = iter.next()) != NULL) {
// Ignore subsessions without a data source:
FramedSource* subsessionSource = subsession->readSource();
if (subsessionSource == NULL) continue;
// If "subsession's" SDP description specified screen dimension
// or frame rate parameters, then use these.
if (subsession->videoWidth() != 0) {
fMovieWidth = subsession->videoWidth();
}
if (subsession->videoHeight() != 0) {
fMovieHeight = subsession->videoHeight();
}
if (subsession->videoFPS() != 0) {
fMovieFPS = subsession->videoFPS();
}
AVISubsessionIOState* ioState
= new AVISubsessionIOState(*this, *subsession);
subsession->miscPtr = (void*)ioState;
// Also set a 'BYE' handler for this subsession's RTCP instance:
if (subsession->rtcpInstance() != NULL) {
subsession->rtcpInstance()->setByeHandler(onRTCPBye, ioState);
}
++fNumSubsessions;
}
// Begin by writing an AVI header:
addFileHeader_AVI();
}
示例3: iter
void CAimer39RTSPClient::shutdownStream( RTSPClient* rtspClient )
{
UsageEnvironment& env = rtspClient->envir(); // alias
StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias
CAimer39RTSPClient * arc = findClient( (ourRTSPClient*)rtspClient );
if ( NULL == arc ) {
env << "some how the system in to a dangerous situation!" << "\n";
return;
}
// First, check whether any subsessions have still to be closed:
if (scs.session != NULL) {
Boolean someSubsessionsWereActive = False;
MediaSubsessionIterator iter(*scs.session);
MediaSubsession* subsession;
while ((subsession = iter.next()) != NULL) {
if (subsession->sink != NULL) {
Medium::close(subsession->sink);
subsession->sink = NULL;
if (subsession->rtcpInstance() != NULL) {
subsession->rtcpInstance()->setByeHandler(NULL, NULL); // in case the server sends a RTCP "BYE" while handling "TEARDOWN"
}
someSubsessionsWereActive = True;
}
}
if (someSubsessionsWereActive) {
// Send a RTSP "TEARDOWN" command, to tell the server to shutdown the stream.
// Don't bother handling the response to the "TEARDOWN".
rtspClient->sendTeardownCommand(*scs.session, NULL);
}
}
env << *rtspClient << "Closing the stream.\n";
arc->m_bIsShutDown = true;
if (arc->m_pFinishCallback) arc->m_pFinishCallback(arc->m_pCallBackParam, arc); //call back inform stream over
Medium::close(rtspClient);
// Note that this will also cause this stream's "StreamClientState" structure to get reclaimed.
}
示例4: shutdownStream
// Used to shut down and close a stream (including its "RTSPClient" object):
void StreamClient::shutdownStream()
{
// First, check whether any subsessions have still to be closed:
if (_state.session != nullptr) {
Boolean someSubsessionsWereActive = False;
MediaSubsessionIterator iter(*_state.session);
MediaSubsession * subsession = nullptr;
while ((subsession = iter.next()) != nullptr) {
if (subsession->sink != nullptr) {
Medium::close(subsession->sink);
subsession->sink = nullptr;
if (subsession->rtcpInstance() != nullptr) {
subsession->rtcpInstance()->setByeHandler(nullptr, nullptr); // in case the server sends a RTCP "BYE" while handling "TEARDOWN"
}
someSubsessionsWereActive = True;
}
}
if (someSubsessionsWereActive) {
sendTeardown(*_state.session);
}
}
crLogN("StreamClient::shutdownStream() Closing the stream.");
Medium::close(this);
// Note that this will also cause this stream's "StreamClientState" structure to get reclaimed.
// if (--rtspClientCount == 0) {
// // The final stream has ended, so exit the application now.
// // (Of course, if you're embedding this code into your own application, you might want to comment this out,
// // and replace it with "eventLoopWatchVariable = 1;", so that we leave the LIVE555 event loop, and continue running "main()".)
// exit(exitCode);
// }
exit(0);
}
示例5: MediaNet_Thread
//.........这里部分代码省略.........
}
}
}
if (!madeProgress)
break;
// Perform additional 'setup' on each subsession, before playing them:
pThis->SetRtspStatus( RTSPStatus_Setup );
unsigned nResponseCode = NULL;
BOOL bSetupSuccess = setupStreams( &nResponseCode );
if ( !bSetupSuccess )
{
// setup失败!
if ( RTSPResp_Error_Server_Full == nResponseCode )
{
pThis->SetRtspStatus( RTSPStatus_Error_Server_Full );
}
else
{
pThis->SetRtspStatus( RTSPStatus_Idle );
}
break;
}
// Create output files:
if ( true )
{
// Create and start "FileSink"s for each subsession:
madeProgress = False;
iter.reset();
while ((subsession = iter.next()) != NULL)
{
if (subsession->readSource() == NULL) continue; // was not initiated
MediaSink *pDecodeSink = 0;
if (strcmp(subsession->mediumName(), "video") == 0 )
{
int nBandWidth = subsession->GetBandWidth();
if ( strcmp(subsession->codecName(), "MP4V-ES") == 0 )
{
CMpeg4StreamDecodeSink *pMsds = CMpeg4StreamDecodeSink::CreateNew( *env, 20000, nBandWidth );
pDecodeSink = pMsds;
}
else if ( strcmp( subsession->codecName(), "H264" ) == 0 )
{
CH264StreamDecodeSink *pHsds = CH264StreamDecodeSink::CreateNew( *env, 20000, nBandWidth );
pDecodeSink = pHsds;
}
else
{
continue;
}
}
subsession->sink = pDecodeSink;
if (subsession->sink == NULL)
{
*env << "Failed to create CH264StreamDecodeSink \"" << "\n";
}
subsession->sink->startPlaying(*(subsession->readSource()),
subsessionAfterPlaying,
subsession);
// Also set a handler to be called if a RTCP "BYE" arrives
// for this subsession:
if (subsession->rtcpInstance() != NULL)
{
subsession->rtcpInstance()->setByeHandler(subsessionByeHandler,
subsession);
}
// 发送NAT探测包。
unsigned char temp[112] = {0};
temp[0] = 0x80;
subsession->rtpSource()->RTPgs()->output( *env, 0,temp, 112 );
madeProgress = True;
}
}
// Finally, start playing each subsession, to start the data flow:
pThis->SetRtspStatus( RTSPStatus_Play );
startPlayingStreams();
pThis->SetRtspStatus( RTSPStatus_Running );
// 传入结束标志指针。
env->taskScheduler().doEventLoop( &pThis->m_runFlag );
pThis->SetRtspStatus( RTSPStatus_Idle );
} while(0);
return 0;
}
示例6: handSetup
bool MtkRTSPClient::handSetup(char* resultString)
{
CHECK_NULL_COND(session, false);
CHECK_NULL_COND(rtsp::env, false);
bool bSuccess = false;
// Then, setup the "RTPSource"s for the session:
MediaSubsessionIterator iter(*(session));
MediaSubsession *subsession = NULL;
while ((subsession = iter.next()) != NULL)
{
if (subsession->readSource() == NULL)
{
LOG_ERR("warning");
continue; // was not initiated
}
if (subsession->sink != NULL)/*already be set*/
{
continue;
}
unsigned int type = getBufType(subsession);
if (type == 0)
{
LOG_ERR("error type=%d", type);
continue;
}
{
iSetupCount--;
/*set mediay info*/
setMediaInfo(subsession, type);
}
CmpbSink *sink = NULL;
if ((type != mediatype_audio) && (strcmp(subsession->codecName(), "H264") == 0))
{
sink = CmpbH264Sink::createNew(*env, *subsession, type, fileSinkBufferSize);
}
else if ((type == mediatype_audio) &&
((stMediaInfo.audioCodec == MEDIACODEC_AC3) ||
(stMediaInfo.audioCodec == MEDIACODEC_EAC3) ||
(stMediaInfo.audioCodec == MEDIACODEC_MPEG4_GENERIC)))
{
sink = CmpbAACSink::createNew(*env, *subsession, type, fileSinkBufferSize);
}
else if ((type == mediatype_audio) && (stMediaInfo.audioCodec == MEDIACODEC_MP4A_LATM))
{
sink = CmpbLATMSink::createNew(*env, *subsession, type, fileSinkBufferSize);
}
else
{
sink = CmpbSink::createNew(*env, *subsession, type, fileSinkBufferSize);
}
subsession->sink = sink;
if (subsession->sink == NULL)
{
LOG_ERR("error!");
}
else
{
#if 0 /*this should be remove to cmpb sink*/
if ((type != mediatype_audio) && (strcmp(subsession->codecName(), "MP4V-ES") == 0)
&& (subsession->fmtp_config() != NULL))
{
// For MPEG-4 video RTP streams, the 'config' information
// from the SDP description contains useful VOL etc. headers.
// Insert this data at the front of the output file:
unsigned configLen;
unsigned char* configData
= parseGeneralConfigStr(subsession->fmtp_config(), configLen);
struct timeval timeNow;
gettimeofday(&timeNow, NULL);
sink->sendData(configData, configLen, timeNow);
delete[] configData;
}
#endif
subsession->sink->startPlaying(*(subsession->readSource()),
subsessionAfterPlaying,
subsession);
// Also set a handler to be called if a RTCP "BYE" arrives
// for this subsession:
if (subsession->rtcpInstance() != NULL)
{
subsession->rtcpInstance()->setByeHandler(subsessionAfterPlaying, subsession);
}
bSuccess = true;
}
break;
}
if (iSetupCount == 0)
{
mediaInfoReady();
}
//.........这里部分代码省略.........
示例7: shutdownStream
void shutdownStream(RTSPClient* rtspClient, int exitCode) {
OUTPUT_DEBUG_STRING("%s \n", __FUNCTION__);
OUTPUT_DEBUG_STRING("open times = %d close times = %d\n", open_times, ++close_times);
UsageEnvironment& env = rtspClient->envir(); // alias
StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias
// First, check whether any subsessions have still to be closed:
if (scs.session != NULL) {
Boolean someSubsessionsWereActive = False;
MediaSubsessionIterator iter(*scs.session);
MediaSubsession* subsession;
while ((subsession = iter.next()) != NULL) {
if (subsession->sink != NULL) {
//subsession->sink->stopPlaying();
Medium::close(subsession->sink);
subsession->sink = NULL;
OUTPUT_DEBUG_STRING("22 add = %d, del = %d\n", sum_add, ++sum_del);
if (subsession->rtcpInstance() != NULL) {
subsession->rtcpInstance()->setByeHandler(NULL, NULL); // in case the server sends a RTCP "BYE" while handling "TEARDOWN"
}
someSubsessionsWereActive = True;
}
}
if (someSubsessionsWereActive) {
// Send a RTSP "TEARDOWN" command, to tell the server to shutdown the stream.
// Don't bother handling the response to the "TEARDOWN".
//gEnv->taskScheduler().unscheduleDelayedTask(scs.streamTimerTask);
rtspClient->sendTeardownCommand(*scs.session, NULL);
}
//Medium::close(scs.session);
//gEnv->taskScheduler().unscheduleDelayedTask(scs.streamTimerTask);
Medium::close(rtspClient);
rtspClient = NULL;
//gEnv->reclaim(); //del by huguohu
//gEnv = NULL;
if(gScheduler != NULL){
delete gScheduler;
gScheduler = NULL;
}
}
//env << *rtspClient << "Closing the stream.\n";
//Medium::close(scs.session);
// Note that this will also cause this stream's "StreamClientState" structure to get reclaimed.
//
// if (--rtspClientCount == 0) {
// // The final stream has ended, so exit the application now.
// // (Of course, if you're embedding this code into your own application, you might want to comment this out,
// // and replace it with "eventLoopWatchVariable = 1;", so that we leave the LIVE555 event loop, and continue running "main()".)
// //exit(exitCode);
// }
}
示例8: OpenStream
//.........这里部分代码省略.........
if (desiredPortNum != 0)
{
subsession->setClientPortNum(desiredPortNum);
desiredPortNum += 2;
}
if (createReceivers)
{
if (!subsession->initiate(simpleRTPoffsetArg))
{
XBMC->Log(LOG_DEBUG, "Unable to create receiver for %s %s %s" ,subsession->mediumName(),subsession->codecName(),m_env->getResultMsg());
}
else
{
XBMC->Log(LOG_DEBUG, "Created receiver for type=%s codec=%s ports: %d %d " ,subsession->mediumName(),subsession->codecName(),subsession->clientPortNum(),subsession->clientPortNum()+1 );
madeProgress = True;
if (subsession->rtpSource() != NULL)
{
// Because we're saving the incoming data, rather than playing
// it in real time, allow an especially large time threshold
// (1 second) for reordering misordered incoming packets:
int socketNum= subsession->rtpSource()->RTPgs()->socketNum();
XBMC->Log(LOG_DEBUG, "rtsp:increaseReceiveBufferTo to 2000000 for s:%d",socketNum);
increaseReceiveBufferTo( *m_env, socketNum, 2000000 );
unsigned const thresh = 1000000; // 1 second
subsession->rtpSource()->setPacketReorderingThresholdTime(thresh);
if (socketInputBufferSize > 0)
{
// Set the RTP source's input buffer size as specified:
int socketNum= subsession->rtpSource()->RTPgs()->socketNum();
unsigned curBufferSize= getReceiveBufferSize(*m_env, socketNum);
unsigned newBufferSize= setReceiveBufferTo(*m_env, socketNum, socketInputBufferSize);
XBMC->Log(LOG_DEBUG, "Changed socket receive buffer size for the %s %s %d %d",
subsession->mediumName(),subsession->codecName(),curBufferSize,newBufferSize);
}
}
}
}
else
{
if (subsession->clientPortNum() == 0)
{
XBMC->Log(LOG_DEBUG, "No client port was specified for the %s %s",subsession->mediumName(),subsession->codecName());
}
else
{
madeProgress = True;
}
}
}
if (!madeProgress)
{
shutdown();
return false;
}
// Perform additional 'setup' on each subsession, before playing them:
if (!setupStreams())
{
return false;
}
// Create output files:
// Create and start "FileSink"s for each subsession:
madeProgress = False;
iter.reset();
while ((subsession = iter.next()) != NULL)
{
if (subsession->readSource() == NULL) continue; // was not initiated
// Mediaportal:
CMemorySink* fileSink= CMemorySink::createNew(*m_env, *m_buffer, fileSinkBufferSize);
// XBMC test via file:
//FileSink* fileSink = FileSink::createNew(*m_env, m_outFileName, fileSinkBufferSize, false); //oneFilePerFrame
subsession->sink = fileSink;
if (subsession->sink == NULL)
{
XBMC->Log(LOG_DEBUG, "Failed to create FileSink %s",m_env->getResultMsg());
shutdown();
return false;
}
XBMC->Log(LOG_DEBUG, "Created output sink: %s", m_outFileName);
subsession->sink->startPlaying(*(subsession->readSource()),my_subsessionAfterPlaying,subsession);
// Also set a handler to be called if a RTCP "BYE" arrives
// for this subsession:
if (subsession->rtcpInstance() != NULL)
{
subsession->rtcpInstance()->setByeHandler(my_subsessionByeHandler,subsession);
}
madeProgress = True;
}
return true;
}
示例9: OpenConnection
//.........这里部分代码省略.........
if (result != STATUS_OK)
{
// error occured
TCHAR *message = FormatString(METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("error while setup subsession"));
this->LogRtspMessage(LOGGER_ERROR, message);
FREE_MEM(message);
}
else
{
this->logger.Log(LOGGER_WARNING, METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("subsession audio codec not supported"));
}
}
else if (_tcsncicmp(subSessionName, _T("video"), 5) == 0)
{
// video
this->logger.Log(LOGGER_VERBOSE, _T("%s: %s: video subsession '%s'"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, subSessionName);
result |= (!rtspClient->setupMediaSubsession(*subsession));
if (result != STATUS_OK)
{
// error occured
TCHAR *message = FormatString(METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("error while setup subsession"));
this->LogRtspMessage(LOGGER_ERROR, message);
FREE_MEM(message);
}
else
{
if (_tcsncicmp(subSessionCodecName, _T("MP2T"), 4) == 0)
{
// MPEG2 Transport Stream
// set new RTSP source
this->rtspSource = subsession->rtpSource();
if (subsession->rtcpInstance() != NULL)
{
this->logger.Log(LOGGER_VERBOSE, METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("set subsession 'Bye' handler"));
subsession->rtcpInstance()->setByeHandler(SubsessionByeHandler, this);
}
}
else if (_tcsncicmp(subSessionCodecName, _T("H264"), 4) == 0)
{
// H264 codec, HD TV
this->logger.Log(LOGGER_ERROR, METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("H264 not supported"));
result = STATUS_ERROR;
}
else
{
// SD TV
this->logger.Log(LOGGER_ERROR, METHOD_MESSAGE_FORMAT, PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, _T("other subsession video codec than MP2T not supported"));
result = STATUS_ERROR;
}
}
}
else
{
this->logger.Log(LOGGER_WARNING, _T("%s: %s: unknown subsession '%s', ignored"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, subSessionName);
}
}
else
{
this->logger.Log(LOGGER_WARNING, _T("%s: %s: subsession '%s' doesn't have RTP source"), PROTOCOL_IMPLEMENTATION_NAME, METHOD_OPEN_CONNECTION_NAME, subSessionName);
}
}
// free subsession name and codec name
FREE_MEM(subSessionName);
示例10: iter
Boolean MediaSession
::initiateByMediaType(char const* mimeType,
MediaSubsession*& resultSubsession,
PrioritizedRTPStreamSelector*& resultMultiSource,
int& resultMultiSourceSessionId,
int useSpecialRTPoffset) {
// Look through this session's subsessions for media that match "mimeType"
resultSubsession = NULL;
resultMultiSource = NULL;
resultMultiSourceSessionId = 0;
unsigned maxStaggerSeconds = 0;
MediaSubsessionIterator iter(*this);
MediaSubsession* subsession;
while ((subsession = iter.next()) != NULL) {
if (resultMultiSourceSessionId != 0
&& subsession->mctSLAPSessionId() != resultMultiSourceSessionId) {
// We're using a multi-source SLAP session, but this subsession
// isn't part of it
continue;
}
Boolean wasAlreadyInitiated = subsession->readSource() != NULL;
if (!wasAlreadyInitiated) {
// Try to create a source for this subsession:
if (!subsession->initiate(useSpecialRTPoffset)) return False;
}
// Make sure the source's MIME type is one that we handle:
if (strcmp(subsession->readSource()->MIMEtype(), mimeType) != 0) {
if (!wasAlreadyInitiated) subsession->deInitiate();
continue;
}
if (subsession->mctSLAPSessionId() == 0) {
// Normal case: a single session
resultSubsession = subsession;
break; // use this
} else {
// Special case: a multi-source SLAP session
resultMultiSourceSessionId = subsession->mctSLAPSessionId();
unsigned subsessionStaggerSeconds = subsession->mctSLAPStagger();
if (subsessionStaggerSeconds > maxStaggerSeconds) {
maxStaggerSeconds = subsessionStaggerSeconds;
}
}
}
if (resultSubsession == NULL && resultMultiSourceSessionId == 0) {
envir().setResultMsg("Session has no usable media subsession");
return False;
}
if (resultMultiSourceSessionId != 0) {
// We have a multi-source MCT SLAP session; create a selector for it:
unsigned seqNumStagger = computeSeqNumStagger(maxStaggerSeconds);
resultMultiSource
= PrioritizedRTPStreamSelector::createNew(envir(), seqNumStagger);
if (resultMultiSource == NULL) return False;
// Note: each subsession has its own RTCP instance; we don't return them
// Then run through the subsessions again, adding each of the sources:
iter.reset();
while ((subsession = iter.next()) != NULL) {
if (subsession->mctSLAPSessionId() == resultMultiSourceSessionId) {
resultMultiSource->addInputRTPStream(subsession->rtpSource(),
subsession->rtcpInstance());
}
}
}
return True;
}
示例11: main
//.........这里部分代码省略.........
fileSinkBufferSize,
movieWidth, movieHeight,
movieFPS,
packetLossCompensate);
if (aviOut == NULL) {
*env << "Failed to create AVI file sink for stdout: " << env->getResultMsg();
shutdown();
}
aviOut->startPlaying(sessionAfterPlaying, NULL);
} else {
// Create and start "FileSink"s for each subsession:
madeProgress = False;
iter.reset();
while ((subsession = iter.next()) != NULL) {
if (subsession->readSource() == NULL) continue; // was not initiated
// Create an output file for each desired stream:
char outFileName[1000];
if (singleMedium == NULL) {
// Output file name is
// "<filename-prefix><medium_name>-<codec_name>-<counter>"
static unsigned streamCounter = 0;
snprintf(outFileName, sizeof outFileName, "%s%s-%s-%d",
fileNamePrefix, subsession->mediumName(),
subsession->codecName(), ++streamCounter);
} else {
sprintf(outFileName, "stdout");
}
FileSink* fileSink;
if (strcmp(subsession->mediumName(), "audio") == 0 &&
(strcmp(subsession->codecName(), "AMR") == 0 ||
strcmp(subsession->codecName(), "AMR-WB") == 0)) {
// For AMR audio streams, we use a special sink that inserts AMR frame hdrs:
fileSink = AMRAudioFileSink::createNew(*env, outFileName,
fileSinkBufferSize, oneFilePerFrame);
} else if (strcmp(subsession->mediumName(), "video") == 0 &&
(strcmp(subsession->codecName(), "H264") == 0)) {
// For H.264 video stream, we use a special sink that insert start_codes:
fileSink = H264VideoFileSink::createNew(*env, outFileName,
fileSinkBufferSize, oneFilePerFrame);
} else {
// Normal case:
fileSink = FileSink::createNew(*env, outFileName,
fileSinkBufferSize, oneFilePerFrame);
}
subsession->sink = fileSink;
if (subsession->sink == NULL) {
*env << "Failed to create FileSink for \"" << outFileName
<< "\": " << env->getResultMsg() << "\n";
} else {
if (singleMedium == NULL) {
*env << "Created output file: \"" << outFileName << "\"\n";
} else {
*env << "Outputting data from the \"" << subsession->mediumName()
<< "/" << subsession->codecName()
<< "\" subsession to 'stdout'\n";
}
if (strcmp(subsession->mediumName(), "video") == 0 &&
strcmp(subsession->codecName(), "MP4V-ES") == 0 &&
subsession->fmtp_config() != NULL) {
// For MPEG-4 video RTP streams, the 'config' information
// from the SDP description contains useful VOL etc. headers.
// Insert this data at the front of the output file:
unsigned configLen;
unsigned char* configData
= parseGeneralConfigStr(subsession->fmtp_config(), configLen);
struct timeval timeNow;
gettimeofday(&timeNow, NULL);
fileSink->addData(configData, configLen, timeNow);
delete[] configData;
}
subsession->sink->startPlaying(*(subsession->readSource()),
subsessionAfterPlaying,
subsession);
// Also set a handler to be called if a RTCP "BYE" arrives
// for this subsession:
if (subsession->rtcpInstance() != NULL) {
subsession->rtcpInstance()->setByeHandler(subsessionByeHandler,
subsession);
}
madeProgress = True;
}
}
if (!madeProgress) shutdown();
}
}
// Finally, start playing each subsession, to start the data flow:
startPlayingStreams();
env->taskScheduler().doEventLoop(); // does not return
return 0; // only to prevent compiler warning
}