Java(JMF)獲取本地攝像頭,實時顯示圖像

這幾天用了JMF,感受這個好坑,在win7,jdk1.7版本上支持都不太好,多是JMF是一個老的東西把,如今apache好像都放棄了,沒去了解。。java

搞了我3天的時間。主要仍是在環境搭建這邊花了好多時間,太坑了,最後還弄不到我想要的效果,網上資料也不是不少,不說了,如今把我在網上找的幾行代碼整理一下,方便往後查看apache

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,對於這個不瞭解)ide

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)
相關文章
相關標籤/搜索