2010-10-28 36 views
13

Un projet de vidéoconférence Je travaillais sur JMF utilisé pour capturer la vidéo et l'audio, et le transmettre à un autre point final. Un problème était que mon équipe ne voulait pas que l'utilisateur du produit ait à installer JMF.Comment capturer la vidéo en utilisant JMF, mais sans installer JMF

Je pensais qu'il pourrait être utile de partager notre solution à ce problème. Ça marche. Ça marche bien. Ma question est la suivante: quelqu'un a-t-il une meilleure façon de le faire?

Environnement: Windows, XP et plus

  1. Télécharger JMF pour Windows
  2. Installez-le sur votre machine

  3. Localisez les dll s suivantes dans le dossier system32 après JMF installs:

    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. Copiez le dll s dans un dossier temporaire

  5. Localisez le fichier jmf.properties (faire une recherche sur Télécharger le code source JMF
    Dans le code source, trouver les fichiers suivants:

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

  1. Créer un package; Je vais l'appeler JMFNoInstall
  2. Ajouter les fichiers listés à l'étape 6
  3. Ajouter une classe appelée Main à ce paquet en tant que tel:

 

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

Le fichier jmf.properties doit aller dans le même dossier que la classe qui a votre méthode main ou le même dossier que l'archive JAR qui contient la méthode main.
Les dll doivent être placés dans le dossier win32. Vous pouvez vérifier votre programme pour voir s'il se trouve dans le dossier win32. Si ce n'est pas le cas, vous pouvez le faire copier à partir d'un endroit. Le fichier jmf.properties est mis à jour lorsque la classe Main répertoriée ci-dessus s'exécute. Vous n'avez besoin de l'exécuter qu'une seule fois, la première fois que le programme est exécuté ou si l'utilisateur souhaite ajouter de nouveaux périphériques de capture. Enfin, assurez-vous que le fichier jmf.jar et jmfcom.jar fourni avec le téléchargement Windows JMF est inclus dans le classpath. Vous êtes bon à aller à ce stade. Toutes les fonctionnalités de JMF sans avoir à l'installer.

Il n'y a pas vraiment beaucoup de travail à faire avec ceci, et vous pouvez l'intégrer assez facilement dans votre programme d'installation personnalisé.

Est-ce que quelqu'un a trouvé une meilleure façon de faire cela? Il y a quelques pièges à faire de cette façon.

EDIT: J'ai pensé qu'il pourrait être utile de partager une partie du code que j'ai créé. Bien sûr, vous devrez le modifier pour gérer ce que vous. Il ne compilera probablement pas, mais les choses manquantes devraient être assez faciles à recréer. Mais pensé que ce pourrait être un bon point de départ pour aider les gens. La fonction detectCaptureDevices est probablement ce qui va aider la plupart des gens. Je mets à jour cette classe comme je vais.

 

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

Ce serait une meilleure idée de partager quelques informations plus sur cet exemple/exemple de codes et quelques étapes, j'essayais aussi similaire. Et pensait à passer à l'accès JMF ou Native? – YumYumYum

+1

@Stackfan J'ai ajouté une partie de mon code si cela aide quelqu'un – user489041

+0

@ user489041 Vous dites "Les dll doivent aller dans le dossier win32" vous voulez dire 'system32'? – MikeNereson

Répondre

4

Je ne pense pas qu'il y ait une meilleure façon. À moins que les DLL ne soient explicitement chargées par le nom du chemin d'accès, vous devez simplement vous assurer qu'elles se trouvent dans le chemin d'accès au système, donc si elles se trouvaient juste à côté des exécutables JVM, cela devrait également fonctionner. Windows inclut implicitement le répertoire dans lequel le programme a été démarré dans le chemin d'accès au système, ce qui constitue un autre emplacement potentiel. Les installateurs sont une épée à double tranchant, ils facilitent l'ajout de nouvelles fonctionnalités et les suppriment plus tard, mais rendent également plus difficile le déploiement de solutions utilisant le produit. L'une des bonnes choses à propos de Java en général est que vous n'avez pas à l'installer pour que cela fonctionne. Essentiellement, une fois que vous avez effectué l'installation du JRE sur un système, vous pouvez le regrouper et l'utiliser sur un autre système en tant que fichier zip. Java n'a pas besoin d'enregistrer explicitement les DLL car il les charge dynamiquement selon les besoins.

+1

Tout cela est très vrai. D'autre part, JMF nécessite une installation. C'est exactement la raison pour laquelle vous avez déclaré: «L'un des avantages de Java en général est que vous n'avez pas besoin de l'installer pour que cela fonctionne.» 'Nous ne voulions pas que l'utilisateur final doive installer autre chose pour que notre application fonctionne. Ceci est également très vrai si l'application fonctionnait en tant qu'applet. Nous voulions juste pouvoir copier les fichiers dans les coulisses et tout fonctionner. Ce n'était pas facile de se moquer de l'installation de JMF. Il y a beaucoup de propriétés qui sont définies dans les coulisses. – user489041