smack 虽然提供多媒体通信 jingle 的框架,无奈却没有发布它的API,在网上到处搜罗即便是有人在讨论都极少发布自己的源码,这让我的IMtalk开发很是受阻,没有办法,只能放弃jingle自己去开发多媒体通信,于是乎想到了jmf这样一个多媒体框架
网上有很多人都写了测试用例,源码如下
import java.awt.BorderLayout; import java.awt.Component; import java.awt.Graphics; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.HeadlessException; import java.awt.Image; import java.awt.Transparency; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.PixelGrabber; import java.io.File; import java.io.IOException; import java.util.Vector; import javax.imageio.ImageIO; import javax.media.Buffer; import javax.media.CaptureDeviceInfo; import javax.media.CaptureDeviceManager; import javax.media.Format; import javax.media.MediaLocator; import javax.media.NoPlayerException; import javax.media.control.FrameGrabbingControl; import javax.media.format.RGBFormat; import javax.media.format.VideoFormat; import javax.media.protocol.DataSource; import javax.media.protocol.PushBufferDataSource; import javax.media.util.BufferToImage; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JPanel; import jmapps.jmstudio.CaptureDialog; import jmapps.ui.PlayerFrame; import jmapps.util.CDSWrapper; import jmapps.util.JMFUtils; /** * JMF 测试DEMO * @author 张立冬 * @project IMTalk项目 * 2010-8-14 */ public class Demo001 extends PlayerFrame { public Demo001() { super(null, "视频捕获窗口"); } DataSource dataSource; private CaptureDeviceInfo infor; private MediaLocator mediaLocator; String str1 = "vfw:Logitech USB Video Camera:0"; String str2 = "vfw:Microsoft WDM Image Capture (Win32):0"; private String url = "vfw:Microsoft WDM Image Capture (Win32):0"; private Component com; private JPanel panel; private int captureCount = 0; FrameGrabbingControl controlGrabber; public void play() { if (mediaPlayerCurrent.getState() != mediaPlayerCurrent.Started) { mediaPlayerCurrent.start(); } } private void init() throws NoPlayerException, IOException { // setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); String nameCaptureDeviceAudio = null; String nameCaptureDeviceVideo = null; CaptureDialog dialogCapture = new CaptureDialog(this, null); dialogCapture.show(); if (dialogCapture.getAction() == CaptureDialog.ACTION_CANCEL) return; CaptureDeviceInfo cdi = dialogCapture.getAudioDevice(); if (cdi != null && dialogCapture.isAudioDeviceUsed()) nameCaptureDeviceAudio = cdi.getName(); cdi = dialogCapture.getVideoDevice(); if (cdi != null && dialogCapture.isVideoDeviceUsed()) nameCaptureDeviceVideo = cdi.getName(); dataSource = JMFUtils.createCaptureDataSource(nameCaptureDeviceAudio, dialogCapture.getAudioFormat(), nameCaptureDeviceVideo, dialogCapture.getVideoFormat()); DataSource cdswrapper = new CDSWrapper( (PushBufferDataSource) dataSource); dataSource = cdswrapper; dataSource.connect(); open(dataSource); JPanel controlPanel = new JPanel(); controlPanel.setName("controlPnael is here"); add(BorderLayout.SOUTH, controlPanel); JButton capture = new JButton("Capture Image"); capture.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { mediaPlayerCurrent.stop(); Buffer bufferFrame; BufferToImage bufferToImage; Image image; BufferedImage bi; controlGrabber = (FrameGrabbingControl) mediaPlayerCurrent .getControl("javax.media.control.FrameGrabbingControl"); bufferFrame = controlGrabber.grabFrame(); bufferToImage = new BufferToImage((VideoFormat) bufferFrame .getFormat()); image = bufferToImage.createImage(bufferFrame); File out = new File("capture" + (++captureCount) + ".png"); try { bi = toBufferedImage(image); ImageIO.write(bi, "png", out); } catch (IOException e1) { e1.printStackTrace(); } mediaPlayerCurrent.start(); } }); controlPanel.add(BorderLayout.CENTER, capture); JButton playStop = new JButton("stop"); // add(BorderLayout.SOUTH,playControl); playStop.addActionListener(new ActionListener() { // @Override public void actionPerformed(ActionEvent arg0) { mediaPlayerCurrent.stop(); } }); controlPanel.add(BorderLayout.EAST, playStop); JButton playStart = new JButton("start"); // add(BorderLayout.SOUTH,playControl); playStart.addActionListener(new ActionListener() { // @Override public void actionPerformed(ActionEvent arg0) { // mediaPlayerCurrent.stop(); if (mediaPlayerCurrent.getState() != mediaPlayerCurrent.Started) { mediaPlayerCurrent.start(); } } }); controlPanel.add(BorderLayout.WEST, playStart); addWindowListener(new WindowAdapter() { // @Override public void windowClosing(WindowEvent e) { mediaPlayerCurrent.close(); dataSource.disconnect(); System.out.println("exit....."); System.exit(0); } }); } public static boolean hasAlpha(Image image) { // If buffered image, the color model is readily available if (image instanceof BufferedImage) { BufferedImage bimage = (BufferedImage) image; return bimage.getColorModel().hasAlpha(); } // Use a pixel grabber to retrieve the image's color model; // grabbing a single pixel is usually sufficient PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false); try { pg.grabPixels(); } catch (InterruptedException e) { } // Get the image's color model ColorModel cm = pg.getColorModel(); return cm.hasAlpha(); } public static BufferedImage toBufferedImage(Image image) { if (image instanceof BufferedImage) { return (BufferedImage) image; } // This code ensures that all the pixels in the image are loaded image = new ImageIcon(image).getImage(); // Determine if the image has transparent pixels; for this method's // implementation, see e661 Determining If an Image Has Transparent // Pixels boolean hasAlpha = hasAlpha(image); // Create a buffered image with a format that's compatible with the // screen BufferedImage bimage = null; GraphicsEnvironment ge = GraphicsEnvironment .getLocalGraphicsEnvironment(); try { // Determine the type of transparency of the new buffered image int transparency = Transparency.OPAQUE; if (hasAlpha) { transparency = Transparency.BITMASK; } // Create the buffered image GraphicsDevice gs = ge.getDefaultScreenDevice(); GraphicsConfiguration gc = gs.getDefaultConfiguration(); bimage = gc.createCompatibleImage(image.getWidth(null), image .getHeight(null), transparency); } catch (HeadlessException e) { // The system does not have a screen System.err.println("The system does not have a screen!"); System.exit(-1); } if (bimage == null) { // Create a buffered image using the default color model int type = BufferedImage.TYPE_INT_RGB; if (hasAlpha) { type = BufferedImage.TYPE_INT_ARGB; } bimage = new BufferedImage(image.getWidth(null), image .getHeight(null), type); } // Copy image to buffered image Graphics g = bimage.createGraphics(); // Paint the image onto the buffered image g.drawImage(image, 0, 0, null); g.dispose(); return bimage; } private MediaLocator autoDetect() {// 自动识别功能函数 MediaLocator ml = null; // 视频采集设备对应的MediaLocator VideoFormat currentFormat = null;// 用户定制获得视频采集设备支持的格式 Format setFormat = null;// 用户定制视频采集设备输出的格式 Format[] videoFormats = null;// 视频采集设备支持的所有格式 System.out.println(" AutoDetect for VFW");// VFW:微软的 Video for Windows // 获得当前所有设备列表 Vector deviceList = CaptureDeviceManager.getDeviceList(null); CaptureDeviceInfo device = CaptureDeviceManager.getDevice(url); if (deviceList != null) { // 根据设备列表,找出可用设备名称 for (int i = 0; i < deviceList.size(); i++) { try { CaptureDeviceInfo di = (CaptureDeviceInfo) deviceList .elementAt(i); // 如果设备名称以vfw开头 if (di.getName().startsWith("vfw:")) { // 获得所有支持RGB格式 videoFormats = di.getFormats(); for (int j = 0; j < videoFormats.length; j++) { // 我们只需要第一种RGB格式 if (videoFormats[j] instanceof RGBFormat) { currentFormat = (RGBFormat) videoFormats[i]; break; } } if (currentFormat == null) { System.err.println("Search For RGBFormat Failed"); System.exit(-1); } // 通过设备,获得MediaLocator,这个很重要 ml = di.getLocator(); } } catch (Exception npe) { System.err.println("Unable to get Processor for device"); System.exit(-1); } } } else { System.err.println("No Capture Device OK"); System.exit(-1); } mediaLocator = ml; return ml;// 返回可用的设备medialocator } public static void main(String[] args) throws NoPlayerException, IOException { Demo001 demo = new Demo001(); demo.setSize(100, 100); demo.autoDetect(); demo.init(); demo.play(); demo.setVisible(true); } }
但是跑起来却报了这样一个错
AutoDetect for VFW Exception in thread "main" java.lang.NullPointerException at cn.zld.imtalk.client.test.Demo001.play(Demo001.java:79) at cn.zld.imtalk.client.test.Demo001.main(Demo001.java:304)
我是直接将它的压缩文件里面的JAR文件导入的,在网上找了下,说是只要将jmf安装目录下的jar文件导入就可以了,我试了下发现果然可以了,分析了下原因所在,发现与JAR文件同一个目录下有一下properties文件,这应当是它初始化的一些配置信息,再次尝试不替换JAR文件,只是将安装目录下的properties文件改动,发现果然可以用了,这应该是问题的所在