//3.3晚上修订版import java.io.IOException;import javax.media.Buffer;
import javax.media.CaptureDeviceManager;
import javax.media.ConfigureCompleteEvent;
import javax.media.ControllerEvent;
import javax.media.DataSink;
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.RealizeCompleteEvent;
import javax.media.protocol.DataSource;
import javax.media.protocol.FileTypeDescriptor;
import javax.media.*;
import javax.swing.*;
import javax.imageio.ImageIO;
import javax.media.control.FrameGrabbingControl;
import javax.media.format.VideoFormat;
import javax.media.protocol.SourceCloneable;
import javax.media.util.BufferToImage;
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.RenderedImage;
import java.io.File;//public class WebCamSwing extends Object implements ActionListener
//public class WebCamSwing extends Container implements ActionListener
public class WebCamSwing extends Applet implements ActionListener {
String url = "vfw:Microsoft WDM Image Capture (Win32):0"; // 获取的摄像头信息
private CaptureDeviceInfo cdinfo = null; // 从获取的摄像头信息中提取的摄像头地址
private MediaLocator medialocator = null; // 原始的数据源
private DataSource datasource = null; // 由原始数据源转变成的,可以被克隆的数据源
private DataSource cloneabledatasource = null; // 由可以克隆的数据源cloneabledatasource克隆出来的cloneddatasource
private DataSource cloneddatasource = null; // 用来播放的player
public static Player player = null; // 处理录制的视频的Processor
private Processor processor = null; // 保存录制数据的数据池
private DataSink dataSink = null; private StateHelper sh = null; /** * ImagePanel类是将 */
private ImagePanel imgpanel = null; // buf用于截取实时图像的缓冲区
private Buffer buf = null; // 将buf转换为图像的“中间变量”
private BufferToImage btoi = null; // 拍下来的照片赋给img
private Image img = null; // 保存图片的宽度和高度
private int imgWidth = 320; private int imgHeight = 240; // 拍照按钮
private JButton capture = null; // 保存照片按钮
private JButton save = null; // 录像按钮
private JButton luxiang = null; // 停止录像按钮
private JButton tuichuluxiang = null; /**
 * 此WebCamSwing函数完成的功能: 创建一个对话框。 将摄像头的物理地址转化为电脑能够识别的medialocator,
 * 并且通过medialocator产生一个数据源datasource, 通过这个datasource数据源生成player用来播放视频。
 * 然后将数据源进行处理,产生一个能够被克隆的cloneabledatasource,
 * 再这个cloneabledatasource进行克隆,产生一个cloneddatasource数据源, 用于后面的processor录制视频
 */
public WebCamSwing() {
Panel editor = new Panel();
/** * */
editor.setPreferredSize(new Dimension());
editor.setLayout(null);
editor.setLayout(new GridLayout(1, 3));
imgpanel = new ImagePanel();
capture = new JButton("拍照");
capture.addActionListener(this);
save = new JButton("保存照片");
save.addActionListener(this);
luxiang = new JButton("开始录像");
luxiang.addActionListener(this);
tuichuluxiang = new JButton("停止录像");
tuichuluxiang.addActionListener(this);
cdinfo = CaptureDeviceManager.getDevice(url);
medialocator = cdinfo.getLocator();
try {
datasource = Manager.createDataSource(medialocator);
cloneabledatasource = Manager.createCloneableDataSource(datasource);
cloneddatasource = ((SourceCloneable) cloneabledatasource)
.createClone();
player = Manager.createRealizedPlayer(cloneabledatasource);
player.start();
Component comp;
if ((comp = player.getVisualComponent()) != null) {
add(comp);
}
Panel panel = new Panel(new GridLayout(4, 1));
panel.add(capture);
panel.add(save);
panel.add(luxiang);
panel.add(tuichuluxiang);
add(panel);
add(imgpanel); } catch (Exception b) {
b.printStackTrace();
} }

解决方案 »

  1.   

    /**接上面的程序*/
    /* 点击拍照 */
    /*
     * ActionEvent: 指示发生了组件定义的动作的语义事件。 当特定于组件的动作(比如
     * 
     * 被按下)发生时, 由组件(比如 Button)生成此高级别事件。 事件被传递给每一个 ActionListener 对象, 这些对
     * 
     * 象是使用组件的 addActionListener 方法注册的,用以接收这类事件。 注:要使用键盘在 Button 上触发
     * ActionEvent,请使用空格键。
     */
    public void actionPerformed(ActionEvent e) {
    // ??捕获ActionEvent,将其转化为JComponent类,应该转化为是“单击按钮的意思”
    JComponent c = (JComponent) e.getSource();
    if (c == capture) {
    // 取得对Player的控制
    FrameGrabbingControl fgc = (FrameGrabbingControl) player
    .getControl("javax.media.control.FrameGrabbingControl");
    // 传输buf数据量大还是传输img数据量大??
    buf = fgc.grabFrame();
    btoi = new BufferToImage((VideoFormat) buf.getFormat());
    img = btoi.createImage(buf);
    imgpanel.setImage(img); } else if (c == save && img == null) {
    JOptionPane.showMessageDialog(null, "请先拍照再保存"); }
    // 保存图片
    else if (c == save && img != null) {
    Frame savephotoframe = new Frame("保存");
    FileDialog savephotofiledialog = new FileDialog(savephotoframe,
    "保存图像文件", FileDialog.SAVE); savephotofiledialog.setFile("*.GIF");
    savephotofiledialog.setVisible(true);
    String savepath = savephotofiledialog.getDirectory();
    String savename = savephotofiledialog.getFile();
    // ImageIO.write是将图片保存到上面已经写好的路径里,并且用上面的savename命名
    try {
    ImageIO.write((RenderedImage) img, "GIF", new File(savepath
    + savename)); } catch (IOException e1) {
    // TODO 自动生成 catch 块
    e1.printStackTrace();
    }
    img = null;
    }
    // 如果单击了“开始录像”按钮,但是processor不为空,那么就弹出提示表明正在录像
    else if (c == luxiang && processor != null) {
    JOptionPane.showMessageDialog(null, "正在录像!"); }
    // 如果单击了“开始录像”按钮,且processor为空,那么就开始录像
    else if (c == luxiang && processor == null) { Frame saveluxiangframe = new Frame("保存视频文件");
    FileDialog fshipin = new FileDialog(saveluxiangframe, "保存视频文件",
    FileDialog.SAVE);
    fshipin.setFile("*.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();
    } catch (NoDataSinkException ez1) {
    ez1.printStackTrace();
    System.exit(-1);
    } catch (IOException ez2) {
    ez2.printStackTrace();
    System.exit(-1);
    } catch (SecurityException ez3) {
    ez3.printStackTrace();
    System.exit(-1);
    } try {
    dataSink.start();
    } catch (IOException ez4) {
    ez4.printStackTrace();
    System.exit(-1);
    } }
      

  2.   

    /***接上面的程序*/
    else if (c == tuichuluxiang && processor == null) {
    JOptionPane.showMessageDialog(null, "请先单击录像才能停止!");
    } else if (c == tuichuluxiang && processor != null) {
    /*
     * 如果要是能够连续录像,关键在于两点: 1 、重新设置cloneddatasource ,
     * 我认为在cloneddatasource被调用后 , cloneddatasource被改变了 2、清空processor
     */
    processor.close();
    processor.deallocate();
    dataSink.close();
    cloneddatasource = ((SourceCloneable) cloneabledatasource)
    .createClone();
    processor = null;
    }
    } public class StateHelper implements javax.media.ControllerListener
    {
    Player xplayer = null; boolean configured = false; boolean realized = false;// boolean prefetched = false;// boolean eom = false;// End of media. 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();
    }
    } 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);
    }
    }
    } public static void main(String[] args) {
    Frame frame = new Frame("拍照程序");
    WebCamSwing cf = new WebCamSwing();
    frame.addWindowListener(new WindowAdapter() {
    public void windowClosing(WindowEvent e) { System.exit(0);
    } });
    frame.add("Center", cf);
    frame.pack();
    frame.setVisible(true);
    }}
    这是我的原代码,能够完成将摄像头数据捕获并保存为QUICKTIME格式的文件,但是将源代码中的
    fshipin.setFile("*.quicktime");中的QuickTime改为mpg

    processor.setContentDescriptor(new FileTypeDescriptor(
    FileTypeDescriptor.QUICKTIME));
    这一句中的QUICKTIME改为MPEG
    就会出现如下错误:
    javax.media.NoDataSinkException: Cannot find a DataSink for: com.sun.media.multiplexer.RawBufferMux$RawBufferDataSource@1f5d386
    at javax.media.Manager.createDataSink(Manager.java:1894)
    at WebCamSwing.actionPerformed(WebCamSwing.java:245)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
    at java.awt.Component.processMouseEvent(Component.java:6038)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3265)
    at java.awt.Component.processEvent(Component.java:5803)
    at java.awt.Container.processEvent(Container.java:2058)
    at java.awt.Component.dispatchEventImpl(Component.java:4410)
    at java.awt.Container.dispatchEventImpl(Container.java:2116)
    at java.awt.Component.dispatchEvent(Component.java:4240)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4322)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3986)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3916)
    at java.awt.Container.dispatchEventImpl(Container.java:2102)
    at java.awt.Component.dispatchEvent(Component.java:4240)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)
      

  3.   

    /***接上面的程序*/
    else if (c == tuichuluxiang && processor == null) {
    JOptionPane.showMessageDialog(null, "请先单击录像才能停止!");
    } else if (c == tuichuluxiang && processor != null) {
    /*
     * 如果要是能够连续录像,关键在于两点: 1 、重新设置cloneddatasource ,
     * 我认为在cloneddatasource被调用后 , cloneddatasource被改变了 2、清空processor
     */
    processor.close();
    processor.deallocate();
    dataSink.close();
    cloneddatasource = ((SourceCloneable) cloneabledatasource)
    .createClone();
    processor = null;
    }
    } public class StateHelper implements javax.media.ControllerListener
    {
    Player xplayer = null; boolean configured = false; boolean realized = false;// boolean prefetched = false;// boolean eom = false;// End of media. 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();
    }
    } 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);
    }
    }
    } public static void main(String[] args) {
    Frame frame = new Frame("拍照程序");
    WebCamSwing cf = new WebCamSwing();
    frame.addWindowListener(new WindowAdapter() {
    public void windowClosing(WindowEvent e) { System.exit(0);
    } });
    frame.add("Center", cf);
    frame.pack();
    frame.setVisible(true);
    }}
    这是我的原代码,能够完成将摄像头数据捕获并保存为QUICKTIME格式的文件,但是将源代码中的
    fshipin.setFile("*.quicktime");中的QuickTime改为mpg

    processor.setContentDescriptor(new FileTypeDescriptor(
    FileTypeDescriptor.QUICKTIME));
    这一句中的QUICKTIME改为MPEG
    就会出现如下错误:
    javax.media.NoDataSinkException: Cannot find a DataSink for: com.sun.media.multiplexer.RawBufferMux$RawBufferDataSource@1f5d386
    at javax.media.Manager.createDataSink(Manager.java:1894)
    at WebCamSwing.actionPerformed(WebCamSwing.java:245)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
    at java.awt.Component.processMouseEvent(Component.java:6038)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3265)
    at java.awt.Component.processEvent(Component.java:5803)
    at java.awt.Container.processEvent(Container.java:2058)
    at java.awt.Component.dispatchEventImpl(Component.java:4410)
    at java.awt.Container.dispatchEventImpl(Container.java:2116)
    at java.awt.Component.dispatchEvent(Component.java:4240)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4322)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3986)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3916)
    at java.awt.Container.dispatchEventImpl(Container.java:2102)
    at java.awt.Component.dispatchEvent(Component.java:4240)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)
      

  4.   

    你好!你用Applet写的视频录制系统,怎么保存视频?
    我用你写的程序,可以保存照片,但是不能保存视频,报一下错误: No permission to write files from applets  ,这个如何解决??真的很期待你的回答,非常感谢!!!
      

  5.   

    修改所用JRE下的\lib\security的 java.policy  看看Applet签名的资料,要签名才能访问本地资源
      

  6.   

    程序一运行medialocator = cdinfo.getLocator();这句是空指针,怎样才能解决啊??
    我的QQ419984686
      

  7.   

    请问生成的录像怎么播放啊? 比如生成的文件是:test.QUICKTIME
      

  8.   

    楼主,我想打开avi格式的视频,就有这么一段话,是什么原因呢?Failed to configure: com.sun.media.PlaybackEngine@1551b0
      Bad header in the media: strh: header length should be atleast 56 but is 52Error: Unable to realize com.sun.media.PlaybackEngine@1551b0