Пример #1
0
  private synchronized boolean waitForState(Processor p, int state) {
    p.addControllerListener(new StateListener());
    failed = false;

    // Call the required method on the processor
    if (state == Processor.Configured) {
      p.configure();
    } else if (state == Processor.Realized) {
      p.realize();
    }

    // Wait until we get an event that confirms the
    // success of the method, or a failure event.
    // See StateListener inner class
    while (p.getState() < state && !failed) {
      synchronized (getStateLock()) {
        try {
          getStateLock().wait();
        } catch (InterruptedException ie) {
          return false;
        }
      }
    }

    if (failed) return false;
    else return true;
  }
Пример #2
0
  /**
   * Implements {@link ReceiveStreamListener#update(ReceiveStreamEvent)}.
   *
   * <p>{@link #rtpManager} will use this to notify us of <tt>ReceiveStreamEvent</tt>s.
   */
  @Override
  public void update(ReceiveStreamEvent event) {
    if (event == null) return;
    ReceiveStream receiveStream = event.getReceiveStream();

    if (event instanceof NewReceiveStreamEvent) {
      if (receiveStream == null) {
        logger.warn("NewReceiveStreamEvent: null");
        return;
      }

      final long ssrc = getReceiveStreamSSRC(receiveStream);

      ReceiveStreamDesc receiveStreamDesc = findReceiveStream(ssrc);

      if (receiveStreamDesc != null) {
        String s = "NewReceiveStreamEvent for an existing SSRC. ";
        if (receiveStream != receiveStreamDesc.receiveStream)
          s += "(but different ReceiveStream object)";
        logger.warn(s);
        return;
      } else receiveStreamDesc = new ReceiveStreamDesc(receiveStream);

      if (logger.isInfoEnabled()) logger.info("New ReceiveStream, ssrc=" + ssrc);

      // Find the format of the ReceiveStream
      DataSource dataSource = receiveStream.getDataSource();
      if (dataSource instanceof PushBufferDataSource) {
        Format format = null;
        PushBufferDataSource pbds = (PushBufferDataSource) dataSource;
        for (PushBufferStream pbs : pbds.getStreams()) {
          if ((format = pbs.getFormat()) != null) break;
        }

        if (format == null) {
          logger.error("Failed to handle new ReceiveStream: " + "Failed to determine format");
          return;
        }

        receiveStreamDesc.format = format;
      } else {
        logger.error("Failed to handle new ReceiveStream: " + "Unsupported DataSource");
        return;
      }

      int rtpClockRate = -1;
      if (receiveStreamDesc.format instanceof AudioFormat)
        rtpClockRate = (int) ((AudioFormat) receiveStreamDesc.format).getSampleRate();
      else if (receiveStreamDesc.format instanceof VideoFormat) rtpClockRate = 90000;
      getSynchronizer().setRtpClockRate(ssrc, rtpClockRate);

      // create a Processor and configure it
      Processor processor = null;
      try {
        processor = Manager.createProcessor(receiveStream.getDataSource());
      } catch (NoProcessorException npe) {
        logger.error("Failed to create Processor: ", npe);
        return;
      } catch (IOException ioe) {
        logger.error("Failed to create Processor: ", ioe);
        return;
      }

      if (logger.isInfoEnabled()) logger.info("Created processor for SSRC=" + ssrc);

      processor.addControllerListener(this);
      receiveStreamDesc.processor = processor;

      final int streamCount;
      synchronized (receiveStreams) {
        receiveStreams.add(receiveStreamDesc);
        streamCount = receiveStreams.size();
      }

      /*
       * XXX TODO IRBABOON
       * This is a terrible hack which works around a failure to realize()
       * some of the Processor-s for audio streams, when multiple streams
       * start nearly simultaneously. The cause of the problem is currently
       * unknown (and synchronizing all FMJ calls in RecorderRtpImpl
       * does not help).
       * XXX TODO NOOBABRI
       */
      if (receiveStreamDesc.format instanceof AudioFormat) {
        final Processor p = processor;
        new Thread() {
          @Override
          public void run() {
            // delay configuring the processors for the different
            // audio streams to decrease the probability that they
            // run together.
            try {
              int ms = 450 * (streamCount - 1);
              logger.warn(
                  "Sleeping for "
                      + ms
                      + "ms before"
                      + " configuring processor for SSRC="
                      + ssrc
                      + " "
                      + System.currentTimeMillis());
              Thread.sleep(ms);
            } catch (Exception e) {
            }

            p.configure();
          }
        }.run();
      } else {
        processor.configure();
      }
    } else if (event instanceof TimeoutEvent) {
      if (receiveStream == null) {
        // TODO: we might want to get the list of ReceiveStream-s from
        // rtpManager and compare it to our list, to see if we should
        // remove a stream.
        logger.warn("TimeoutEvent: null.");
        return;
      }

      // FMJ silently creates new ReceiveStream instances, so we have to
      // recognize them by the SSRC.
      ReceiveStreamDesc receiveStreamDesc = findReceiveStream(getReceiveStreamSSRC(receiveStream));
      if (receiveStreamDesc != null) {
        if (logger.isInfoEnabled()) {
          logger.info("ReceiveStream timeout, ssrc=" + receiveStreamDesc.ssrc);
        }

        removeReceiveStream(receiveStreamDesc, true);
      }
    } else if (event != null && logger.isInfoEnabled()) {
      logger.info("Unhandled ReceiveStreamEvent (" + event.getClass().getName() + "): " + event);
    }
  }
 StateWaiter(Processor p) {
   this.p = p;
   p.addControllerListener(this);
 }
  /**
   * Given an array of input media locators and an output locator, this method will concatenate the
   * input media files to generate a single concatentated output.
   */
  public boolean doIt(MediaLocator inML[], MediaLocator outML) {
    // Guess the output content descriptor from the file extension.
    ContentDescriptor cd;

    if ((cd = fileExtToCD(outML.getRemainder())) == null) {
      System.err.println("Couldn't figure out from the file extension the type of output needed!");
      return false;
    }

    // Build the ProcInfo data structure for each processor.
    ProcInfo pInfo[] = new ProcInfo[inML.length];

    for (int i = 0; i < inML.length; i++) {
      pInfo[i] = new ProcInfo();
      pInfo[i].ml = inML[i];

      try {
        System.err.println("- Create processor for: " + inML[i]);
        pInfo[i].p = Manager.createProcessor(inML[i]);
      } catch (Exception e) {
        System.err.println("Yikes!  Cannot create a processor from the given url: " + e);
        return false;
      }
    }

    // Try to match the tracks from different processors.
    if (!matchTracks(pInfo, cd)) {
      System.err.println("Failed to match the tracks.");
      return false;
    }

    // Program each processors to perform the necessary transcoding
    // to concatenate the tracks.
    if (!buildTracks(pInfo)) {
      System.err.println("Failed to build processors for the inputs.");
      return false;
    }

    // Generate a super glue data source from the processors.
    SuperGlueDataSource ds = new SuperGlueDataSource(pInfo);

    // Create the processor to generate the final output.
    Processor p;
    try {
      p = Manager.createProcessor(ds);
    } catch (Exception e) {
      System.err.println("Failed to create a processor to concatenate the inputs.");
      return false;
    }

    p.addControllerListener(this);

    // Put the Processor into configured state.
    if (!waitForState(p, Processor.Configured)) {
      System.err.println("Failed to configure the processor.");
      return false;
    }

    // Set the output content descriptor on the final processor.
    System.err.println("- Set output content descriptor to: " + cd);
    if ((p.setContentDescriptor(cd)) == null) {
      System.err.println("Failed to set the output content descriptor on the processor.");
      return false;
    }

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

    // Now, we'll need to create a DataSink.
    DataSink dsink;
    if ((dsink = createDataSink(p, outML)) == null) {
      System.err.println("Failed to create a DataSink for the given output MediaLocator: " + outML);
      return false;
    }

    dsink.addDataSinkListener(this);
    fileDone = false;

    System.err.println("- Start concatenation...");

    // OK, we can now start the actual concatenation.
    try {
      p.start();
      dsink.start();
    } catch (IOException e) {
      System.err.println("IO error during concatenation");
      return false;
    }

    // Wait for EndOfStream event.
    waitForFileDone();

    // Cleanup.
    try {
      dsink.close();
    } catch (Exception e) {
    }
    p.removeControllerListener(this);

    System.err.println("  ...done concatenation.");

    return true;
  }