2010-10-28 8 views
13

Un progetto di videoconferenza Stavo lavorando su JMF usato per acquisire video e audio e trasmetterlo a un altro endpoint. Un problema era che il mio team non voleva che l'utente del prodotto dovesse installare JMF.Come acquisire video usando JMF, ma senza installare JMF

Ho pensato che valesse la pena condividere la nostra soluzione a questo problema. Funziona. Funziona bene. La mia domanda per voi è: qualcuno ha un modo migliore per farlo?

Ambiente: Windows, XP e sopra

  1. Scarica JMF per Windows
  2. Installare sulla vostra macchina

  3. Individuare i seguenti dll s nella cartella system32 dopo JMF installa:

    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. Copiare i dll s in una cartella temporanea

  5. individuare il file jmf.properties (fare una ricerca su il tuo computer)
  6. Scarica il codice sorgente JMF
    Nel codice sorgente, trova i seguenti file:

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

  1. Creare un pacchetto; Lo chiamerò JMFNoInstall
  2. Aggiungi i file elencati nel passaggio 6
  3. Aggiungere una classe chiamata principale di questo pacchetto in quanto tale:

 

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" 
     }); 
    } 
} 

Il file jmf.properties ha bisogno di andare nella stessa cartella della classe con il metodo main o la stessa cartella dell'archivio JAR contenente il metodo main.
Gli dll s devono entrare nella cartella win32. È possibile fare controllare il programma per vedere se si trovano nella cartella win32. Se non lo sono, puoi copiarli da qualche postazione. Il file jmf.properties viene aggiornato ogni volta che viene eseguita la classe Main elencata sopra. È sufficiente eseguire questa operazione una volta, la prima volta che viene eseguito il programma o se l'utente desidera aggiungere nuovi dispositivi di acquisizione. Infine, assicurati che il file jmf.jar e jmfcom.jar fornito con il download di Windows JMF sia incluso nel classpath. Sei a posto a questo punto. Tutte le funzionalità di JMF senza doverla installare.

Non c'è davvero molto lavoro in questo, e puoi incorporarlo facilmente nel tuo programma di installazione personalizzato.

Qualcuno ha trovato un modo migliore per farlo? Ci sono alcune insidie ​​nel farlo in questo modo.

EDIT: Ho pensato che valesse la pena condividere il codice che ho creato. Ovviamente avrai bisogno di modificarlo per gestire ciò che tu. Probabilmente non verrà compilato, ma le cose che mancano dovrebbero essere abbastanza facili da ricreare. Ma pensato che potrebbe essere un buon punto di partenza per aiutare le persone. La funzione detectCaptureDevices è probabilmente ciò che aiuterà la maggior parte delle persone. Aggiornerò questa lezione mentre vado.

 

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

Sarebbe un'idea migliore per condividere alcune informazioni in più su questo esempio/codici di esempio e pochi passaggi, stavo anche cercando simile. E stava pensando di passare a JMF o accesso nativo? – YumYumYum

+1

@Stackfan Ho aggiunto parte del mio codice se questo aiuta qualcuno – user489041

+0

@ user489041 Si dice "Le DLL devono entrare nella cartella win32" intendete 'system32'? – MikeNereson

risposta

4

Non credo ci sia un modo migliore. A meno che le DLL non siano caricate esplicitamente dal nome del percorso, è necessario solo accertarsi che si trovino nel percorso di sistema, quindi se si trovano proprio accanto agli eseguibili JVM dovrebbe funzionare. Windows include implicitamente la directory da cui è stato avviato il programma nel percorso di sistema, quindi questa è un'altra posizione potenziale.

Gli installatori sono un'arma a doppio taglio, facilitano l'aggiunta di nuove funzionalità e la rimozione in seguito, ma rendono anche più difficile l'implementazione di soluzioni che utilizzano il prodotto.

Una delle cose carine di Java in generale è che non è necessario installarlo perché funzioni. In sostanza, una volta eseguita l'installazione di JRE su un sistema, è possibile raggrupparlo e utilizzarlo su un altro sistema come file zip. Java non ha bisogno di registrare esplicitamente le DLL perché le carica dinamicamente secondo necessità.

+1

Questo è tutto molto vero. D'altro canto, JMF richiede un'installazione. È esattamente la ragione per cui hai affermato "Una delle cose belle di Java in generale è che non devi installarlo perché funzioni." "Non volevamo che l'utente finale dovesse installare altro perché la nostra applicazione funzioni. Questo è anche molto vero se l'applicazione era in esecuzione come applet. Volevamo solo essere in grado di copiare i file dietro le quinte e far funzionare tutto. Non è stato facile prendere in giro l'installazione di JMF. Ci sono molte proprietà che vengono impostate dietro le quinte. – user489041

Problemi correlati