2011-08-08 37 views
0

目前,我正在寻找一个选项,将RTP上的JPanel内容流式传输到接收客户端。 JPanel会例如包含一个JFreeChart和一些应该在远程客户端播放器上显示的标签(实际上它是一个支持RTP的演示软件)。通过RTP流Java Swing组件

是否有任何库允许从UI组件生成这样的流并通过RTP进行后续传输?

感谢任何暗示和建议 KC

P.S。: 响应于Qwerky的问题:只有他们的视觉表示(例如他们的图像)应被发送。

+3

Doe你想要流式传输实际的组件(包括状态/功能)或只是它们的表示,例如图像/视频。 – Qwerky

回答

0

Concludingly,我结束了实施基于JMF组分流包:

JpegHelper:

package ch.beo.streaming.swing; 

import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.Graphics2D; 
import java.awt.image.BufferedImage; 
import java.io.ByteArrayOutputStream; 
import java.io.IOException; 

import javax.imageio.ImageIO; 

    /** 
    * Helper class to convert UI components to JPEG images. 
    */ 
    public final class JpegHelper { 
     private JpegHelper() { 
    } 

    /** 
    * Transforms any given UI {@link java.awt.Component Component} to a JPEG 
    * image. 
    * 
    * @param component 
    *   A paintable {@link java.awt.Component Component}. 
    * @return The binary representation of JPEG image, representing 
    *   <code>component's</code> current visual state. 
    */ 
    public static byte[] componentToJpeg(Component component) { 
     Dimension size = component.getSize(); 
     BufferedImage image = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_RGB); 
     Graphics2D graphics2d = image.createGraphics(); 
     component.paint(graphics2d); 
     graphics2d.dispose(); 
     ByteArrayOutputStream out = new ByteArrayOutputStream(); 
     try { 
      ImageIO.write(image, "jpg", out); 
     } catch (IOException e) { 
      throw new RuntimeException(e); 
     } finally { 
      if (out != null) { 
       try { 
        out.close(); 
       } catch (IOException e) { 
        throw new RuntimeException(e); 
       } 
      } 
     } 
     return out.toByteArray(); 
    } 
} 

ComponentBufferStream:

package ch.beo.streaming.swing; 

import java.awt.Component; 
import java.awt.Dimension; 
import java.io.IOException; 

import javax.media.Buffer; 
import javax.media.Format; 
import javax.media.format.VideoFormat; 
import javax.media.protocol.ContentDescriptor; 
import javax.media.protocol.PullBufferStream; 

import ch.beo.streaming.base.ControlHelper; 

/** 
* Implements a {@link javax.media.protocol.PullBufferStream PullBufferStream} 
* based on a given {@link java.awt.Component Component}. The current visual 
* representation of the {@link java.awt.Component component} is continuously 
* provided as a JPEG image. 
*/ 
public class ComponentBufferStream implements PullBufferStream { 
    private static final int KEY_FRAME_RATE = 100; 
    private final Component component; 
    private int frameCount = -1; 

    public ComponentBufferStream(Component component) { 
     this.component = component; 
    } 

    /* 
    * (non-Javadoc) 
    * @see javax.media.protocol.SourceStream#endOfStream() 
    */ 
    @Override 
    public boolean endOfStream() { 
     return false; 
    } 

    /* 
    * (non-Javadoc) 
    * @see javax.media.protocol.SourceStream#getContentDescriptor() 
    */ 
    @Override 
    public ContentDescriptor getContentDescriptor() { 
     return new ContentDescriptor(ContentDescriptor.RAW); 
    } 

    /* 
    * (non-Javadoc) 
    * @see javax.media.protocol.SourceStream#getContentLength() 
    */ 
    @Override 
    public long getContentLength() { 
     return LENGTH_UNKNOWN; 
    } 

    /* 
    * (non-Javadoc) 
    * @see javax.media.Controls#getControl(java.lang.String) 
    */ 
    @Override 
    public Object getControl(String controlType) { 
     return ControlHelper.getControl(this, controlType); 
    } 

    /* 
    * (non-Javadoc) 
    * @see javax.media.Controls#getControls() 
    */ 
    @Override 
    public Object[] getControls() { 
     return ControlHelper.getControls(this); 
    } 

    /* 
    * (non-Javadoc) 
    * @see javax.media.protocol.PullBufferStream#getFormat() 
    */ 
    @Override 
    public Format getFormat() { 
     Dimension size = component.getSize(); 
     return new VideoFormat(VideoFormat.JPEG, size, Format.NOT_SPECIFIED, Format.byteArray, 0.1f); 
    } 

    /* 
    * (non-Javadoc) 
    * @see javax.media.protocol.PullBufferStream#read(javax.media.Buffer) 
    */ 
    @Override 
    public void read(Buffer buffer) throws IOException { 
     byte[] image = JpegHelper.componentToJpeg(component); 
     byte[] data = (byte[]) buffer.getData(); 
     if (data != null && data.length - buffer.getOffset() >= image.length) { 
      System.arraycopy(image, 0, data, buffer.getOffset(), image.length); 
     } else { 
      buffer.setData(image); 
      buffer.setOffset(0); 
     } 
     buffer.setLength(image.length); 
     buffer.setFormat(getFormat()); 
     if (isKeyFrame()) { 
      buffer.setFlags(buffer.getFlags() | Buffer.FLAG_KEY_FRAME); 
     } 
    } 

    private boolean isKeyFrame() { 
     if (++frameCount % KEY_FRAME_RATE == 0) { 
      frameCount = 0; 
      return true; 
     } 
     return false; 
    } 

    /* 
    * (non-Javadoc) 
    * @see javax.media.protocol.PullBufferStream#willReadBlock() 
    */ 
    @Override 
    public boolean willReadBlock() { 
     Dimension dimension = component.getSize(); 
     return dimension.height > 0 && dimension.width > 0; 
    } 
} 

ComponentDataSource:

package ch.beo.streaming.swing; 

import java.awt.Component; 
import java.io.IOException; 

import javax.media.Time; 
import javax.media.protocol.PullBufferDataSource; 
import javax.media.protocol.PullBufferStream; 

import ch.beo.streaming.base.ControlHelper; 

/** 
* Implements a {@link javax.media.protocol.PullBufferDataSource 
* PullBufferDataSource} based on a given {@link java.awt.Component Component}. 
* The current visual representation of the {@link java.awt.Component component} 
* is continuously provided as a JPEG image. 
*/ 
public class ComponentDataSource extends PullBufferDataSource { 
    private final PullBufferStream[] streams; 

    public ComponentDataSource(Component component) { 
     streams = new PullBufferStream[] { new ComponentBufferStream(component) }; 
    } 

    /* 
    * (non-Javadoc) 
    * @see javax.media.protocol.DataSource#connect() 
    */ 
    @Override 
    public void connect() throws IOException { 
    } 

    /* 
    * (non-Javadoc) 
    * @see javax.media.protocol.DataSource#disconnect() 
    */ 
    @Override 
    public void disconnect() { 
    } 

    /* 
    * (non-Javadoc) 
    * @see javax.media.protocol.DataSource#getContentType() 
    */ 
    @Override 
    public String getContentType() { 
     return streams[0].getContentDescriptor().getContentType(); 
    } 

    /* 
    * (non-Javadoc) 
    * @see javax.media.protocol.DataSource#getControl(java.lang.String) 
    */ 
    @Override 
    public Object getControl(String controlType) { 
     return ControlHelper.getControl(this, controlType); 
    } 

    /* 
    * (non-Javadoc) 
    * @see javax.media.protocol.DataSource#getControls() 
    */ 
    @Override 
    public Object[] getControls() { 
     return ControlHelper.getControls(this); 
    } 

    /* 
    * (non-Javadoc) 
    * @see javax.media.protocol.DataSource#getDuration() 
    */ 
    @Override 
    public Time getDuration() { 
     return Time.TIME_UNKNOWN; 
    } 

    /* 
    * (non-Javadoc) 
    * @see javax.media.protocol.DataSource#start() 
    */ 
    @Override 
    public void start() throws IOException { 
    } 

    /* 
    * (non-Javadoc) 
    * @see javax.media.protocol.DataSource#stop() 
    */ 
    @Override 
    public void stop() throws IOException { 
    } 

    /* 
    * (non-Javadoc) 
    * @see javax.media.protocol.PullBufferDataSource#getStreams() 
    */ 
    @Override 
    public PullBufferStream[] getStreams() { 
     return streams; 
    } 
} 

与其他一些辅助类一起,这个伎俩。