java - JMF:为网络摄像头设置 FPS

标签 java webcam jmf

我有一个网络摄像头(实际上是 3 个)和用于捕获帧的 java 程序。但是,我还没有找到设置 FPS 的方法。例如,当我使用新的 VideoFormat 设置 FPS 时,我可以看到 camFormat.intersects(newFormat) 正确应用了它。但是,当我从相机获取帧时(通过 BufferTransferHandler 或通过手动获取),我得到的帧数多于选定的 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)
    {}
}

最佳答案

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

关于java - JMF:为网络摄像头设置 FPS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8194875/

相关文章:

java - For 循环的阶乘仅适用于 12

c++ - 在 opencv 中使用网络摄像头未显示图像

python - 开放CV : Detect object without displaying the webcam view window

objective-c - 以编程方式访问 iSight?

用于基于视频的应用程序的 Java : Good choice?

java - 无法使用 JMF 播放 mp3 流

java - Spring-MVC - 创建名称为 'procesarController' : Injection of autowired dependencies failed 的 bean 时出错

java - 使用共享首选项来保存一些整数

java - 似乎无法将 JTextArea 添加到 JScrollPane 中?

java - JMF无法处理格式