WebCam (JMF e DSj) via internet (java.net)

Bom pessoal, meu primeiro tópico no GUJ portanto desconsiderem qualquer erro de post.

Estou querendo fazer um programa (cliente), onde o servidor está conectado à uma WebCam
e o cliente visualiza as imagens, para a comunicacao via web uso o Java.net, e para a webcam encontrei dois métodos,
um com JMF e outro com Direct Show, ambos Funcionando.(mais abaixo seguem os códigos)

agora, … como fazer o envio do video, como o java.net envia?? (stream, buffer ???)

Código WebCam DSj :


/**
*
* @author Leandro
*/
import de.humatic.dsj.CaptureDeviceControls;
import de.humatic.dsj.DSCapture;
import de.humatic.dsj.DSFilterInfo;
import de.humatic.dsj.DSFiltergraph;
import de.humatic.dsj.DSGraph;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;
/**
* This program demonstrates the basics of creating a frame
* user interface with a menubar. It also shows how to
* add a menubar and dropdown menus to the applet, which wasn't
* possible in the basic AWT heavyweight component.
**/
public class DScamTest extends JApplet
implements PropertyChangeListener {
private DSGraph netGraph = null;
private DSFilterInfo dSFilterInfo = null;
private DSCapture graph = null;
private JComboBox comCameras = new JComboBox();
private JDesktopPane desPreview = new JDesktopPane();
private JInternalFrame frame = new JInternalFrame();
private List<DSFilterInfo> filterInfoList = null;
private HashMap<String, DSFilterInfo> hashCams = new HashMap<String,
DSFilterInfo>();
/** Build an applet interface with a menubar. A
* a drop down menu includes Open/Close items
* for opening and closing an instance of ParticleFrame.
**/
@Override
public void init() {
chargeCams();
comCameras.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
comCamerasActionPerformed(evt);
}
});
add(java.awt.BorderLayout.NORTH, comCameras);
addDesktopPane();
} // init
public void addDesktopPane() {
desPreview = new JDesktopPane();
desPreview.setBackground(new java.awt.Color(240, 240, 240));
desPreview.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
this.add(desPreview);
add(java.awt.BorderLayout.CENTER, desPreview);
}
public List<DSFilterInfo> getVideoDevices() {
DSFilterInfo[][] lista = null;
try {
lista = DSCapture.queryDevices();
} catch (Exception e) {
e.printStackTrace();
}
return Arrays.asList(lista[0]);
}
public void chargeCams() {
try {
filterInfoList = getVideoDevices();
String[] camNames = new String[filterInfoList.size()];
camNames[0] = "";
for (int i = 0; i < filterInfoList.size(); i++) {
if (!filterInfoList.get(i).getName().equalsIgnoreCase("none")) {
camNames[i + 1] = filterInfoList.get(i).getName();
hashCams.put(filterInfoList.get(i).getName(),
filterInfoList.get(i));
}
}
comCameras.setModel(
new javax.swing.DefaultComboBoxModel(camNames));
} catch (Exception e) {
e.printStackTrace();
}
}
private void comCamerasActionPerformed(java.awt.event.ActionEvent evt) {
String selectedCam = comCameras.getSelectedItem().toString();
if ((selectedCam != null) && (!selectedCam.trim().equals(""))) {
for (JInternalFrame f : desPreview.getAllFrames()) {
if (f.getTitle().equalsIgnoreCase(selectedCam)) {
return;
}
}
dSFilterInfo = hashCams.get(selectedCam);
graph = new DSCapture(DSFiltergraph.RENDER_NATIVE,
dSFilterInfo,
false, DSFilterInfo.doNotRender(), this);
frame.addInternalFrameListener(
new InternalFrameAdapter() {
@Override
public void internalFrameClosing(InternalFrameEvent e) {
finalizeFrame();
}
});
frame.setTitle(hashCams.get(selectedCam).getName());
frame.setClosable(true);
frame.setSize(620, 440);
frame.setResizable(false);
frame.add(java.awt.BorderLayout.CENTER, graph.asComponent());
frame.setVisible(true);
desPreview.add(frame);
JPanel jf = new JPanel();
jf.setLayout(new java.awt.GridLayout(0, 1));
CaptureDeviceControls controls = ((DSCapture)
graph).getActiveVideoDevice().getControls();
if (controls != null) {
for (int i = CaptureDeviceControls.BRIGHTNESS; i <
CaptureDeviceControls.FOCUS; i++) {
try {
jf.add(controls.getController(i, 0, true));
} catch (Exception e) {
System.out.println("Erro aou inserir controle: " +
controls.getController(i, 0, true));
}
}
}
frame.add(java.awt.BorderLayout.WEST, jf);
jf.setVisible(true);
JButton jb = new JButton("Capturar");
jb.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
try {
Object image = graph.getImage();
JFileChooser jf = new JFileChooser();
jf.setMultiSelectionEnabled(false);
jf.showSaveDialog(desPreview);
if (jf.getSelectedFile() != null) {
ImageIO.write((BufferedImage) image, "jpg",
jf.getSelectedFile());
}
//ImageIO.write((BufferedImage) image, "jpg", new
//File("C:/Users/Leandro/Desktop/image.jpg"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
frame.add(java.awt.BorderLayout.SOUTH, jb);
}
}
public void finalizeFrame() {
frame.dispose();
graph.dispose();
graph = null;
desPreview.remove(frame);
}
public void propertyChange(PropertyChangeEvent evt) {
}
} // class FrameApplet

e Código WebCam JMF:


/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package webcamteleop;


   import java.awt.BorderLayout;
   import java.awt.Component;
   import java.awt.Graphics;
 
   import javax.media.Buffer;
   import javax.media.Manager;
   import javax.media.MediaLocator;
   import javax.media.Player;
   import javax.media.format.VideoFormat;
 

   public class WebCamCapture extends java.applet.Applet {

       private static final long serialVersionUID = 1L; //?
       public static Player player = null;
       public MediaLocator ml = null;  //  @jve:decl-index=0:
       public Buffer buf = null;
       public VideoFormat vf = null;
       private ImagePanel imgpanel = null;


       //achar as configuracoes de Jpanel e refazer em ImagePanel.java
        
       
    @Override
      public void init() {
          this.setLayout(new BorderLayout());
          this.setSize(550, 550);
          this.setVisible(true);
          imgpanel = new ImagePanel();

          // This may differ check the jmf registry for
         // correct entry
          String str2 = "vfw//0";
          ml =  new MediaLocator("vfw://0");
          try {
              player = Manager.createRealizedPlayer(ml);
              player.start();
              Component comp;
             if ((comp = player.getVisualComponent()) != null) {
              add(comp, BorderLayout.NORTH);
              }
              } catch (Exception e) {
              e.printStackTrace();
             }

       }

    @Override
       public void paint(Graphics g) {

       }
   }


Creio que preciso criar uma classe que recebe a webcam a ser exibida, e me retorna só o video (mas como???)

Muito Obrigado

Caramba. tirou as palavras dos meus dedos.

Estava justamente procurando algum tópico relacionado a webcam e como enviar as imagens pela net.

Quanto ao uso das APIs eu indico a DSj, que ao meu ver é muito mais funcional.

Você ja conseguiu solucionar como enviar o vídeo :?:

Será que alguem pode nos ajudar? :wink:

Muito obrigado a todos

Este exemplo de code, nao funcionou aqui com DSJ

Fazer um servidor http e enviar imagens jpeg não é complicado.
A idéia é capturar quadros durante a execução do vídeo, e a cada get do cliente, o post é a imagem jpeg. Porém é lerdo e não é a solução adequada a um trabalho profissional.

Pesquisem por RTP(Real time protocol).

A JMF tem suporte, e o directshow também.

Boa tarde a todos.

Creio eu que não dá para misturar JMF (Java Media Framework) com DSJ (Direct Show Java), até porque fui imformado que o JMF já está obsoleto.

Fiz uma classe WebCam que extende um JFrame assim:

public class WebCam extends JFrame implements ActionListener, PropertyChangeListener {
    private static final long serialVersionUID = -3928731214864757072L;
   
    private DSCapture graph;
    private DSFilterInfo[][] dsivideo;
    private JButton start, capture, clearimage, saveimage;
    private String nameimage;
    private JPanel foto;
    private JTextArea liststatus;
    
    public static void main(String args[]){
        WebCam wc = new WebCam();
        wc.setVisible(true);
    }
    
    public WebCam(){
        super("WebCam Capture");
        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
        setLayout(new BorderLayout());
        setSize(new Dimension(600,319));
  //      setResizable(false);
        JLabel lblfoto = new JLabel("Foto");
        lblfoto.setHorizontalAlignment(JLabel.CENTER);
        JLabel lblstatus = new JLabel("Status da operação");
        lblstatus.setHorizontalAlignment(JLabel.CENTER);
        JPanel painelcabecalho = new JPanel(new GridLayout(1,2));
        painelcabecalho.add(lblfoto);
        painelcabecalho.add(lblstatus);
        painelcabecalho.setBorder(BorderFactory.createLineBorder(Color.BLACK,1));
        add(painelcabecalho, BorderLayout.NORTH);
        foto = new JPanel();
        foto.setSize(new Dimension(307,230));
        foto.setBorder(BorderFactory.createLineBorder(Color.BLACK,1));
        add(foto, BorderLayout.CENTER);
        liststatus = new JTextArea();
        liststatus.setPreferredSize(new Dimension(270,250));
        add(new JScrollPane(liststatus), BorderLayout.EAST);
        start = new JButton("Iniciar");
        start.addActionListener(this);
        capture = new JButton("Capturar");
        capture.addActionListener(this);
        capture.setEnabled(false);
        clearimage = new JButton("Limpar");
        clearimage.addActionListener(this);
        clearimage.setEnabled(false);
        saveimage = new JButton("Salvar");
        saveimage.addActionListener(this);
        saveimage.setEnabled(false);
        JPanel painelbotoes = new JPanel(new GridLayout(1,4));
        painelbotoes.add(start);
        painelbotoes.add(capture);
        painelbotoes.add(clearimage);
        painelbotoes.add(saveimage);
        painelbotoes.setBorder(BorderFactory.createLineBorder(Color.BLACK,1));
        add(painelbotoes, BorderLayout.SOUTH);
        addWindowListener(new WindowAdapter(){
           @Override
           public void windowClosing(WindowEvent e){
                exitProgram();
           }
        });
        setLocationRelativeTo(null);
    }
    
    private void exitProgram(){
       int yesno = JOptionPane.YES_NO_OPTION;
       int message = JOptionPane.INFORMATION_MESSAGE;
       int result = JOptionPane.showConfirmDialog(this,"Deseja fechar o programa ?","Saindo do programa",yesno,message);
       if (result == JOptionPane.YES_OPTION){
           clearImage();
           dispose();
           System.exit(0);
       }
    }

    public void clearImage(){
        if (graph!=null){
            foto.remove(graph);
            graph.dispose();
            dsivideo = null;
        }
        liststatus.setText("");
        repaint();
    }
  
    public Image getImage(){
        if (graph == null){
            return null;
        } else {
            return graph.getImage();
        }    
    }

    public void record(){ 
       try {
          if ("".equals(getNameimage())){
              clearImage();
              liststatus.append("Nome da imagem não foi especificado.\n");
          } else {
              File arquivo = new File("//10.3.1.27/upload/servidores/fotos/"+getNameimage()+".jpg");
              if (!arquivo.exists()) arquivo.createNewFile();
              ImageIO.write((RenderedImage)graph.getImage(),"JPG",arquivo);
          }  
       } catch(IOException ioex){
          clearImage(); 
          liststatus.append("Não foi possível encontrar o caminho especificado\n" + ioex.getMessage());
       }   
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt){
       liststatus.append("ID status da câmera = "+evt.getNewValue().toString()+"\n");
    }

    @Override
    public void actionPerformed(ActionEvent e){
       if (e.getSource()==start){
           try {
               setNameimage(JOptionPane.showInputDialog(this,"Digite a matrícula (só números)","Nome da imagem",JOptionPane.INFORMATION_MESSAGE));
               clearImage();
               dsivideo = DSCapture.queryDevices(DSCapture.SKIP_AUDIO);
               graph = new DSCapture(DSFiltergraph.RENDER_NATIVE, dsivideo[0][0],false,DSFilterInfo.doNotRender(),this);
               graph.setSize(307,230);
               foto.add(graph.asComponent());
               graph.setPreview();
               start.setEnabled(false);
               capture.setEnabled(true);
           } catch (DSJException | Exception ex){
               liststatus.append(ex.getMessage());
           }
       } else if (e.getSource()==capture){
           graph.stop();
           capture.setEnabled(false);
           clearimage.setEnabled(true);
           saveimage.setEnabled(true);
       } else if (e.getSource()==clearimage){
           clearImage();
           clearimage.setEnabled(false);
           saveimage.setEnabled(false);
           start.setEnabled(true);
       } else if (e.getSource()==saveimage){
           record();
           clearimage.setEnabled(false);
           saveimage.setEnabled(false);
           start.setEnabled(true);
       }
    }

    public String getNameimage(){
       return nameimage;
    }

    public void setNameimage(String nameimage){
       this.nameimage = nameimage;
    }

}

Com essa classe eu só estou tendo um problema, que é o redimensionamento do componente “Graph.asComponent”, onde ele parece ser ciumento e se autoredesenha com proporções as vezes maior ou menor do que o componente que o contém, por isso eu procurei evitar os métodos pack(), setResizeble(false), repaint() e etc.

Por outro lado, existe também o recurso de voce publicar um Applet ou até mesmo uma aplicação desktop em Web, que se chama Web Start.

Este conceito utiliza o recurso chamado JNLP (Java Network Launch Protocol), onde um Applet ou Desktop pode ser invocado de um servidor remoto, e ser executado fora do navegador de internet, voce pode até baixar um aplicativo para ser instalado no computador cliente, e posteriormente ele possa ser executado até mesmo com a internet desconectado.

Como esse assunto é extenso, procure por Web Start e o recurso JNLP.

Um abraço

Bom, passei horas tentando usar o dsj e não conseguia salvar a imagem sempre ficava “escura”, seu código muito show discorpio.

Galera, estou a algum tempo pesquisando sobre como utilizar webcam em java, gosto mto deste forum/site
já achei varios posts q resolveram bastantes problemas meus, inclusive este, só que algo me intriga:

Ao conseguir finalmente q o código n desse mais erros irritantes do netbeans, qnd rodo ele diz q nao foi possivel achar player para vfw://0
Oq consegui pesquisando foi q este é um comando para reconhecer a webcam em windows(vfm://0), q nao funciona no meu Ubuntu 14.04, qual seria entao este bendito comando?
Meses com isto já! kk

[quote=DennerP]Galera, estou a algum tempo pesquisando sobre como utilizar webcam em java, gosto mto deste forum/site
já achei varios posts q resolveram bastantes problemas meus, inclusive este, só que algo me intriga:

Ao conseguir finalmente q o código n desse mais erros irritantes do netbeans, qnd rodo ele diz q nao foi possivel achar player para vfw://0
Oq consegui pesquisando foi q este é um comando para reconhecer a webcam em windows(vfm://0), q nao funciona no meu Ubuntu 14.04, qual seria entao este bendito comando?
Meses com isto já! kk[/quote]

Bom dia DennerP.

Infelizmente, até onde eu sei, o Direct Show Java escrito no meu código, só foi desenvolvido para funcionar no Windows.

Há muito tempo escrevi esse código utilizando o recurso do DSJ, porém não sei se ele já está obsoleto. Já ouviu falar de um software para vídeos chamado Virtual DJ for Umbutu ou MIXX, alguma coisa desse tipo. Não tive tempo e nem a oportunidade de pesquisar porque eu não trabalho com linux, porém assim que tiver, eu pesquisarei.