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
}
Beispiel #3
0
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();
}