[英]JMF: Setting FPS for webcam
我有一个摄像头(实际上是3个)和java程序来捕获帧。 但是,我还没有找到设置FPS的方法。 例如,当我使用新的VideoFormat
设置FPS时,可以看到camFormat.intersects(newFormat)
正确应用了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包装器的替代品,它的运行速度虽然慢很多,但却可以完成工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.