MPEG and Director:
October 1, 1998
by Al Hospers
MPEG playback in Director should be a cakewalk. Instead, it is a trial-by-fire. This article will attempt to take some of the sting out of the process.
The Options
Currently the only MPEG solution for the Mac is Quicktime 3. It supports MPEG with, from what I hear, good quality and a choice between half raster and full raster allowing for playback on slower machines. There is talk about an update for Quicktime 3 on Windows that promises MPEG playback, but as of this writing it does not seem to be available. So this is not a fully cross-platform solution. Keep your eyes open and ears to the Apple QT developer site for late breaking news.In Windows you have 2 options for playing native MPEG files: 1) purchase a MPEG dedicated 3rd party Xtra or 2) use a combination of MCI, ActiveMovie and the BudAPI Xtra (or possibly the old dllGlue Xobject) to get you the interactivity during playback that you need. Which of these solutions you choose depends on how much money you have available and how much you want to write code. I've always been a bit of a code-horse myself.
Clearly the simplest solution is to purchase one of the available Xtras. The two I am aware of currently are:
Xtra | Manufacturer | Contact |
OnStage SE | Visible Light | http://www.visiblelight.com/mall/onstage/ |
MpegXtra | Tabuleiro da Baiana | http://www.tbaiana.com |
Both work well and the support is good. Mauricio Piacentini, from Tabuleiro da Baiana, is often on Direct-L and has been very free with his advice, even to those using MCI. I have used OnStage for a project and their support was also good. They each have somewhat similar feature sets and licensing agreements and each also has upgrade paths to more powerful versions. You should check out their web sites for more information. A real plus for the MpegXtra is the fact that it uses Microsoft's new technology, DirectShow, to play. This is the technology of the future.
MCI and Director
You should be aware that Microsoft is phasing out MCI. DirectShow is the technology that is taking its place. But if you still want to roll-your-own using MCI, for whatever reasons maybe you're a masochist, you will certainly learn a lot.First you will want to read Technote ID # 3521 at Macromedia Support. It gives you a lot of information about the various MCI related commands that are available to you. Right now it is the only documentation available on the web since Microsoft removed its references. Through MCI Director gives you quite a lot of control over the various media types that Windows deals with. You can use MCI to control MPEG video and audio, Wave audio and AVI files using Lingo.
Second, you will need to make sure that your system is configured to use MCI. You will need to install the ActiveMovie drivers on your machine, and/or your target machine, if it is not already installed. The latest version of DirectShow (the new name for ActiveMovie) can be downloaded from Microsoft.
There is a direct link to Microsoft's download page on the Tabulario site. If you are running Windows 98 and IE4 you might find yourself someplace else, but the end result should be the same.
Most machines shipped after November 1996 already contain these drivers. However some older machines running Windows 95A, version number 4.00.950, may need to be upgraded. You can actually use MCI itself to check and see if ActiveMovie is installed. You can use the following Lingo to check:
mci( "info mpegvideo product" ) put the result -- "ActiveMovie"
Obviously ActiveMovie is what you want to see here.
If this comes up with something other than ActiveMovie, or if the test movie does not play, you'll need to make sure that your WIN.INI file is configured properly. Look for a line in the [mci extensions] section that looks like:
mpg=ActiveMovie
If it says something like mpg=MpegVideo, then it is probably configured for a RealMagic driver. You might also see mpg=SoftPeg. This is for the SoftPeg software MPEG driver. In any event, you want to change it to ActiveMovie.
You also want to look in the [mci] section and make sure you have a line:
ActiveMovie=mciqtz.drv
This is the driver that ActiveMovie uses to play your files.
As Mauricio from Tabulario says, "This is the stuff that will give you headache and a lot of tech support calls, and one of the reasons Microsoft is now promoting the use of the ActiveMovie/DirectShow interface instead of MCI."
Interactivity
There is one last piece of this puzzle that you will need to deal with and that is interactivity. Director is a real HOG for CPU clock cycles. There is no way internally to tell it to back off, and this has a real effect on video playback. The 3rd party media playback Xtras like OnStage and DirectMedia both have some code inside that gives some extra priority to the media playback process, and takes a little away from Director itself. That way each gets what they need to perform properly. Without this you get either stuttering media playback, or you cannot do anything in Director until the media is finished.Both are pretty unacceptable for most multimedia applications. Currently the only way around this is with the "baSleep" command in the BuddyAPI Xtra. You can download an evaluation copy that will allow you to use any 3 commands for FREE. FWIW - I can almost guarantee you that there are over 3 commands in this Swiss Army Knife of Xtras that you will find a use for. That's fair warning! You can play with the values, but for this use a setting of 50 seems to work well.
Getting down to some CODE at last
While it is easy to use MCI just by writing a few lines of code and attaching them to a button or a mouseUp event, that's really inefficient. The best way to work with something like MCI for ActiveMovie, or even Quicktime for that matter, is to wrap it up in an OOP layer. You know, an Object. That way, if you keep the same methods in a series of objects you use to play different media types you can play one of those other media types simply by replacing the object.
If your Quicktime object has playMedia, stopMedia, pauseMedia and rewindMedia methods, and your ActiveMovie MCI object has the same AND you pass info into then in the same manner and you give them the same global variable reference they will be basically interchangeable. It's very cool, and very flexible. Try it, you'll love it!
So, we're going to create an object that performs the following functions:
New me
-- instantiates the object and loads the MPEG
PlayMedia me
-- play the MPEG
StopMedia me
-- stop the MPEG
SearchToLocation me
-- jump to a specified location
It uses the actorList to activate the baSleep function when the media is playing and also to check to see if the movie is finished and rewind to the start if it does.
We'll pass the full path and filename of our movie into the object as we instantiate it. We are going to use the BudApi Xtra to create a short file name from this path. The reason for this is that some machines, NT for one, choke on long filenames or ones containing spaces and will give you an MCI Error message. So why take a chance? (See, I told you we couldn't use just one function!)
We're also going to pass in the location on the stage that we want to place the MPEG and its size using a list consisting of the MovieTop, MovieLeft, MovieWidth and MovieHeight parameters in pixels. All this makes the object a lot more flexible.
Here is the code we need to put in the startMovie handler to set things up:
set mediaPath = the moviePath & "test.mpg" set screenLocList = [#movieLeft: 80, #movieTop: 10, ¬ #movieWidth: 160, #movieHeight: 120] set gMediaDeviceObject = new(script ¬ "MediaDeviceObject",mediaPath, screenLocList)
This code assumes a movie stage size of 320 x 240, requires an MPEG video in the same path as the movie and named "test.mpg", and creates a list that gets passed into the object to position the video on the screen.
Now let's look at the "on new me" handler. I've commented almost every line:
on new me, mediaPath, ScreenLocList -- make the short file name set mediaPath = baShortFileName(mediaPath ) -- setup the video position values setMovieWindowLoc me, ScreenLocList -- the video window is going to be -- a child of the stage set MovieStyle = "child" -- get the window handle of the stage set hWinStage = baStageHandle() -- open the file mci "open " & mediaPath && "alias" && "myMovie" ¬ && "style" && MovieStyle && "parent" ¬ && string(hWinStage) -- position the video window mci "put" && "myMovie" && "window at" && MovieLeft ¬ && MovieTop && MovieWidth && MovieHeight -- a little error checking is a good thing mci "status myMovie mode" set mciStatus = the Result if mciStatus contains "MCI Error: " then set errorMessage = "Movie not loaded due to - ¬ " & the result alert errorMessage HALT end if -- set the correct time format for the video mci "set myMovie time format milliseconds" -- we need the length so we can rewind at the end set MediaLength = getMediaLength() -- put the object into the actorList (check -- out the "on stepFrame" handler add the actorList me -- pass a global reference to the object -- back to the movie return me end
Have a good look at the way the MCI commands are built to open the video and then position it on the screen. Notice that all MCI commands are strings. Later you may want to step through this using the Debugger.
Next here's the stepFrame handler that gets executed on every exitFrame, but is completely contained in the object.
on stepFrame me if playStatus = TRUE then baSleep (50) endOfMediaCallback end
The playStatus property is set when we press the Play or Stop buttons. Notice that the baSleep command is only executed if the playStatus is TRUE. After all, it is unnecessary if the video is not playing!
Here is the handler that checks to see if the movie has gotten to the end. We check the position by using the MCI "status" command. If we are at the end, we make sure that we pause the video and then use the searchToMediaPosition handler to go back to the start.
on endOfMediaCallback me mci "status myMovie position" if the result > (MediaLength - 1) then -- pause the video pauseMedia me -- rewind to the beginning SearchToMediaPosition me, 0 end if end
We've created play and pause handlers that we drop onto a button in the score. Each contains an MCI command and sets the current playStatus flag appropriately. When you create these handlers make sure that they are Score Scripts. Here is the pauseMedia handler:
on pauseMedia me set playStatus = FALSE mci "pause myMovie" end
The playMedia handler looks almost identical.
Last here is the code in the killObject handler which is executed by the stopMovie handler.
on killObject me deleteOne (the actorList, me ) mci "close myMovie" set me = VOID end
It is important when working with the actorList to make sure that you remove objects from it when you are done. You'll notice that we explicitly close the video and VOID out the object reference. This is all good programming practice. Also, if you try to open a new movie without explicitly closing the movie alias you already have open, you will get an MCI Error.
Summary
So there you have it. There are a few other handlers, but you can look through the code in the example movie for yourself. The example movie (PC format only), contains all you will need to get a start. You might think about adding other MCI commands that you find in the Macromedia Technote quoted above to the object. All of this could be rolled into a behavior that could be attached to a button on the stage. There are a lot of possibilities. Give them a try and have fun. MCI is a powerful tool that will open up your programming capabilities.Good luck,
Al Hospers
Additional On-line Resources
Here are some resources on the web that you should definitely check out:Glossary of MPEG terms
MPEG FAQ 4.1
MPEG.ORG
MPEG Home Page
MARICOPA Director Web
John F. McGowan's site - (yes this is mostly about AVI, but it is great)
I used to have a URL for the OpenMPEG Consortium's "MPEG Command Set for MCI" but it is no longer valid as is the Microsoft URL for the MCI spec. The most recent physical address for OpenMPEG is:
OpenMPEG Consortium
849 Independence Avenue, Suite B
Phone: (415) 903-8320
Mountain View, CA 94043
Fax: (415) 967-0995
Credits
Several people have been very helpful to me in figuring out how to deal with MCI and object programming in general. They include:Gary Smith
Cyril Bouaziz
Mauricio Piacentini
Paul Hamilton
John Dowdell
Mikhail Sherman
Thanks guys.
Copyright 1997-2024, Director Online. Article content copyright by respective authors.