2011-11-19 137 views
2

我有一个摄像头(实际上是3)和java程序来捕捉帧。但是,我还没有找到设置FPS的方法。例如,当我使用新的VideoFormat设置FPS时,我可以看到它正确应用camFormat.intersects(newFormat)。但是,当我从相机中取出相框(通过BufferTransferHandler或通过手动取出)时,我获得的帧数多于所选的FPS。JMF:设置摄像头的FPS

如果新框架已经准备就绪,那么是否有可能进行轮询?

我发现了更多信息,所以我正在编辑它。 看来问题的根源在于Microsoft WDM Image Capture驱动程序。在VirtualDub捕捉模式下,我可以选择每个单独的网络摄像头,并选择WDM。选择WDM时,我会得到与JFM中的自定义格式对话框中相同的选项,并且它不会以全FPS捕获。但是,CaptureDeviceManager.getDeviceList似乎只返回WDM驱动程序,而不是单个网络摄像头(和两个话筒内的网络摄像头,但不是声卡麦克风)。为什么是这样?

这让我很奇怪,我可以指定帧率,但是我找不到实际执行它的方法,即使在搜索互联网并尝试了不同的示例代码后的几天。我发现的每一个例子都只是以自己的速度请求帧,或者根本不在乎fps。

我的测试类:

运行,使用顶部的按钮(重新)打开格式控制窗口(内部JMF),并尝试改变FPS。这也是奇怪的是,除了非功能性的FPS领域,像分辨率场等领域也有非功能性(因为它是由分辨率字段中覆盖“自定义格式...”窗口。

import java.awt.BorderLayout; 
import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Image; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.WindowEvent; 
import java.awt.event.WindowListener; 
import java.awt.image.BufferedImage; 
import java.util.Vector; 

import javax.media.Buffer; 
import javax.media.CaptureDeviceInfo; 
import javax.media.CaptureDeviceManager; 
import javax.media.ControllerAdapter; 
import javax.media.ControllerClosedEvent; 
import javax.media.ControllerErrorEvent; 
import javax.media.Manager; 
import javax.media.MediaLocator; 
import javax.media.Player; 
import javax.media.RealizeCompleteEvent; 
import javax.media.StartEvent; 
import javax.media.StopEvent; 
import javax.media.control.FormatControl; 
import javax.media.control.FrameGrabbingControl; 
import javax.media.format.FormatChangeEvent; 
import javax.media.format.VideoFormat; 
import javax.media.format.YUVFormat; 
import javax.media.util.BufferToImage; 
import javax.swing.JButton; 
import javax.swing.JComponent; 
import javax.swing.JDialog; 
import javax.swing.JFrame; 
import javax.swing.JOptionPane; 

public class CaptureTest extends JComponent implements ActionListener, WindowListener, Runnable 
{ 
    public static void main(String[] args) 
    { 
     Runnable r = new Runnable() 
     { 
      @Override 
      public void run() 
      { 
       new CaptureTest(); 
      } 
     }; 
     EventQueue.invokeLater(r); 
    } 

    Player     player; 
    FrameGrabbingControl grabber; 
    FormatControl   formatControl; 
    final JFrame   frame; 
    public Image   image; 

    public CaptureTest() 
    { 
     setLayout(new BorderLayout()); 

     Vector<?> deviceVector = CaptureDeviceManager.getDeviceList(new YUVFormat()); 

     final CaptureDeviceInfo[] deviceList = new CaptureDeviceInfo[deviceVector.size()]; 
     for (int i = 0; i < deviceList.length; i++) 
     { 
      deviceList[i] = (CaptureDeviceInfo)deviceVector.get(i); 
      System.out.println("Capture Device found: " + deviceList[i].getName()); 
     } 

     frame = new JFrame("Capture test"); 
     frame.addWindowListener(this); 

     { 
      JButton b = new JButton("Format Control"); 
      b.setEnabled(true); 
      b.addActionListener(this); 

      frame.add(b, BorderLayout.NORTH); 
     } 
     { 
      setPreferredSize(new Dimension(640, 480)); 
      frame.add(this, BorderLayout.CENTER); 
     } 

     ControllerAdapter cl = new ControllerAdapter() 
     { 
      @Override 
      public void realizeComplete(RealizeCompleteEvent rce) 
      { 
       formatControl = (FormatControl)player.getControl("javax.media.control.FormatControl"); 
       grabber = (FrameGrabbingControl)player.getControl("javax.media.control.FrameGrabbingControl"); 

       Component co = formatControl.getControlComponent(); 
       if (co != null) 
       { 
        player.stop(); 
        JDialog d = new JDialog(frame, "Format Control", true); 
        d.add(co); 
        d.pack(); 
        d.setLocationRelativeTo(frame); 
        d.setVisible(true); 
        d.dispose(); 
        player.start(); 
       } 

       System.out.println("realizeComplete: " + formatControl.getFormat()); 
      } 

      @Override 
      public void formatChange(FormatChangeEvent fce) 
      {} 

      @Override 
      public void start(StartEvent se) 
      {} 

      @Override 
      public void stop(StopEvent se) 
      {} 

      @Override 
      public void controllerError(ControllerErrorEvent cee) 
      { 
       System.err.println(cee.getMessage()); 
       System.err.println("Caused by: " + cee.getSource()); 
       System.exit(0); 
      } 

      @Override 
      public void controllerClosed(ControllerClosedEvent cce) 
      {} 
     }; 

     MediaLocator ml = deviceList[0].getLocator(); 
     try 
     { 
      Manager.setHint(Manager.PLUGIN_PLAYER, Boolean.TRUE); 
      player = Manager.createPlayer(ml); 
      player.addControllerListener(cl); 
      player.start(); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
      JOptionPane.showMessageDialog(frame, "Could Not Create Player", "ERROR", JOptionPane.ERROR_MESSAGE); 
     } 

     frame.pack(); 
     frame.setVisible(true); 

     new Thread(this).start(); 
    } 

    public void grab() 
    { 
     if (grabber == null) 
      return; 

     Buffer buf = grabber.grabFrame(); 
     // System.out.println(fps.getFPS() + "\t" + buf.getFormat()); 
     BufferToImage b2i = new BufferToImage((VideoFormat)buf.getFormat()); 
     BufferedImage bi = (BufferedImage)b2i.createImage(buf); 
     if (bi != null) 
     { 
      setImage(bi); 
      repaint(); 
     } 
    } 

    public void setImage(Image im) 
    { 
     image = im; 
     Dimension size = new Dimension(im.getWidth(null), im.getHeight(null)); 

     setPreferredSize(size); 
     setSize(size); 
    } 

    @Override 
    public void paintComponent(Graphics g) 
    { 
     if (image != null) 
      g.drawImage(image, 0, 0, this); 
    } 

    @Override 
    public void run() 
    { 
     while (true) 
     { 
      grab(); 
      Thread.yield(); 
     } 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) 
    { 
     Component co = formatControl.getControlComponent(); 
     if (co != null) 
     { 
      player.stop(); 
      JDialog d = new JDialog(frame, "Format Control", true); 
      d.add(co); 
      d.pack(); 
      d.setLocationRelativeTo(frame); 
      d.setVisible(true); 
      d.dispose(); 
      player.start(); 
     } 
    } 

    @Override 
    public void windowOpened(WindowEvent e) 
    {} 

    @Override 
    public void windowClosing(WindowEvent we) 
    { 
     if (player != null) 
     { 
      player.stop(); 
      player.close(); 
     } 
     System.exit(0); 
    } 

    @Override 
    public void windowClosed(WindowEvent e) 
    {} 

    @Override 
    public void windowIconified(WindowEvent e) 
    {} 

    @Override 
    public void windowDeiconified(WindowEvent e) 
    {} 

    @Override 
    public void windowActivated(WindowEvent e) 
    {} 

    @Override 
    public void windowDeactivated(WindowEvent e) 
    {} 
} 

回答

0

我发现JMF的DirectShow to Java包装器更换(http://www.humatic.de/htools/dsj.htm),这个过程要慢很多,但是完成这个工作。

+0

你可能是对的。自2003年以来已更新/发布,并且我无法在64位Linux(仅提供32位库)上检测到我的网络摄像头! –