Package de.medint.rtpsharer.main

Source Code of de.medint.rtpsharer.main.Streamer$StateListener

package de.medint.rtpsharer.main;

import java.awt.Dimension;
import java.io.IOException;
import java.net.InetAddress;

import javax.media.Codec;
import javax.media.Control;
import javax.media.Controller;
import javax.media.ControllerClosedEvent;
import javax.media.ControllerEvent;
import javax.media.ControllerListener;
import javax.media.Format;
import javax.media.NoProcessorException;
import javax.media.Owned;
import javax.media.Player;
import javax.media.Processor;
import javax.media.control.QualityControl;
import javax.media.control.TrackControl;
import javax.media.format.VideoFormat;
import javax.media.protocol.ContentDescriptor;
import javax.media.protocol.DataSource;
import javax.media.protocol.PushBufferDataSource;
import javax.media.protocol.PushBufferStream;
import javax.media.rtp.RTPManager;
import javax.media.rtp.SendStream;
import javax.media.rtp.SessionAddress;
import javax.media.rtp.rtcp.SourceDescription;

import org.apache.log4j.Logger;

import de.medint.rtpsharer.datasource.*;
import de.medint.rtpsharer.util.ConfigUtil;



/**
* Class for Streaming ScreenCaptures via RTP
* @author o.becherer
*
*/
public class Streamer {
 
  private static Logger log = Logger.getLogger(Streamer.class);
 
  /** RTP Target Address */
  private String ipAddress = "10.136.110.255";
  
  /** PortBase for RTP*/
  private int portBase = 22224;
  
  /** SourcePort RTP */
  private int sourcePort = 22300;
  
  /** Processor*/
  private Processor processor = null;
     
  /** RTP MANAGER */
  private RTPManager rtpMgrs[];
  
  /** DataSource from ImageDataSource via Processor*/
  private DataSource dataOutput = null;
  
 
  /** Error Indicator (waitSync)*/
  private boolean failed = false;
 
  private Integer stateLock = new Integer(0);
 
 
  /**
   *
   * @param address
   * @param destPort
   * @param sourcePort
   */
  public Streamer(){
   
    this.ipAddress = ConfigUtil.destinationAddress;
    this.portBase = ConfigUtil.destinationPort;
    this.sourcePort = 22300; //ConfigUtil.sourcePort; //TODO  :CHANGE TO NOT HARDCODED PORT!!
                  //Why do we have to change that? swagner 11.09.2009
   
   
    //Extend and capture different Screen Resolutions
    Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
   
    ConfigUtil.videoWidth = Long.valueOf(Math.round(screenSize.getWidth())).intValue();
    ConfigUtil.videoHeight = Long.valueOf(Math.round(screenSize.getHeight())).intValue();
   
    ConfigUtil.videoWidth = 640;
    ConfigUtil.videoHeight = 480;
  }
  
   /**
    * Start Streaming Captured
    */
   //------------------------------------------------------------------------------------------
   public synchronized String start(){
     try {
      log.debug("START IP:Port , Source-Port" + this.ipAddress + ":"
          + this.portBase + " , " + this.sourcePort);

      log.debug("Screen Width and Height "+ConfigUtil.videoWidth+" "+ConfigUtil.videoHeight);
      
      String result;

      // Create a processor for the specified media locator
      // and program it to output JPEG/RTP
      result = createProcessor();
     
      //If Result is NULL then everything is ok
      if (result != null) {
        System.out.println(result);
        throw new Exception("ERROR IN CREATING PROCESSOR "+result);
        //return result;
      }

      // Create an RTP session to transmit the output of the
      // processor to the specified IP address and port no.
      result = createTransmitter();
      if (result != null) {
        processor.close();
        processor = null;
        System.out.println(result);
        throw new Exception("ERROR IN CREATING Transmitter "+result);
        //return result;
      }

      // Start the transmission
      processor.start();
     
     } catch (Exception err) {
       log.error("[start]",err);
     }
   
    return null;

   }
   //------------------------------------------------------------------------------------------
 
  
  /**
   * Use the RTPManager API to create sessions for each media
   * track of the processor.
   */
   private String createTransmitter() {

    // Cheated.  Should have checked the type.
    PushBufferDataSource pbds = (PushBufferDataSource)dataOutput;
    PushBufferStream pbss[] = pbds.getStreams();

    rtpMgrs = new RTPManager[pbss.length];
    SessionAddress localAddr, destAddr;
    InetAddress ipAddr;
    SendStream sendStream;
    int port;
    SourceDescription srcDesList[];

    for (int i = 0; i < pbss.length; i++) {
        try {
      rtpMgrs[i] = RTPManager.newInstance();     
     
      port = portBase + 2*i;
      ipAddr = InetAddress.getByName(ipAddress);
     
     
      System.out.println("createTransmitter  localAddress: " + InetAddress.getLocalHost() + "=" + sourcePort);

      localAddr = new SessionAddress( InetAddress.getLocalHost(),sourcePort);
     
      System.out.println("createTransmitter  destAddress: " + ipAddress + "=" + port);

      destAddr = new SessionAddress( ipAddr, port);

      rtpMgrs[i].initialize( localAddr);
     
      rtpMgrs[i].addTarget( destAddr);
     
      sendStream = rtpMgrs[i].createSendStream(dataOutput, i);
     
      sendStream.start();
        } catch (Exception  e) {
          return e.getMessage();
        }
    }

    return null;
      }
 
   /** Stop Streaming Captures*/
   //------------------------------------------------------------------------------------------
   public void stop(){
    
     synchronized (this) {
          if (processor != null) {
            processor.stop();
            processor.close();
            processor = null;
       
            for (int i = 0; i < rtpMgrs.length; i++) {
              rtpMgrs[i].removeTargets( "Session ended.");
              rtpMgrs[i].dispose();
            }
          }
      }
   }
   //------------------------------------------------------------------------------------------
  
   /**
    * Creating the Processor
    */
   //------------------------------------------------------------------------------------------
   private String createProcessor() {
    try
    
      // ImageDataSource reading ScreenCaptures
      ImageDataSource ids = new ImageDataSource(ConfigUtil.videoWidth, ConfigUtil.videoHeight, ConfigUtil.frameRate);
        
       
       // Try to create a processor to handle the input media locator
      try {
          processor = javax.media.Manager.createProcessor(ids);
      } catch (NoProcessorException npe) {
          return "Couldn't create processor : " + npe.getMessage();
      } catch (IOException ioe) {
          return "IOException creating processor " + ioe.getMessage();
      }
 
      // 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";
      }
      // Set the output content descriptor to RAW_RTP
      // This will limit the supported formats reported from
      // Track.getSupportedFormats to only valid RTP formats.
      ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW_RTP);
     
      processor.setContentDescriptor(cd);

      Format supported[];
      Format chosen;
      boolean atLeastOneTrack = false;

      // Program the tracks.
      for (int i = 0; i < tracks.length; i++) {
          Format format = tracks[i].getFormat();
          if (tracks[i].isEnabled()) {

        supported = tracks[i].getSupportedFormats();

        // We've set the output content to the RAW_RTP.
        // So all the supported formats should work with RTP.
        // We'll just pick the first one.

        if (supported.length > 0) {
            if (supported[0] instanceof VideoFormat) {
          // For video formats, we should double check the
          // sizes since not all formats work in all sizes.
          chosen = checkForVideoSizes(format,
                  supported[0], ConfigUtil.videoWidth, ConfigUtil.videoHeight);
            } else
          chosen = supported[0];
            tracks[i].setFormat(chosen);
            System.err.println("Track " + i + " is set to transmit as:");
            System.err.println("  " + chosen);
            atLeastOneTrack = true;
        } else
            tracks[i].setEnabled(false);
          } else
        tracks[i].setEnabled(false);
      }

      if (!atLeastOneTrack)
          return "Couldn't set any of the tracks to a valid RTP format";

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

     
      // Setting JPEG Quality
      setJPEGQuality(processor, ConfigUtil.quality);

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

    } catch (Exception err) {
      log.error("[createProcessor]",err);
    }
    return null;
   }
   //------------------------------------------------------------------------------------------
  
   /**
    * Waiting for ProcessorStates
    */
   //------------------------------------------------------------------------------------------
  private synchronized boolean waitForState(Processor p, int state) {
    try {
     
      p.addControllerListener(new StateListener());
      failed = false;
 
      // Call the required method on the processor
      if (state == Processor.Configured) {
        p.configure();
      } else if (state == Processor.Realized) {
        log.debug("DO Realize");
        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;
   
    } catch (Exception err) {
      log.error("[waitForState]",err);
    }
    return false;
  }
   //------------------------------------------------------------------------------------------
  
  
  
   /**
    * Setting the encoding quality to the specified value on the JPEG encoder.
    * 0.5 is a good default.
    */
   //------------------------------------------------------------------------------------------
    void setJPEGQuality(Player p, float val) {

    Control cs[] = p.getControls();
    QualityControl qc = null;
    VideoFormat jpegFmt = new VideoFormat(VideoFormat.JPEG);

    // Loop through the controls to find the Quality control for
     // the JPEG encoder.
    for (int i = 0; i < cs.length; i++) {

        if (cs[i] instanceof QualityControl &&
      cs[i] instanceof Owned) {
      Object owner = ((Owned)cs[i]).getOwner();

      // Check to see if the owner is a Codec.
      // Then check for the output format.
      if (owner instanceof Codec) {
          Format fmts[] = ((Codec)owner).getSupportedOutputFormats(null);
          for (int j = 0; j < fmts.length; j++) {
        if (fmts[j].matches(jpegFmt)) {
         
            qc = (QualityControl)cs[i];
                qc.setQuality(val);
             
            System.err.println("- Setting quality to " +
            val + " on " + qc);
            break;
        }
          }
      }
      if (qc != null)
          break;
        }
    }
      }
      //---------------------------------------------------------------------------------------
    
  
   /**
     * For JPEG and H263, we know that they only work for particular
     * sizes.  So we'll perform extra checking here to make sure they
     * are of the right sizes.
    */
   //------------------------------------------------------------------------------------------
    private Format checkForVideoSizes(Format original, Format supported, int videoWidth, int videoHeight) {

     
    Format jpegFmt = new Format(VideoFormat.JPEG_RTP);
   
    //Format h263Fmt = new Format(VideoFormat.H263_RTP);
   
    // Setting our Dimensions within jpegFormat
    Format myFormat =new VideoFormat(null,
        new Dimension(videoWidth, videoHeight),
        Format.NOT_SPECIFIED,
        null,
        Format.NOT_SPECIFIED).intersects(jpegFmt);
   
     
   
    return myFormat;
   
      }

    //------------------------------------------------------------------------------------------
   
   /**
    * InnerClass for StateListening
    */
   class StateListener implements ControllerListener {

      public void controllerUpdate(ControllerEvent ce) {

          // If there was an error during configure or
          // realize, the processor will be closed
          if (ce instanceof ControllerClosedEvent)
            setFailed();

          // All controller events, send a notification
          // to the waiting thread in waitForState method.
          if (ce instanceof ControllerEvent) {
            synchronized (getStateLock()) {
              getStateLock().notifyAll();
            }
          }
      }
   }
  
   void setFailed() {
    failed = true;
   }
  
   Integer getStateLock() {
    return stateLock;
   }
}
TOP

Related Classes of de.medint.rtpsharer.main.Streamer$StateListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.