Download NetBeans!

20070121 Sunday January 21, 2007

How to Create a Movie Player (Step 1: Setting Up and Testing JMF)

This is the first of a 3 part series of blog entries in which I intend to show you, as exactly as possible, how to create the movie player shown in yesterday's blog entry. At the end of this series, you should have something that looks a lot like the movie player shown in yesterday's blog entry.

The three part series will consist of the following:

So, this is part 1, the most complex part, in which we set up Java Media Framework API (JMF). Everything I know about JMF I learned from blogs and discussion threads, because I trust bloggers more than technical writers. (And I am a technical writer, so go figure.) But, seriously, bloggers tend to find the pain points of a product, while the official documentation tends to describe the best-case scenario, with some low-threshold troubleshooting tips near the end. I'm adding this disclaimer up front, because the procedure that follows is my own ad-hoc JMF setup procedure, and hasn't been tried and tested, and has worked for me only on Windows (although the same procedure should work on other operating systems, with the variations specified below).

But first, what is JMF? Here is the definition according to the website: "The Java Media Framework API (JMF) enables audio, video and other time-based media to be added to applications and applets built on Java technology. This optional package, which can capture, playback, stream, and transcode multiple media formats, extends the Java 2 Platform, Standard Edition (J2SE) for multimedia developers by providing a powerful toolkit to develop scalable, cross-platform technology."

Here's how I personally recommend getting JMF up and running:

  1. Click this link. You now find yourself in the JMF Diagnostics Applet. It tells you whether you have JMF set up or not. At the start of this procedure, I'm assuming you have nothing set up. Here is what I see in the text area in the JMF Diagnostics Applet:

    JMF Diagnostics:
    
    Java 1.1 compliant browser.....Maybe
    JMF classes.....Not Found

    Later we will go this JMF Diagnostics Applet again, and we will notice that the message we see here is different.

  2. Next, go to a command prompt and type the following:

    java JMStudio

    You should now see the following:

    Exception in thread "main" java.lang.NoClassDefFoundError: JMStudio

    This tells you that JMF's most important tool, JMStudio, is not available. It will be available after you install JMF. Let's do that and come back to the command prompt afterwards.

  3. Click here to go to the JMF download page. Click the Download button on that page. Click the Accept button. Next, select the JMF download applicable to your platform. (I don't know what the Java all-platform download is for, but somehow I haven't been able to download it thus far.)

  4. At the end of the wizard that installs JMF, you will be prompted to restart your computer. Do so. Then, go back to the JMF Diagnostics Applet. Depending on your operating system, you should now see this in the text area:

    JMF Version... 2.1.1e
    
    Win32 Build
    Native Libraries Found

  5. Next, start up the JMStudio application, which should now start up, because it is part of your JMF installation and because the right environment variables have been set by the installer. So type this in the command prompt:

    java JMStudio

    Now JMStudio starts up. Go to File | Open File. Browse to a movie (or music). Depending on the type of file you want to view, possibly you will now see a JMStudio Error dialog with this message:

    Controller Error: 
    Failed to realize: input media not supported: XVID video,
    mpgelayer3 audio

    Now here is an important rule to all of this stuff: If something does not play in JMStudio, it will not play in your own application either.

    So, we need to extend JMF. Let's do that in the next step.

  6. Click here to get to the Fobs download page. What is Fobs and why do you need it? This is what the Fobs website says about itself: "FOBS (Ffmpeg OBjectS) is a set of object oriented APIs to deal with media. It relies on the ffmpeg library, but provides developers with a much simpler programming interface."

    So, download Fobs. I use the Windows ZIP file. After you have unzipped it, double-click runjmstudio.bat. Now JMStudio starts up, with the Fobs JAR files registered. Choose File | Open File again and browse to your file. The movie should start. And the command prompt should now show you this:

    Fobs4JMF - Native shared library found
    7283.99First Position: 0, 41 Duration: 7283992
    Frame Rate: 23.976
    Opening Thread[JMF thread: com.sun.media.PlaybackEngine@111a3ac[ com.sun.media.P
    laybackEngine@111a3ac ] ( configureThread),9,system]
    Fobs Java2DRenderer: setInputFormat
    Fobs Java2DRenderer: setInputFormat
    Fobs Java2DRenderer: start

  7. Meanwhile, your movie is now playing in JMStudio. At the bottom of JMStudio, you see a slider for increasing/decreasing the volume. On the right side of the slider, in the far right corner, you see two buttons, one for toggling the sound on/off and another for calling up information on JMStudio. Click that button. In "Media Properties", click the "Plug-in Settings" tab. Then click the "Plugin Viewer" button. The Plugin Viewer dialog appears, showing you a diagram that should show you that both the video and audio are functioning. This is good news.

  8. Now type the following in the command prompt:

    java JMFRegistry

    You now end up in the JMF Registry Editor. (You could also get here by choosing File | Preferences in JMStudio.) Now look in the very useful Configuration of Fobs4JMF document. Specifically, look in step 5 of the "Manual Configuration" section. Check that everything has been registered correctly, which happened in the previous step, when you clicked the BAT file (or whatever file relevant to your operating system). For example, look in Plugins | Codec and check that the three Fobs Codecs have been added to the end of the list. If something has not been added automatically for some reason, do so manually, as described in step 5 of the "Manual Instructions" section.

As far as I can tell, you have now completed the set up of JMF, and extended it with Fobs. You need Fobs for a lot of file types that are not covered by JMF by default. Without Fobs, I have not been able to watch a single movie in JMStudio (and, therefore, not in my own application either). There's also an MP3 Plugin for JMF (here), which only works under Windows.

Next, we are going to create a simple Swing application which will test our JMF set up. Once we have that, we are ready for the next stage (part 2 of this series), where we port our Swing application to a NetBeans module which we integrate in the IDE. Here are the steps for creating our simple swing application:

  1. Start up NetBeans IDE 5.5 or a 6.0 build. (Or start up 5.0, but why are you still using 5.0 anyway?)

  2. Create a new Java application called "MoviePlayer".

  3. Create a new JPanel called "MediaPanel". Rewrite the default constructor as follows:

    public MediaPanel( URL mediaURL ) {
    
        initComponents();
    
        setLayout( new BorderLayout() ); // use a BorderLayout
    
        try {
    
            // Create a JMF player to play the media specified in the URL:
            Player mediaPlayer = Manager.createRealizedPlayer( new MediaLocator(mediaURL) );
    
            // Get the components for the video and the playback controls:
            Component video = mediaPlayer.getVisualComponent();
            Component controls = mediaPlayer.getControlPanelComponent();
    
            if ( video != null )
                add( video, BorderLayout.CENTER ); // add video component
    
            if ( controls != null )
                add( controls, BorderLayout.SOUTH ); // add controls
    
            // Start the JMF player:
            mediaPlayer.start(); // start playing the media clip
    
        } // end try
    
        catch ( NoPlayerException noPlayerException ) {
            System.err.println( "No media player found" );
        } // end catch
    
        catch (CannotRealizeException ex) {
                ex.printStackTrace();
        } // end catch
    
        catch ( IOException iOException ) {
            System.err.println( "Error reading from the source" );
        } // end catch
    
    } // end MediaPanel constructor

    Notice that the constructor receives a URL. This URL is the URL to your movie. (We will use the IDE-generated Main.java class, in step 5 below, which will pass the URL, after the user has selected a movie via a file chooser.) Next, we create a JMF player object. We also create two components, a visual component and a controller component. The controller is the sliding bar at the bottom of a JMF application, for controlling the volume, as well as the additional buttons for toggling the sound, and so on. In other words, the controller is something you get for free when you use JMF. Finally, after adding the visual component and controller component, we start the player. And that's it! JMF in a nutshell.

  4. However, assuming that you want to wrap the JARs with the application (instead of using the installed JMF libraries that, thanks to the installer, must be on your classpath at this stage), we haven't put the JMF JAR on the application's classpath. Let's do that now. Right-click the Libraries node, choose "Add JAR/Folder" and browse to the two JARs provided by the Fobs download. In other words, you should have fobs4jmf.jar and jmf.jar added to the Libraries node. Also include the native library there. For example, create a Java library and put fobs4jmf.dll in its default package. That's all I need to do and it works. (You could also add the native library to the PATH environment variable, or its equivalent on your operating system.) Now the red underlines, if any, in the MediaPanel code should disappear.

  5. Next, we use the Main.java class that the IDE generated for us to pass the movie's URL to the MediaPanel. Here's the constructor:

    public static void main( String args[] ) {
    
        // Create a File Chooser:
        JFileChooser fileChooser = new JFileChooser();
    
        // Show Open File dialog:
        int result = fileChooser.showOpenDialog( null );
    
        if ( result == JFileChooser.APPROVE_OPTION ) // User chose a file
        {
            URL mediaURL = null;
    
            try {
                // Get the file as URL:
                mediaURL = fileChooser.getSelectedFile().toURI.toURL();
            } // end try
    
            catch ( MalformedURLException malformedURLException ) {
                System.err.println( "Could not create URL for the file" );
            } // end catch
    
            if ( mediaURL != null ) // Only display if there is a valid URL
            {
                JFrame mediaTest = new JFrame( "Movie Player" );
                mediaTest.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
                MediaPanel mediaPanel = new MediaPanel( mediaURL );
                mediaTest.add( mediaPanel );
                mediaTest.setSize( 300, 300 );
                mediaTest.setVisible( true );
            } // end inner if
    
        } // end outer if
    
    } // end main

    So here we have a simple file chooser. We convert the chosen file to a URL and send it to the MediaPanel. That's all.

  6. Now run the application. The file chooser appears. Select a movie. You should see this, after a moment, in the Output window:

    init:
    deps-jar:
    compile:
    run:
    Fobs4JMF - Native shared library found
    4820First Position: 0, 40 Duration: 4820000
    Frame Rate: 25
    Opening Thread[JMF thread: com.sun.media.PlaybackEngine@eb7859[ com.sun.media.PlaybackEngine@eb7859 ] ( configureThread),9,system]
    Fobs Java2DRenderer: setInputFormat
    Fobs Java2DRenderer: setInputFormat
    Fobs Java2DRenderer: start
    BUILD SUCCESSFUL (total time: 45 seconds)

    And now your movie starts up. Hurray, you've successfully set up and tested JMF.

I hope the above steps all make sense and, if they don't, especially for non-Windows operating systems, please leave a note at the end of this blog entry. Plus, note that many/all of the instructions could be wrong, since they're all based on my personal flounderings in JMF land, during the past few days.

In the next entry in this 3 part series, we will port our Swing application to a NetBeans module, which we will install in the IDE. This will give us a movie player inside our IDE.

Jan 21 2007, 08:02:28 AM PST Permalink