Java(JMF)获取本地摄像头,实时显示图像

原创
2015/05/07 23:00
阅读数 2.3K

这几天用了JMF,感觉这个好坑,在win7,jdk1.7版本上支持都不太好,可能是JMF是一个老的东西把,现在apache好像都放弃了,没去了解。。

搞了我3天的时间。主要还是在环境搭建这边花了好多时间,太坑了,最后还弄不到我想要的效果,网上资料也不是很多,不说了,现在把我在网上找的几行代码整理一下,方便日后查看

package com.rola.luming;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.Vector;

import javax.media.CannotRealizeException;
import javax.media.CaptureDeviceInfo;
import javax.media.CaptureDeviceManager;
import javax.media.DataSink;
import javax.media.Format;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.NoDataSourceException;
import javax.media.NoPlayerException;
import javax.media.Player;
import javax.media.Processor;
import javax.media.ProcessorModel;
import javax.media.control.FormatControl;
import javax.media.protocol.DataSource;
import javax.media.protocol.FileTypeDescriptor;
import javax.media.protocol.SourceCloneable;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class MainUI extends JFrame{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private JButton startVideo;		//开始录像按钮
	private JButton stopVideo;		//停止录像按钮
	private JPanel videoPanel;		//填充视频的面板
	private JPanel buttonPanel;		//放置按钮的面板
	
	private DataSource source;		//原始视频数据
	private Player play = null;		//视频播放器
	private DataSource cloneableSource;		//可以克隆的视频数据
	private DataSource clonedDataSource;	//克隆出来的视频数据
	private Processor processor;		//视频处理器
	private DataSink dataSink;			//保存录制数据的数据池(datasink: 数据接收装置; 数据接收器)
	private JFileChooser fileChooser = new JFileChooser();		//文件选择框
	
	public void init() {
		JFrame frame = new JFrame("视 频 监 控 窗 口");
		frame.setLayout(new BorderLayout());
		String url = "vfw:Microsoft WDM Image Capture (Win32):0";		//摄像头设备的驱动,在JMStudio可查看
		CaptureDeviceInfo newCameraDevice = CaptureDeviceManager.getDevice(url);	//获取摄像头设备
		//获取系统所有的视频,音频设备
		//Vector<CaptureDeviceInfo> deviceList = CaptureDeviceManager.getDeviceList(null);
		//for(CaptureDeviceInfo info:deviceList) {
			//System.out.println(info.getName());	//输出所有的设备驱动名称
		//}
		//System.out.println("end---------------");
		MediaLocator ml = newCameraDevice.getLocator();//设备定位器
		try {
			//source = Manager.createDataSource(ml);
			//在调用createCloneableDataSource(source)后source不能再调用了
			//本来是要弄可以录制的,但是不知道为什么在弄数据流的时候老是出错,可能是视频源那边出错了,
			//我在网上找了很多都没找到合适的答案,希望有人能告诉我,不胜感激
			cloneableSource = Manager.createCloneableDataSource(source);
			play = Manager.createRealizedPlayer(ml);
			//play = Manager.createRealizedPlayer(cloneableSource);
			
			
		} catch (NoPlayerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (CannotRealizeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		videoPanel = new JPanel();
		play.start();
		Component comp = null;
		if ((comp = play.getVisualComponent()) != null) 
			videoPanel.add(comp); 
		
		startVideo = new JButton("开始录像");//该功能实现不了
		stopVideo = new JButton("停止录像");	//该功能实现不了
		videoPanel.setSize(500, 500); 
		buttonPanel = new JPanel();
		buttonPanel.add(startVideo);
		buttonPanel.add(stopVideo);
		frame.add("South",buttonPanel);
		frame.add("Center",videoPanel);
		startVideo.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				start();
			}
		});
		
		stopVideo.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				stop();
			}
		});
		frame.setSize(500,600);
		frame.setVisible(true);
	}
	/**
	 * 开始摄像按钮方法
	 * 该功能在win7,jdk1.6环境下实现不了,不知道是什么原因了,希望实现的朋友能告诉我一下
	 * 主要是在获取可克隆数据流时出错了,调试的结果是clonedDataSource 未null,这个我就不知道了
	 * 
	 */
	private void start() {
		
		clonedDataSource = ((SourceCloneable)cloneableSource).createClone();
		FormatControl formatControl = (FormatControl) play.getControl("javax.media.control.FormatControl");
		Format defaultFormat = formatControl.getFormat();
		//第三个参数
		FileTypeDescriptor outputFileType = new FileTypeDescriptor(FileTypeDescriptor.QUICKTIME);
		ProcessorModel processorModel = new ProcessorModel(clonedDataSource,
				new Format[]{defaultFormat},outputFileType);
		
		try{
			processor = Manager.createRealizedProcessor(processorModel);
		}catch (Exception e) {
			e.printStackTrace();
		}
		String locatorString = this.getLocatorString();//表示存储的位置
		if (locatorString == null) {
			return ;
		}
		
		MediaLocator dest = new MediaLocator(locatorString);
		DataSource outputDataSource = processor.getDataOutput();
		//本地文件传输
		try {
			dataSink = Manager.createDataSink(outputDataSource, dest);
			dataSink.open();
			dataSink.start();
		}catch (Exception e) {
			e.printStackTrace();
		}
		processor.start();
		startVideo.setEnabled(false);
		stopVideo.setEnabled(true);
	}
	//停止按钮方法
	public void stop() {
		processor.close();
		processor.deallocate();
		dataSink.close();
		processor = null;
		startVideo.setEnabled(true);
		stopVideo.setEnabled(false);
	}
	//获得文件路径
	public String getLocatorString() {
		if(JFileChooser.APPROVE_OPTION != fileChooser.showSaveDialog(this) )
			return null;
		File file = fileChooser.getSelectedFile();
		if(file == null) 
			return null;
		System.out.println(file);
		String locatorString = file.getAbsolutePath();
		//加文件后缀
		if(!locatorString.endsWith(".QUICKTIME"))
			locatorString += ".QUICKTIME";
		
		locatorString = "file://"+locatorString;
		System.out.println(locatorString);
		return locatorString;
	}
	public static void main(String[] args) {
		MainUI main = new MainUI();
		//main.initCamera();
		main.init();
	}
	
}

在开始摄像这里会报错:错误原因:(本人调试的结果是clonedDataSource为null,对于这个不了解)

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
	at com.sise.luming.MainUI.start(MainUI.java:126)
	at com.sise.luming.MainUI.access$0(MainUI.java:124)
	at com.sise.luming.MainUI$1.actionPerformed(MainUI.java:103)
	at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
	at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
	at java.awt.Component.processMouseEvent(Unknown Source)
	at javax.swing.JComponent.processMouseEvent(Unknown Source)
	at java.awt.Component.processEvent(Unknown Source)
	at java.awt.Container.processEvent(Unknown Source)
	at java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Window.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)


展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部