The Multimedia Library is an application-level API used to control the playback and recording of audio-visual media on Palm OS® devices. It provides a standard means for applications to reference media content stored locally on the device, stored on a network, or accessible from some attached hardware device such as a microphone or camera. The Multimedia Library also provides a means for applications to query and configure codecs and devices.
Multiple concurrent playback and recording sessions may be configured, and the processing of playback or recording sessions may continue in the background as the user uses other applications. Multiple components may interact with a session simultaneously.
The Multimedia Library does not provide a means for developers to write file format handlers or codecs.
Overview
Using the Multimedia Library
Example Playback Session
Example Recording Session
Overview
This section provides an architectural overview of the Multimedia subsystem.
Figure 3.1 shows the portions of the system that bring multimedia to the device.
Figure 3.1 Multimedia architecture

- The multimedia client application is an application that a third-party developer may write; it runs in the Application process. The Media Player is an example of such an application.
- The Multimedia Library provides the public APIs that multimedia clients use to access multimedia features.
- The Movie Server runs in the System process and provides all multimedia functionality. It spawns sessions that usually run in the Background process. Applications can control sessions via Multimedia Library function calls.
- Device drivers enable the use of specific multimedia hardware components such as cameras, microphones, speakers, and so forth.
The multimedia subsystem consists of several different kinds of objects that are described in the following sections.
Sessions
A multimedia session represents a recording or playback request, and controls the data transport. To use the Multimedia Library for playback, for example, you create a session, tell it where to find the data to play back, and then tell the session to start playing. The session automatically sends the data to the appropriate media output device such as the screen and/or the audio mixer.
For more information about using sessions, see "Working with Sessions."
Sources
A source represents a source device. For a recording session, the source device might be a camera or a microphone. For a playback session, the source device might be a file or a network stream.
A source contains one or more streams of data from the source device. The stream defines the media format produced by the source device and is used to connect with the track. You connect each stream to a different track so that each stream's data goes to a different destination.
Destinations
A destination represents a destination device. For a recording session, the destination device might be a file or network stream. For a playback session, the destination might be the screen or the speakers.
Like sources, destinations contain one or more streams that specify the media format the destination expects, and they connect to a track.
Streams
A stream object represents multimedia data of a particular format. Each source and destination has at least one stream, which represents a single kind of data it produces or consumes. For example, a movie file source might have an audio stream and a video stream.
A stream object is created when you finalize a source or destination. You can enumerate the streams in sources and destinations by calling MMSourceEnumerateStreams()
and MMDestEnumerateStreams()
.
Tracks
A track represents a route for one type of media data from a source device to a destination device. For example, to play a movie would require two tracks: an audio track and a video track.
Tracks are responsible for encoding or decoding data as it is recorded or played.
Tracks sometimes use a track callback filter, which is usually supplied by the application. A multimedia application can set a track callback filter if it wants to handle the data itself. If so, the track ensures that data is passed from the source device to the track filter, which forwards it to the callback function and then passes it on to the destination.
To register a track callback filter, call MMTrackInsertCallbackFilter()
.
Codecs
In order to play from and capture to encoded media files, the Multimedia Library uses software components called codecs (an abbreviation for encoder/decoder.) A codec translates media data from one format to another. Each codec supports a particular encoding algorithm, such as MP3 or MS-ADPCM.
A stream uses a codec during playback. During recording, the stream uses an encoder before writing to the file stream.
Applications can enumerate the available codecs with MMCodecClassEnumerate()
, and can enumerate the available file formats with MMFileFormatEnumerate()
. File formats are distinct from codecs because a file format may encapsulate many kinds of encoded data.
File formats are described by an MMFormatType
value. Codecs are represented by an MMCodecClassID
, and the MMPropertyGet()
function may be used to obtain more information about a given codec (such as name, creator, and source or destination format.) All codec properties are read-only.
PalmSource provides several built-in codecs:
- MS-ADPCM Audio Decoder
- DVI-ADPCM Audio Decoder
- MPEG Audio Layer I/II Decoder
- MPEG-1 Video Decoder
- MS-ADPCM Audio Encoder
- AVI Extractor
- MPEG Audio Extractor
- MPEG-1 Extractor
- WAV Extractor
- WAV Composer
Different codecs, such as MP3 and MPEG-4, might be available depending on the device manufacturer.
Formats
Formats are used to specify what multimedia formats an object can work with.
An object that can handle both audio and video data typically has two format objects: one specifying its audio constraints and one specifying its video constraints. Format objects themselves are made up of key/value pairs specifying one value for one attribute. For example, a raw audio format has keys for sample type, frame rate, channel count, and so on.
A format object is referenced by an MMFormat
. Formats may be retrieved as property values by MMPropertyGet()
or returned by MMFormatCreate()
, and in every case must be explicitly deleted by the application when it has finished using them. An MMFormat
has a type, MMFormatType
, which describes the basic kind of media such as P_FORMAT_RAW_AUDIO
, P_FORMAT_MPEG4_VIDEO
, etc. Every format type has an associated set of format keys, which are documented in MMFormatDefs.h
. See Chapter 6, "Multimedia Formats," for a list of the keys and values that formats use.
During format negotiation, two formats are inspected to see if they are compatible, and any wild values are replaced with actual values.
A format object stores a value for each format key. Values are typed by an MMTypeCode
, allowing formats to contain a wide range of data. Some common value types are P_MM_INT32_TYPE
, P_MM_BOOL_TYPE
, and P_MM_WILD_TYPE
. The last type simply means that any value is acceptable for the key; the library assigns that key an appropriate value when a session is finalized, and no data is stored.
Property Sets
Property sets expose configurable parameters, or properties, which control an object's behavior. For example, an audio-renderer supports the P_MM_TRACK_PROP_VOLUME
property to allow control of output volume.
A property consists of a key/value pair, where the key is a 32-bit constant identifier and the value is a typed chunk of data with a given size. Property values are generally either 32-bit integers or character strings, though some properties may have more complex values (such as those that represent dimensions, regions, or media formats).
All objects that support properties are identified by 32-bit ID values, which identify both the object instance and its type.
For more information on properties, see "Working with Properties."
Using the Multimedia Library
The Multimedia Library is a shared library that the system automatically loads when needed and unloads when not needed. You don't need to do anything to load or initialize the library.
This section covers these topics:
Working with Sessions
A session provides a context for an application's media playback or recording tasks. Before using the Multimedia Library to play or record, you must create a session by calling MMSessionCreate()
. In this function, you specify the session class, which indicates if the session is for playback or recording (capture).
A session is described in terms of sources, destinations, streams, and tracks. Sources and destinations represent the files, network streams, and devices used to get multimedia data into and out of the media-processing engine. Each source and destination has at least one stream, which represents a single kind of data it produces or consumes. For example, a movie file source might have an audio stream and a video stream.
A track represents a route for media data in the session. Tracks take data from a source stream, apply some processing (such as decoding and filtering), and send it to a destination stream.
To configure a session, your application must first add whichever sources and destinations it requires by calling MMSessionAddSource()
and MMSessionAddDest()
. Then finalize the sources and destinations by calling MMSourceFinalize()
and MMDestFinalize()
(if there are destinations). Then, enumerate the available streams by calling MMSourceEnumerateStreams()
and MMDestEnumerateStreams()
.
Finally, add tracks for the streams you wish to play back or capture. You can add tracks manually one at a time with MMSessionAddTrack()
, or automatically by using MMSessionAddDefaultTracks()
. When you have added all the desired tracks to the session, call MMSessionFinalize()
to prepare it for performance. After calling this function, no new sources, destinations, or tracks may be added.
To reconfigure a session after it has been finalized, you must first call MMSessionRemoveAll()
.
To start, stop, pause, or otherwise control the playback or capture process, call MMSessionControl()
. This call exposes the various transport operations such as run, pause, stop, prefetch, grab a still image, and refresh the display.
For playback sessions you can also call MMSessionSeek()
, which instructs the decoder to jump to a new position in the content stream. Note that seek functionality may not always be available, depending on the kind of content and on the location it's being streamed from.
You can determine the current state of the session by calling MMSessionGetState()
.
If you want your application to receive multimedia event notifications from a session, call MMSessionRegisterCallback()
to register a callback function. If you want your application to receive multimedia event notifications of a persistent session even when the application is no longer running, call MMSessionRegisterLaunch()
. Then, when session events occur, the application is sublaunched with the launch code sysAppLaunchCmdMultimediaEvent
.
Working with Properties
All objects that support properties are identified by 32-bit ID values, which identify both the object instance and its type. This allows a single set of property functions to operate on any kind of property-bearing object. There are four property functions:
-
MMPropertySet()
: sets a property value -
MMPropertyGet()
: returns a property value -
MMPropertyInfo()
: returns various information about a property, such as its minimum, maximum, and default values, whether it is readable and/or writable, and its type -
MMPropertyEnumerate()
: lists the potential values of a property
Not all of these operations are applicable to all properties, or to all entities that have associated properties; for example, MMPropertyEnumerate()
may return sysErrNotAllowed
if the specified MMPropInfoType
parameter does not apply. For example, some properties, such as P_MM_TRACK_PROP_VOLUME
, have continuous values with a well-defined minimum and maximum, but have such a wide range of possible values that it doesn't make sense for MMPropertyEnumerate()
to list them. These are referred to as "continuous-valued" properties. Other properties, such as P_MM_TRACK_PROP_CODEC_CLASS
, allow a discrete set of values for which the concepts of minimum and maximum do not apply, and are thus termed "discrete-valued" properties.
Here's an example of retrieving the current value of a property by calling MMPropertyGet()
and passing the key:
err = MMPropertyGet(session, P_MM_CONTENT_PROP_DURATION, P_MM_INT64_TYPE, &longduration, 0);
Here's an example of setting the value of a property by calling MMPropertySet()
and passing both the key and the value. The value must have the same type as the current value of the property:
err = MMPropertySet(session, P_MM_SESSION_PROP_PLAYBACK_RATE, P_MM_INT32_TYPE, &rate, 0);
Working with Enumerations
There are several cases in the Multimedia Library where a given component or object provides access to a set of values or references to objects. A common iterator-based enumeration scheme is used in each case. For example, here is the file format enumerator function:
status_t MMFileFormatEnumerate (int32_t *ioIterator, MMFormatType *outFormat)
The value pointed to by ioIterator
must be treated as opaque by the caller, with two exceptions:
- Before the first call to the enumeration function, the value of
ioIterator
must be set toP_MM_ENUM_BEGIN
. - When the set has been exhausted, the enumeration function will set the value of
ioIterator
toP_MM_ENUM_END
.
Other values are only guaranteed to be meaningful to the Multimedia Library. If an enumeration function is called with an invalid iterator, or an iterator value of P_MM_ENUM_END
, it returns sysErrBadIndex
.
An example of enumerating the tracks in a session is shown in Listing 3.1.
Listing 3.1 Enumerating tracks
status_t err; MMTrackID outTrack; int32_t ioIterator = P_MM_ENUM_BEGIN; while(true) { err = MMSessionEnumerateTracks(session, &ioIterator, &outTrack); if(err != errNone) break; // do something with each track returned in outTrack }
Working with the URL Scheme
Files on expansion cards or other VFS volumes can be accessed using URLs with the following syntax:
FileURL = "file://" ["localhost"] "/" [
VolumeLabel] "/" Path
where VolumeLabel can use any characters except for control codes (unprintable characters), "/", and "?"; and Path can use any characters except for control codes and "?".
You may use or omit the optional server name component of the URL ("localhost") when using the file scheme. When omitting it, you must still specify the following slash, so you would write the scheme like this: file:///
...
instead of this: file://locahost/
...
The volume label is case-sensitive. The case requirements of the rest of the URL follow the convention of the file system that this volume is mounted on.
If no volume label is specified, all volumes are searched for the given path.
file://localhost/MySDCardVolumeName/PALM/Launcher/Giraffe.prc
file:///OtherCardVolumeName/PALM/Launcher/Giraffe.prc
file:////PALM/Launcher/Giraffe.prc
URL name conflicts are resolved as follows: All volumes matching the specified name are searched and if multiple databases sharing the same pathname are found, the most recent is returned. If multiple selections share the same date, the file-selection behavior is nondeterministic (this only happens if no volume label is specified).
URLs are also used to access specific devices (such as a camera or a microphone) using URLs with the scheme palmdev://
. For example, the URL palmdev:///Media/Default/VideoOut
specifies any video playback device. For more examples of palmdev://
URLs, see "Default URLs."
Example Playback Session
This section describes how to use the Multimedia Library to play multimedia content.
The basic steps involved in playback are listed here and described in more detail later:
- "Creating the Session."
- "Adding Source Content."
- "Adding Tracks."
- "Finalizing the Session."
- "Playing the File."
Creating the Session
The first basic step is to create the multimedia session:
- Call the function
MMSessionCreate()
, passingP_MM_SESSION_CLASS_DEFAULT_PLAYBACK
as the session class (to create a playback session).This tells the Movie Server to create the session. It publishes the following keys and values in the session property set:
P_MM_SESSION_PROP_PLAYBACK_RATE
: 1P_MM_SESSION_DEFAULT_AUDIO_ENABLE
: trueP_MM_SESSION_DEFAULT_VIDEO_ENABLE
: trueP_MM_SESSION_DEFAULT_SOURCE_RECT
: null - Optionally, call
MMSessionRegisterCallback()
to register a callback function that will receive event notifications from the session. This step is not required, but is quite useful.
Adding Source Content
After creating the session, you need to add source content:
- Call
MMSessionAddSource()
, passing it the URL of the multimedia file to be opened. - Call
MMSourceFinalize()
, which prepares the media streams for use. One stream is created for each track in the content; for a movie, there is typically one track for audio and one track for video.
Adding Tracks
You now need to specify where the multimedia data should go. To do so, call MMSessionAddDefaultTracks()
, passing the session ID (returned by MMSessionCreate()
), the source ID (returned by MMSessionAddSource()
), and the constant P_MM_DEFAULT_DEST
.
Finalizing the Session
Now you need to finalize the session:
- Call
MMSessionFinalize()
. - You may want to call
MMSessionReleaseOwnership()
. This transfers ownership of the session back to the Movie Server now that your application has finished creating it.When the Movie Server owns the session, if the application exits, the session can continue playing in the background.
- For video playback, set a destination rectangle of the size required by the session so that it is ready to display the content. To do this, call
MMPropertySet()
to set aP_MM_TRACK_PROP_DEST_RECT
property for the track, like this:MMPropertySet(track, P_MM_TRACK_PROP_DEST_RECT, P_MM_RECT_TYPE, rect, 0);
The
rect
parameter is the destination rectangle for the video content.
Playing the File
Now that the file has been opened and the objects that are required to play the file have been created, the application can return control to the user. The user presses the Play button on the device, specifying that playback should begin. (The Play button can be a hardware button or a button displayed by the application in its user interface.)
Call MMSessionControl()
with the P_MM_SESSION_CTL_RUN
control code. This function forwards the control code to the Movie Server session. It sets its state to P_MM_SESSION_RUNNING
and sends an event to notify the application of its change in state.
You can call MMSessionControl()
with other control codes to perform other functions such as pause and stop. To seek forward or backward in the session, for example, to implement fast forward and rewind functions, call MMSessionSeek()
.
Video and audio playback occur in separate threads.
Example Recording Session
This section describes how to use the Multimedia Library to record audio content.
A recording session begins when the user presses the Record button in the application. The Record button can be a hardware button or a button displayed by the application in its user interface, or some other mechanism that you devise.
- First, the application must create a name for the file that will hold the recorded data.
- Then create the session by calling the function
MMSessionCreate()
, passingP_MM_SESSION_CLASS_DEFAULT_CAPTURE
as the session class (to create a recording session). - Call
MMSessionRegisterCallback()
to register a callback function that will receive event notifications from the session. - Add the source by calling
MMSessionAddSource()
, specifyingP_MM_DEFAULT_AUDIO_CAPTURE_URL
as the URL. This source represents the means by which the device receives audio input, such as a microphone or line-input jack. - Call
MMSourceFinalize()
. - Obtain the source stream ID by enumerating the source streams (there should be only one) by calling
MMSourceEnumerateStreams()
. - Add the destination by calling
MMSessionAddDest()
. - Set the
P_MM_DEST_PROP_FILE_FORMAT
property of the destination toP_FORMAT_WAV_STREAM
(or whatever audio format you want) by callingMMPropertySet()
, like this:int32_t streamFormat = P_FORMAT_WAV_STREAM; MMPropertySet(dest, P_MM_DEST_PROP_FILE_FORMAT, P_MM_INT32_TYPE, &streamFormat, 0);
- Finalize the destination by calling
MMDestFinalize()
. - Obtain the destination stream ID by enumerating the destination streams (there should be only one) by calling
MMDestEnumerateStreams()
. - Create a media format object and set its type to
P_FORMAT_MSADPCM_AUDIO
, like this:MMFormat encoding = 0; MMFormatCreate(&encoding); MMFormatSetType(encoding, P_FORMAT_MSADPCM_AUDIO);
- Add a track to provide a route from the audio source to the file destination by calling
MMSessionAddTrack()
, like this:err = MMSessionAddTrack(session, sourceStream, 0, destStream, encoding, &track);
The source stream ID is returned by
MMSourceEnumerateStreams()
in step 6. The destination stream ID is returned byMMDestEnumerateStreams()
in step 10. - Finalize the session by calling
MMSessionFinalize()
.Then the session's state is set to
P_MM_SESSION_READY
to signal that recording can begin. - To start recording, call
MMSessionControl()
with theP_MM_SESSION_CTL_RUN
control code.This function forwards the control code to the Movie Server session. It sets its state to
P_MM_SESSION_RUNNING
and sends an event to notify the application of its change in state.
You can call MMSessionControl()
with other control codes to perform other functions such as pause and stop. Pass the control code P_MM_SESSION_CTL_STOP
to stop recording (and write header data to the file so that it can be used immediately.)
The session is deleted after the application that created it exits, unless it has called MMSessionReleaseOwnership()
to allow the session to keep running in the background. If the application does call this function, then it should call MMSessionDelete()
or MMSessionAcquireOwnership()
to ensure that the session gets deleted.