2011-11-19 71 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位庫)上檢測到我的網絡攝像頭! –