JMF:设置摄像头的FPS



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

是否有一种方法来轮询一个新的帧是否准备好了?

我发现了更多的信息,所以我正在编辑这个。似乎问题的根源是微软WDM图像捕获驱动程序。在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)
    {}
}

我找到了一个DirectShow到Java包装器替换JMF (http://www.humatic.de/htools/dsj.htm),它要慢得多,但可以完成工作。

最新更新