int main(int argc, char** argv) { // Begin by setting up our usage environment: TaskScheduler* scheduler = BasicTaskScheduler::createNew(); env = BasicUsageEnvironment::createNew(*scheduler); // Parse command-line arguments: programName = argv[0]; if (argc != 2) usage(); char const* dssNameOrAddress = argv[1]; // Create a 'Darwin injector' object: DarwinInjector* injector = DarwinInjector::createNew(*env, programName); // Create 'groupsocks' for RTP and RTCP. // (Note: Because we will actually be streaming through a remote Darwin server, // via TCP, we just use dummy destination addresses, port numbers, and TTLs here.) struct in_addr dummyDestAddress; dummyDestAddress.s_addr = 0; Groupsock rtpGroupsockVideo(*env, dummyDestAddress, 0, 0); Groupsock rtcpGroupsockVideo(*env, dummyDestAddress, 0, 0); // Create a 'MPEG-4 Video RTP' sink from the RTP 'groupsock': videoSink = MPEG4ESVideoRTPSink::createNew(*env, &rtpGroupsockVideo, 96); // HACK, specifically for MPEG-4 video: // Before we can use this RTP sink, we need its MPEG-4 'config' information (for // use in the SDP description). Unfortunately, this config information depends // on the the properties of the MPEG-4 input data. Therefore, we need to start // 'playing' this RTP sink from the input source now, and wait until we get // the needed config information, before continuing: // that we need: *env << "Beginning streaming...\n"; play(); if (!awaitConfigInfo(videoSink)) { *env << "Failed to get MPEG-4 'config' information from input file: " << env->getResultMsg() << "\n"; exit(1); } // Create (and start) a 'RTCP instance' for this RTP sink: const unsigned estimatedSessionBandwidthVideo = 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* videoRTCP = RTCPInstance::createNew(*env, &rtcpGroupsockVideo, estimatedSessionBandwidthVideo, CNAME, videoSink, NULL /* we're a server */); // Note: This starts RTCP running automatically // Add these to our 'Darwin injector': injector->addStream(videoSink, videoRTCP); // Next, specify the destination Darwin Streaming Server: if (!injector->setDestination(dssNameOrAddress, remoteStreamName, programName, "LIVE555 Streaming Media")) { *env << "injector->setDestination() failed: " << env->getResultMsg() << "\n"; exit(1); } *env << "Play this stream (from the Darwin Streaming Server) using the URL:\n" << "\trtsp://" << dssNameOrAddress << "/" << remoteStreamName << "\n"; env->taskScheduler().doEventLoop(); // does not return return 0; // only to prevent compiler warning }
int main(int argc, char** argv) { // Begin by setting up our usage environment: TaskScheduler* scheduler = BasicTaskScheduler::createNew(); env = BasicUsageEnvironment::createNew(*scheduler); // Parse command-line arguments: programName = argv[0]; if (argc != 2) usage(); char const* dssNameOrAddress = argv[1]; // Create a 'Darwin injector' object: DarwinInjector* injector = DarwinInjector::createNew(*env, programName); ////////// AUDIO ////////// // Create 'groupsocks' for RTP and RTCP. // (Note: Because we will actually be streaming through a remote Darwin server, // via TCP, we just use dummy destination addresses, port numbers, and TTLs here.) struct in_addr dummyDestAddress; dummyDestAddress.s_addr = 0; Groupsock rtpGroupsockAudio(*env, dummyDestAddress, 0, 0); Groupsock rtcpGroupsockAudio(*env, dummyDestAddress, 0, 0); // Create a 'MPEG Audio RTP' sink from the RTP 'groupsock': audioSink = MPEG1or2AudioRTPSink::createNew(*env, &rtpGroupsockAudio); // Create (and start) a 'RTCP instance' for this RTP sink: const unsigned estimatedSessionBandwidthAudio = 160; // 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* audioRTCP = RTCPInstance::createNew(*env, &rtcpGroupsockAudio, estimatedSessionBandwidthAudio, CNAME, audioSink, NULL /* we're a server */); // Note: This starts RTCP running automatically // Add these to our 'Darwin injector': injector->addStream(audioSink, audioRTCP); ////////// END AUDIO ////////// ////////// VIDEO ////////// // Create 'groupsocks' for RTP and RTCP. // (Note: Because we will actually be streaming through a remote Darwin server, // via TCP, we just use dummy destination addresses, port numbers, and TTLs here.) Groupsock rtpGroupsockVideo(*env, dummyDestAddress, 0, 0); Groupsock rtcpGroupsockVideo(*env, dummyDestAddress, 0, 0); // Create a 'MPEG Video RTP' sink from the RTP 'groupsock': videoSink = MPEG1or2VideoRTPSink::createNew(*env, &rtpGroupsockVideo); // Create (and start) a 'RTCP instance' for this RTP sink: const unsigned estimatedSessionBandwidthVideo = 4500; // in kbps; for RTCP b/w share RTCPInstance* videoRTCP = RTCPInstance::createNew(*env, &rtcpGroupsockVideo, estimatedSessionBandwidthVideo, CNAME, videoSink, NULL /* we're a server */); // Note: This starts RTCP running automatically // Add these to our 'Darwin injector': injector->addStream(videoSink, videoRTCP); ////////// END VIDEO ////////// // Next, specify the destination Darwin Streaming Server: if (!injector->setDestination(dssNameOrAddress, remoteStreamName, programName, "LIVE555 Streaming Media")) { *env << "injector->setDestination() failed: " << env->getResultMsg() << "\n"; exit(1); } *env << "Play this stream (from the Darwin Streaming Server) using the URL:\n" << "\trtsp://" << dssNameOrAddress << "/" << remoteStreamName << "\n"; // Finally, start the streaming: *env << "Beginning streaming...\n"; play(); env->taskScheduler().doEventLoop(); // does not return return 0; // only to prevent compiler warning }
void Java_ob_android_Stream_stream(JNIEnv *env, jobject obj) { jclass streamClazz = env->GetObjectClass(obj); if(streamClazz == NULL) return; jobject videoPipe, audioPipe; if(!getObjectField(env, obj, "video", "Ljnix/Pipe;", &videoPipe)) return; if(!getObjectField(env, obj, "audio", "Ljnix/Pipe;", &audioPipe)) return; jobject videoInputFD, audioInputFD; if(!getObjectField(env, videoPipe, "input", "Ljava/io/FileDescriptor;", &videoInputFD)) return; if(!getObjectField(env, audioPipe, "input", "Ljava/io/FileDescriptor;", &audioInputFD)) return; jint vfd, afd; if(!getIntField(env, videoInputFD, "descriptor", &vfd)) return; if(!getIntField(env, audioInputFD, "descriptor", &afd)) return; if((videoFile = fdopen(vfd, "rb")) == NULL) { throwException(env, "java/lang/RuntimeException", "Unable to open the video pipe as a file"); return; } logDebug("Video file descriptor opened as a file"); if((audioFile = fdopen(afd, "rb")) == NULL) { throwException(env, "java/lang/RuntimeException", "Unable to open the video pipe as a file"); return; } logDebug("Audio file descriptor opened as a file"); logDebug("Starting to stream"); BasicTaskScheduler* scheduler = BasicTaskScheduler::createNew(); logDebug("Loaded scheduler"); uenv = BasicUsageEnvironment::createNew(*scheduler); logDebug("Loaded environment"); DarwinInjector* injector = DarwinInjector::createNew(*uenv, "streamer"); logDebug("Loaded Darwin injector"); struct in_addr dummyDestAddress; dummyDestAddress.s_addr = 0; Groupsock rtpGroupsockVideo(*uenv, dummyDestAddress, 0, 0); Groupsock rtcpGroupsockVideo(*uenv, dummyDestAddress, 0, 0); Groupsock rtpGroupsockAudio(*uenv, dummyDestAddress, 0, 0); Groupsock rtcpGroupsockAudio(*uenv, dummyDestAddress, 0, 0); logDebug("Created group sockets"); // Create an 'MPEG-4 Video RTP' sink from the RTP 'groupsock': rtpVideoSink = MPEG4ESVideoRTPSink::createNew(*uenv, &rtpGroupsockVideo, 96); rtpAudioSink = AMRAudioRTPSink::createNew(*uenv, &rtpGroupsockVideo, 97); logDebug("Created a video sink"); logDebug("Created an audio sink"); logDebug("Beginning to play"); play(); if(!awaitConfigInfo(rtpVideoSink)) { *uenv << "Failed to get MPEG-4 'config' information from input file: " << uenv->getResultMsg() << "\n"; exit(1); } // Create (and start) a 'RTCP instance' for this RTP sink: const unsigned estimatedSessionBandwidthVideo = 200; // 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 logDebug((const char*)CNAME); RTCPInstance* videoRTCP = RTCPInstance::createNew(*uenv, &rtcpGroupsockVideo, estimatedSessionBandwidthVideo, CNAME, rtpVideoSink, NULL /* we're a server */); RTCPInstance* audioRTCP = RTCPInstance::createNew(*uenv, &rtcpGroupsockAudio, estimatedSessionBandwidthVideo, CNAME, rtpAudioSink, NULL /* we're a server */); // Note: This starts RTCP running automatically // Add these to our 'Darwin injector': injector->addStream(rtpVideoSink, videoRTCP); injector->addStream(rtpAudioSink, audioRTCP); if(!injector->setDestination( "192.168.1.100", "hero.sdp", "herosession", "", 554, "broadcast", "broadcast")) { *uenv << "injector->setDestination() failed: " << uenv->getResultMsg() << "\n"; exit(1); } *uenv << "Play this stream (from the Darwin Streaming Server) using the URL:\n" << "\trtsp://" << "localhost" << "/" << "test.sdp" << "\n"; uenv->taskScheduler().doEventLoop(); }