import java.awt.BorderLayout; import java.awt.Component; import java.awt.Container; import java.awt.FileDialog; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.Graphics; import java.awt.Image; import java.awt.LayoutManager; import java.awt.Panel; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.Vector; import javax.imageio.ImageIO; import javax.media.Buffer; import javax.media.CannotRealizeException; import javax.media.CaptureDeviceInfo; import javax.media.CaptureDeviceManager; import javax.media.ConfigureCompleteEvent; import javax.media.ControllerEvent; import javax.media.DataSink; import javax.media.Format; import javax.media.IncompatibleSourceException; import javax.media.Manager; import javax.media.MediaLocator; import javax.media.NoDataSinkException; import javax.media.NoProcessorException; import javax.media.Player; import javax.media.Processor; import javax.media.ProcessorModel; import javax.media.RealizeCompleteEvent; import javax.media.Time; import javax.media.control.FrameGrabbingControl; import javax.media.control.StreamWriterControl; import javax.media.datasink.DataSinkListener; import javax.media.format.AudioFormat; import javax.media.format.VideoFormat; import javax.media.protocol.DataSource; import javax.media.protocol.FileTypeDescriptor; import javax.media.protocol.SourceCloneable; import javax.media.util.BufferToImage; import javax.swing.JApplet; import javax.swing.JButton; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.media.protocol.DataSource; import jmfPackage.WebCamSwing.StateHelper; import java.awt.*; import java.awt.event.*; import java.applet.*; import java.io.*; public class VApplet extends JApplet implements ActionListener{ private JPanel jContentPane= null; private JButton jbok,jbcancel,tuichuluxiang ; private MediaLocator ml = null; private Player player = null; private DataSource datasource=null; private Buffer buffer=null; private BufferToImage bufferToImage=null; private Image image=null; private Processor processor=null; //由原始数据源转变成的,可以被克隆的数据源 private DataSource cloneabledatasource = null; //由可以克隆的数据源cloneabledatasource克隆出来的cloneddatasource private DataSource cloneddatasource = null; //保存录制数据的数据池 private DataSink dataSink = null; private StateHelper sh=null; //构造函数 public VApplet() { super(); } public void init() { jbok=new JButton("拍 照"); jbok.addActionListener(this); jbcancel=new JButton("开始录像"); jbcancel.addActionListener(this); tuichuluxiang=new JButton("停止录像"); tuichuluxiang.addActionListener(this); this.setSize(400, 320); //(650, 550) jContentPane=getJContentPane(); jbok.setVisible(true); jbcancel.setVisible(true); tuichuluxiang.setVisible(true); Container cp=getContentPane(); cp.add(jContentPane,BorderLayout.NORTH); cp.add(jbok,BorderLayout.WEST); cp.add(jbcancel,BorderLayout.CENTER); cp.add(tuichuluxiang,BorderLayout.EAST); this.setContentPane(cp); this.setName("VApplet"); } //取系统所有可采集的硬件设备列表 private CaptureDeviceInfo[] getDevices() { Vector devices = CaptureDeviceManager.getDeviceList(null); CaptureDeviceInfo[] info = new CaptureDeviceInfo[devices.size()]; for (int i = 0; i < devices.size(); i++) { info[i]= (CaptureDeviceInfo) devices.get(i); } return info; } //从已知设备中取所有视频设备的列表 private CaptureDeviceInfo[] getVideoDevices() { CaptureDeviceInfo[] info = getDevices(); CaptureDeviceInfo[] videoDevInfo; Vector vc = new Vector(); for (int i = 0; i < info.length; i++) { //取设备支持的格式,如果有一个是视频格式,则认为此设备为视频设备 Format[] fmt = info[i].getFormats(); for (int j = 0; j < fmt.length; j++) { if (fmt[j] instanceof VideoFormat) { vc.add(info[i]); } break; } } videoDevInfo = new CaptureDeviceInfo[vc.size()]; for (int i = 0; i < vc.size(); i++) { videoDevInfo[i]= (CaptureDeviceInfo) vc.get(i); } return videoDevInfo; } private JPanel getJContentPane() { if (jContentPane == null) { BorderLayout borderLayout = new BorderLayout(); jContentPane = new JPanel(); jContentPane.setLayout(borderLayout); try { //这里我只有一个视频设备,直接取第一个 // 取得当前设备的MediaLocator ml = getVideoDevices()[0].getLocator();////从已知设备中取所有视频设备的列表 datasource = Manager.createDataSource(ml); cloneabledatasource = Manager.createCloneableDataSource(datasource); cloneddatasource = ((SourceCloneable) cloneabledatasource).createClone(); //用已经取得的MediaLocator得到一个Player player = Manager.createRealizedPlayer(cloneabledatasource); player.start(); //取得Player的AWT Component Component comp = player.getVisualComponent(); //如果是音频设备这个方法将返回null,这里要再判断一次 if (comp != null) { //将Component加到窗体 jContentPane.add(comp,BorderLayout.NORTH); } }catch (Exception e) { e.printStackTrace(); } } return jContentPane; } public void actionPerformed(ActionEvent e) { //保存图片 if(e.getSource()==jbok){//拍照 Component comp = player.getVisualComponent(); comp.getGraphics(); FrameGrabbingControl fgc=(FrameGrabbingControl)player.getControl("javax.media.control.FrameGrabbingControl"); buffer=fgc.grabFrame(); bufferToImage=new BufferToImage((VideoFormat)buffer.getFormat()); image=bufferToImage.createImage(buffer); if(image==null||image.equals("null")||image.equals(null)){ JOptionPane.showMessageDialog(null, "请先拍照再保存"); }else{ try { ImageIO.write((RenderedImage)image, "GIF", new File("D:\\2.jpg")); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } }else if(e.getSource()==jbcancel&&processor!=null){//录像 JOptionPane.showMessageDialog(null, "正在录像!"); }else if(e.getSource()==jbcancel&&processor==null){//录像 Frame saveluxiangframe = new Frame("保存视频文件"); FileDialog fshipin = new FileDialog(saveluxiangframe, "保存视频文件", FileDialog.SAVE); fshipin.setFile("w.QUICKTIME"); fshipin.setVisible(true); String luxiangsavepath = fshipin.getDirectory(); String luxiangsavename = fshipin.getFile(); // 如果输入了保存名字(没有点取消)的话,才可运行 if (luxiangsavename != null) { // 后面的路径不认\\,只认/ luxiangsavepath.replace("\\", "/"); // 录像源代码 try {// player用cloneabledatasource数据源,processor用cloneddatasource的数据源 processor = Manager.createProcessor(cloneddatasource); sh = new StateHelper(processor); } catch (IOException ez5) { ez5.printStackTrace(); System.exit(-1); } catch (NoProcessorException ez6) { ez6.printStackTrace(); System.exit(-1); } // Configure the processor,让processor进入configured状态 if (!sh.configure(10000)) { System.out.println("configure wrong!"); System.exit(-1); } /* * if ( processor instanceof Processor) processor.configure(); */ // 设置视频输出格式 processor.setContentDescriptor(new FileTypeDescriptor( FileTypeDescriptor.QUICKTIME)); // realize the processor,让processor进入realized状态 if (!sh.realize(10000)) { System.out.println("realize wrong!"); System.exit(-1); } // get the output of the processor,并且启动processor DataSource outsource = processor.getDataOutput(); MediaLocator dest = new MediaLocator(new java.lang.String( "file:///" + luxiangsavepath + luxiangsavename)); processor.start(); try{ //////////////////////////////////// dataSink = Manager.createDataSink(outsource, dest); dataSink.open(); dataSink.start(); }catch(Exception ez1) { ez1.printStackTrace(); System.exit(-1); } } }else if(e.getSource()==tuichuluxiang && processor == null){//退出录像 JOptionPane.showMessageDialog(null, "请先单击录像才能停止!"); }else if(e.getSource()==tuichuluxiang && processor!= null){//退出录像 /* * 如果要是能够连续录像,关键在于两点: 1 、重新设置cloneddatasource , * 我认为在cloneddatasource被调用后 , cloneddatasource被改变了 2、清空processor */ processor.close(); processor.deallocate(); dataSink.close(); cloneddatasource = (DataSource)((SourceCloneable) cloneabledatasource).createClone(); processor = null; } } /////////////////////////状态辅助子类//////////////////////////////////////////////// public class StateHelper implements javax.media.ControllerListener { Player xplayer = null; boolean configured = false; boolean realized = false; boolean failed = false; boolean closed = false; public StateHelper(Player p) { xplayer = p; p.addControllerListener(this); } public boolean configure(int timeOutMillis) { // RealizeCompleteEvent发生了的话使ce事件与之比较,若相等,那么realized为true。 /*监听ConfigureCompleteEvent和ConfigureCompleteEvent事件的发生。 * 如ConfigureCompleteEvent事件发生,那么就会赋给configured为ture, * 使得public boolean configure方法中的 * while (!configured && !failed){}这个循环退出。*/ long startTime = System.currentTimeMillis(); synchronized (this) { if (xplayer instanceof Processor) ((Processor) xplayer).configure(); else return false; while (!configured && !failed) { try { wait(timeOutMillis); } catch (InterruptedException ie) { } if (System.currentTimeMillis() - startTime > timeOutMillis) break; } } return configured; } public boolean realize(int timeOutMillis) { long startTime = System.currentTimeMillis(); synchronized (this) { xplayer.realize(); while (!realized && !failed) { try { wait(timeOutMillis); } catch (InterruptedException ie) { } if (System.currentTimeMillis() - startTime > timeOutMillis) break; } } return realized; } public synchronized void controllerUpdate(ControllerEvent ce) { if (ce instanceof RealizeCompleteEvent) { realized = true; } else if (ce instanceof ConfigureCompleteEvent) { configured = true; } else { return; } notifyAll(); } }//子类结束 //保存图片的宽度和高度 private int imgWidth = 400; private int imgHeight = 300; ////////////////////////图形面板子类/////////////////////////////////////////////////// class ImagePanel extends Panel { private Image ImagePanelimg = null; public ImagePanel() { setLayout(null); setSize(imgWidth, imgHeight); } public void setImage(Image img) { this.ImagePanelimg = img; this.setVisible(true); repaint(); } public void update(Graphics graphics) { if (ImagePanelimg != null) { graphics.drawImage(ImagePanelimg, 0, 0, this); } } } //////////////////////dataSink子类////////////////////////////////////////////////// class dataSinkS implements DataSink{ public void addDataSinkListener(DataSinkListener arg0) { // TODO Auto-generated method stub } public void close() { try { super.clone(); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public String getContentType() { // TODO Auto-generated method stub return null; } public MediaLocator getOutputLocator() { // TODO Auto-generated method stub return null; } public void open() throws IOException, SecurityException { // TODO Auto-generated method stub } public void removeDataSinkListener(DataSinkListener arg0) { // TODO Auto-generated method stub } public void setOutputLocator(MediaLocator arg0) { // TODO Auto-generated method stub } public void start() throws IOException { // TODO Auto-generated method stub } public void stop() throws IOException { // TODO Auto-generated method stub } public void setSource(DataSource arg0) throws IOException, IncompatibleSourceException { // TODO Auto-generated method stub } public Object getControl(String arg0) { // TODO Auto-generated method stub return null; } public Object[] getControls() { // TODO Auto-generated method stub return null; } } }