JMF(视频传输)

    技术2022-05-11  119

    在coogo上面看到有人在做项目,是多人视频聊天系统。要我做的感觉是很麻烦的一块。视频传输。我是还没有接触过jmf啊。一开始的时候就是只能捕获摄像头,怎么都不能传输,网络上面这方面的资料也比较上,找了很就都没有找到。没有办法,只有到sun公司去看JMF 2.1.1 Solutions。看了半天的例子,终于算是拼凑出来了。现在的问题就是可以传输,但是本地的影像却看不见了,只能看见远端的。

    代码如下:package jmfsample;

    import java.io.*;import javax.media.*;import javax.media.util.*;import javax.media.format.*;import javax.media.control.*;import javax.media.control.TrackControl;import javax.media.protocol.DataSource;import javax.media.protocol.ContentDescriptor;import javax.media.protocol.PushBufferDataSource;import javax.media.protocol.PushBufferStream;import javax.media.control.QualityControl;import javax.media.rtp.*;import javax.media.rtp.rtcp.*;import com.sun.media.rtp.*;import java.awt.*;import java.awt.event.*;import javax.swing.*;import java.net.*;

    public class JmfV extends JFrame{    public static Player player=null;    private CaptureDeviceInfo di=null;    private MediaLocator locator=null;    String str1="vfw:Logitech USB Video Camera:0";    String str2="vfw:Microsoft WDM Image Capture (Win32):0";    private Processor processor = null;    private RTPManager rtpMgrs[];    private DataSource dataOutput = null,ds=null,ds_1=null;    private String ipAddress;    private int portBase;    public JmfV( String ipAddress,    String pb,    Format format )    {     this.ipAddress = ipAddress;     Integer integer = Integer.valueOf(pb);     if (integer != null)         this.portBase = integer.intValue();        di=CaptureDeviceManager.getDevice(str2);        locator=di.getLocator();        try        {            dataOutput=Manager.createDataSource(locator);               player=Manager.createRealizedPlayer(ds);            player.start();            Component comp=null,comp_v=null;            if((comp=player.getControlPanelComponent())!=null)            {                this.getContentPane().add(comp,"North");                if((comp_v=player.getVisualComponent())!=null)                    this.getContentPane().add(comp_v,"Center");            }              ds=Manager.createCloneableDataSource(dataOutput);            this.setSize(320,320);            this.setVisible(true);            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        }catch(Exception e )        {            e.printStackTrace();        }    }    public synchronized String start() {     String result;

         // Create a processor for the specified media locator     // and program it to output JPEG/RTP     result = createProcessor();     if (result != null)         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;         return result;     }

         // Start the transmission     processor.start();          return null;        }

                 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();      }         }     }        }

            private String createProcessor() {     if (locator == null)         return "Locator is null";     // Try to create a processor to handle the input media locator     try {         processor = javax.media.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";

         // 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(tracks[i].getFormat(),            supported[0]);          } 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";

         // 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";

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

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

         return null;        }

                 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();    

          // The local session address will be created on the      // same port as the the target port. This is necessary      // if you use AVTransmit2 in conjunction with JMStudio.      // JMStudio assumes -  in a unicast session - that the      // transmitter transmits from the same port it is receiving      // on and sends RTCP Receiver Reports back to this port of      // the transmitting host.            port = portBase + 2*i;      ipAddr = InetAddress.getByName(ipAddress);

          localAddr = new SessionAddress( InetAddress.getLocalHost(),          port);            destAddr = new SessionAddress( ipAddr, port);

          rtpMgrs[i].initialize( localAddr);            rtpMgrs[i].addTarget( destAddr);            System.err.println( "Created RTP session: " + ipAddress + " " + port);            sendStream = rtpMgrs[i].createSendStream(dataOutput, i);        sendStream.start();         } catch (Exception  e) {      return e.getMessage();         }     }

         return null;        }

                 Format checkForVideoSizes(Format original, Format supported) {

         int width, height;     Dimension size = ((VideoFormat)original).getSize();     Format jpegFmt = new Format(VideoFormat.JPEG_RTP);     Format h263Fmt = new Format(VideoFormat.H263_RTP);

         if (supported.matches(jpegFmt)) {         // For JPEG, make sure width and height are divisible by 8.         width = (size.width % 8 == 0 ? size.width :        (int)(size.width / 8) * 8);         height = (size.height % 8 == 0 ? size.height :        (int)(size.height / 8) * 8);     } else if (supported.matches(h263Fmt)) {         // For H.263, we only support some specific sizes.         if (size.width < 128) {      width = 128;      height = 96;         } else if (size.width < 176) {      width = 176;      height = 144;         } else {      width = 352;      height = 288;         }     } else {         // We don't know this particular format.  We'll just         // leave it alone then.         return supported;     }

         return (new VideoFormat(null,         new Dimension(width, height),         Format.NOT_SPECIFIED,        null,        Format.NOT_SPECIFIED)).intersects(supported);        }

                 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;         }     }        }

            private Integer stateLock = new Integer(0);        private boolean failed = false;                Integer getStateLock() {     return stateLock;        }

            void setFailed() {     failed = true;        }                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;        }

            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();      }         }     }        }

              public static void main(String [] args) {     // We need three parameters to do the transmission     // For example,     //   java AVTransmit2 file:/C:/media/test.mov  129.130.131.132 42050          Format fmt = null;     int i = 0;

         // Create a audio transmit object with the specified params.     JmfV at = new JmfV("169.254.252.50", "42050", fmt);     System.out.println("Test");     // Start the transmission     String result = at.start();

         // result will be non-null if there was an error. The return     // value is a String describing the possible error. Print it.     if (result != null) {         System.err.println("Error : " + result);         System.exit(0);     }          System.err.println("Start transmission for 60 seconds...");

         // Transmit for 60 seconds and then close the processor     // This is a safeguard when using a capture data source     // so that the capture device will be properly released     // before quitting.     // The right thing to do would be to have a GUI with a     // "Stop" button that would call stop on AVTransmit2     try {         Thread.currentThread().sleep(60000);     } catch (InterruptedException ie) {     }

         // Stop the transmission     at.stop();          System.err.println("...transmission ended.");

         System.exit(0);}}

    要是有那位熟悉这方面的。希望给点建议


    最新回复(0)