int main (int argc, char **argv) { // env TaskScheduler *scheduler = BasicTaskScheduler::createNew(); _env = BasicUsageEnvironment::createNew(*scheduler); // test //test(*_env); // rtsp server RTSPServer *rtspServer = RTSPServer::createNew(*_env, 9554); if (!rtspServer) { fprintf(stderr, "ERR: create RTSPServer err\n"); ::exit(-1); } // add live stream do { WebcamFrameSource *webcam_source = 0; ServerMediaSession *sms = ServerMediaSession::createNew(*_env, "webcam", 0, "Session from /dev/video1"); sms->addSubsession(WebcamOndemandMediaSubsession::createNew(*_env, webcam_source)); rtspServer->addServerMediaSession(sms); char *url = rtspServer->rtspURL(sms); *_env << "using url \"" << url << "\"\n"; delete [] url; } while (0); // run loop _env->taskScheduler().doEventLoop(); return 1; }
void RTSPManager::createRTSPServer(unsigned int id , unsigned int port , volatile char * watcher) { std::unique_lock<std::mutex> lock(_lock); TaskScheduler* taskSchedular = BasicTaskScheduler::createNew(); BasicUsageEnvironment* usageEnvironment = BasicUsageEnvironment::createNew(*taskSchedular); RTSPServer* rtspServer = RTSPServer::createNew(*usageEnvironment, port, NULL); if(rtspServer == NULL) { logger::log(usageEnvironment->getResultMsg() , logger::logType::FAILURE); *watcher = -1; this->_done = true; this->_condition.notify_all(); return; } H264LiveServerMediaSession *liveSubSession = H264LiveServerMediaSession::createNew(*usageEnvironment, true , id); std::string streamName = "camera_" + std::to_string(id); ServerMediaSession* sms = ServerMediaSession::createNew(*usageEnvironment, streamName.c_str(), streamName.c_str(), "Live H264 Stream"); sms->addSubsession(liveSubSession); rtspServer->addServerMediaSession(sms); char* url = rtspServer->rtspURL(sms); logger::log(INFO_RTSP_URL(url) , logger::logType::PRIORITY); delete[] url; this->_done = true; this->_condition.notify_all(); lock.unlock(); taskSchedular->doEventLoop(watcher); return; }
int main (int argc, char **argv) { // env TaskScheduler *scheduler = BasicTaskScheduler::createNew(); _env = BasicUsageEnvironment::createNew(*scheduler); // rtsp server RTSPServer *rtspServer = RTSPServer::createNew(*_env, SINK_PORT); if (!rtspServer) { fprintf(stderr, "ERR: create RTSPServer err\n"); exit(-1); } // add live stream do { // low resolution ServerMediaSession *sms = ServerMediaSession::createNew(*_env, "live", 0, "Session from /dev/video0"); sms->addSubsession(WebcamOndemandMediaSubsession::createNew(*_env, 640, 360, PIX_FMT_YUV420P, FRAME_PER_SEC)); rtspServer->addServerMediaSession(sms); char *url = rtspServer->rtspURL(sms); *_env << "using url \"" << url << "\"\n"; delete [] url; // high resolution sms = ServerMediaSession::createNew(*_env, "live-high", 0, "Session from /dev/video0 with high resolution"); sms->addSubsession(WebcamOndemandMediaSubsession::createNew(*_env, 1280, 720, PIX_FMT_YUV420P, FRAME_PER_SEC)); rtspServer->addServerMediaSession(sms); url = rtspServer->rtspURL(sms); *_env << "using url \"" << url << "\"\n"; delete [] url; } while (0); // run loop _env->taskScheduler().doEventLoop(); return 1; }
int main(int argc, char** argv) { // Begin by setting up our usage environment: TaskScheduler* scheduler = BasicTaskScheduler::createNew(); UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler); UserAuthenticationDatabase* authDB = NULL; #ifdef ACCESS_CONTROL // To implement client access control to the RTSP server, do the following: authDB = new UserAuthenticationDatabase; authDB->addUserRecord("username1", "password1"); // replace these with real strings // Repeat the above with each <username>, <password> that you wish to allow // access to the server. #endif // Create the RTSP server: RTSPServer* rtspServer = RTSPServer::createNew(*env, 554, authDB); if (rtspServer == NULL) { *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n"; exit(1); } // Add live stream WW_H264VideoSource * videoSource = 0; ServerMediaSession * sms = ServerMediaSession::createNew(*env, "live", 0, "ww live test"); sms->addSubsession(WW_H264VideoServerMediaSubsession::createNew(*env, videoSource)); rtspServer->addServerMediaSession(sms); char * url = rtspServer->rtspURL(sms); *env << "using url \"" << url << "\"\n"; delete[] url; // Run loop env->taskScheduler().doEventLoop(); rtspServer->removeServerMediaSession(sms); Medium::close(rtspServer); env->reclaim(); delete scheduler; return 1; }
int main(int argc, char** argv) { // Begin by setting up our usage environment: TaskScheduler* scheduler = BasicTaskScheduler::createNew(); env = BasicUsageEnvironment::createNew(*scheduler); // Create 'groupsocks' for RTP and RTCP: struct in_addr destinationAddress; destinationAddress.s_addr = chooseRandomIPv4SSMAddress(*env); // Note: This is a multicast address. If you wish instead to stream // using unicast, then you should use the "testOnDemandRTSPServer" // test program - not this test program - as a model. const unsigned short rtpPortNum = 18888; const unsigned short rtcpPortNum = rtpPortNum+1; const unsigned char ttl = 255; const Port rtpPort(rtpPortNum); const Port rtcpPort(rtcpPortNum); Groupsock rtpGroupsock(*env, destinationAddress, rtpPort, ttl); rtpGroupsock.multicastSendOnly(); // we're a SSM source Groupsock rtcpGroupsock(*env, destinationAddress, rtcpPort, ttl); rtcpGroupsock.multicastSendOnly(); // we're a SSM source // Create a 'H264 Video RTP' sink from the RTP 'groupsock': OutPacketBuffer::maxSize = 100000; videoSink = H264VideoRTPSink::createNew(*env, &rtpGroupsock, 96); // Create (and start) a 'RTCP instance' for this RTP sink: const unsigned estimatedSessionBandwidth = 5000; // in kbps; for RTCP b/w share const unsigned maxCNAMElen = 100; unsigned char CNAME[maxCNAMElen+1]; gethostname((char*)CNAME, maxCNAMElen); CNAME[maxCNAMElen] = '\0'; // just in case RTCPInstance* rtcp = RTCPInstance::createNew(*env, &rtcpGroupsock, estimatedSessionBandwidth, CNAME, videoSink, NULL /* we're a server */, True /* we're a SSM source */); // Note: This starts RTCP running automatically RTSPServer* rtspServer = RTSPServer::createNew(*env, 8554); if (rtspServer == NULL) { *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n"; exit(1); } ServerMediaSession* sms = ServerMediaSession::createNew(*env, "testStream", inputFileName, "Session streamed by \"testH264VideoStreamer\"", True /*SSM*/); sms->addSubsession(PassiveServerMediaSubsession::createNew(*videoSink, rtcp)); rtspServer->addServerMediaSession(sms); char* url = rtspServer->rtspURL(sms); *env << "Play this stream using the URL \"" << url << "\"\n"; delete[] url; // Start the streaming: *env << "Beginning streaming...\n"; play(); env->taskScheduler().doEventLoop(); // does not return return 0; // only to prevent compiler warning }
int main(int argc, char** argv) { // Increase the maximum size of video frames that we can 'proxy' without truncation. // (Such frames are unreasonably large; the back-end servers should really not be sending frames this large!) OutPacketBuffer::maxSize = 100000; // bytes // Begin by setting up our usage environment: TaskScheduler* scheduler = BasicTaskScheduler::createNew(); env = BasicUsageEnvironment::createNew(*scheduler); *env << "LIVE555 Proxy Server\n" << "\t(LIVE555 Streaming Media library version " << LIVEMEDIA_LIBRARY_VERSION_STRING << "; licensed under the GNU LGPL)\n\n"; // Check command-line arguments: optional parameters, then one or more rtsp:// URLs (of streams to be proxied): progName = argv[0]; if (argc < 2) usage(); while (argc > 1) { // Process initial command-line options (beginning with "-"): char* const opt = argv[1]; if (opt[0] != '-') break; // the remaining parameters are assumed to be "rtsp://" URLs switch (opt[1]) { case 'v': { // verbose output verbosityLevel = 1; break; } case 'V': { // more verbose output verbosityLevel = 2; break; } case 't': { // Stream RTP and RTCP over the TCP 'control' connection. // (This is for the 'back end' (i.e., proxied) stream only.) streamRTPOverTCP = True; break; } case 'T': { // stream RTP and RTCP over a HTTP connection if (argc > 3 && argv[2][0] != '-') { // The next argument is the HTTP server port number: if (sscanf(argv[2], "%hu", &tunnelOverHTTPPortNum) == 1 && tunnelOverHTTPPortNum > 0) { ++argv; --argc; break; } } // If we get here, the option was specified incorrectly: usage(); break; } case 'p': { // specify a rtsp server port number if (argc > 3 && argv[2][0] != '-') { // The next argument is the rtsp server port number: if (sscanf(argv[2], "%hu", &rtspServerPortNum) == 1 && rtspServerPortNum > 0) { ++argv; --argc; break; } } // If we get here, the option was specified incorrectly: usage(); break; } case 'u': { // specify a username and password (to be used if the 'back end' (i.e., proxied) stream requires authentication) if (argc < 4) usage(); // there's no argv[3] (for the "password") username = argv[2]; password = argv[3]; argv += 2; argc -= 2; break; } case 'U': { // specify a username and password to use to authenticate incoming "REGISTER" commands if (argc < 4) usage(); // there's no argv[3] (for the "password") usernameForREGISTER = argv[2]; passwordForREGISTER = argv[3]; if (authDBForREGISTER == NULL) authDBForREGISTER = new UserAuthenticationDatabase; authDBForREGISTER->addUserRecord(usernameForREGISTER, passwordForREGISTER); argv += 2; argc -= 2; break; } case 'R': { // Handle incoming "REGISTER" requests by proxying the specified stream: proxyREGISTERRequests = True; break; } default: { usage(); break; } } ++argv; --argc; } if (argc < 2 && !proxyREGISTERRequests) usage(); // there must be at least one "rtsp://" URL at the end // Make sure that the remaining arguments appear to be "rtsp://" URLs: int i; for (i = 1; i < argc; ++i) { if (strncmp(argv[i], "rtsp://", 7) != 0) usage(); } // Do some additional checking for invalid command-line argument combinations: if (authDBForREGISTER != NULL && !proxyREGISTERRequests) { *env << "The '-U <username> <password>' option can be used only with -R\n"; usage(); } if (streamRTPOverTCP) { if (tunnelOverHTTPPortNum > 0) { *env << "The -t and -T options cannot both be used!\n"; usage(); } else { tunnelOverHTTPPortNum = (portNumBits)(~0); // hack to tell "ProxyServerMediaSession" to stream over TCP, but not using HTTP } } #ifdef ACCESS_CONTROL // To implement client access control to the RTSP server, do the following: authDB = new UserAuthenticationDatabase; authDB->addUserRecord("username1", "password1"); // replace these with real strings // Repeat this line with each <username>, <password> that you wish to allow access to the server. #endif // Create the RTSP server. Try first with the configured port number, // and then with the default port number (554) if different, // and then with the alternative port number (8554): RTSPServer* rtspServer; rtspServer = createRTSPServer(rtspServerPortNum); if (rtspServer == NULL) { if (rtspServerPortNum != 554) { *env << "Unable to create a RTSP server with port number " << rtspServerPortNum << ": " << env->getResultMsg() << "\n"; *env << "Trying instead with the standard port numbers (554 and 8554)...\n"; rtspServerPortNum = 554; rtspServer = createRTSPServer(rtspServerPortNum); } } if (rtspServer == NULL) { rtspServerPortNum = 8554; rtspServer = createRTSPServer(rtspServerPortNum); } if (rtspServer == NULL) { *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n"; exit(1); } // Create a proxy for each "rtsp://" URL specified on the command line: for (i = 1; i < argc; ++i) { char const* proxiedStreamURL = argv[i]; char streamName[30]; if (argc == 2) { sprintf(streamName, "%s", "proxyStream"); // there's just one stream; give it this name } else { sprintf(streamName, "proxyStream-%d", i); // there's more than one stream; distinguish them by name } ServerMediaSession* sms = ProxyServerMediaSession::createNew(*env, rtspServer, proxiedStreamURL, streamName, username, password, tunnelOverHTTPPortNum, verbosityLevel); rtspServer->addServerMediaSession(sms); char* proxyStreamURL = rtspServer->rtspURL(sms); *env << "RTSP stream, proxying the stream \"" << proxiedStreamURL << "\"\n"; *env << "\tPlay this stream using the URL: " << proxyStreamURL << "\n"; delete[] proxyStreamURL; } if (proxyREGISTERRequests) { *env << "(We handle incoming \"REGISTER\" requests on port " << rtspServerPortNum << ")\n"; } // Also, attempt to create a HTTP server for RTSP-over-HTTP tunneling. // Try first with the default HTTP port (80), and then with the alternative HTTP // port numbers (8000 and 8080). if (rtspServer->setUpTunnelingOverHTTP(80) || rtspServer->setUpTunnelingOverHTTP(8000) || rtspServer->setUpTunnelingOverHTTP(8080)) { *env << "\n(We use port " << rtspServer->httpServerPortNum() << " for optional RTSP-over-HTTP tunneling.)\n"; } else { *env << "\n(RTSP-over-HTTP tunneling is not available.)\n"; } // Now, enter the event loop: env->taskScheduler().doEventLoop(); // does not return return 0; // only to prevent compiler warning }
JNIEXPORT void JNICALL Java_com_parizene_streamer_Streamer_loop(JNIEnv *env, jobject obj, jstring addr) { // Begin by setting up our usage environment: TaskScheduler* scheduler = BasicTaskScheduler::createNew(); uEnv = BasicUsageEnvironment::createNew(*scheduler); // Create 'groupsocks' for RTP and RTCP: struct in_addr destinationAddress; const char *_addr = env->GetStringUTFChars(addr, NULL); destinationAddress.s_addr = our_inet_addr(_addr); /*chooseRandomIPv4SSMAddress(*uEnv);*/ env->ReleaseStringUTFChars(addr, _addr); // Note: This is a multicast address. If you wish instead to stream // using unicast, then you should use the "testOnDemandRTSPServer" // test program - not this test program - as a model. const unsigned short rtpPortNum = 18888; const unsigned short rtcpPortNum = rtpPortNum + 1; const unsigned char ttl = 255; const Port rtpPort(rtpPortNum); const Port rtcpPort(rtcpPortNum); Groupsock rtpGroupsock(*uEnv, destinationAddress, rtpPort, ttl); Groupsock rtcpGroupsock(*uEnv, destinationAddress, rtcpPort, ttl); // Create a 'H264 Video RTP' sink from the RTP 'groupsock': OutPacketBuffer::maxSize = 100000; videoSink = H264VideoRTPSink::createNew(*uEnv, &rtpGroupsock, 96); // Create (and start) a 'RTCP instance' for this RTP sink: const unsigned estimatedSessionBandwidth = 500; // in kbps; for RTCP b/w share const unsigned maxCNAMElen = 100; unsigned char CNAME[maxCNAMElen + 1]; gethostname((char*) CNAME, maxCNAMElen); CNAME[maxCNAMElen] = '\0'; // just in case RTCPInstance* rtcp = RTCPInstance::createNew(*uEnv, &rtcpGroupsock, estimatedSessionBandwidth, CNAME, videoSink, NULL /* we're a server */, True /* we're a SSM source */); // Note: This starts RTCP running automatically RTSPServer* rtspServer = RTSPServer::createNew(*uEnv, 8554); if (rtspServer == NULL) { LOGE("Failed to create RTSP server: %s", uEnv->getResultMsg()); exit(1); } ServerMediaSession* sms = ServerMediaSession::createNew(*uEnv, "streamer", inputFilename, "Session streamed by \"testH264VideoStreamer\"", True /*SSM*/); sms->addSubsession( PassiveServerMediaSubsession::createNew(*videoSink, rtcp)); rtspServer->addServerMediaSession(sms); char* url = rtspServer->rtspURL(sms); LOGI("Play this stream using the URL \"%s\"", url); delete[] url; // Start the streaming: LOGI("Beginning streaming...\n"); play(); uEnv->taskScheduler().doEventLoop(); // does not return }
int main(int argc, char** argv) { // Begin by setting up our usage environment: TaskScheduler* scheduler = BasicTaskScheduler::createNew(); env = BasicUsageEnvironment::createNew(*scheduler); UserAuthenticationDatabase* authDB = NULL; #ifdef ACCESS_CONTROL // To implement client access control to the RTSP server, do the following: authDB = new UserAuthenticationDatabase; authDB->addUserRecord("username1", "password1"); // replace these with real strings // Repeat the above with each <username>, <password> that you wish to allow // access to the server. #endif // 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\""; // Set up each of the possible streams that can be served by the // RTSP server. Each such stream is implemented using a // "ServerMediaSession" object, plus one or more // "ServerMediaSubsession" objects for each audio/video substream. // A MPEG-4 video elementary stream: { char const* streamName = "mpeg4ESVideoTest"; char const* inputFileName = "test.m4e"; ServerMediaSession* sms = ServerMediaSession::createNew(*env, streamName, streamName, descriptionString); sms->addSubsession(MPEG4VideoFileServerMediaSubsession ::createNew(*env, inputFileName, reuseFirstSource)); rtspServer->addServerMediaSession(sms); announceStream(rtspServer, sms, streamName, inputFileName); } // A H.264 video elementary stream: { char const* streamName = "h264ESVideoTest"; char const* inputFileName = "test.264"; ServerMediaSession* sms = ServerMediaSession::createNew(*env, streamName, streamName, descriptionString); sms->addSubsession(H264VideoFileServerMediaSubsession ::createNew(*env, inputFileName, reuseFirstSource)); rtspServer->addServerMediaSession(sms); announceStream(rtspServer, sms, streamName, inputFileName); } // A H.265 video elementary stream: { char const* streamName = "h265ESVideoTest"; char const* inputFileName = "test.265"; ServerMediaSession* sms = ServerMediaSession::createNew(*env, streamName, streamName, descriptionString); sms->addSubsession(H265VideoFileServerMediaSubsession ::createNew(*env, inputFileName, reuseFirstSource)); rtspServer->addServerMediaSession(sms); announceStream(rtspServer, sms, streamName, inputFileName); } // A MPEG-1 or 2 audio+video program stream: { char const* streamName = "mpeg1or2AudioVideoTest"; char const* inputFileName = "test.mpg"; // NOTE: This *must* be a Program Stream; not an Elementary Stream ServerMediaSession* sms = ServerMediaSession::createNew(*env, streamName, streamName, descriptionString); MPEG1or2FileServerDemux* demux = MPEG1or2FileServerDemux::createNew(*env, inputFileName, reuseFirstSource); sms->addSubsession(demux->newVideoServerMediaSubsession(iFramesOnly)); sms->addSubsession(demux->newAudioServerMediaSubsession()); rtspServer->addServerMediaSession(sms); announceStream(rtspServer, sms, streamName, inputFileName); } // A MPEG-1 or 2 video elementary stream: { char const* streamName = "mpeg1or2ESVideoTest"; char const* inputFileName = "testv.mpg"; // NOTE: This *must* be a Video Elementary Stream; not a Program Stream ServerMediaSession* sms = ServerMediaSession::createNew(*env, streamName, streamName, descriptionString); sms->addSubsession(MPEG1or2VideoFileServerMediaSubsession ::createNew(*env, inputFileName, reuseFirstSource, iFramesOnly)); rtspServer->addServerMediaSession(sms); announceStream(rtspServer, sms, streamName, inputFileName); } // A MP3 audio stream (actually, any MPEG-1 or 2 audio file will work): // To stream using 'ADUs' rather than raw MP3 frames, uncomment the following: //#define STREAM_USING_ADUS 1 // To also reorder ADUs before streaming, uncomment the following: //#define INTERLEAVE_ADUS 1 // (For more information about ADUs and interleaving, // see <http://www.live555.com/rtp-mp3/>) { char const* streamName = "mp3AudioTest"; char const* inputFileName = "test.mp3"; ServerMediaSession* sms = ServerMediaSession::createNew(*env, streamName, streamName, descriptionString); Boolean useADUs = False; Interleaving* interleaving = NULL; #ifdef STREAM_USING_ADUS useADUs = True; #ifdef INTERLEAVE_ADUS unsigned char interleaveCycle[] = {0,2,1,3}; // or choose your own... unsigned const interleaveCycleSize = (sizeof interleaveCycle)/(sizeof (unsigned char)); interleaving = new Interleaving(interleaveCycleSize, interleaveCycle); #endif #endif sms->addSubsession(MP3AudioFileServerMediaSubsession ::createNew(*env, inputFileName, reuseFirstSource, useADUs, interleaving)); rtspServer->addServerMediaSession(sms); announceStream(rtspServer, sms, streamName, inputFileName); } // A WAV audio stream: { char const* streamName = "wavAudioTest"; char const* inputFileName = "test.wav"; ServerMediaSession* sms = ServerMediaSession::createNew(*env, streamName, streamName, descriptionString); // To convert 16-bit PCM data to 8-bit u-law, prior to streaming, // change the following to True: Boolean convertToULaw = False; sms->addSubsession(WAVAudioFileServerMediaSubsession ::createNew(*env, inputFileName, reuseFirstSource, convertToULaw)); rtspServer->addServerMediaSession(sms); announceStream(rtspServer, sms, streamName, inputFileName); } // An AMR audio stream: { char const* streamName = "amrAudioTest"; char const* inputFileName = "test.amr"; ServerMediaSession* sms = ServerMediaSession::createNew(*env, streamName, streamName, descriptionString); sms->addSubsession(AMRAudioFileServerMediaSubsession ::createNew(*env, inputFileName, reuseFirstSource)); rtspServer->addServerMediaSession(sms); announceStream(rtspServer, sms, streamName, inputFileName); } // A 'VOB' file (e.g., from an unencrypted DVD): { char const* streamName = "vobTest"; char const* inputFileName = "test.vob"; ServerMediaSession* sms = ServerMediaSession::createNew(*env, streamName, streamName, descriptionString); // Note: VOB files are MPEG-2 Program Stream files, but using AC-3 audio MPEG1or2FileServerDemux* demux = MPEG1or2FileServerDemux::createNew(*env, inputFileName, reuseFirstSource); sms->addSubsession(demux->newVideoServerMediaSubsession(iFramesOnly)); sms->addSubsession(demux->newAC3AudioServerMediaSubsession()); rtspServer->addServerMediaSession(sms); announceStream(rtspServer, sms, streamName, inputFileName); } // A MPEG-2 Transport Stream: { char const* streamName = "mpeg2TransportStreamTest"; char const* inputFileName = "test.ts"; char const* indexFileName = "test.tsx"; ServerMediaSession* sms = ServerMediaSession::createNew(*env, streamName, streamName, descriptionString); sms->addSubsession(MPEG2TransportFileServerMediaSubsession ::createNew(*env, inputFileName, indexFileName, reuseFirstSource)); rtspServer->addServerMediaSession(sms); announceStream(rtspServer, sms, streamName, inputFileName); } // An AAC audio stream (ADTS-format file): { char const* streamName = "aacAudioTest"; char const* inputFileName = "test.aac"; ServerMediaSession* sms = ServerMediaSession::createNew(*env, streamName, streamName, descriptionString); sms->addSubsession(ADTSAudioFileServerMediaSubsession ::createNew(*env, inputFileName, reuseFirstSource)); rtspServer->addServerMediaSession(sms); announceStream(rtspServer, sms, streamName, inputFileName); } // A DV video stream: { // First, make sure that the RTPSinks' buffers will be large enough to handle the huge size of DV frames (as big as 288000). OutPacketBuffer::maxSize = 2000000; char const* streamName = "dvVideoTest"; char const* inputFileName = "test.dv"; ServerMediaSession* sms = ServerMediaSession::createNew(*env, streamName, streamName, descriptionString); sms->addSubsession(DVVideoFileServerMediaSubsession ::createNew(*env, inputFileName, reuseFirstSource)); rtspServer->addServerMediaSession(sms); announceStream(rtspServer, sms, streamName, inputFileName); } // A AC3 video elementary stream: { char const* streamName = "ac3AudioTest"; char const* inputFileName = "test.ac3"; ServerMediaSession* sms = ServerMediaSession::createNew(*env, streamName, streamName, descriptionString); sms->addSubsession(AC3AudioFileServerMediaSubsession ::createNew(*env, inputFileName, reuseFirstSource)); rtspServer->addServerMediaSession(sms); announceStream(rtspServer, sms, streamName, inputFileName); } // A Matroska ('.mkv') file, with video+audio+subtitle streams: { char const* streamName = "matroskaFileTest"; char const* inputFileName = "test.mkv"; ServerMediaSession* sms = ServerMediaSession::createNew(*env, streamName, streamName, descriptionString); newDemuxWatchVariable = 0; MatroskaFileServerDemux::createNew(*env, inputFileName, onMatroskaDemuxCreation, NULL); env->taskScheduler().doEventLoop(&newDemuxWatchVariable); Boolean sessionHasTracks = False; ServerMediaSubsession* smss; while ((smss = matroskaDemux->newServerMediaSubsession()) != NULL) { sms->addSubsession(smss); sessionHasTracks = True; } if (sessionHasTracks) { rtspServer->addServerMediaSession(sms); } // otherwise, because the stream has no tracks, we don't add a ServerMediaSession to the server. announceStream(rtspServer, sms, streamName, inputFileName); } // A WebM ('.webm') file, with video(VP8)+audio(Vorbis) streams: // (Note: ".webm' files are special types of Matroska files, so we use the same code as the Matroska ('.mkv') file code above.) { char const* streamName = "webmFileTest"; char const* inputFileName = "test.webm"; ServerMediaSession* sms = ServerMediaSession::createNew(*env, streamName, streamName, descriptionString); newDemuxWatchVariable = 0; MatroskaFileServerDemux::createNew(*env, inputFileName, onMatroskaDemuxCreation, NULL); env->taskScheduler().doEventLoop(&newDemuxWatchVariable); Boolean sessionHasTracks = False; ServerMediaSubsession* smss; while ((smss = matroskaDemux->newServerMediaSubsession()) != NULL) { sms->addSubsession(smss); sessionHasTracks = True; } if (sessionHasTracks) { rtspServer->addServerMediaSession(sms); } // otherwise, because the stream has no tracks, we don't add a ServerMediaSession to the server. announceStream(rtspServer, sms, streamName, inputFileName); } // An Ogg ('.ogg') file, with video and/or audio streams: { char const* streamName = "oggFileTest"; char const* inputFileName = "test.ogg"; ServerMediaSession* sms = ServerMediaSession::createNew(*env, streamName, streamName, descriptionString); newDemuxWatchVariable = 0; OggFileServerDemux::createNew(*env, inputFileName, onOggDemuxCreation, NULL); env->taskScheduler().doEventLoop(&newDemuxWatchVariable); Boolean sessionHasTracks = False; ServerMediaSubsession* smss; while ((smss = oggDemux->newServerMediaSubsession()) != NULL) { sms->addSubsession(smss); sessionHasTracks = True; } if (sessionHasTracks) { rtspServer->addServerMediaSession(sms); } // otherwise, because the stream has no tracks, we don't add a ServerMediaSession to the server. announceStream(rtspServer, sms, streamName, inputFileName); } // An Opus ('.opus') audio file: // (Note: ".opus' files are special types of Ogg files, so we use the same code as the Ogg ('.ogg') file code above.) { char const* streamName = "opusFileTest"; char const* inputFileName = "test.opus"; ServerMediaSession* sms = ServerMediaSession::createNew(*env, streamName, streamName, descriptionString); newDemuxWatchVariable = 0; OggFileServerDemux::createNew(*env, inputFileName, onOggDemuxCreation, NULL); env->taskScheduler().doEventLoop(&newDemuxWatchVariable); Boolean sessionHasTracks = False; ServerMediaSubsession* smss; while ((smss = oggDemux->newServerMediaSubsession()) != NULL) { sms->addSubsession(smss); sessionHasTracks = True; } if (sessionHasTracks) { rtspServer->addServerMediaSession(sms); } // otherwise, because the stream has no tracks, we don't add a ServerMediaSession to the server. announceStream(rtspServer, sms, streamName, inputFileName); } // A MPEG-2 Transport Stream, coming from a live UDP (raw-UDP or RTP/UDP) source: { char const* streamName = "mpeg2TransportStreamFromUDPSourceTest"; char const* inputAddressStr = "239.255.42.42"; // This causes the server to take its input from the stream sent by the "testMPEG2TransportStreamer" demo application. // (Note: If the input UDP source is unicast rather than multicast, then change this to NULL.) portNumBits const inputPortNum = 1234; // This causes the server to take its input from the stream sent by the "testMPEG2TransportStreamer" demo application. Boolean const inputStreamIsRawUDP = False; ServerMediaSession* sms = ServerMediaSession::createNew(*env, streamName, streamName, descriptionString); sms->addSubsession(MPEG2TransportUDPServerMediaSubsession ::createNew(*env, inputAddressStr, inputPortNum, inputStreamIsRawUDP)); rtspServer->addServerMediaSession(sms); char* url = rtspServer->rtspURL(sms); *env << "\n\"" << streamName << "\" stream, from a UDP Transport Stream input source \n\t("; if (inputAddressStr != NULL) { *env << "IP multicast address " << inputAddressStr << ","; } else { *env << "unicast;"; } *env << " port " << inputPortNum << ")\n"; *env << "Play this stream using the URL \"" << url << "\"\n"; delete[] url; } // Also, attempt to create a HTTP server for RTSP-over-HTTP tunneling. // Try first with the default HTTP port (80), and then with the alternative HTTP // port numbers (8000 and 8080). if (rtspServer->setUpTunnelingOverHTTP(80) || rtspServer->setUpTunnelingOverHTTP(8000) || rtspServer->setUpTunnelingOverHTTP(8080)) { *env << "\n(We use port " << rtspServer->httpServerPortNum() << " for optional RTSP-over-HTTP tunneling.)\n"; } else { *env << "\n(RTSP-over-HTTP tunneling is not available.)\n"; } env->taskScheduler().doEventLoop(); // does not return return 0; // only to prevent compiler warning }
int main( int argc, char **argv ) { //int ret = 0; PTZControlInit(); demo_setting * ext_gSettings = NULL; // Allocate the "global" settings ext_gSettings = (demo_setting*)malloc( sizeof( demo_setting ) ); if ( NULL == ext_gSettings ) { printf( "main::out of memory!\n" ); return -1; } sig_init(); atexit(appExit); //init the setting struct Settings_Initialize( ext_gSettings ); read_Parse(ext_gSettings); //printf("video type = %d \n", ext_gSettings->video_types); //...do your job //close the led setled_off(); //init dma memory akuio_pmem_init(); encode_init(); printf("encode_init ok\n"); //open camera camera_open(ext_gSettings->width, ext_gSettings->height); printf("camera_open ok\n"); //encode_open T_ENC_INPUT encInput; encInput.width = ext_gSettings->width; //实际编码图像的宽度,能被4整除 encInput.height = ext_gSettings->height; //实际编码图像的长度,能被2整除 encInput.kbpsmode = ext_gSettings->kbpsmode; encInput.qpHdr = ext_gSettings->qpHdr; //初始的QP的值 encInput.iqpHdr = ext_gSettings->iqpHdr; //初始的QP的值 encInput.bitPerSecond = ext_gSettings->bitPerSecond; //目标bps encInput.minQp = ext_gSettings->minQp; encInput.maxQp = ext_gSettings->maxQp; encInput.framePerSecond = ext_gSettings->framePerSecond; encInput.video_tytes = ext_gSettings->video_types; encode_open(&encInput); printf("encode_open ok\n"); //set mux mux_input.rec_path = ext_gSettings->rec_path; mux_input.m_MediaRecType = MEDIALIB_REC_AVI_NORMAL; if (ext_gSettings->bhasAudio) { bHasAudio = 1; //mux_input.m_bCaptureAudio = 1; } else { bHasAudio = 0; //mux_input.m_bCaptureAudio = 0; } mux_input.m_bCaptureAudio = 1; //mux video if(parse.format2 == 0) { mux_input.m_eVideoType = MEDIALIB_VIDEO_H264; } else if(parse.format2 == 1) { mux_input.m_eVideoType = MEDIALIB_VIDEO_MJPEG; } mux_input.m_nWidth = parse.width2; mux_input.m_nHeight = parse.height2; //mux audio mux_input.m_eAudioType = MEDIALIB_AUDIO_AAC; mux_input.m_nSampleRate = 8000; //mux_input.abitsrate = ext_gSettings->abitsrate; printf("mux_open ok\n"); //if (ext_gSettings->bhasAudio) { T_AUDIO_INPUT audioInput; audioInput.enc_type = (AUDIO_ENCODE_TYPE_CC)ext_gSettings->audioType; audioInput.nBitsRate = ext_gSettings->abitsrate; audioInput.nBitsPerSample = 16; audioInput.nChannels = 1; audioInput.nSampleRate = ext_gSettings->aSamplerate; audio_open(&audioInput); printf("audio_open ok\n"); audio_start(); } //start ftp server //startFTPSrv(); Init_photograph(); //PTZControlInit(); //start video process video_process_start(); InitMotionDetect(); DemuxForLiveSetCallBack(); TaskScheduler* scheduler = BasicTaskScheduler::createNew(); env = BasicUsageEnvironment::createNew(*scheduler); UserAuthenticationDatabase* authDB = NULL; #ifdef ACCESS_CONTROL // To implement client access control to the RTSP server, do the following: authDB = new UserAuthenticationDatabase; authDB->addUserRecord("username1", "password1"); // replace these with real strings // Repeat the above with each <username>, <password> that you wish to allow // access to the server. #endif // Create the RTSP server: RTSPServer* rtspServer = AKRTSPServer::createNew(*env, RTSPPORT, authDB); if (rtspServer == NULL) { *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n"; appExit(); exit(1); } char const* descriptionString = "Session streamed by \"testOnDemandRTSPServer\""; // Set up each of the possible streams that can be served by the // RTSP server. Each such stream is implemented using a // "ServerMediaSession" object, plus one or more // "ServerMediaSubsession" objects for each audio/video substream. int vsIndex = 0; VIDEO_MODE vm[2] = {VIDEO_MODE_VGA,VIDEO_MODE_VGA}; const char* streamName1 = "vs1"; const char* streamName2 = "vs2"; ((AKRTSPServer*)rtspServer)->SetStreamName(streamName1, streamName2); if(ext_gSettings->video_types == 1) { if(ext_gSettings->width == 640) { vm[0] = VIDEO_MODE_VGA; } else if(ext_gSettings->width == 320) { vm[0] = VIDEO_MODE_QVGA; } else if(ext_gSettings->width == 720) { vm[0] = VIDEO_MODE_D1; } AKIPCMJPEGFramedSource* ipcMJPEGSourcecam = NULL; ServerMediaSession* smsMJPEGcam = ServerMediaSession::createNew(*env, streamName1, 0, descriptionString); AKIPCMJPEGOnDemandMediaSubsession* subsMJPEGcam = AKIPCMJPEGOnDemandMediaSubsession::createNew(*env,ipcMJPEGSourcecam, ext_gSettings->width, ext_gSettings->height, vsIndex); smsMJPEGcam->addSubsession(subsMJPEGcam); subsMJPEGcam->getframefunc = video_process_get_buf; subsMJPEGcam->setledstart = setled_view_start; subsMJPEGcam->setledexit = setled_view_stop; if(bHasAudio) smsMJPEGcam->addSubsession(AKIPCAACAudioOnDemandMediaSubsession::createNew(*env,True,getAACBuf, vsIndex)); rtspServer->addServerMediaSession(smsMJPEGcam); char* url1 = rtspServer->rtspURL(smsMJPEGcam); *env << "using url \"" << url1 <<"\"\n"; delete[] url1; } else if(ext_gSettings->video_types == 0) { if(ext_gSettings->width == 1280) { vm[0] = VIDEO_MODE_720P; } else if(ext_gSettings->width == 640) { vm[0] = VIDEO_MODE_VGA; } else if(ext_gSettings->width == 320) { vm[0] = VIDEO_MODE_QVGA; } else if(ext_gSettings->width == 720) { vm[0] = VIDEO_MODE_D1; } AKIPCH264FramedSource* ipcSourcecam = NULL; ServerMediaSession* smscam = ServerMediaSession::createNew(*env, streamName1, 0, descriptionString); AKIPCH264OnDemandMediaSubsession* subscam = AKIPCH264OnDemandMediaSubsession::createNew(*env,ipcSourcecam, 0, vsIndex); smscam->addSubsession(subscam); if(bHasAudio) smscam->addSubsession(AKIPCAACAudioOnDemandMediaSubsession::createNew(*env,True,getAACBuf, vsIndex)); subscam->getframefunc = video_process_get_buf; subscam->setledstart = setled_view_start; subscam->setledexit = setled_view_stop; rtspServer->addServerMediaSession(smscam); char* url1 = rtspServer->rtspURL(smscam); *env << "using url \"" << url1 <<"\"\n"; delete[] url1; } vsIndex = 1; if(parse.format2 == 0)//264 { if(parse.width2 == 1280) { vm[1] = VIDEO_MODE_720P; } else if(parse.width2 == 640) { vm[1] = VIDEO_MODE_VGA; } else if(parse.width2 == 320) { vm[1] = VIDEO_MODE_QVGA; } else if(parse.width2 == 720) { vm[1] = VIDEO_MODE_D1; } AKIPCH264FramedSource* ipcSourcecam = NULL; ServerMediaSession* smscam = ServerMediaSession::createNew(*env, streamName2, 0, descriptionString); AKIPCH264OnDemandMediaSubsession* subscam = AKIPCH264OnDemandMediaSubsession::createNew(*env,ipcSourcecam, 0, vsIndex); smscam->addSubsession(subscam); if(bHasAudio) smscam->addSubsession(AKIPCAACAudioOnDemandMediaSubsession::createNew(*env,True,getAACBuf, vsIndex)); subscam->getframefunc = video_process_get_buf; subscam->setledstart = setled_view_start; subscam->setledexit = setled_view_stop; rtspServer->addServerMediaSession(smscam); char* url2 = rtspServer->rtspURL(smscam); *env << "using url \"" << url2 <<"\"\n"; delete[] url2; } else if(parse.format2 == 1)//mjpeg { if(parse.width2 == 640) { vm[1] = VIDEO_MODE_VGA; } else if(parse.width2 == 320) { vm[1] = VIDEO_MODE_QVGA; } else if(parse.width2 == 720) { vm[1] = VIDEO_MODE_D1; } AKIPCMJPEGFramedSource* ipcMJPEGSourcecam = NULL; ServerMediaSession* smsMJPEGcam = ServerMediaSession::createNew(*env, streamName2, 0, descriptionString); AKIPCMJPEGOnDemandMediaSubsession* subsMJPEGcam = AKIPCMJPEGOnDemandMediaSubsession::createNew(*env,ipcMJPEGSourcecam, parse.width2, parse.height2, vsIndex); smsMJPEGcam->addSubsession(subsMJPEGcam); subsMJPEGcam->getframefunc = video_process_get_buf; subsMJPEGcam->setledstart = setled_view_start; subsMJPEGcam->setledexit = setled_view_stop; if(bHasAudio) smsMJPEGcam->addSubsession(AKIPCAACAudioOnDemandMediaSubsession::createNew(*env,True,getAACBuf, vsIndex)); rtspServer->addServerMediaSession(smsMJPEGcam); char* url2 = rtspServer->rtspURL(smsMJPEGcam); *env << "using url \"" << url2 <<"\"\n"; delete[] url2; } #if 0 if (rtspServer->setUpTunnelingOverHTTP(80) || rtspServer->setUpTunnelingOverHTTP(8000) || rtspServer->setUpTunnelingOverHTTP(8080)) { *env << "\n(We use port " << rtspServer->httpServerPortNum() << " for optional RTSP-over-HTTP tunneling.)\n"; } else { *env << "\n(RTSP-over-HTTP tunneling is not available.)\n"; } #endif //printf("streamName:%s,Port:%d\n", streamName1, RTSPPORT); NetCtlSrvPar ncsp; memset(&ncsp, 0, sizeof(ncsp)); getDeviceID(ncsp.strDeviceID); printf("device id:**%s**\n", ncsp.strDeviceID); strcpy(ncsp.strStreamName1, streamName1); strcpy(ncsp.strStreamName2, streamName2); ncsp.vm1 = vm[0]; ncsp.vm2 = vm[1]; ncsp.nRtspPort = RTSPPORT; ncsp.nMainFps = parse.fps1; ncsp.nSubFps = parse.fps2; //start net command server startNetCtlServer(&ncsp); printf("[##]start record...\n"); auto_record_file(); printf("[##]auto_record_file() called..\n"); //at last,start rtsp loop env->taskScheduler().doEventLoop(); // does not return return 0; }
int main(int argc, char** argv) { init_signals(); setpriority(PRIO_PROCESS, 0, 0); int IsSilence = 0; int svcEnable = 0; int cnt=0; int activePortCnt=0; if( GetSampleRate() == 16000 ) { audioOutputBitrate = 128000; audioSamplingFrequency = 16000; }else{ audioOutputBitrate = 64000; audioSamplingFrequency = 8000; } // Begin by setting up our usage environment: TaskScheduler* scheduler = BasicTaskScheduler::createNew(); UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler); int msg_type, video_type; APPROInput* MjpegInputDevice = NULL; APPROInput* H264InputDevice = NULL; APPROInput* Mpeg4InputDevice = NULL; static pid_t child[4] = { -1,-1,-1,-1 }; StreamingMode streamingMode = STREAMING_UNICAST; netAddressBits multicastAddress = 0;//our_inet_addr("224.1.4.6"); portNumBits videoRTPPortNum = 0; portNumBits audioRTPPortNum = 0; IsSilence = 0; svcEnable = 0; audioType = AUDIO_G711; streamingMode = STREAMING_UNICAST; for( cnt = 1; cnt < argc ;cnt++ ) { if( strcmp( argv[cnt],"-m" )== 0 ) { streamingMode = STREAMING_MULTICAST_SSM; } if( strcmp( argv[cnt],"-s" )== 0 ) { IsSilence = 1; } if( strcmp( argv[cnt],"-a" )== 0 ) { audioType = AUDIO_AAC; } if( strcmp( argv[cnt],"-v" )== 0 ) { svcEnable = 1; } } #if 0 printf("###########IsSilence = %d ################\n",IsSilence); printf("###########streamingMode = %d ################\n",streamingMode); printf("###########audioType = %d ################\n",audioType); printf("###########svcEnable = %d ################\n",svcEnable); #endif child[0] = fork(); if( child[0] != 0 ) { child[1] = fork(); } if( child[0] != 0 && child[1] != 0 ) { child[2] = fork(); } if( child[0] != 0 && child[1] != 0 && child[2] != 0 ) { child[3] = fork(); } if(svcEnable) { if( child[0] != 0 && child[1] != 0 && child[2] != 0 && child[3] != 0) { child[4] = fork(); } if( child[0] != 0 && child[1] != 0 && child[2] != 0 && child[3] != 0 && child[4] != 0) { child[5] = fork(); } if( child[0] != 0 && child[1] != 0 && child[2] != 0 && child[3] != 0 && child[4] != 0 && child[5] != 0) { child[6] = fork(); } if( child[0] != 0 && child[1] != 0 && child[2] != 0 && child[3] != 0 && child[4] != 0 && child[5] != 0 && child[6] != 0) { child[7] = fork(); } } if( child[0] == 0 ) { /* parent, success */ msg_type = LIVE_MSG_TYPE4; video_type = VIDEO_TYPE_H264_CIF; rtspServerPortNum = 8556; H264VideoBitrate = 12000000; videoRTPPortNum = 6012; audioRTPPortNum = 6014; } if( child[1] == 0 ) { /* parent, success */ msg_type = LIVE_MSG_TYPE3; video_type = VIDEO_TYPE_MJPEG; rtspServerPortNum = 8555; MjpegVideoBitrate = 12000000; videoRTPPortNum = 6008; audioRTPPortNum = 6010; } if( child[2] == 0 ) { /* parent, success */ msg_type = LIVE_MSG_TYPE; video_type = VIDEO_TYPE_MPEG4; rtspServerPortNum = 8553; Mpeg4VideoBitrate = 12000000; videoRTPPortNum = 6000; audioRTPPortNum = 6002; } if( child[3] == 0 ) { /* parent, success */ msg_type = LIVE_MSG_TYPE2; video_type = VIDEO_TYPE_MPEG4_CIF; rtspServerPortNum = 8554; Mpeg4VideoBitrate = 12000000; videoRTPPortNum = 6004; audioRTPPortNum = 6006; } if(svcEnable) { if( child[4] == 0 ) { /* parent, success */ msg_type = LIVE_MSG_TYPE5; video_type = VIDEO_TYPE_H264_SVC_30FPS; rtspServerPortNum = 8601; H264VideoBitrate = 12000000; videoRTPPortNum = 6016; audioRTPPortNum = 6018; } if( child[5] == 0 ) { /* parent, success */ msg_type = LIVE_MSG_TYPE6; video_type = VIDEO_TYPE_H264_SVC_15FPS; rtspServerPortNum = 8602; H264VideoBitrate = 12000000; videoRTPPortNum = 6020; audioRTPPortNum = 6022; } if( child[6] == 0 ) { /* parent, success */ msg_type = LIVE_MSG_TYPE7; video_type = VIDEO_TYPE_H264_SVC_7FPS; rtspServerPortNum = 8603; H264VideoBitrate = 12000000; videoRTPPortNum = 6024; audioRTPPortNum = 6026; } if( child[7] == 0 ) { /* parent, success */ msg_type = LIVE_MSG_TYPE8; video_type = VIDEO_TYPE_H264_SVC_3FPS; rtspServerPortNum = 8604; H264VideoBitrate = 12000000; videoRTPPortNum = 6028; audioRTPPortNum = 6030; } if( child[0] != 0 && child[1] != 0 && child[2] != 0 && child[3] != 0 && child[4] != 0 && child[5] != 0 && child[6] != 0 && child[7] != 0) { /* parent, success */ msg_type = LIVE_MSG_TYPE9; video_type = VIDEO_TYPE_H264; rtspServerPortNum = 8557; H264VideoBitrate = 12000000; videoRTPPortNum = 6032; audioRTPPortNum = 6034; } } else { if( child[0] != 0 && child[1] != 0 && child[2] != 0 && child[3] != 0) { /* parent, success */ msg_type = LIVE_MSG_TYPE5; video_type = VIDEO_TYPE_H264; rtspServerPortNum = 8557; H264VideoBitrate = 12000000; videoRTPPortNum = 6032; audioRTPPortNum = 6034; } } videoType = video_type; // Objects used for multicast streaming: static Groupsock* rtpGroupsockAudio = NULL; static Groupsock* rtcpGroupsockAudio = NULL; static Groupsock* rtpGroupsockVideo = NULL; static Groupsock* rtcpGroupsockVideo = NULL; static FramedSource* sourceAudio = NULL; static RTPSink* sinkAudio = NULL; static RTCPInstance* rtcpAudio = NULL; static FramedSource* sourceVideo = NULL; static RTPSink* sinkVideo = NULL; static RTCPInstance* rtcpVideo = NULL; share_memory_init(msg_type); //init_signals(); *env << "Initializing...\n"; // Initialize the WIS input device: if( video_type == VIDEO_TYPE_MJPEG) { MjpegInputDevice = APPROInput::createNew(*env, VIDEO_TYPE_MJPEG); if (MjpegInputDevice == NULL) { err(*env) << "Failed to create MJPEG input device\n"; exit(1); } } if( video_type == VIDEO_TYPE_H264 || video_type == VIDEO_TYPE_H264_CIF || video_type == VIDEO_TYPE_H264_SVC_30FPS || video_type == VIDEO_TYPE_H264_SVC_15FPS || video_type == VIDEO_TYPE_H264_SVC_7FPS || video_type == VIDEO_TYPE_H264_SVC_3FPS) { H264InputDevice = APPROInput::createNew(*env, video_type); if (H264InputDevice == NULL) { err(*env) << "Failed to create MJPEG input device\n"; exit(1); } } if( video_type == VIDEO_TYPE_MPEG4 || video_type == VIDEO_TYPE_MPEG4_CIF ) { Mpeg4InputDevice = APPROInput::createNew(*env, video_type); if (Mpeg4InputDevice == NULL) { err(*env) << "Failed to create MPEG4 input device\n"; exit(1); } } // Create the RTSP server: RTSPServer* rtspServer = NULL; // Normal case: Streaming from a built-in RTSP server: rtspServer = RTSPServer::createNew(*env, rtspServerPortNum, NULL); if (rtspServer == NULL) { *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n"; exit(1); } *env << "...done initializing\n"; if( streamingMode == STREAMING_UNICAST ) { if( video_type == VIDEO_TYPE_MJPEG) { ServerMediaSession* sms = ServerMediaSession::createNew(*env, MjpegStreamName, MjpegStreamName, streamDescription,streamingMode == STREAMING_MULTICAST_SSM); sms->addSubsession(WISJPEGVideoServerMediaSubsession ::createNew(sms->envir(), *MjpegInputDevice, MjpegVideoBitrate)); if( IsSilence == 0) { sms->addSubsession(WISPCMAudioServerMediaSubsession::createNew(sms->envir(), *MjpegInputDevice)); } rtspServer->addServerMediaSession(sms); char *url = rtspServer->rtspURL(sms); *env << "Play this stream using the URL:\n\t" << url << "\n"; delete[] url; } if( video_type == VIDEO_TYPE_H264 || video_type == VIDEO_TYPE_H264_CIF || video_type == VIDEO_TYPE_H264_SVC_30FPS || video_type == VIDEO_TYPE_H264_SVC_15FPS || video_type == VIDEO_TYPE_H264_SVC_7FPS || video_type ==VIDEO_TYPE_H264_SVC_3FPS) { ServerMediaSession* sms; sms = ServerMediaSession::createNew(*env, H264StreamName, H264StreamName, streamDescription,streamingMode == STREAMING_MULTICAST_SSM); sms->addSubsession(WISH264VideoServerMediaSubsession ::createNew(sms->envir(), *H264InputDevice, H264VideoBitrate)); if( IsSilence == 0) { sms->addSubsession(WISPCMAudioServerMediaSubsession::createNew(sms->envir(), *H264InputDevice)); } rtspServer->addServerMediaSession(sms); char *url = rtspServer->rtspURL(sms); *env << "Play this stream using the URL:\n\t" << url << "\n"; delete[] url; } // Create a record describing the media to be streamed: if( video_type == VIDEO_TYPE_MPEG4 || video_type == VIDEO_TYPE_MPEG4_CIF ) { ServerMediaSession* sms = ServerMediaSession::createNew(*env, Mpeg4StreamName, Mpeg4StreamName, streamDescription,streamingMode == STREAMING_MULTICAST_SSM); sms->addSubsession(WISMPEG4VideoServerMediaSubsession ::createNew(sms->envir(), *Mpeg4InputDevice, Mpeg4VideoBitrate)); if( IsSilence == 0) { sms->addSubsession(WISPCMAudioServerMediaSubsession::createNew(sms->envir(), *Mpeg4InputDevice)); } rtspServer->addServerMediaSession(sms); char *url = rtspServer->rtspURL(sms); *env << "Play this stream using the URL:\n\t" << url << "\n"; delete[] url; } }else{ if (streamingMode == STREAMING_MULTICAST_SSM) { if (multicastAddress == 0) multicastAddress = chooseRandomIPv4SSMAddress(*env); } else if (multicastAddress != 0) { streamingMode = STREAMING_MULTICAST_ASM; } struct in_addr dest; dest.s_addr = multicastAddress; const unsigned char ttl = 255; // For RTCP: const unsigned maxCNAMElen = 100; unsigned char CNAME[maxCNAMElen + 1]; gethostname((char *) CNAME, maxCNAMElen); CNAME[maxCNAMElen] = '\0'; // just in case ServerMediaSession* sms=NULL; if( video_type == VIDEO_TYPE_MJPEG) { sms = ServerMediaSession::createNew(*env, MjpegStreamName, MjpegStreamName, streamDescription,streamingMode == STREAMING_MULTICAST_SSM); sourceAudio = MjpegInputDevice->audioSource(); sourceVideo = WISJPEGStreamSource::createNew(MjpegInputDevice->videoSource()); // Create 'groupsocks' for RTP and RTCP: const Port rtpPortVideo(videoRTPPortNum); const Port rtcpPortVideo(videoRTPPortNum+1); rtpGroupsockVideo = new Groupsock(*env, dest, rtpPortVideo, ttl); rtcpGroupsockVideo = new Groupsock(*env, dest, rtcpPortVideo, ttl); if (streamingMode == STREAMING_MULTICAST_SSM) { rtpGroupsockVideo->multicastSendOnly(); rtcpGroupsockVideo->multicastSendOnly(); } setVideoRTPSinkBufferSize(); sinkVideo = JPEGVideoRTPSink::createNew(*env, rtpGroupsockVideo); } if( video_type == VIDEO_TYPE_H264 || video_type == VIDEO_TYPE_H264_CIF || video_type == VIDEO_TYPE_H264_SVC_30FPS || video_type == VIDEO_TYPE_H264_SVC_15FPS || video_type == VIDEO_TYPE_H264_SVC_7FPS || video_type == VIDEO_TYPE_H264_SVC_3FPS) { sms = ServerMediaSession::createNew(*env, H264StreamName, H264StreamName, streamDescription,streamingMode == STREAMING_MULTICAST_SSM); sourceAudio = H264InputDevice->audioSource(); sourceVideo = H264VideoStreamFramer::createNew(*env, H264InputDevice->videoSource()); // Create 'groupsocks' for RTP and RTCP: const Port rtpPortVideo(videoRTPPortNum); const Port rtcpPortVideo(videoRTPPortNum+1); rtpGroupsockVideo = new Groupsock(*env, dest, rtpPortVideo, ttl); rtcpGroupsockVideo = new Groupsock(*env, dest, rtcpPortVideo, ttl); if (streamingMode == STREAMING_MULTICAST_SSM) { rtpGroupsockVideo->multicastSendOnly(); rtcpGroupsockVideo->multicastSendOnly(); } setVideoRTPSinkBufferSize(); { char BuffStr[200]; extern int GetSprop(void *pBuff, char vType); GetSprop(BuffStr,video_type); sinkVideo = H264VideoRTPSink::createNew(*env, rtpGroupsockVideo,96, 0x64001F,BuffStr); } } // Create a record describing the media to be streamed: if( video_type == VIDEO_TYPE_MPEG4 || video_type == VIDEO_TYPE_MPEG4_CIF ) { sms = ServerMediaSession::createNew(*env, Mpeg4StreamName, Mpeg4StreamName, streamDescription,streamingMode == STREAMING_MULTICAST_SSM); sourceAudio = Mpeg4InputDevice->audioSource(); sourceVideo = MPEG4VideoStreamDiscreteFramer::createNew(*env, Mpeg4InputDevice->videoSource()); // Create 'groupsocks' for RTP and RTCP: const Port rtpPortVideo(videoRTPPortNum); const Port rtcpPortVideo(videoRTPPortNum+1); rtpGroupsockVideo = new Groupsock(*env, dest, rtpPortVideo, ttl); rtcpGroupsockVideo = new Groupsock(*env, dest, rtcpPortVideo, ttl); if (streamingMode == STREAMING_MULTICAST_SSM) { rtpGroupsockVideo->multicastSendOnly(); rtcpGroupsockVideo->multicastSendOnly(); } setVideoRTPSinkBufferSize(); sinkVideo = MPEG4ESVideoRTPSink::createNew(*env, rtpGroupsockVideo,97); } /* VIDEO Channel initial */ if(1) { // Create (and start) a 'RTCP instance' for this RTP sink: unsigned totalSessionBandwidthVideo = (Mpeg4VideoBitrate+500)/1000; // in kbps; for RTCP b/w share rtcpVideo = RTCPInstance::createNew(*env, rtcpGroupsockVideo, totalSessionBandwidthVideo, CNAME, sinkVideo, NULL /* we're a server */ , streamingMode == STREAMING_MULTICAST_SSM); // Note: This starts RTCP running automatically sms->addSubsession(PassiveServerMediaSubsession::createNew(*sinkVideo, rtcpVideo)); // Start streaming: sinkVideo->startPlaying(*sourceVideo, NULL, NULL); } /* AUDIO Channel initial */ if( IsSilence == 0) { // there's a separate RTP stream for audio // Create 'groupsocks' for RTP and RTCP: const Port rtpPortAudio(audioRTPPortNum); const Port rtcpPortAudio(audioRTPPortNum+1); rtpGroupsockAudio = new Groupsock(*env, dest, rtpPortAudio, ttl); rtcpGroupsockAudio = new Groupsock(*env, dest, rtcpPortAudio, ttl); if (streamingMode == STREAMING_MULTICAST_SSM) { rtpGroupsockAudio->multicastSendOnly(); rtcpGroupsockAudio->multicastSendOnly(); } if( audioSamplingFrequency == 16000 ) { if( audioType == AUDIO_G711) { sinkAudio = SimpleRTPSink::createNew(*env, rtpGroupsockAudio, 96, audioSamplingFrequency, "audio", "PCMU", 1); } else { char const* encoderConfigStr = "1408";// (2<<3)|(8>>1) = 0x14 ; ((8<<7)&0xFF)|(1<<3)=0x08 ; sinkAudio = MPEG4GenericRTPSink::createNew(*env, rtpGroupsockAudio, 96, audioSamplingFrequency, "audio", "AAC-hbr", encoderConfigStr, audioNumChannels); } } else{ if(audioType == AUDIO_G711) { sinkAudio = SimpleRTPSink::createNew(*env, rtpGroupsockAudio, 0, audioSamplingFrequency, "audio", "PCMU", 1); } else{ char const* encoderConfigStr = "1588";// (2<<3)|(11>>1) = 0x15 ; ((11<<7)&0xFF)|(1<<3)=0x88 ; sinkAudio = MPEG4GenericRTPSink::createNew(*env, rtpGroupsockAudio, 96, audioSamplingFrequency, "audio", "AAC-hbr", encoderConfigStr, audioNumChannels); } } // Create (and start) a 'RTCP instance' for this RTP sink: unsigned totalSessionBandwidthAudio = (audioOutputBitrate+500)/1000; // in kbps; for RTCP b/w share rtcpAudio = RTCPInstance::createNew(*env, rtcpGroupsockAudio, totalSessionBandwidthAudio, CNAME, sinkAudio, NULL /* we're a server */, streamingMode == STREAMING_MULTICAST_SSM); // Note: This starts RTCP running automatically sms->addSubsession(PassiveServerMediaSubsession::createNew(*sinkAudio, rtcpAudio)); // Start streaming: sinkAudio->startPlaying(*sourceAudio, NULL, NULL); } rtspServer->addServerMediaSession(sms); { struct in_addr dest; dest.s_addr = multicastAddress; char *url = rtspServer->rtspURL(sms); //char *url2 = inet_ntoa(dest); *env << "Mulicast Play this stream using the URL:\n\t" << url << "\n"; //*env << "2 Mulicast addr:\n\t" << url2 << "\n"; delete[] url; } } // Begin the LIVE555 event loop: env->taskScheduler().doEventLoop(&watchVariable); // does not return if( streamingMode!= STREAMING_UNICAST ) { Medium::close(rtcpAudio); Medium::close(sinkAudio); Medium::close(sourceAudio); delete rtpGroupsockAudio; delete rtcpGroupsockAudio; Medium::close(rtcpVideo); Medium::close(sinkVideo); Medium::close(sourceVideo); delete rtpGroupsockVideo; delete rtcpGroupsockVideo; } Medium::close(rtspServer); // will also reclaim "sms" and its "ServerMediaSubsession"s if( MjpegInputDevice != NULL ) { Medium::close(MjpegInputDevice); } if( H264InputDevice != NULL ) { Medium::close(H264InputDevice); } if( Mpeg4InputDevice != NULL ) { Medium::close(Mpeg4InputDevice); } env->reclaim(); delete scheduler; ApproInterfaceExit(); return 0; // only to prevent compiler warning }