OS/2 Multimedia Chapter – Multimedia Input/Output
by Maria Ingold
X.8 MULTIMEDIA INPUT/OUTPUT
Programmers of multimedia applications want to view images, hear audio, or watch movies without being concerned about how the data bytes are laid out in the file, or what storage media is holding these data bytes. The Multimedia Input/Output (MMIO) file services isolate applications, media control drivers, and stream handlers from these file format and storage system details. This means that as far as the application is concerned, access to files stored in memory, on CD-ROM, hard drive, diskette, or across a network, can all be accessed and manipulated transparently. The Multimedia I/O provides an application with a consistent set of interfaces for different file formats, storage systems and compression types. As shown in Figure X.8, the MMIO manager provides format independence by using installable I/O procedures (IOProcs) and CODEC procedures.
Figure X.8 MMIO Subsystem Architecture
IOProcs and CODEC procedures can be used to extend the capabilities of the Multimedia I/O subsystem. A simple example of this is when a new image format comes into use, a new IOProc for that format can be installed, and the Multimedia I/O will automatically take advantage of it. An IOProc is a Ring 3 DLL that performs operations on a specific data object or file type. Each IOProc is uniquely identified by a four-character code (FOURCC). IOProcs are divided into two types: storage system IOProcs and file format IOProcs.
X.8.1 Storage System IOProcs
A storage system IOProc operates on the storage mechanism used to contain the data rather than the data content itself. This type of IOProc “unwraps” data objects such as Resource Interchange File Format (RIFF) files, or RIFF compound files (CF). The storage system IOProc does not know what type of data is contained inside the wrapper. For example, the file may be contained in a DOS wrapper. The file format IOProc would call the storage system IOProc which would use DosOpen, DosRead, DosWrite and DosClose to unwrap the data. Inside it might contain wave or image file data which the file format IOProc would then process. Storage system IOProcs include the internal IOProcs provided for DOS files, memory (MEM) files, and RIFF compound files.
X.8.1.1 Resource Interchange File Format
RIFF is the standard format used for storing multimedia files. RIFF allows audio, image, animation, video, and other multimedia elements to be stored in a common format. This ensures portability of the file. RIFF files are composed of chunks. A RIFF chunk is a block of data identified by a FOURCC chunk id, or tag. The tag indicates the type of data that is contained in the chunk. For example, in a RIFF AVI file, the ‘movi’ tag says that the following data chunk contains audio and video tracks . The advantage of tagged file formats is that they allow an application to process only the blocks of data it is interested in. Additionally, by adding new tags, RIFF files can be easily extended without breaking existing applications.
A FOURCC tag can be created by using the mmioFOURCC function to convert four alphanumeric characters into the code. If less than four characters are specified, mmioFOURCC pads the end with blanks. A null terminated sting can also be converted into a FOURCC by using mmioStringToFOURCC.
RIFF chunks can be created, located, entered, and exited. A RIFF chunk is created by specifying mmioCreateChunk. This creates a new chunk at the current position in the open file. To process chunk data, the chunk is entered, or descended into, using the mmioDescend function. The mmioDescend function can also locate chunks. Before another chunk can be processed, the current chunk must be exited, or ascended out of, by using mmioAscend. RIFF files can be opened, read from, and written to the same way as other file types using the MMIO APIs.
X.8.1.1.1 Compound Files
A RIFF compound file, or a bundle file (BND), can hold one or many file elements. A file element can be an entire RIFF file, a non RIFF file, an arbitrary RIFF chunk, or arbitrary binary data. A RIFF compound file contains a resource group (CGRP) chunk, and a table of contents (CTOC) chunk. The CGRP chunk contains all of the compound file elements concatenated together into one contiguous block of data. The CTOC chunk provides the location, name, and other information about the individual compound file elements contained in the CGRP.
There are two IOProcs that operate on compound files: the compound file IOProc and the bundle IOProc. The compound file IOProc is a storage system IOProc. It operates on the entire compound file rather than on the elements in the file. This IOProc is limited to operations required by the system to ensure storage system transparency at the application level. The bundle IOProc is a file format IOProc. It performs operations on the file elements themselves. There are a special set of MMIO functions that are used to manipulate compound files. See Table X.10 for a complete list of all the compound file functions.
MMIO Compound File Function | Description |
mmioCFOpen | Opens a RIFF compound file by name |
mmioCFClose | Closes an open RIFF compound file |
mmioCFGetInfo | Retrieves CTOC header of an open RIFF compound file |
mmioCFSetInfo | Modifies information stored in CTOC |
mmioCFAddEntry | Adds entry to CTOC of open RIFF compound file |
mmioCFChangeEntry | Changes a CTOC entry in an open RIFF compound file |
mmioCFFindEntry | Finds a CTOC entry in an open RIFF compound file |
mmioCFDeleteEntry | Deletes a CTOC entry from an open RIFF compound file |
mmioCFAddElement | Adds element to CGRP of an open RIFF compound file |
mmioCFCopy | Copies CTOC and CGRP to another RIFF compound file |
mmioCFCompact | Removes elements marked as deleted |
mmioFindElement | Enumerates entries of a compound file |
mmioRemoveElement | Removes specified element from a compound file |
Table X.10 MMIO Compound File Functions
X.8.2 File Format IOProcs
File format IOProcs manipulate different multimedia element types such as audio, image, or MIDI. Each file format IOProc handles the specific element type for which it was written. For example, there are separate IOProcs to handle AVI video, AutoDesk animation, OS/2 2.0 bitmaps, and RIFF Waveform digital audio. For a complete list of the file formats provided with OS/2 multimedia see Table X.11.
File Format IOProc | FOURCC |
AIFF Wave Digital Audio | AIFF |
Amiga IFF Format | IFF |
Creative Labs Inc. Voice Audio | VOC |
IBM Audio Visual Connection (AVC) ADPCM Digital Audio | AVCA |
RIFF Waveform Digital Audio | WAVE |
Unix (NeXT/SUN) SND Format | SND |
Musical Instrument Digital Interface (MIDI) | MIDI, RMID |
GIF (Graphics Interchange Format) Image Compressed | GIFC |
IBM Audio Visual Connection (AVC) Still Video Image | AVCI |
IBM M-Motion Still Video Image | MMOT |
IBM OS/2 1.3 Bitmap | OS13 |
IBM OS/2 2.0 Bitmap | OS20 |
Kodak PhotoCD | PCD |
MS Windows Device Independent Bitmap (DIB) | W130 |
PCX (PC Paintbrush) Image Compressed | PCXC |
RIFF Device Independent Bitmap (RDIB) | RDIB |
Targa Image Compressed | TGAC |
Targa Image Uncompressed | TGAU |
TIFF (Tagged Interchange File Format) FAX Compressed | TFFC |
TIFF Intel Compressed | TFIC |
TIFF Intel Uncompressed | TFIU |
TIFF Motorola Compressed | TFMC |
TIFF Motorola Uncompressed | TFMU |
Autodesk Animation (FLI/FLC) | FLIC |
Audio Video Interleaved (AVI) Video | AVI |
Motion Pictures Expert Group (MPEG) | MPEG |
Table X.11 OS/2 Multimedia Provided File Format IOProcs
Additional IOProcs can be installed into the system and immediately taken advantage of by existing applications. An IOProc can be installed temporarily, semipermanently, or permanently. An IOProc DLL is temporarily installed by loading the DLL using the DosLoadModule and DosQueryProcAddr functions, and then calling mmioOpen to open a file and associate it with that IOProc. To install an IOProc semipermanently requires changing the IOProc table managed by the MMIO manager for the current application. The mmioInstallIOProc function maintains and modifies this table. This table exists separately for each application that uses MMIO. This means that IOProcs that are added or changed in one application can not be used by other applications. The IOProc is available until the application process terminates, or the IOProc is removed from the table. An IOProc can be permanently installed and used by all applications by storing information about the IOProc in the OS/2 multimedia MMIO initialization file (MMPMMMIO.INI). The mmioIniFileHandler function is used to do this installation.
X.8.3 CODEC Procedures
MMIO also provides the ability to compress and decompress data through the use of compression/decompression (CODEC) procedures. Like I/O procedures, CODEC procedures are DLL routines that operate on data within a file or buffer. CODECs are typically loaded by a file format IOProc to compress or decompress the data. OS/2 multimedia provides a set of set of CODECs for the compression of audio and video data. See Table X.12 for details. Additional CODEC procedures can only be permanently installed into the initialization file using the mmioIniFileCODEC function. An existing CODEC can also be replaced provided that the name of the entry point and the FOURCC are the same as the original.
CODEC | FOURCC |
Ultimotion Video Decompressor | ULTI |
Indeo Video 2.1 Compressor/Decompressor | rt21/RT21 |
Indeo 3.1/3.2 Decompressor | iv31/IV31/iv32/IV32 |
Ultimotion Video Real-time Compressor | ULTI |
Ultimotion Video Frame-step Compressor | ULTI |
Intel Video 3.1 Real-time Compressor | IV31 |
Intel Video 3.1 Frame-step Compressor | IV31 |
MONDO Uncompressed Video Playback | DIB |
Autodesk Animation (FLI/FLC) Playback | flic |
Motion Picture Expert Group (MPEG) Hardware Interface | MPEG |
MS ADPCM Audio Compressor/Decompressor | N/A |
IMA ADPCM Audio Compressor/Decompressor | N/A |
Table X.12 OS/2 Multimedia Provided CODECs
X.8.4 The AVI File Format
The Ultimotion and Indeo CODECs store their data in the standard Audio Video Interleaved (AVI) Resource Interchange File Format (RIFF). See Figure X.9. The AVI RIFF format is identified by the FOURCC (four character code) ‘AVI ‘. Note that in the case of the ‘AVI ‘ FOURCC, the last character is padded with a blank. This format includes a header, ‘hdrl’, which lists details about the movie. The main AVI header, ‘avih’, contains the movie size and the number of audio and video tracks, or streams. The stream header, ‘strl’, specifies whether the track contains audio, ‘auds’, or video, ‘vids’. It also contains the FOURCC of the decompression algorithm. For example, ‘ULTI’ represents the decompressor for Ultimotion. The stream format, ‘strf’, contains the bitmap and audio structures for each track. The optional decompressor header data, ‘strd’, contains the configuration information specific to that decompressor. Following the AVI header, in ‘movi’, are the audio and video tracks. The optional index, ‘idx1’, lists the location of the track data within the file. This is useful for random access of the data.
RIFF ('AVI' LIST ('hdrl'; 'avih'(<Main AVI Header>) LIST ('strl' 'strl'(<Stream header>) 'strf'(<Stream format>) 'strd'(additional header data) . . . ) . . . ) LIST ('movi' {SubChunk | LIST ('rec' SubChunk1 SubChunk2 . . . ) . . . } . . . ) ['idx1'<AVIIndex>] )
Figure X.9 The AVI RIFF file format
X.8.5 Translating File Formats
Each media type has a specific standard format. The media types that are currently supported include PCM digital audio, MIDI, image, digital video, and multitrack audio and video movies. The standard format provides a superset of all of the information that can be expected for that particular media type. Each specific format then stores and uses its subset of that information.
MMIO allows an IOProc to access files in both their untranslated native format, or in a translated standard format. When a file is untranslated, all of the file manipulations are done in its native format. In a translated file, all of the descriptive and data information stored in the original file is presented in a standardized format. The file manipulations then use this standard format.
If two IOProcs of the same media type store their data in the standard format, file conversion between the two files is very easy. The file is simply loaded in one format and saved into the other. For example, to convert a PhotoCD image into a device independent bitmap, the PhotoCD image is loaded and translated into the standard image format by the PhotoCD IOProc, and then written to the device independent bitmap IOProc with translation enabled.
X.8.6 Unbuffered and Buffered I/O
Applications or Media Control Drivers can use unbuffered I/O or buffered I/O to handle I/O operations. The mmioOpen call is used to open a file for either buffered or unbuffered I/O. Unbuffered I/O is best in the case of data streaming since the Synchronization Streaming Manager provides its own internal buffers to process the data. When an application accesses a media device, it may need to perform numerous I/O operations. If the amount of data transferred in I/O operations is small (less than 4 KB in size) it is best to use buffered I/O. With buffered file I/O, the file system maintains a buffer cache that stores data as it is read from or written to a secondary storage device. Since the data is already in the buffer, the file system can transfer the buffer to the application without having to read the data sector again from the device. Lowering the number of secondary storage device accesses improves the performance of the application.
The buffer used for buffered I/O can be supplied by the MMIO manager or provided by the application. If the MMIO supplied buffer is used, then reading, writing, and seeking of the data is performed the same way as for unbuffered I/O. This is accomplished by respectively using the mmioRead, mmioWrite, and mmioSeek function calls. When writing is done using buffered I/O, the mmioFlush function should be called to make sure that the contents of the buffer are written to disk. The mmioClose call performs this flush automatically when it closes a file.
If an application is performance sensitive it may chose to supply and directly access its own buffer. The application can specify its buffer on an mmioOpen call or use mmioSetBuffer function. Applications use mmioGetInfo to access the buffer. All read and write operations are done through the mmioAdvance call. No other MMIO function calls can be made until the mmioSetInfo function is called indicating that direct access of the file buffer has ended.
X.8.7 MMIO Functions
See Table X.13 for a list of all the MMIO function calls. (This list excludes the RIFF compound file functions listed in Table X.10.)
MMIO Functions | Description |
mmioOpen | Opens or creates file for reading, writing, or both |
mmioRead | Reads specified number of bytes from open file |
mmioWrite | Writes specified number of bytes to open file |
mmioSeek | Changes current position for reading, writing, or both |
mmioClose | Closes an open file |
mmioFlush | Writes or empties the I/O buffer out to disk |
mmioSetBuffer | Enables or disables buffered I/O |
mmioGetInfo | Retrieves information and allows direct access to I/O buffer |
mmioAdvance | Fills and empties the contents of a direct access I/O buffer |
mmioSetInfo | Changes information on the file I/O buffer |
mmioInstallIOProc | Installs, removes, or finds an IOProc in MMIO IOProc table |
mmioIniFileHandler | Adds, replaces, removes, or finds entry in ini file |
mmioSendMessage | Sends a message to IOProc associated with the open file |
mmioIniFileCODEC | Adds, replaces, removes, or finds CODEC entry in ini file |
mmioQueryCODECName | Returns associated CODEC proc name |
mmioQueryCODECNameLength | Returns associated CODEC proc name length |
mmioLoadCODECProc | Loads the installed CODEC proc |
mmioSet | Sets or queries extended file information and CODEC proc |
mmioFOURCC | Converts four characters to a four character code |
mmioStringToFOURCC | Converts a null terminated string to a four character code |
mmioCreateChunk | Creates a chunk in an open RIFF file |
mmioAscend | Moves the file position to the end of the chunk |
mmioDescend | Descends into a chunk of an open RIFF file |
mmioGetHeader | Returns header of the media structure of the open file |
mmioSetHeader | Sets attributes of the media in an open file |
mmioQueryHeaderLength | Determines the size of header for the open file |
mmioGetFormats | Lists the formats supported by the currently installed IOProc |
mmioGetFormatName | Returns the format name associated with the IOProc |
mmioQueryFormatCount | Provides the number of IOProcs that match the format data |
mmioIdentifyFile | Determines the file format and its associated loaded IOProc |
mmioIdentifyStorageSystem | Determines storage system and IOProc associated with file |
mmioDetermineSSIOProc | Determines storage system and FOURCC of media object |
mmioQueryIOProcModuleHandle | Provides module handle of an IOProc |
mmioGetLastError | Returns the last error condition |
Table X.13 MMIO Functions