Example #1
0
void continueAfterDESCRIBE(RTSPClient* rtspClient, int resultCode, char* resultString) {
  do {
    UsageEnvironment& env = rtspClient->envir(); // alias
    StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias

    if (resultCode != 0) {
      env << *rtspClient << "Failed to get a SDP description: " << resultString << "\n";
      break;
    }

    char* const sdpDescription = resultString;
    env << *rtspClient << "Got a SDP description:\n" << sdpDescription << "\n";

    // Create a media session object from this SDP description:
    scs.session = MediaSession::createNew(env, sdpDescription);
    delete[] sdpDescription; // because we don't need it anymore
    if (scs.session == NULL) {
      env << *rtspClient << "Failed to create a MediaSession object from the SDP description: " << env.getResultMsg() << "\n";
      break;
    } else if (!scs.session->hasSubsessions()) {
      env << *rtspClient << "This session has no media subsessions (i.e., no \"m=\" lines)\n";
      break;
    }

    // Then, create and set up our data source objects for the session.  We do this by iterating over the session's 'subsessions',
    // calling "MediaSubsession::initiate()", and then sending a RTSP "SETUP" command, on each one.
    // (Each 'subsession' will have its own data source.)
    scs.iter = new MediaSubsessionIterator(*scs.session);
    setupNextSubsession(rtspClient);
    return;
  } while (0);

  // An unrecoverable error occurred with this stream.
  shutdownStream(rtspClient);
}
void setupNextSubsession(RTSPClient* rtspClient) {
  UsageEnvironment& env = rtspClient->envir(); // alias
  StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias
  
  scs.subsession = scs.iter->next();
  if (scs.subsession != NULL) {
    if (!scs.subsession->initiate()) {
      env << *rtspClient << "Failed to initiate the \"" << *scs.subsession << "\" subsession: " << env.getResultMsg() << "\n";
      setupNextSubsession(rtspClient); // give up on this subsession; go to the next one
    } else {
      env << *rtspClient << "Initiated the \"" << *scs.subsession
	  << "\" subsession (client ports " << scs.subsession->clientPortNum() << "-" << scs.subsession->clientPortNum()+1 << ")\n";

      // Continue setting up this subsession, by sending a RTSP "SETUP" command:
      rtspClient->sendSetupCommand(*scs.subsession, continueAfterSETUP);
    }
    return;
  }

  // We've finished setting up all of the subsessions.  Now, send a RTSP "PLAY" command to start the streaming:
  if (scs.session->absStartTime() != NULL) {
    // Special case: The stream is indexed by 'absolute' time, so send an appropriate "PLAY" command:
    rtspClient->sendPlayCommand(*scs.session, continueAfterPLAY, scs.session->absStartTime(), scs.session->absEndTime());
  } else {
    scs.duration = scs.session->playEndTime() - scs.session->playStartTime();
    rtspClient->sendPlayCommand(*scs.session, continueAfterPLAY);
  }
}
Example #3
0
/*!
 * \brief Sets up the next subsession which is stored in the scs.subsession object.
 *
 * This function sends the rtsp SETUP command to the source and sets up the callback function (continueAfterSETUP)
 * Changes by the author: If the subsession isn't a MotionJPEG, dismiss it.
 * \param rtspClient Environment vars
 */
void setupNextSubsession(RTSPClient* rtspClient) {
    scs.subsession = scs.iter->next();
    std::string result = scs.subsession->mediumName();        //Get the medium name
    std::string encoding = scs.subsession->codecName();
    if ((scs.subsession != NULL) && (result != "audio") && (encoding == "JPEG")) {     //We don't want audio. We want JPEG video for now, so ignore the rest
        if (!scs.subsession->initiate()) {
            *env << *rtspClient << "Failed to initiate the \"" << *scs.subsession << "\" subsession: " << *env->getResultMsg() << "\n";
            setupNextSubsession(rtspClient); // give up on this subsession; go to the next one
        } else {
            *env << *rtspClient << "Initiated the \"" << *scs.subsession
                 << "\" subsession (client ports " << scs.subsession->clientPortNum() << "-" << scs.subsession->clientPortNum()+1 << ")\n";
            // Continue setting up this subsession, by sending a RTSP "SETUP" command:
            rtspClient->sendSetupCommand(*scs.subsession, continueAfterSETUP, False, REQUEST_STREAMING_OVER_TCP);
            //  }
        }
        return;
    }

    // We've finished setting up all of the subsessions.  Now, send a RTSP "PLAY" command to start the streaming:
    if (scs.session->absStartTime() != NULL) {
        // Special case: The stream is indexed by 'absolute' time, so send an appropriate "PLAY" command:
        rtspClient->sendPlayCommand(*scs.session, continueAfterPLAY, scs.session->absStartTime(), scs.session->absEndTime());
    } else {
        scs.duration = scs.session->playEndTime() - scs.session->playStartTime();
        rtspClient->sendPlayCommand(*scs.session, continueAfterPLAY);
    }
}
Example #4
0
void setupNextSubsession(RTSPClient* rtspClient) {
  UsageEnvironment& env = rtspClient->envir(); // alias
  StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias
  
  scs.subsession = scs.iter->next();
  if (scs.subsession != NULL) {
    if (!scs.subsession->initiate()) {
      env << *rtspClient << "Failed to initiate the \"" << *scs.subsession << "\" subsession: " << env.getResultMsg() << "\n";
      setupNextSubsession(rtspClient); // give up on this subsession; go to the next one
    } else {
     // env << *rtspClient << "Initiated the \"" << *scs.subsession
	 // << "\" subsession (client ports " << scs.subsession->clientPortNum() << "-" << scs.subsession->clientPortNum()+1 << ")\n";

      // Continue setting up this subsession, by sending a RTSP "SETUP" command:
	  char tranProtocol	= ((ourRTSPClient*)rtspClient)->_tranProtocol;
      rtspClient->sendSetupCommand(*scs.subsession, continueAfterSETUP, false, tranProtocol == 0, tranProtocol == 2);
     // rtspClient->sendSetupCommand(*scs.subsession, continueAfterSETUP, false, true);
    }
    return;
  }

  // We've finished setting up all of the subsessions.  Now, send a RTSP "PLAY" command to start the streaming:
  scs.duration = scs.session->playEndTime() - scs.session->playStartTime();
  rtspClient->sendPlayCommand(*scs.session, continueAfterPLAY);
}
void setupNextSubsession(RTSPClient* rtspClient) {
    UsageEnvironment& env = rtspClient->envir(); // alias
    StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias
    
    scs.subsession = scs.iter->next();
    if (scs.subsession != NULL) {
        if ( strcmp(scs.subsession->mediumName(),"audio") != 0 ||
        	(scs.subsession->getFlag() == 0 && bEnableBackChannel)	// flag= 0:receive only 1:send only
        		|| !scs.subsession->initiate()) {
            env << *rtspClient << "Failed to initiate the \"" << *scs.subsession << "\" subsession: " << env.getResultMsg() << "\n";
            setupNextSubsession(rtspClient); // give up on this subsession; go to the next one
        } else {
            env << *rtspClient << "Initiated the \"" << *scs.subsession
            << "\" subsession (client ports " << scs.subsession->clientPortNum() << "-" << scs.subsession->clientPortNum()+1 << ")\n";
            
            // 20140625 albert.liao modified start
            // Continue setting up this subsession, by sending a RTSP "SETUP" command:
            rtspClient->sendSetupCommand(*scs.subsession, continueAfterSETUP, False, REQUEST_STREAMING_OVER_TCP);
            
            // TODO: rtsp server should create PassiveServerMediaSubsession,
            // so that multicast can work
            //            rtspClient->sendSetupCommand(*scs.subsession,
            //                                         continueAfterSETUP,
            //                                         False,//True, /* streamOutgoing, for darwin */
            //                                         REQUEST_STREAMING_OVER_TCP,
            //                                         True, /*Multicast*/
            //                                         NULL);
            // 20140625 albert.liao modified end
        }
        return;
    }

    //startPlay(rtspClient);
    shutdownStream(rtspClient);
}
Example #6
0
void CAimer39RTSPClient::setupNextSubsession(RTSPClient* rtspClient) 
{
	UsageEnvironment& env = rtspClient->envir(); // alias
	StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias
	CAimer39RTSPClient * arc = findClient( (ourRTSPClient*)rtspClient );

	if ( NULL == arc ) {
		arc->m_errorCode = -1;
		env << "some how the system in to a dangerous situation!" << "\n";
		return;
	}

	scs.subsession = scs.iter->next();
	if (scs.subsession != NULL) {
		vector<MediaSubsession *>::iterator iter = arc->m_vecNoNeedStream.begin();
		for ( ; iter != arc->m_vecNoNeedStream.end(); ++iter ) {
			if ( *iter == scs.subsession ) {
				setupNextSubsession(rtspClient); // give up on this subsession; go to the next one
				return;
			}
		}

		if (!scs.subsession->initiate()) {
			env << *rtspClient << "Failed to initiate the \"" << *scs.subsession << "\" subsession: " << env.getResultMsg() << "\n";
			arc->m_errorCode = 3;
			arc->m_lastErrorMsg = env.getResultMsg();
			setupNextSubsession(rtspClient); // give up on this subsession; go to the next one
		} else {
			env << *rtspClient << "Initiated the \"" << *scs.subsession
			<< "\" subsession (client ports " << scs.subsession->clientPortNum() << "-" << scs.subsession->clientPortNum()+1 << ")\n";

			// Continue setting up this subsession, by sending a RTSP "SETUP" command:
			rtspClient->sendSetupCommand(*scs.subsession, continueAfterSETUP);
		}
		return;
	}

	// We've finished setting up all of the subsessions.  Now, send a RTSP "PLAY" command to start the streaming:
	if (scs.session->absStartTime() != NULL) {
		// Special case: The stream is indexed by 'absolute' time, so send an appropriate "PLAY" command:
		rtspClient->sendPlayCommand(*scs.session, continueAfterPLAY, scs.session->absStartTime(), scs.session->absEndTime());
	} else {
		scs.duration = scs.session->playEndTime() - scs.session->playStartTime();
		rtspClient->sendPlayCommand(*scs.session, continueAfterPLAY);
	}
}
void continueAfterSETUP(RTSPClient* rtspClient, int resultCode, char* resultString) {
    do {
        UsageEnvironment& env = rtspClient->envir(); // alias
        StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias
        
        if (resultCode != 0) {
            env << *rtspClient << "Failed to set up the \"" << *scs.subsession << "\" subsession: " << resultString << "\n";
            break;
        }
        
        env << *rtspClient << "Set up the \"" << *scs.subsession
        << "\" subsession (client ports " << scs.subsession->clientPortNum() << "-" << scs.subsession->clientPortNum()+1 << ")\n";
        
        // Having successfully setup the subsession, create a data sink for it, and call "startPlaying()" on it.
        // (This will prepare the data sink to receive data; the actual flow of data from the client won't start happening until later,
        // after we've sent a RTSP "PLAY" command.)
        
        // 20140624 albert.liao modified start
        if(scs.subsession->getFlag()==FLAG_RECVONLY)
        {
            //scs.subsession->sink = DummySink::createNew(env, *scs.subsession, rtspClient->url());
            scs.subsession->sink = FileSink::createNew(env, "back.pcm");
            // perhaps use your own custom "MediaSink" subclass instead
            if (scs.subsession->sink == NULL) {
                env << *rtspClient << "Failed to create a data sink for the \"" << *scs.subsession
                << "\" subsession: " << env.getResultMsg() << "\n";
                break;
            }
            
            env << *rtspClient << "Created a data sink for the \"" << *scs.subsession << "\" subsession\n";
            scs.subsession->miscPtr = rtspClient; // a hack to let subsession handle functions get the "RTSPClient" from the subsession
            scs.subsession->sink->startPlaying(*(scs.subsession->readSource()),
                                               subsessionAfterPlaying, scs.subsession);
        }
        else
        {
            //scs.subsession->sink is equal to scs.subsession->fRTPSink;
            
            env << *rtspClient << "Created a data sink for the \"" << *scs.subsession << "\" subsession\n";
            scs.subsession->miscPtr = rtspClient; // a hack to let subsession handle functions get the "RTSPClient" from the subsession
            
            // This sink is created by function MediaSubsession::createSinkObjects
            scs.subsession->sink->startPlaying(*(scs.subsession->readSource()),
                                               subsessionAfterPlaying, scs.subsession);
        }
        // 20140624 albert.liao modified end
        
        
        // Also set a handler to be called if a RTCP "BYE" arrives for this subsession:
        if (scs.subsession->rtcpInstance() != NULL) {
            scs.subsession->rtcpInstance()->setByeHandler(subsessionByeHandler, scs.subsession);
        }
    } while (0);
    delete[] resultString;
    
    // Set up the next subsession, if any:
    setupNextSubsession(rtspClient);
}
void continueAfterSETUP(RTSPClient* rtspClient, int resultCode, char* resultString) {
  do {
    UsageEnvironment& env = rtspClient->envir(); // alias
    StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias

    if (resultCode != 0) {
      env << *rtspClient << "Failed to set up the \"" << *scs.subsession << "\" subsession: " << env.getResultMsg() << "\n";
      break;
    }

    env << *rtspClient << "Set up the \"" << *scs.subsession
	<< "\" subsession (client ports " << scs.subsession->clientPortNum() << "-" << scs.subsession->clientPortNum()+1 << ")\n";

    // Having successfully setup the subsession, create a data sink for it, and call "startPlaying()" on it.
    // (This will prepare the data sink to receive data; the actual flow of data from the client won't start happening until later,
    // after we've sent a RTSP "PLAY" command.)

    scs.subsession->sink = DummySink::createNew(env, *scs.subsession, rtspClient->url());	

      // perhaps use your own custom "MediaSink" subclass instead
    if (scs.subsession->sink == NULL) {
      env << *rtspClient << "Failed to create a data sink for the \"" << *scs.subsession
	  << "\" subsession: " << env.getResultMsg() << "\n";
      break;
    }

	const char* spandPp= scs.subsession->fmtp_spropparametersets();
	unsigned int  numOfRecords = -1;
	SPropRecord* rec =  parseSPropParameterSets(spandPp, numOfRecords);

	for (unsigned i = 0; i < numOfRecords; ++i)
	{
			unsigned nalUnitSize = rec[i].sPropLength;
			unsigned char* nalUnitBytes = rec[i].sPropBytes;  // this is a byte array, of size "nalUnitSize".
 // Then do whatever you like with this NAL unit data
	}

    env << *rtspClient << "Created a data sink for the \"" << *scs.subsession << "\" subsession\n";
    scs.subsession->miscPtr = rtspClient; // a hack to let subsession handle functions get the "RTSPClient" from the subsession 
    scs.subsession->sink->startPlaying(*(scs.subsession->readSource()),subsessionAfterPlaying, scs.subsession);
	
	
    // Also set a handler to be called if a RTCP "BYE" arrives for this subsession:
    if (scs.subsession->rtcpInstance() != NULL) {
      scs.subsession->rtcpInstance()->setByeHandler(subsessionByeHandler, scs.subsession);
    }
  } while (0);

  	

  // Set up the next subsession, if any:
  setupNextSubsession(rtspClient);
}
void continueAfterSETUP(RTSPClient* rtspClient, int resultCode, char* resultString) {
	OUTPUT_DEBUG_STRING("%s \n", __FUNCTION__);
	do {
		UsageEnvironment& env = rtspClient->envir(); // alias
		StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias

		static int SessionID = 0;

		if (resultCode != 0) {
			OUTPUT_DEBUG_STRING("Failed to set up the subsession: %s \n", \
				resultString);
			//env << *rtspClient << "Failed to set up the \"" << *scs.subsession << "\" subsession: " << resultString << "\n";
			break;
		}

		OUTPUT_DEBUG_STRING("Set up the subsession (client ports %u-%u)\n", \
			scs.subsession->clientPortNum(), scs.subsession->clientPortNum()+1);
		//env << *rtspClient << "Set up the \"" << *scs.subsession << "\" subsession (client ports " << scs.subsession->clientPortNum() << "-" << scs.subsession->clientPortNum()+1 << ")\n";

		// Having successfully setup the subsession, create a data sink for it, and call "startPlaying()" on it.
		// (This will prepare the data sink to receive data; the actual flow of data from the client won't start happening until later,
		// after we've sent a RTSP "PLAY" command.)

		scs.subsession->sink = DummySink::createNew(env, *scs.subsession, rtspClient->url());

		OUTPUT_DEBUG_STRING("add = %d, del = %d\n", ++sum_add, sum_del);

		((DummySink *)scs.subsession)->SetCallBackFunction(gAVDataFun, gLostDetectFun, SessionID, rtspClient);
		SessionID ++;
		// perhaps use your own custom "MediaSink" subclass instead
		if (scs.subsession->sink == NULL) {
			OUTPUT_DEBUG_STRING("Failed to create a data sink for the subsession: %s\n", \
				env.getResultMsg());
			//env << *rtspClient << "Failed to create a data sink for the \"" << *scs.subsession<< "\" subsession: " << env.getResultMsg() << "\n";
			break;
		}
		OUTPUT_DEBUG_STRING("Created a data sink for the subsession\n");
		//env << *rtspClient << "Created a data sink for the \"" << *scs.subsession << "\" subsession\n";
		scs.subsession->miscPtr = rtspClient; // a hack to let subsession handle functions get the "RTSPClient" from the subsession 
		scs.subsession->sink->startPlaying(*(scs.subsession->readSource()),
			subsessionAfterPlaying, scs.subsession);
		// Also set a handler to be called if a RTCP "BYE" arrives for this subsession:
		if (scs.subsession->rtcpInstance() != NULL) {
			scs.subsession->rtcpInstance()->setByeHandler(subsessionByeHandler, scs.subsession);
		}
	} while (0);
	delete[] resultString;

	// Set up the next subsession, if any:
	setupNextSubsession(rtspClient);
}
Example #10
0
/*!
 * \brief Sets up the filesink for a rtsp subsession
 *
 * This function sets up the filesink for a given rtsp subsession, sets up the callback handler continueAfterPLAY() and sends the PLAY-command to the source (requesting it to start sending data, that is).
 * As it is only called after filtering all subsessions, it will be only called, if the given subsession is JPEG-encoded.
 * This ensures that the DBSink inserts only valid data into the DB.
 * > Changes by the author: Included the build process of a variable camname for saving it in the DB.
 * > Scheme: cam<camno>.jpeg
 *
 * \param rtspClient            Environment vars
 * \param resultCode            Result of the rtsp SETUP command
 * \param resultString          Result of the rtsp SETUP command
 */
void continueAfterSETUP(RTSPClient* rtspClient, int resultCode, char* resultString) {
    do {

        if (resultCode != 0) {
            *env << *rtspClient << "Failed to set up the \"" << *scs.subsession << "\" subsession: " << resultString << "\n";
            break;
        }

        *env << *rtspClient << "Set up the \"" << *scs.subsession
             << "\" subsession (client ports " << scs.subsession->clientPortNum() << "-" << scs.subsession->clientPortNum()+1 << ")\n";

        // Having successfully setup the subsession, create a data sink for it, and call "startPlaying()" on it.
        // (This will prepare the data sink to receive data; the actual flow of data from the client won't start happening until later,
        // after we've sent a RTSP "PLAY" command.)


        //Neue Elemente von mir:
        //Wir bauen uns den Camnamen

        std::string camprefix = "cam";
        std::string camsuffix = ".jpeg";
        if(camno == "")
            camno = "xx";

        std::stringstream sstr;
        sstr << camprefix << camno << camsuffix;
        scs.subsession->sink = ExtendedFileSink::createNew(*env, sstr.str() , 60000);

        // Ende Neue Elemente von mir
        if (scs.subsession->sink == NULL) {
            *env << *rtspClient << "Failed to create a data sink for the \"" << *scs.subsession
                 << "\" subsession: " << *env->getResultMsg() << "\n";
            break;
        }
        else
            *env << "Stream creation succeeded! \n";

        *env << *rtspClient << "Created a data sink for the \"" << *scs.subsession << "\" subsession" << "ID: " << scs.subsession->sink->name() << "\n";
        scs.subsession->miscPtr = rtspClient; // a hack to let subsession handle functions get the "RTSPClient" from the subsession
        scs.subsession->sink->startPlaying(*(scs.subsession->readSource()),
                                           subsessionAfterPlaying, scs.subsession);
        // Also set a handler to be called if a RTCP "BYE" arrives for this subsession:
        if (scs.subsession->rtcpInstance() != NULL) {
            scs.subsession->rtcpInstance()->setByeHandler(subsessionByeHandler, scs.subsession);
        }
    } while (0);
    delete[] resultString;

    // Set up the next subsession, if any:
    setupNextSubsession(rtspClient);
}
Example #11
0
void setupNextSubsession(RTSPClient* rtspClient) {

	OUTPUT_DEBUG_STRING("%s \n", __FUNCTION__);
	UsageEnvironment& env = rtspClient->envir(); // alias
	StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias

	scs.subsession = scs.iter->next();
	if (scs.subsession != NULL) {
		if (!scs.subsession->initiate()) {
			//env << *rtspClient << "Failed to initiate the \"" << *scs.subsession << "\" subsession: " << env.getResultMsg() << "\n";
			OUTPUT_DEBUG_STRING("Failed to initiate the \" %p \" subsession: %s \n", *scs.subsession, env.getResultMsg());
			setupNextSubsession(rtspClient); // give up on this subsession; go to the next one
		} else {
			OUTPUT_DEBUG_STRING("Initiated the subsession %p (client ports %u-%u)\n", \
				scs.subsession, \
				scs.subsession->clientPortNum(), \
				scs.subsession->clientPortNum() + 1);

			//env << *rtspClient << "Initiated the \"" << *scs.subsession << "\" subsession (client ports " << scs.subsession->clientPortNum() << "-" << scs.subsession->clientPortNum()+1 << ")\n";

			// Continue setting up this subsession, by sending a RTSP "SETUP" command:

			Boolean stream_over_tcp = False;

			if (gStream_Over_Protocol == STREAMING_OVER_TCP)
			{
				stream_over_tcp = True;
			}
			else if (gStream_Over_Protocol == STREAMING_OVER_UDP)
			{
				stream_over_tcp = False;
			}
			
			
			rtspClient->sendSetupCommand(*scs.subsession, continueAfterSETUP, False, stream_over_tcp);
		}
		return;
	}

	// We've finished setting up all of the subsessions.  Now, send a RTSP "PLAY" command to start the streaming:
	if (scs.session->absStartTime() != NULL) {
		// Special case: The stream is indexed by 'absolute' time, so send an appropriate "PLAY" command:
		rtspClient->sendPlayCommand(*scs.session, continueAfterPLAY, scs.session->absStartTime(), scs.session->absEndTime());
	} else {
		scs.duration = scs.session->playEndTime() - scs.session->playStartTime();
		rtspClient->sendPlayCommand(*scs.session, continueAfterPLAY);
	}
}
Example #12
0
void CAimer39RTSPClient::continueAfterSETUP(RTSPClient* rtspClient, int resultCode, char* resultString) 
{
	do {
		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";
			break;
		}
		
		arc->m_errorCode = resultCode;
		if (resultCode != 0) {
			arc->m_lastErrorMsg = resultString;
			env << *rtspClient << "Failed to set up the \"" << *scs.subsession << "\" subsession: " << resultString << "\n";
			break;
		}

		env << *rtspClient << "Set up the \"" << *scs.subsession
		<< "\" subsession (client ports " << scs.subsession->clientPortNum() << "-" << scs.subsession->clientPortNum()+1 << ")\n";

		// Having successfully setup the subsession, create a data sink for it, and call "startPlaying()" on it.
		// (This will prepare the data sink to receive data; the actual flow of data from the client won't start happening until later,
		// after we've sent a RTSP "PLAY" command.)

		scs.subsession->sink = DummySink::createNew(env, *scs.subsession, arc, rtspClient->url());
		  // perhaps use your own custom "MediaSink" subclass instead
		if (scs.subsession->sink == NULL) {
			env << *rtspClient << "Failed to create a data sink for the \"" << *scs.subsession
			<< "\" subsession: " << env.getResultMsg() << "\n";
			break;
		}

		env << *rtspClient << "Created a data sink for the \"" << *scs.subsession << "\" subsession\n";
		scs.subsession->miscPtr = rtspClient; // a hack to let subsession handle functions get the "RTSPClient" from the subsession 
		scs.subsession->sink->startPlaying(*(scs.subsession->readSource()),
						   subsessionAfterPlaying, scs.subsession);
		// Also set a handler to be called if a RTCP "BYE" arrives for this subsession:
		if (scs.subsession->rtcpInstance() != NULL) {
			scs.subsession->rtcpInstance()->setByeHandler(subsessionByeHandler, scs.subsession);
		}
	} while (0);
	delete[] resultString;

	// Set up the next subsession, if any:
	setupNextSubsession(rtspClient);
}
Example #13
0
int CAimer39RTSPClient::Play()
{
	// Then, create and set up our data source objects for the session.  We do this by iterating over the session's 'subsessions',
	// calling "MediaSubsession::initiate()", and then sending a RTSP "SETUP" command, on each one.
	// (Each 'subsession' will have its own data source.)
	m_pRTSPClient->scs.iter = new MediaSubsessionIterator(*(m_pRTSPClient->scs.session));
	setupNextSubsession( m_pRTSPClient );

	m_bIsPlay = true;
	m_nRecvBytes = 0;
	m_nRecvVideoBytes = 0;
	
	timeval stTime = {0};
	m_StaticClock.start(stTime);
	
	return m_errorCode;
}
Example #14
0
void continueAfterSETUP(RTSPClient* rtspClient, int resultCode, char* resultString) {
	(void)resultString;
  do {
    UsageEnvironment& env = rtspClient->envir(); // alias
    StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias

    if (resultCode != 0) {
      env << *rtspClient << "Failed to set up the \"" << *scs.subsession << "\" subsession: " << env.getResultMsg() << "\n";
      break;
    }

    // env << *rtspClient << "Set up the \"" << *scs.subsession
	//<< "\" subsession (client ports " << scs.subsession->clientPortNum() << "-" << scs.subsession->clientPortNum()+1 << ")\n";

    // Having successfully setup the subsession, create a data sink for it, and call "startPlaying()" on it.
    // (This will prepare the data sink to receive data; the actual flow of data from the client won't start happening until later,
    // after we've sent a RTSP "PLAY" command.)

    scs.subsession->sink = DummySink::createNew(env, *scs.subsession, rtspClient->url());
      // perhaps use your own custom "MediaSink" subclass instead
    if (scs.subsession->sink == NULL) {
      env << *rtspClient << "Failed to create a data sink for the \"" << *scs.subsession
	  << "\" subsession: " << env.getResultMsg() << "\n";
      break;
    }
	ourRTSPClient* ourClient	= (ourRTSPClient*)rtspClient;
	DummySink*	   ourSink		= (DummySink*)scs.subsession->sink;
	ourSink->SetDataCallback(ourClient->_channel, ourClient->_cb);

    // env << *rtspClient << "Created a data sink for the \"" << *scs.subsession << "\" subsession\n";
    scs.subsession->miscPtr = rtspClient; // a hack to let subsession handle functions get the "RTSPClient" from the subsession 
    scs.subsession->sink->startPlaying(*(scs.subsession->readSource()),
				       subsessionAfterPlaying, scs.subsession);
    // Also set a handler to be called if a RTCP "BYE" arrives for this subsession:
    if (scs.subsession->rtcpInstance() != NULL) {
      scs.subsession->rtcpInstance()->setByeHandler(subsessionByeHandler, scs.subsession);
    }
  } while (0);

  // Set up the next subsession, if any:
  setupNextSubsession(rtspClient);
}
void setupNextSubsession(RTSPClient* rtspClient) {
    UsageEnvironment& env = rtspClient->envir(); // alias
    StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias

    scs.subsession = scs.iter->next();
    if (scs.subsession != NULL) {
        if (!scs.subsession->initiate()) {
            env << *rtspClient << "Failed to initiate the \"" << *scs.subsession << "\" subsession: " << env.getResultMsg() << "\n";
            setupNextSubsession(rtspClient); // give up on this subsession; go to the next one
        } else {
            env << *rtspClient << "Initiated the \"" << *scs.subsession
                << "\" subsession (client ports " << scs.subsession->clientPortNum() << "-" << scs.subsession->clientPortNum()+1 << ")\n";

            // 20140625 albert.liao modified start
            // Continue setting up this subsession, by sending a RTSP "SETUP" command:
            rtspClient->sendSetupCommand(*scs.subsession, continueAfterSETUP, False, REQUEST_STREAMING_OVER_TCP);

            // TODO: rtsp server should create PassiveServerMediaSubsession,
            // so that multicast can work
//            rtspClient->sendSetupCommand(*scs.subsession,
//                                         continueAfterSETUP,
//                                         False,//True, /* streamOutgoing, for darwin */
//                                         REQUEST_STREAMING_OVER_TCP,
//                                         True, /*Multicast*/
//                                         NULL);
            // 20140625 albert.liao modified end
        }
        return;
    }

    // We've finished setting up all of the subsessions.  Now, send a RTSP "PLAY" command to start the streaming:
    if (scs.session->absStartTime() != NULL) {
        // Special case: The stream is indexed by 'absolute' time, so send an appropriate "PLAY" command:
        rtspClient->sendPlayCommand(*scs.session, continueAfterPLAY, scs.session->absStartTime(), scs.session->absEndTime());
    } else {
        scs.duration = scs.session->playEndTime() - scs.session->playStartTime();
        rtspClient->sendPlayCommand(*scs.session, continueAfterPLAY);
    }
}
void continueAfterSETUP(RTSPClient* rtspClient, int resultCode, char* resultString) {
  do {
    UsageEnvironment& env = rtspClient->envir(); // alias
    StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias

    if (resultCode != 0) {
      env << *rtspClient << "Failed to set up the \"" << *scs.subsession << "\" subsession: " << resultString << "\n";
      break;
    }

    env << *rtspClient << "Set up the \"" << *scs.subsession
	<< "\" subsession (client ports " << scs.subsession->clientPortNum() << "-" << scs.subsession->clientPortNum()+1 << ")\n";

const char *sprop = scs.subsession->fmtp_spropparametersets();
uint8_t const* sps = NULL;
unsigned spsSize = 0;
uint8_t const* pps = NULL;
unsigned ppsSize = 0;

if (sprop != NULL) {
	unsigned numSPropRecords;
	SPropRecord* sPropRecords = parseSPropParameterSets(sprop, numSPropRecords);
	for (unsigned i = 0; i < numSPropRecords; ++i) {
		if (sPropRecords[i].sPropLength == 0) continue; // bad data
		u_int8_t nal_unit_type = (sPropRecords[i].sPropBytes[0])&0x1F;
		if (nal_unit_type == 7/*SPS*/) {
			sps = sPropRecords[i].sPropBytes;
			spsSize = sPropRecords[i].sPropLength;
		} else if (nal_unit_type == 8/*PPS*/) {
			pps = sPropRecords[i].sPropBytes;
			ppsSize = sPropRecords[i].sPropLength;
		}
	}
}

    // Having successfully setup the subsession, create a data sink for it, and call "startPlaying()" on it.
    // (This will prepare the data sink to receive data; the actual flow of data from the client won't start happening until later,
    // after we've sent a RTSP "PLAY" command.)
    scs.subsession->sink = DummySink::createNew(env, *scs.subsession, rtspClient->url());
      // perhaps use your own custom "MediaSink" subclass instead
    if (scs.subsession->sink == NULL) {
      env << *rtspClient << "Failed to create a data sink for the \"" << *scs.subsession
	  << "\" subsession: " << env.getResultMsg() << "\n";
      break;
    }

    env << *rtspClient << "Created a data sink for the \"" << *scs.subsession << "\" subsession\n";
    scs.subsession->miscPtr = rtspClient; // a hack to let subsession handle functions get the "RTSPClient" from the subsession 
if (sps != NULL) {
	((DummySink *)scs.subsession->sink)->setSprop(sps, spsSize);
}
if (pps != NULL) {
	((DummySink *)scs.subsession->sink)->setSprop(pps, ppsSize);
}
    scs.subsession->sink->startPlaying(*(scs.subsession->readSource()),
				       subsessionAfterPlaying, scs.subsession);
    // Also set a handler to be called if a RTCP "BYE" arrives for this subsession:
    if (scs.subsession->rtcpInstance() != NULL) {
      scs.subsession->rtcpInstance()->setByeHandler(subsessionByeHandler, scs.subsession);
    }
  } while (0);
  delete[] resultString;

  // Set up the next subsession, if any:
  setupNextSubsession(rtspClient);
}