2010-10-28 9 views
13

Un proyecto de videoconferencia en el que estaba trabajando usó JMF para capturar video y audio, y transmitirlo a otro punto final. Un problema fue que mi equipo no quería que el usuario del producto tuviera que instalar JMF.Cómo capturar video usando JMF, pero sin instalar JMF

Pensé que podría valer la pena compartir nuestra solución a este problema. Funciona. Funciona bien. Mi pregunta es: ¿alguien tiene una mejor manera de hacerlo?

Medio Ambiente: Windows, XP y superior

  1. Descargar JMF para Windows
  2. Instalar en su máquina

  3. Localizar las siguientes dll s en la carpeta system32 después de JMF Instalaciones:

    jmacm.dll
    jmam.dll
    jmcvid.dll
    jmdaud.dll
    jmdaudc.dll
    jmddraw.dll
    jmfjawt.dll
    jmg723.dll
    jmgdi.dll
    jmgsm.dll
    jmh261.dll
    jmh263enc.dll
    jmjpeg.dll
    jmmci.dll
    jmmpa.dll
    jmmpegv.dll
    jmutil.dll
    jmvcm.dll
    jmvfw.dll
    jmvh263.dll
    jsound.dll

  4. Copiar los dll s en una carpeta temporal

  5. localizar el archivo jmf.properties (hacer una búsqueda en su computadora para ello)
  6. Descargue el código fuente JMF
    En el código fuente, busque los siguientes archivos:

JMFinit.java
JMRPropertiesGen.java
Registry.java
RegistryGen.java

  1. Crear un paquete; Lo llamaré JMFNoInstall
  2. Añadir los archivos que aparecen en el paso 6
  3. Añadir una clase llamada principal de este paquete como tal:

 

package JMFNoInstall; 
// add your imports and whatnot here 
public class Main() 
{ 
    public Main() 
    { 
     JMFinit.main(null); 
     JMFPropertiesGen.main(null); 
     Registry.main(null); 
     RegistryGen.main(new String[] { 
      new File(".").getAbsolutePath(), 
      "registrylib" 
     }); 
    } 
} 

El archivo jmf.properties tiene que ir en la misma carpeta que la clase que tiene su método main o la misma carpeta que el archivo JAR que contiene el método main.
El dll s necesita ir a la carpeta win32. Puede hacer que su programa verifique si están en la carpeta win32. Si no lo son, puede hacer que los copie desde algún lugar. El archivo jmf.properties se actualiza cada vez que se ejecuta la clase Main listada anteriormente. Solo necesita ejecutar esto una vez, la primera vez que se ejecuta el programa, o si el usuario desea agregar nuevos dispositivos de captura. Por último, solo asegúrese de que el archivo jmf.jar y el jmfcom.jar que viene junto con la descarga de Windows JMF estén incluidos en el classpath. Eres bueno para ir en este punto. Toda la funcionalidad de JMF sin tener que instalarlo.

Realmente no hay mucho trabajo involucrado con esto, y puede incorporarlo fácilmente en su instalador personalizado.

¿Alguien ha encontrado una mejor manera de hacer esto? Hay algunas trampas de hacerlo de esta manera.

EDIT: Pensé que podría valer la pena compartir parte del código que creé. Por supuesto, tendrá que modificarlo para manejarlo. Es probable que no compile, pero las cosas que faltan deberían ser lo suficientemente fáciles de recrear. Pero pensó que podría ser un buen punto de partida para ayudar a la gente. La función detectCaptureDevices es probablemente lo que ayudará a la mayoría de las personas. Ill actualizar esta clase como yo voy.

 

import GUI.Window; 
import GlobalUtilities.OS; 
import GlobalUtilities.ProgressBar; 
import GlobalUtilities.FileUtilities; 
import java.io.File; 
import java.util.ArrayList; 
import java.util.Vector; 
import javax.swing.text.Utilities; 


/** 
* This class providex easy access to the most needed info about JMF. You can test 
* a JMF install (Windows only currently) and also get info about the captrue 
* devices hooked up to JMF. 
* @author dvargo 
*/ 
public class JMFRunner 
{ 
    /** 
    * Show the status of operations 
    */ 
    final ProgressBar theBar = new ProgressBar(); 
    /** 
    * Location where the dll's JMF relies on need to be placed 
    */ 
    final String windowsDllFolder = "C:\\WINDOWS\\system32\\"; 

    final String linuxDllFolder = "/usr/lib/"; 

    /** 
    * Dll's that JMF uses 
    */ 
    final String[] windowsDllList = new String[]{ 
     "jmacm.dll", 
     "jmam.dll", 
     "jmcvid.dll", 
     "jmdaud.dll", 
     "jmdaudc.dll", 
     "jmddraw.dll", 
     "jmfjawt.dll", 
     "jmg723.dll", 
     "jmgdi.dll", 
     "jmgsm.dll", 
     "jmh261.dll", 
     "jmh263enc.dll", 
     "jmjpeg.dll", 
     "jmmci.dll", 
     "jmmpa.dll", 
     "jmmpegv.dll", 
     "jmutil.dll", 
     "jmvcm.dll", 
     "jmvfw.dll", 
     "jmvh263.dll", 
     "jsound.dll"}; 

    String[] linuxDllList = new String[]{ 
     "libjmcvid.so", 
     "libjmdaud.so", 
     "libjmfjawt.so", 
     "libjmg723.so", 
     "libjmgsm.so", 
     "libjmh261.so", 
     "libjmh263enc.so", 
     "libjmjpeg.so", 
     "libjmmpa.so", 
     "libjmmpegv.so", 
     "libjmmpx.so", 
     "libjmutil.so", 
     "libjmv4l.so", 
     "libjmxlib.so" 
    }; 

    String [] dlls= null; 
    String dir = null; 

    /** 
    * List of the video capture devices found by JMF 
    */ 
    Vector videoDevices = null; 
    /** 
    * List of the audio capture devices found by JMF 
    */ 
    Vector audioDevices = null; 

    public JMFRunner() 
    { 
     if(OS.isWindows()) 
     { 
      dlls = windowsDllList; 
      dir = windowsDllFolder; 
     } 
     else if(OS.isLinux()) 
     { 
      dlls = linuxDllList; 
      dir = linuxDllFolder; 
     } 
     else 
     { 
      Window.getLogger().severe("Operating system does not support JMF"); 
     } 

    } 

    /** 
    * Adds new capture devices 
    */ 
    public void detectCaptureDecives() 
    { 


     Thread theTread = new Thread(theBar); 
     theTread.start(); 
     theBar.repaint(); 

     JMFInit.main(new String[] {""}); 
     JMFPropertiesGen.main(new String[] {""}); 
     Registry.main(new String[] {""}); 
     RegistryGen.main(new String[] {"-d", 
      new File(".").getAbsolutePath(), 
      "registrylib" 
     }); 

     theBar.setMessage(""); 
     theBar.stop(); 
    } 

    /** 
    * Verifies that all the dll's that JMF needs are in their correct spot 
    * @return True if all dlls are in their correct spot, false otherwise 
    */ 
    public boolean detectDlls() 
    { 
     boolean retVal = true; 
     String currFile; 
     for(String currDll : dlls) 
     { 
      currFile = dir + currDll; 
      if(! new File(currFile).exists()) 
      { 
       Window.getLogger().severe("Can not find dll " + currFile + " for JMF"); 
       retVal = false; 
      } 
     } 
     return retVal; 
    } 

    //Doesnt work quite yet 
    public boolean installLibraryFiles() 
    { 
     boolean retVal = true; 
     String currFile; 
     for(String currDll : dlls) 
     { 
      currFile = dir + currDll; 
      File newDll = new File(currFile); 
      //see if this dll is already there 
      if(!newDll.exists()) 
      { 
       //its not there so lets copy it 
       try 
       { 
        FileUtilities.copy(newDll,FileUtilities.getResourceFile("/JMFManager/Resources/"+currDll,currDll)); 
       } 
       catch(Exception e) 
       { 
        retVal = false; 
       } 
      } 
     } 
     return retVal; 
    } 

    /** 
    * Returns the location of the jmf.properties file that STix is using 
    * @return THe locaiton of the JMF properties 
    */ 
    public String getJMFPropertiesFileLocation() 
    { 
     return Registry.getJMFPropertiesFileLocation(); 
    } 

    /** 
    * Returns a list of the audio devices found by JMF 
    * @return Returns an Arraylist containing info about the audio capture devices 
    */ 
    public ArrayList getAudioDevices() 
    { 
     DeviceFinder df = new DeviceFinder(); 
     audioDevices = df.getSoundCaptureDevices(); 
     return new ArrayList(audioDevices); 
    } 

    /** 
    * Returns a list of the video decives deteced by JMF 
    * @return returns an arraylist with info of the video capture devices 
    */ 
    public ArrayList getVideoDevices() 
    { 
     DeviceFinder df = new DeviceFinder(); 
     videoDevices = df.getVideoCaptureDevices(); 
     return new ArrayList(videoDevices); 
    } 


    public static void main(String [] args) 
    { 
     JMFRunner x = new JMFRunner(); 
     //x.detectCaptureDecives(); 
     x.installLibraryFiles(); 
     System.out.println(x.detectDlls()); 
     System.out.println(x.getJMFPropertiesFileLocation()); 
     System.out.println(x.getAudioDevices()); 
     System.out.println(x.getVideoDevices()); 
    } 
} 
 

DeviceFinder.java

 

import java.util.Vector; 
import javax.media.*; 
import javax.media.format.*; 

/** 
* this class gets information about capture devices (mics and cameras) 
*/ 
public class DeviceFinder { 

    Vector videoDevices = new Vector(); 
    Vector audioDevices = new Vector(); 

    /** 
    * Constructor 
    * Creates a new DeviceFinder 
    */ 
    public DeviceFinder() 
    { 
     /*retrieve ALL video and audio devices*/ 
     videoDevices = CaptureDeviceManager.getDeviceList(new VideoFormat(null)); 
     audioDevices = CaptureDeviceManager.getDeviceList(new AudioFormat(null)); 
    } 

    /** 
    * purpose: Get information on all Video capture devices on the system 
    * @return java.util.Vector 
a vector of attributes */ public Vector getVideoCaptureDevices() { return videoDevices; } /** * purpose: Get information on all audio capture devices on the system * @return java.util.Vector
a vector of attributes */ public Vector getSoundCaptureDevices() { return audioDevices; } /** * retrieve the first video capture device */ public CaptureDeviceInfo getPrimaryVideoCaptureDevice() { return (CaptureDeviceInfo)videoDevices.get(0); } /*retrieve the first audio capture device*/ public CaptureDeviceInfo getPrimaryAudioCaptureDevice() { return (CaptureDeviceInfo)audioDevices.get(0); } /** * get the first video device name * @return String
the name of the video device */ public String getVideoCaptureDeviceName() { return ((CaptureDeviceInfo)videoDevices.get(0)).getName(); } /** * get the first audio device name * @return String
the name of the audio device */ public String getAudioCaptureDeviceName() { return ((CaptureDeviceInfo)audioDevices.get(0)).getName(); } /** * get the first video device media locator * @return MediaLocator */ public MediaLocator getVideoMediaLocator() { return ((CaptureDeviceInfo)videoDevices.get(0)).getLocator(); } /** * get the first audio device media locator * @return MediaLocator */ public MediaLocator getAudioMediaLocator() { return ((CaptureDeviceInfo)audioDevices.get(0)).getLocator(); } /** * get the video device media locator at index idx * @param idx index of the media locator (0 is the first/default, * as ordered by *
the JMFRegistry) * @return MediaLocator */ public MediaLocator getVideoMediaLocator(int idx) { if(idx >= videoDevices.size()) { return null; } return ((CaptureDeviceInfo)videoDevices.get(idx)).getLocator(); } /** * get the audio device media locator at index idx * @param idx index of the audio device (as ordered by the JMFRegistry) * @return MediaLocator */ public MediaLocator getAudioMediaLocator(int idx) { return ((CaptureDeviceInfo)audioDevices.get(idx)).getLocator(); } /** * * @param args */ public static void main(String[] args) { DeviceFinder df = new DeviceFinder(); //DEBUG: System.out.println(df.getVideoMediaLocator()); System.out.println(df.getAudioMediaLocator()); } }
+0

Sería una mejor idea compartir algunas informaciones más sobre este ejemplo/ejemplos de códigos y algunos pasos, también lo estaba intentando de forma similar. ¿Y estaba pensando en pasar a JMF o acceso nativo? – YumYumYum

+1

@Stackfan He agregado algo de mi código si eso ayuda a alguien – user489041

+0

@ user489041 Usted dice "¿Los dlls necesitan ir a la carpeta win32" quiere decir 'system32'? – MikeNereson

Respuesta

4

No creo que hay una manera mejor. A menos que los DLL estén cargados explícitamente por nombre de ruta, solo necesita asegurarse de que estén en la ruta del sistema, por lo que si vivieran junto a los ejecutables de JVM también deberían funcionar. Windows incluye implícitamente el directorio desde el que se inició el programa en la ruta del sistema, por lo que esa es otra ubicación potencial.

Los instaladores son un arma de doble filo, hacen que sea fácil agregar nuevas funcionalidades y eliminarlas más adelante, pero también dificultan la implementación de soluciones que usan el producto.

Una de las cosas buenas de Java en general es que no tiene que instalarlo para que funcione. Esencialmente, una vez que realiza la instalación de JRE en un sistema, puede agruparlo y usarlo en otro sistema como un archivo zip. Java no necesita registrar explícitamente las DLL porque las carga dinámicamente según sea necesario.

+1

Eso es todo muy cierto. JMF por otro lado requiere una instalación. Es exactamente la razón por la que afirmó: '" Una de las cosas buenas de Java en general es que no tiene que instalarlo para que funcione "." No queríamos que el usuario final tuviera que instalar otra cosa. para que nuestra aplicación funcione Esto también es muy cierto si la aplicación se ejecuta como un applet. Queríamos solo poder copiar archivos detrás de escena y hacer que todo funcione. No fue fácil simular la instalación de JMF. Hay muchas propiedades que se establecen detrás de escena. – user489041

Cuestiones relacionadas