最近项目要求能对视频和语音进行同步合成,以及对视频进行画面与语音的分离功能,由于没有接触过这类东西,所以想从最基础做起,于是在网上找到sun公司开源的jmf架构,看到网上也有不少小例子,就开始对安装jmf并配置了开发环境,将小例子粘到自己的新建工程下,结果发现不好用,没办法自己也顺手写了一个都发生同样的问题,希望有经验的朋友能够帮助解决一下。 
  我现在干脆就用网上的一个例子来说明问题,实现的功能是,利用点击拍照按钮能,启动摄像头并将捕捉摄像头的画面将生成图片保存到物理硬盘中,代码如下: 
package com.creatplay;
import java.awt.BorderLayout;  
import java.awt.Color;  
import java.awt.Component;  
import java.awt.Dimension;  
import java.awt.Graphics;  
import java.awt.Graphics2D;  
import java.awt.Image;  
import java.awt.Panel;  
import java.awt.Rectangle;  
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.io.FileNotFoundException;  
import java.io.FileOutputStream;  
import java.io.IOException;  
 
import javax.media.Buffer;  
import javax.media.CannotRealizeException;  
import javax.media.CaptureDeviceInfo;  
import javax.media.CaptureDeviceManager;  
import javax.media.Manager;  
import javax.media.MediaLocator;  
import javax.media.NoPlayerException;  
import javax.media.Player;  
import javax.media.control.FrameGrabbingControl;  
import javax.media.format.VideoFormat;  
import javax.media.util.BufferToImage;  
import javax.swing.JButton;  
import javax.swing.JFrame;  
import javax.swing.JPanel;  
 
import com.sun.image.codec.jpeg.ImageFormatException;  
import com.sun.image.codec.jpeg.JPEGCodec;  
import com.sun.image.codec.jpeg.JPEGEncodeParam;  
import com.sun.image.codec.jpeg.JPEGImageEncoder;  
 
 
public class FirstCapture extends JPanel implements ActionListener{  
 
    private CaptureDeviceInfo captureDeviceInfo=null;  
    private MediaLocator mediaLocator=null;  
    private static Player player=null;  
    private ImagePanel imagePanel=null;  
    private JButton capture;  
    private Buffer buffer=null;  
    private VideoFormat videoFormat=null;  
    private BufferToImage bufferToImage=null;  
    private Image image=null;  
     
    public FirstCapture()  
    {  
        
        
         setLayout(new BorderLayout());  
         setSize(320,550);  
        String str="vfw:Microsoft WDM Image Capture (Win32):0";  
        captureDeviceInfo=CaptureDeviceManager.getDevice(str);  
       // MediaLocator mediaLocator=captureDeviceInfo.getLocator();
        mediaLocator=new MediaLocator("vfw://0");  
        imagePanel=new ImagePanel();  
         capture=new JButton("拍照");  
         capture.addActionListener(this);  
        try {  
            player=Manager.createRealizedPlayer(mediaLocator);  
            player.start();  
            Component comp;  
            Component comp1;  
            if((comp=player.getVisualComponent())!=null)  
                add(comp,BorderLayout.NORTH);  
//          if((comp1=player.getControlPanelComponent())!=null)  
//              add(comp1,BorderLayout.CENTER);  
        } catch (NoPlayerException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        } catch (CannotRealizeException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        } catch (IOException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
        add(imagePanel,BorderLayout.SOUTH);  
        add(capture,BorderLayout.CENTER);  
    }  
      
    @Override 
    public void print(Graphics g) {  
        // TODO Auto-generated method stub  
        super.print(g);  
        g.setColor(new Color(255,0,0));  
          g.drawLine(0, 0, 100, 100);  
    }  
 
    public static void main(String[] args) {  
        // TODO Auto-generated method stub  
        JFrame f = new JFrame("FirstCapture");  
        FirstCapture cf = new FirstCapture();  
          
        f.addWindowListener(new WindowAdapter() {  
          public void windowClosing(WindowEvent e) {  
          player.close();  
          System.exit(0);}});  
          
        f.add("Center",cf);  
        f.pack();  
        f.setSize(new Dimension(320,550));  
        f.setVisible(true);  
    }  
   
    public void actionPerformed(ActionEvent e) {  
        // TODO Auto-generated method stub  
        FrameGrabbingControl fgc=(FrameGrabbingControl)player.getControl("javax.media.control.FrameGrabbingControl");  
        buffer=fgc.grabFrame();  
        bufferToImage=new BufferToImage((VideoFormat)buffer.getFormat());  
        image=bufferToImage.createImage(buffer);  
        imagePanel.setImage(image);  
        saveImage(image,"D:/test.jpg");  
    }  
    public static void saveImage(Image image,String path)  
    {  
        BufferedImage bi=new BufferedImage(image.getWidth(null),image.getHeight(null),BufferedImage.TYPE_INT_RGB);  
        Graphics2D g2 = bi.createGraphics();  
        g2.drawImage(image, null, null);  
        FileOutputStream fos=null;  
        try {  
                fos=new FileOutputStream(path);  
              
        } catch (FileNotFoundException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
        JPEGImageEncoder je=JPEGCodec.createJPEGEncoder(fos);  
        JPEGEncodeParam jp=je.getDefaultJPEGEncodeParam(bi);  
        jp.setQuality(0.5f, false);  
        je.setJPEGEncodeParam(jp);  
        try {  
            je.encode(bi);  
            fos.close();  
        } catch (ImageFormatException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        } catch (IOException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
          
    }  
    class ImagePanel extends Panel   
      {  
        public Image myimg = null;  
          
        public ImagePanel()   
        {  
          setLayout(null);  
          setSize(320,240);  
        }  
          
        public void setImage(Image img)   
        {  
          this.myimg = img;  
          repaint();  
        }  
          
        public void paint(Graphics g)   
        {  
          if (myimg != null)   
          {  
            g.drawImage(myimg, 0, 0, this);  
          }  
            
        }  
      }  
      

运行以后老出现这个错误:
javax.media.NoPlayerException: Cannot find a Player for :vfw://0
    at javax.media.Manager.createPlayerForContent(Manager.java:1412)
    at javax.media.Manager.createPlayer(Manager.java:417)
    at javax.media.Manager.createRealizedPlayer(Manager.java:553)
    at com.creatplay.FirstCapture.<init>(FirstCapture.java:67)
    at com.creatplay.FirstCapture.main(FirstCapture.java:100)第一次发帖后没有人关注这个问题,很可能还是分数少我真的是我所有的分数,但是我还是希望哪位朋友能帮助解决一下谢谢了。

解决方案 »

  1.   

    javax.media.NoPlayerException: Cannot find a Player for :vfw://0 看错误,是找不到核实的针对 vfw 协议的播放器。
    而且后面的资源连接怎么试//0 啊?至少也应该是一个规范的资源名称吧
      

  2.   

    java2000_net无论如何先在这里谢谢你了,看照片应该是我的技术前辈呀,呵呵,我现在这个程序实现的就是一个普通的拍照功能,在JMF Registry中我能清晰的找到视频摄像头的驱动如下:
    Name = vfw:Microsoft WDM Image Capture (Win32):0Locator = vfw://0Output Formats---->0. javax.media.format.YUVFormat
      YUV Video Format: Size = java.awt.Dimension[width=640,height=480] MaxDataLength = 614400 DataType = class [B yuvType = 32 StrideY = 1280 StrideUV = 1280 OffsetY = 0 OffsetU = 1 OffsetV = 31. javax.media.format.YUVFormat
      YUV Video Format: Size = java.awt.Dimension[width=160,height=120] MaxDataLength = 38400 DataType = class [B yuvType = 32 StrideY = 320 StrideUV = 320 OffsetY = 0 OffsetU = 1 OffsetV = 32. javax.media.format.YUVFormat
      YUV Video Format: Size = java.awt.Dimension[width=176,height=144] MaxDataLength = 50688 DataType = class [B yuvType = 32 StrideY = 352 StrideUV = 352 OffsetY = 0 OffsetU = 1 OffsetV = 33. javax.media.format.YUVFormat
      YUV Video Format: Size = java.awt.Dimension[width=320,height=240] MaxDataLength = 153600 DataType = class [B yuvType = 32 StrideY = 640 StrideUV = 640 OffsetY = 0 OffsetU = 1 OffsetV = 34. javax.media.format.YUVFormat
      YUV Video Format: Size = java.awt.Dimension[width=352,height=288] MaxDataLength = 202752 DataType = class [B yuvType = 32 StrideY = 704 StrideUV = 704 OffsetY = 0 OffsetU = 1 OffsetV = 3
    所以我就在程序中应用了这个驱动:
    vfw:Microsoft WDM Image Capture (Win32):0
    根据在网上查的很多例子都是以下方式输入摄像头路径
      MediaLocator mediaLocator=new MediaLocator("vfw://0"); 
    当然也有直接获取路径的方式:
    MediaLocator mediaLocator=captureDeviceInfo.getLocator();此刻运行程序此行显示的是空指针异常。
    所以我不知道这里应该怎么写,还望您能指导一下。
    获取摄像头驱动信息和显示路径。
      

  3.   

     
    zwen1573谢谢帮忙顶呀!!!
      

  4.   

    可能你用的jfm.jar不是安装目录lib下的吧,要么换成安装目录下的jar,要么自己设置环境变量。
      

  5.   

    估计是你的JMF安装有问题,我按你的代码试了一下,图像是可以出来的,也就是说能找到设备,再检查一下吧
      

  6.   

    先在buildpath下remove掉原来的jre system library,然后在add jre system library,选择jdk1.6.
    之前remove掉的是sun的jre。  这问题折腾了我两天,希望对你有用。
      

  7.   

    Vector<CaptureDeviceInfo> video = CaptureDeviceManager
    .getDeviceList(new VideoFormat(null));
    Vector<CaptureDeviceInfo> audio = CaptureDeviceManager
    .getDeviceList(new AudioFormat(AudioFormat.LINEAR, 44100, 16, 2));
    使用的上面试一试把,在xp系统中试过了,可以的
      

  8.   

    晕,一看就是没注册摄像头
    在JMFRegister里面注册摄像头,就OK了