Instituto Politécnico Nacional Escuela Superior de Cómputo DESARROLLO DE APLICACCIONES PARA LA WEB II Alumno: Toledo Goméz Israel Hernández Hernández Alex Héctor Martínez Ríos Israel Arellano Ceniceros Grupo: 8CV2 Reporte de Proyecto CAMARA WEB DISTRIBUIDA Profesor: Cifuentes Alvarez Alejandro Sigfrido CAMARA WEB DISTRIBUIDA En este proyecto se realizo una aplicación que permite la comparticion de una camara apoyandose de un servidor. En primer lugar veremos el codigo del servidor: package WebCam; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.EOFException; import java.io.IOException; import java.io.ObjectInputStream; import java.net.ServerSocket; import java.net.Socket; import javax.imageio.ImageIO; public class Server extends javax.swing.JFrame { /** Creates new form Server */ public Server() { initComponents(); setLocationRelativeTo(null); setVisible(true); } @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code"> private void initComponents() { lienzo1 = new WebCam.Lienzo(); jPanel1 = new javax.swing.JPanel(); jButton1 = new javax.swing.JButton(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); setTitle("Servidor - Receptor de video"); javax.swing.GroupLayout lienzo1Layout = new javax.swing.GroupLayout(lienzo1); lienzo1.setLayout(lienzo1Layout); lienzo1Layout.setHorizontalGroup( lienzo1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADIN G) .addGap(0, 380, Short.MAX_VALUE) ); lienzo1Layout.setVerticalGroup( lienzo1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADIN G) .addGap(0, 282, Short.MAX_VALUE) ); jPanel1.setBackground(new java.awt.Color(204, 204, 204)); jButton1.setText("Cerrar"); jButton1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton1ActionPerformed(evt); } }); jPanel1.add(jButton1); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TR AILING) .addComponent(lienzo1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE)) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addComponent(lienzo1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap()) ); pack(); }// </editor-fold> private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: cerrarConexion(); System.exit(0); } public void ejecutarServidor() { try { servidor = new ServerSocket( 12345, 100 ); while ( true ) { try { esperarConexion(); entrada = new ObjectInputStream( conexion.getInputStream() ); System.out.println( "\nSe recibieron los flujos de entrada\n" ); procesarConexion(); } catch ( EOFException excepcionEOF ) { System.err.println( "El servidor terminó la conexión" ); excepcionEOF.printStackTrace(); } finally { cerrarConexion(); } } } catch ( IOException excepcionES ) { excepcionES.printStackTrace(); } } private void esperarConexion() throws IOException { System.out.println( "Esperando una conexión\n" ); conexion = servidor.accept(); System.out.println( "Conexión recibida de: " + conexion.getInetAddress().getHostName() ); } private void procesarConexion() throws IOException { do { try { byte[] bytesImagen = (byte[]) entrada.readObject(); ByteArrayInputStream entradaImagen = new ByteArrayInputStream(bytesImagen); BufferedImage bufferedImage = ImageIO.read(entradaImagen); lienzo1.setImage(bufferedImage); } catch ( ClassNotFoundException excepcionClaseNoEncontrada ) { System.out.println( "\nSe recibió un tipo de objeto desconocido" ); } } while ( true ); } private void cerrarConexion() { System.out.println( "\nFinalizando la conexión\n" ); try { entrada.close(); conexion.close(); } catch( IOException excepcionES ) { excepcionES.printStackTrace(); } } public static void main(String args[]) { //setDefaultLookAndFeelDecorated(true); Server s = new Server(); s.ejecutarServidor(); } private ObjectInputStream entrada; private ServerSocket servidor; private Socket conexion; // Variables declaration - do not modify private javax.swing.JButton jButton1; private javax.swing.JPanel jPanel1; private WebCam.Lienzo lienzo1; // End of variables declaration } El cual espera la conección y recepcion de imagenes como se muestra en la imagen anterior. Posteriormente se hace arrancar el código de el emisor, en donde se nececita seleccionar el dispositivo por el cual transmitir, para lo cual es necesario el Java Media Framework (JMStudio). Por lo cual aparecen las siguientes imagenes: El codigo se muestra acontinuación: package WebCam; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.EOFException; import java.io.IOException; import java.io.ObjectOutputStream; import java.net.InetAddress; import java.net.Socket; import javax.imageio.ImageIO; import javax.media.*; import javax.media.control.FrameGrabbingControl; import javax.media.format.VideoFormat; import javax.media.util.BufferToImage; import javax.swing.Timer; public class Acceder2Frames extends javax.swing.JFrame { //Atributos necesarios para acceder a una cámara web private static Player player = null; private MediaLocator localizador = null; private Processor p; private CaptureDeviceInfo dispositivo = null; private static String source = "vfw:Microsoft WDM Image Capture (Win32):0"; private Timer timer; private Buffer buffer; private BufferToImage buffer_image = null; public Acceder2Frames(String host) { initComponents(); servidorChat = host; //dispositivo = CaptureDeviceManager.getDevice(source); localizador = new MediaLocator(source);//dispositivo.getLocator(); timer = new Timer (42, new ActionListener () { //Cada 1 milisegundo capturará el frame de video public void actionPerformed(ActionEvent e) { FrameGrabbingControl fgc = (FrameGrabbingControl)player.getControl("javax.media.control.FrameGrabbingControl"); buffer = fgc.grabFrame(); buffer_image = new BufferToImage((VideoFormat)buffer.getFormat()); BufferedImage bufferedImage = (BufferedImage)buffer_image.createImage(buffer); ByteArrayOutputStream salidaImagen = new ByteArrayOutputStream(); try { ImageIO.write(bufferedImage, "jpg", salidaImagen); byte[] bytesImagen = salidaImagen.toByteArray(); salida.writeObject( bytesImagen ); salida.flush(); } catch ( Exception excepcionEOF ) { System.err.println( "El cliente termino la conexión" ); } } }); setLocationRelativeTo(null); setVisible(true); } private void iniciarCaptura() { try { player = Manager.createRealizedPlayer(localizador); player.start(); if (player.getVisualComponent() != null) { panelVideo.add(player.getVisualComponent(), BorderLayout.CENTER); panelVideo.updateUI(); } } catch (Exception e) { System.err.println(e.toString()); } } public void acceso2Frames() { timer.start(); } @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code"> private void initComponents() { panelVideo = new javax.swing.JPanel(); panelOpciones = new javax.swing.JPanel(); botonSalir = new javax.swing.JButton(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); setTitle("Captura de Video - Transmisor de video"); panelVideo.setLayout(new java.awt.BorderLayout()); panelOpciones.setBackground(new java.awt.Color(204, 204, 204)); botonSalir.setText("Cerrar"); botonSalir.setOpaque(false); botonSalir.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { botonSalirActionPerformed(evt); } }); panelOpciones.add(botonSalir); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TR AILING) .addComponent(panelVideo, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 351, Short.MAX_VALUE) .addComponent(panelOpciones, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 351, Short.MAX_VALUE)) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addContainerGap() .addComponent(panelVideo, javax.swing.GroupLayout.DEFAULT_SIZE, 278, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(panelOpciones, javax.swing.GroupLayout.PREFERRED_SIZE, 33, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap()) ); pack(); }// </editor-fold> private void botonSalirActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: if(player != null) { player.close(); player.deallocate(); } timer.stop(); cerrarConexion(); System.exit(0); } private void ejecutarCliente() { try { conectarAServidor(); // Paso 1: crear un socket para realizar la conexión salida = new ObjectOutputStream( cliente.getOutputStream() ); salida.flush(); // vacíar búfer de salida para enviar información de encabezado acceso2Frames(); } catch ( EOFException excepcionEOF ) { System.err.println( "El cliente termino la conexión" ); } catch ( IOException excepcionES ) { excepcionES.printStackTrace(); } } private void conectarAServidor() throws IOException { cliente = new Socket( InetAddress.getByName( servidorChat ), 12345 ); } private void cerrarConexion() { System.out.println( "\nCerrando conexión" ); try { salida.close(); cliente.close(); } catch( IOException excepcionES ) { excepcionES.printStackTrace(); } } public static void main(String args[]) { //setDefaultLookAndFeelDecorated(true); Acceder2Frames ventana = new Acceder2Frames("127.0.0.0"); ventana.iniciarCaptura(); ventana.ejecutarCliente(); } private ObjectOutputStream salida; private String servidorChat; private Socket cliente; // Variables declaration - do not modify private javax.swing.JButton botonSalir; private javax.swing.JPanel panelOpciones; private javax.swing.JPanel panelVideo; // End of variables declaration } Por ultimo seleccionamos agregamos unn codigo de apoyo web para el control: package WebCam; import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.Panel; import javax.media.*; public class Web extends Applet implements ControllerListener{ Player player = null; String mediaFile = "vfw:Microsoft WDM Image Capture (Win32):0";//"vfw://0"; Component visualComponent = null; Panel thePanel = null; int videoWidth = 0; int videoHeight = 0; public void init(){ System.out.println("here!"); setLayout(new BorderLayout()); thePanel = new Panel(); thePanel.setLayout(null); add(thePanel); thePanel.setBounds(0,0,320,240); try{ MediaLocator mlr = new MediaLocator(mediaFile); player = Manager.createPlayer(mlr); player.addControllerListener(this); } catch (Exception e){ System.out.println("Exception caught."); } } public void start(){ if (player != null){ player.start(); } } public void stop(){ if (player != null){ player.stop(); player.deallocate(); player.close(); } } public void destroy(){ } public synchronized void controllerUpdate(ControllerEvent theEvent){ if (player == null) return; if (theEvent instanceof RealizeCompleteEvent){ int width = 320; int height = 0; if (visualComponent == null){ if ((visualComponent = player.getVisualComponent()) != null){ thePanel.add("Center",visualComponent); Dimension videoSize = visualComponent.getPreferredSize(); videoWidth = videoSize.width; videoHeight = videoSize.height; width += videoHeight; visualComponent.setBounds(0,0,videoWidth,videoHeight); } } thePanel.setBounds(0,0,width,height); validate(); } else if (theEvent instanceof ControllerErrorEvent){ player = null; getAppletContext().showStatus("Exception event caught."); } else if (theEvent instanceof ControllerClosedEvent){ thePanel.removeAll(); } } } Envio de video, Maquina 1 En el equipo 2 se presenta un retrazo en la transmision por el saturamiento del ancho de banda. Recepción de video, Equipo2 CONCLUSIONES: El uso de Java Media Framework facilita las funciones de cámara web, consiguiendo mostrar la imagen y video de forma correcta para transmitir a los clientes que se conecten. Tuvimos problemáticas a la hora de transmitir el video, pero después de un arduo trabajo conseguimos el objetivo planteado. Este proyecto nos deja con bastante aprendizaje, pues es bastante útil para diversas aplicaciones saber manejar la transmisión de video, como trabajo a futuro sería tambien transmitir audio y video, además poder conjuntar un chat escrito por si acaso.