title: How to capture video using JMF, but without installing JMF
body: <p>A videoconferencing project I was working on used JMF to capture video and audio, and transmit it to another endpoint. An issue was that my team didn't want the user of the product to have to install JMF.</p>
  
  <p>I thought it might be worthwhile to share our solution to this problem. It works. It works well. My question to you is: does anyone have a better way to do it?</p>
  
  <p>Environment: Windows, XP and above</p>
  
  <ol>
  <li>Download JMF for Windows</li>
  <li><p>Install it on your machine</p></li>
  <li><p>Locate the following <code>dll</code>s in the system32 folder after jmf installs:</p>
  
  <p>jmacm.dll<br>
  jmam.dll<br>
  jmcvid.dll<br>
  jmdaud.dll<br>
  jmdaudc.dll<br>
  jmddraw.dll<br>
  jmfjawt.dll<br>
  jmg723.dll<br>
  jmgdi.dll<br>
  jmgsm.dll<br>
  jmh261.dll<br>
  jmh263enc.dll<br>
  jmjpeg.dll<br>
  jmmci.dll<br>
  jmmpa.dll<br>
  jmmpegv.dll<br>
  jmutil.dll<br>
  jmvcm.dll<br>
  jmvfw.dll<br>
  jmvh263.dll<br>
  jsound.dll</p></li>
  <li><p>Copy the <code>dll</code>s into a temporary folder</p></li>
  <li>Locate the <code>jmf.properties</code> file (Do a search on your computer for it)</li>
  <li>Download the JMF source code<br>
  In the source code, find the following files:</li>
  </ol>
  
  <p>JMFinit.java<br>
  JMRPropertiesGen.java<br>
  Registry.java<br>
  RegistryGen.java</p>
  
  <ol>
  <li>Create a package; I'll call it <code>JMFNoInstall</code></li>
  <li>Add the files listed in step 6</li>
  <li>Add a class called Main to this package as such:</li>
  </ol>
  
  <p>&nbsp;</p>
  
  <pre><code>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"
          });
      }
  }
  </code></pre>
  
  <p>The <code>jmf.properties</code> file needs to go in the same folder as the class that has your <code>main</code> method or the same folder as the JAR archive that contains the <code>main</code> method.<br>
  The <code>dll</code>s need to go into the <code>win32</code> folder. You can have your program check to see if they are in the <code>win32</code> folder. If they are not, you can have it copy them over from some location. The <code>jmf.properties</code> file gets updated whenever the the <code>Main</code> class listed above runs. You only need to run this once, the first time the program is ever run, or if the user would like to add new capture devices. Lastly, just make sure the <code>jmf.jar</code> file and <code>jmfcom.jar</code> that comes along with the Windows JMF download is included in the classpath. You're good to go at this point. All the functionality of JMF without actually having to install it.</p>
  
  <p>There really isn't a lot of work involved with this, and you can incorporate it into your custom installer quite easily.</p>
  
  <p>Has anyone found a better way to do this though? There are a few pitfalls of doing it this way.</p>
  
  <p>EDIT: I thought it might be worthwhile to share some of the code that I created. Of course youll need to modify it to handle what you. It prob wont compile, but the stuff that is missing should be easy enough to recreate. But thought it might be a good starting point to help people. The detectCaptureDevices function is probably what will help most people. Ill update this class as I go.</p>
  
  <pre>
  <code>
  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());
      }
  }
  </code>
  </pre>
  
  <p>DeviceFinder.java</p>
  
  <pre>
  <code>
  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 <br> a vector of attributes
     */
     public Vector getVideoCaptureDevices()
     {
        return  videoDevices;
     }
  
  
     /**
     * purpose:  Get information on all audio capture devices on the system
     * @return java.util.Vector <br> 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 <br> the name of the video device
     */
     public String getVideoCaptureDeviceName()
     {
        return ((CaptureDeviceInfo)videoDevices.get(0)).getName();
     }
  
  
     /**
     * get the first audio device name
     * @return String <br> 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
     * <br>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());
     }
  }
  </code>
  </pre>