private InputStream getInputStream(
      String urlStr, Format outputFormat, ContentDescriptor outputContentDescriptor)
      throws Exception {
    final ProcessorModel processorModel =
        new ProcessorModel(
            new MediaLocator(urlStr),
            outputFormat == null ? null : new Format[] {outputFormat},
            outputContentDescriptor);

    final Processor processor = Manager.createRealizedProcessor(processorModel);

    final DataSource ds = processor.getDataOutput();

    final DataSink[] streamDataSinkHolder = new DataSink[] {null};
    // connect the data output of the processor to a StreamDataSink, which
    // will make the data available to PipedInputStream, which we return.
    final PipedInputStream in =
        new PipedInputStream() {
          // override close to clean up everything when the media has been
          // served.
          @Override
          public void close() throws IOException {
            super.close();
            logger.fine("Closed input stream");
            logger.fine("Stopping processor");
            processor.stop();
            logger.fine("Closing processor");
            processor.close();
            logger.fine("Deallocating processor");
            processor.deallocate();
            if (streamDataSinkHolder[0] != null) {
              logger.fine("Closing StreamDataSink");
              streamDataSinkHolder[0].close();
            }
          }
        };
    final PipedOutputStream out = new PipedOutputStream(in);
    final DataSink streamDataSink = new StreamDataSink(out);
    streamDataSinkHolder[0] = streamDataSink;

    streamDataSink.setSource(ds);
    streamDataSink.open();
    streamDataSink.start();

    logger.info("Starting processor");
    processor.start();

    // TODO: if there is an error, make sure we clean up.
    // for example, if the client breaks the connection.
    // we need a controller listener to listen for errors.

    return in;
  }
  /** Create the DataSink. */
  DataSink createDataSink(Processor p, MediaLocator outML) {
    DataSource ds;

    if ((ds = p.getDataOutput()) == null) {
      System.err.println(
          "Something is really wrong: the processor does not have an output DataSource");
      return null;
    }

    DataSink dsink;

    try {
      System.err.println("- Create DataSink for: " + outML);
      dsink = Manager.createDataSink(ds, outML);
      dsink.open();
    } catch (Exception e) {
      System.err.println("Cannot create the DataSink: " + e);
      return null;
    }

    return dsink;
  }
  /** With the given processor info generated from matchTracks, build each of the processors. */
  public boolean buildTracks(ProcInfo pInfo[]) {
    ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW);
    Processor p;

    for (int i = 0; i < pInfo.length; i++) {
      p = pInfo[i].p;
      p.setContentDescriptor(cd);

      // We are done with programming the processor. Let's just
      // realize the it.
      if (!waitForState(p, Controller.Realized)) {
        System.err.println("- Failed to realize the processor.");
        return false;
      }

      // Set the JPEG quality to .5.
      setJPEGQuality(p, 0.5f);

      PushBufferStream pbs[];
      TrackInfo tInfo;
      int trackID;

      // Cheating. I should have checked the type of DataSource
      // returned.
      pInfo[i].ds = (PushBufferDataSource) p.getDataOutput();
      pbs = pInfo[i].ds.getStreams();

      // Find the matching data stream for the given track for audio.

      for (int type = AUDIO; type < MEDIA_TYPES; type++) {
        for (trackID = 0; trackID < pInfo[i].numTracksByType[type]; trackID++) {
          tInfo = pInfo[i].tracksByType[type][trackID];
          tInfo.pbs = pbs[tInfo.idx];
        }
      }
    }

    return true;
  }
Esempio n. 4
0
  /**
   * Creates a video stream of the interactions with the given component at the specified frame rate
   * and saves it as the given file.
   */
  public static Processor recordVideo(Component component, int fps, File dest) {
    if (component == null) return null;
    Dimension size = component.getSize();
    Point location = component.getLocationOnScreen();
    String loc =
        MessageFormat.format(
            "screen://{0},{1},{2},{3}/{4}",
            new Object[] {
              new Integer(location.x), new Integer(location.y),
              new Integer(size.width - size.width % 8), new Integer(size.height - size.height % 8),
              new Integer(fps)
            });
    MediaLocator mSource = new MediaLocator(loc);
    Processor p = null;
    try {
      DataSource data = Manager.createDataSource(mSource);
      p = Manager.createProcessor(mSource);
      waitForState(p, Processor.Configured);
      p.setContentDescriptor(new FileTypeDescriptor("video.x_msvideo"));
      p.getTrackControls()[0].setFormat(new VideoFormat(VideoFormat.MJPG));

      waitForState(p, Processor.Realized);

      DataSource data2 = p.getDataOutput();
      String path = dest.getParent();
      String name = dest.getName();
      if (!name.toLowerCase().endsWith(".avi")) name += ".avi";
      MediaLocator mediaDest = new MediaLocator(new File(path, name).toURL());
      DataSink dataSink = Manager.createDataSink(data2, mediaDest);
      dataSink.open();
      dataSink.start();
      p.start();
    } catch (Exception ex) {
      ex.printStackTrace();
      p = null;
    }
    return p;
  }
  public static void main(String[] args) {
    if (args.length != 2) {
      System.out.println("Usage: rtpaudio <targetIP> <targetPort>");
      System.exit(0);
    }

    try {
      RegistryDefaults.setDefaultFlags(RegistryDefaults.FMJ);

      // create a clean registry
      RegistryDefaults.unRegisterAll(RegistryDefaults.ALL);
      RegistryDefaults.registerAll(RegistryDefaults.FMJ);

      // remove all capture devices
      Vector deviceList = (Vector) CaptureDeviceManager.getDeviceList(null).clone();
      for (int i = 0; i < deviceList.size(); i++) {
        CaptureDeviceInfo cdi = (CaptureDeviceInfo) deviceList.elementAt(i);
        CaptureDeviceManager.removeDevice(cdi);
      }

      // update capture device list
      new net.sf.fmj.media.cdp.javasound.CaptureDevicePlugger().addCaptureDevices();
      PlugInManager.commit();

      deviceList = (Vector) CaptureDeviceManager.getDeviceList(null).clone();
      if ((null == deviceList) || (deviceList.size() == 0)) {
        System.out.println("### ERROR found no audio capture device");
        System.exit(0);
      }

      // enumerate all codec
      Vector codecList = PlugInManager.getPlugInList(null, null, PlugInManager.CODEC);
      System.out.println("found " + codecList.size() + " codec");
      for (int i = 0; i < codecList.size(); i++) {
        String aCodecClass = (String) codecList.elementAt(i);
        System.out.println("# " + (i + 1) + " " + aCodecClass);
      }

      // fetch first available audio capture device
      deviceList = (Vector) CaptureDeviceManager.getDeviceList(null).clone();
      CaptureDeviceInfo captureDeviceInfo = (CaptureDeviceInfo) deviceList.elementAt(0);
      System.out.println("### using " + captureDeviceInfo.getName());
      System.out.println("### locator " + captureDeviceInfo.getLocator());

      javax.media.protocol.DataSource dataSource =
          javax.media.Manager.createDataSource(
              new javax.media.MediaLocator(captureDeviceInfo.getLocator().toString()));
      // javax.media.protocol.DataSource dataSource =
      // javax.media.Manager.createDataSource(new
      // javax.media.MediaLocator("javasound://"));
      System.out.println("### created datasource " + dataSource.getClass().getName());

      javax.media.control.FormatControl[] formatControls =
          ((javax.media.protocol.CaptureDevice) dataSource).getFormatControls();
      System.out.println("got format control " + formatControls[0].getClass().getName());

      System.out.println("current format is " + formatControls[0].getFormat());

      // set audio capture format
      javax.media.Format[] formats = formatControls[0].getSupportedFormats();
      for (int i = 0; i < formats.length; i++) {
        javax.media.format.AudioFormat af = (javax.media.format.AudioFormat) formats[i];
        if ((af.getChannels() == 1) && (af.getSampleSizeInBits() == 16)) {
          if (af.getSampleRate() == Format.NOT_SPECIFIED) {
            javax.media.format.AudioFormat newAudioFormat =
                new javax.media.format.AudioFormat(
                    af.getEncoding(),
                    8000.0f,
                    javax.media.Format.NOT_SPECIFIED,
                    javax.media.Format.NOT_SPECIFIED);
            // javax.media.format.AudioFormat newAudioFormat = new
            // javax.media.format.AudioFormat(af.getEncoding(),
            // 44100.0f, javax.media.Format.NOT_SPECIFIED,
            // javax.media.Format.NOT_SPECIFIED);
            formatControls[0].setFormat(newAudioFormat.intersects(af));
            break;
          }
        }
      }
      System.out.println("current format is now " + formatControls[0].getFormat());

      FrameProcessingControl fpc = null;

      // adujst recording buffer ( to adjust latency )
      dataSource.stop();
      Object[] controls = dataSource.getControls();
      for (int i = 0; i < controls.length; i++) {
        String className = controls[i].getClass().getName();
        if (-1 != className.indexOf("JavaSoundBufferControl")) {
          javax.media.control.BufferControl bc = (javax.media.control.BufferControl) controls[i];
          System.out.println(
              "### current javasound buffer length is " + bc.getBufferLength() + " ms");
          bc.setBufferLength(40);
          System.out.println(
              "### current javasound buffer length is " + bc.getBufferLength() + " ms");
        } else if (-1 != className.indexOf("JitterBufferControl")) {
          javax.media.control.BufferControl bc = (javax.media.control.BufferControl) controls[i];
          System.out.println("### current jitter buffer length is " + bc.getBufferLength() + " ms");
          bc.setBufferLength(80);
          System.out.println("### current jitter buffer length is " + bc.getBufferLength() + " ms");
        } else if (-1 != className.indexOf("FPC")) {
          fpc = (FrameProcessingControl) controls[i];
          System.out.println("### found bitrate control " + fpc.getClass());
        }
      }
      dataSource.start();

      // create processor
      javax.media.Processor processor = javax.media.Manager.createProcessor(dataSource);
      System.out.println("### created processor " + processor.getClass().getName());

      processor.configure();
      for (int idx = 0; idx < 100; idx++) {
        if (processor.getState() == Processor.Configured) {
          break;
        }
        Thread.sleep(100);
      }
      System.out.println("### processor state " + processor.getState());

      processor.setContentDescriptor(
          new javax.media.protocol.ContentDescriptor(ContentDescriptor.RAW_RTP));

      javax.media.control.TrackControl[] tracks = processor.getTrackControls();
      // /tracks[0].setFormat(new
      // javax.media.format.AudioFormat(javax.media.format.AudioFormat.ULAW_RTP,
      // 8000, 8, 1));
      tracks[0].setFormat(
          new javax.media.format.AudioFormat(javax.media.format.AudioFormat.GSM_RTP, 8000, 8, 1));

      processor.realize();
      for (int idx = 0; idx < 100; idx++) {
        if (processor.getState() == Controller.Realized) {
          break;
        }
        Thread.sleep(100);
      }
      System.out.println("### processor state " + processor.getState());

      javax.media.protocol.DataSource dataOutput = processor.getDataOutput();
      System.out.println("### processor data output " + dataOutput.getClass().getName());

      // BitRateControl
      BitRateControl bitrateControl = null;

      Object[] controls2 = dataOutput.getControls();
      for (int i = 0; i < controls2.length; i++) {
        if (controls2[i] instanceof BitRateControl) {
          bitrateControl = (BitRateControl) controls2[i];
          System.out.println("### found bitrate control " + bitrateControl.getClass());
          break;
        }
      }

      // PacketSizeControl
      Object[] controls3 = processor.getControls();
      for (int i = 0; i < controls3.length; i++) {
        if (controls3[i] instanceof PacketSizeControl) {
          PacketSizeControl psc = (PacketSizeControl) controls3[i];
          System.out.println("### current packetsize is " + psc.getPacketSize() + " bytes");
          psc.setPacketSize(66);
          System.out.println("### current packetsize is " + psc.getPacketSize() + " bytes");
          break;
        }
      }

      // enumerate all controls of the processor
      Object[] pcontrols = processor.getControls();
      for (int i = 0; i < pcontrols.length; i++) {
        System.out.println("processor control " + i + " " + pcontrols[i]);
      }

      javax.media.rtp.RTPManager rtpManager = javax.media.rtp.RTPManager.newInstance();

      javax.media.rtp.SessionAddress local =
          new javax.media.rtp.SessionAddress(
              InetAddress.getLocalHost(), Integer.valueOf(args[1]).intValue());
      javax.media.rtp.SessionAddress target =
          new javax.media.rtp.SessionAddress(
              InetAddress.getByName(args[0]), Integer.valueOf(args[1]).intValue());

      rtpManager.initialize(local);
      rtpManager.addTarget(target);

      javax.media.rtp.SendStream sendStream = rtpManager.createSendStream(dataOutput, 0);
      sendStream.start();

      processor.start();
      Thread.sleep(1000);

      System.out.println("\n>>>>>>  TRANSMITTING ULAW/RTP AUDIO NOW");
      while (2 > 1) {
        Thread.sleep(1000);

        if (null != bitrateControl) {
          TransmissionStats stats = sendStream.getSourceTransmissionStats();
          System.out.println(
              "rtp audio send: bitrate="
                  + bitrateControl.getBitRate()
                  + " (pdu="
                  + stats.getPDUTransmitted()
                  + " bytes="
                  + stats.getBytesTransmitted()
                  + " overrun="
                  + fpc.getFramesDropped()
                  + ")");
        }
      }
    } catch (Exception ex) {
      ex.printStackTrace();
    }

    System.exit(0);
  }
Esempio n. 6
0
  /**
   * Implements {@link ControllerListener#controllerUpdate(ControllerEvent)}. Handles events from
   * the <tt>Processor</tt>s that this instance uses to transcode media.
   *
   * @param ev the event to handle.
   */
  public void controllerUpdate(ControllerEvent ev) {
    if (ev == null || ev.getSourceController() == null) {
      return;
    }

    Processor processor = (Processor) ev.getSourceController();
    ReceiveStreamDesc desc = findReceiveStream(processor);

    if (desc == null) {
      logger.warn("Event from an orphaned processor, ignoring: " + ev);
      return;
    }

    if (ev instanceof ConfigureCompleteEvent) {
      if (logger.isInfoEnabled()) {
        logger.info(
            "Configured processor for ReceiveStream ssrc="
                + desc.ssrc
                + " ("
                + desc.format
                + ")"
                + " "
                + System.currentTimeMillis());
      }

      boolean audio = desc.format instanceof AudioFormat;

      if (audio) {
        ContentDescriptor cd = processor.setContentDescriptor(AUDIO_CONTENT_DESCRIPTOR);
        if (!AUDIO_CONTENT_DESCRIPTOR.equals(cd)) {
          logger.error(
              "Failed to set the Processor content "
                  + "descriptor to "
                  + AUDIO_CONTENT_DESCRIPTOR
                  + ". Actual result: "
                  + cd);
          removeReceiveStream(desc, false);
          return;
        }
      }

      for (TrackControl track : processor.getTrackControls()) {
        Format trackFormat = track.getFormat();

        if (audio) {
          final long ssrc = desc.ssrc;
          SilenceEffect silenceEffect;
          if (Constants.OPUS_RTP.equals(desc.format.getEncoding())) {
            silenceEffect = new SilenceEffect(48000);
          } else {
            // We haven't tested that the RTP timestamps survive
            // the journey through the chain when codecs other than
            // opus are in use, so for the moment we rely on FMJ's
            // timestamps for non-opus formats.
            silenceEffect = new SilenceEffect();
          }

          silenceEffect.setListener(
              new SilenceEffect.Listener() {
                boolean first = true;

                @Override
                public void onSilenceNotInserted(long timestamp) {
                  if (first) {
                    first = false;
                    // send event only
                    audioRecordingStarted(ssrc, timestamp);
                  } else {
                    // change file and send event
                    resetRecording(ssrc, timestamp);
                  }
                }
              });
          desc.silenceEffect = silenceEffect;
          AudioLevelEffect audioLevelEffect = new AudioLevelEffect();
          audioLevelEffect.setAudioLevelListener(
              new SimpleAudioLevelListener() {
                @Override
                public void audioLevelChanged(int level) {
                  activeSpeakerDetector.levelChanged(ssrc, level);
                }
              });

          try {
            // We add an effect, which will insert "silence" in
            // place of lost packets.
            track.setCodecChain(new Codec[] {silenceEffect, audioLevelEffect});
          } catch (UnsupportedPlugInException upie) {
            logger.warn("Failed to insert silence effect: " + upie);
            // But do go on, a recording without extra silence is
            // better than nothing ;)
          }
        } else {
          // transcode vp8/rtp to vp8 (i.e. depacketize vp8)
          if (trackFormat.matches(vp8RtpFormat)) track.setFormat(vp8Format);
          else {
            logger.error("Unsupported track format: " + trackFormat + " for ssrc=" + desc.ssrc);
            // we currently only support vp8
            removeReceiveStream(desc, false);
            return;
          }
        }
      }

      processor.realize();
    } else if (ev instanceof RealizeCompleteEvent) {
      desc.dataSource = processor.getDataOutput();

      long ssrc = desc.ssrc;
      boolean audio = desc.format instanceof AudioFormat;
      String suffix = audio ? AUDIO_FILENAME_SUFFIX : VIDEO_FILENAME_SUFFIX;

      // XXX '\' on windows?
      String filename = getNextFilename(path + "/" + ssrc, suffix);
      desc.filename = filename;

      DataSink dataSink;
      if (audio) {
        try {
          dataSink = Manager.createDataSink(desc.dataSource, new MediaLocator("file:" + filename));
        } catch (NoDataSinkException ndse) {
          logger.error("Could not create DataSink: " + ndse);
          removeReceiveStream(desc, false);
          return;
        }

      } else {
        dataSink = new WebmDataSink(filename, desc.dataSource);
      }

      if (logger.isInfoEnabled())
        logger.info(
            "Created DataSink ("
                + dataSink
                + ") for SSRC="
                + ssrc
                + ". Output filename: "
                + filename);
      try {
        dataSink.open();
      } catch (IOException e) {
        logger.error("Failed to open DataSink (" + dataSink + ") for" + " SSRC=" + ssrc + ": " + e);
        removeReceiveStream(desc, false);
        return;
      }

      if (!audio) {
        final WebmDataSink webmDataSink = (WebmDataSink) dataSink;
        webmDataSink.setSsrc(ssrc);
        webmDataSink.setEventHandler(eventHandler);
        webmDataSink.setKeyFrameControl(
            new KeyFrameControlAdapter() {
              @Override
              public boolean requestKeyFrame(boolean urgent) {
                return requestFIR(webmDataSink);
              }
            });
      }

      try {
        dataSink.start();
      } catch (IOException e) {
        logger.error(
            "Failed to start DataSink (" + dataSink + ") for" + " SSRC=" + ssrc + ". " + e);
        removeReceiveStream(desc, false);
        return;
      }

      if (logger.isInfoEnabled()) logger.info("Started DataSink for SSRC=" + ssrc);

      desc.dataSink = dataSink;

      processor.start();
    } else if (logger.isDebugEnabled()) {
      logger.debug(
          "Unhandled ControllerEvent from the Processor for ssrc=" + desc.ssrc + ": " + ev);
    }
  }
Esempio n. 7
0
  public static void main(String[] args) {

    // ---------------- CUT HERE START ----------------- //

    Format formats[] = new Format[2];
    formats[0] = new AudioFormat(AudioFormat.IMA4);
    formats[1] = new VideoFormat(VideoFormat.CINEPAK);
    FileTypeDescriptor outputType = new FileTypeDescriptor(FileTypeDescriptor.QUICKTIME);
    Processor p = null;

    try {
      p = Manager.createRealizedProcessor(new ProcessorModel(formats, outputType));
    } catch (IOException e) {
      System.exit(-1);
    } catch (NoProcessorException e) {
      System.exit(-1);
    } catch (CannotRealizeException e) {
      System.exit(-1);
    }
    // get the output of the processor
    DataSource source = p.getDataOutput();
    // create a File protocol MediaLocator with the location of the file to
    // which bits are to be written
    MediaLocator dest = new MediaLocator("file://foo.mov");
    // create a datasink to do the file writing & open the sink to make sure
    // we can write to it.
    DataSink filewriter = null;
    try {
      filewriter = Manager.createDataSink(source, dest);
      filewriter.open();
    } catch (NoDataSinkException e) {
      System.exit(-1);
    } catch (IOException e) {
      System.exit(-1);
    } catch (SecurityException e) {
      System.exit(-1);
    }
    // now start the filewriter and processor
    try {
      filewriter.start();
    } catch (IOException e) {
      System.exit(-1);
    }
    p.start();
    // stop and close the processor when done capturing...
    // close the datasink when EndOfStream event is received...

    // ----------------- CUT HERE END ---------------- //
    try {
      Thread.currentThread().sleep(4000);
    } catch (InterruptedException ie) {
    }
    p.stop();
    p.close();
    try {
      Thread.currentThread().sleep(1000);
    } catch (InterruptedException ie) {
    }
    filewriter.close();
    try {
      Thread.currentThread().sleep(4000);
    } catch (InterruptedException ie) {
    }

    System.exit(0);
  }
Esempio n. 8
0
  private String createProcessor() {
    if (locator == null) return "Locator is null";

    DataSource ds;
    DataSource clone;

    try {
      ds = Manager.createDataSource(locator);
    } catch (Exception e) {
      return "Couldn't create DataSource";
    }

    // Try to create a processor to handle the input media locator
    try {
      processor = Manager.createProcessor(ds);
    } catch (NoProcessorException npe) {
      return "Couldn't create processor";
    } catch (IOException ioe) {
      return "IOException creating processor";
    }

    // Wait for it to configure
    boolean result = waitForState(processor, Processor.Configured);
    if (result == false) return "Couldn't configure processor";

    // Get the tracks from the processor
    TrackControl[] tracks = processor.getTrackControls();

    // Do we have atleast one track?
    if (tracks == null || tracks.length < 1) return "Couldn't find tracks in processor";

    boolean programmed = false;

    // Search through the tracks for a video track
    for (int i = 0; i < tracks.length; i++) {
      Format format = tracks[i].getFormat();
      if (tracks[i].isEnabled() && format instanceof VideoFormat && !programmed) {

        // Found a video track. Try to program it to output JPEG/RTP
        // Make sure the sizes are multiple of 8's.
        Dimension size = ((VideoFormat) format).getSize();
        float frameRate = ((VideoFormat) format).getFrameRate();
        int w = (size.width % 8 == 0 ? size.width : (int) (size.width / 8) * 8);
        int h = (size.height % 8 == 0 ? size.height : (int) (size.height / 8) * 8);
        VideoFormat jpegFormat =
            new VideoFormat(
                VideoFormat.JPEG_RTP,
                new Dimension(w, h),
                Format.NOT_SPECIFIED,
                Format.byteArray,
                frameRate);
        tracks[i].setFormat(jpegFormat);
        System.err.println("Video transmitted as:");
        System.err.println("  " + jpegFormat);
        // Assume succesful
        programmed = true;
      } else tracks[i].setEnabled(false);
    }

    if (!programmed) return "Couldn't find video track";

    // Set the output content descriptor to RAW_RTP
    ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW_RTP);
    processor.setContentDescriptor(cd);

    // Realize the processor. This will internally create a flow
    // graph and attempt to create an output datasource for JPEG/RTP
    // video frames.
    result = waitForState(processor, Controller.Realized);
    if (result == false) return "Couldn't realize processor";

    // Set the JPEG quality to .5.
    setJPEGQuality(processor, 0.5f);

    // Get the output data source of the processor
    dataOutput = processor.getDataOutput();
    return null;
  }