Wine and Multimedia
This file contains information about the implementation of the
multimedia layer of Wine.
The implementation can be found in the
dlls/winmm/ directory (and in many of its
subdirectories), but also in dlls/msacm/
(for the audio compression/decompression manager) and
dlls/msvideo/ (for the video
compression/decompression manager).
Overview
The multimedia stuff is split into 3 layers. The low level (device
drivers), mid level (MCI commands) and high level abstraction layers.
The low level layer has also some helper DLLs (like the MSACM/MSACM32
and MSVIDEO/MSVFW32 pairs).
All of those components are defined as DLLs (one by one).
The low level layer may depend on current hardware and OS services
(like OSS on Unix). It provides the core of playback/record
using fine grain objects (audio/midi streams...).
Mid level (MCI) and high level layers must be written independently from
the hardware and OS services.
MCI level provides some coarser grain operations (like playing
a Midi file, or playing a video stream).
Multimedia architecture
Windows 95 multimedia architecture
|
Kernel space | Client applications
|
| | | ^ ^ | | | |
| 16>| |<32 16>| |<32 16>| |<32 16>| |<32
| | v | | | v | v
| +----|-----------|---------|------------|-------+
| | | | | | | WinMM.dll
| | | | | | | 32 bit
| +----|-----------|---------|------------|-------+
| | | | ^ | | |
| +------+ | |<16 | | | |<16 |
| | 16>| | | | | | | |
| | v v v | | v v v
| | +---------------+---+-------------+-------------+
| | | waveInXXX | | mciXXX | *playSound* |
| | | waveOutXXX | | | mmioXXX |
| | | midiInXXX | | | timeXXX |
| | | midiOutXXX | | | driverXXX |
| | | midiStreamXXX | | | | MMSystem.dll
| | | mixerXXX | | | | 16 bit
+--------+ | | | auxXXX +---+ +---+ mmThread| |
|MMDEVLDR|<------->| joyXXX | Call back | mmTask | |
+--------+ | | +-----------+-----------+---------+-------------+
^ | | | ^ ^ | ^
| | | 16>| |<16>| 16>| |<16
v | | v | | v |
+--------+ | | +-------------+ +----------+
| VxD |<------->| *.drv | | mci*.drv |
+--------+ | | +--------------+ +-----------+
| | | msacm.drv | | mciwave |
| | +--------------+ +-----------+
| | | midimap.drv | | mcimidi |
| | +-------------+ +-----------+
| | Low-level drivers | ... | MCI drivers
| | +----------+
| | |
| | |<16
| +-------------------------------+
|
The important points to notice are:
all drivers (and most of the core code) is 16 bit
all hardware (or most of it) dependent code reside in the kernel
space (which is not surprising)
Windows NT multimedia architecture
Note that Win 98 has mixed 95/NT architecture, so when
speaking about Windows 95 (resp. NT) architecture, it refers
to the type of architecture, not what's actually
implemented. For example, Windows 98 implements both types
of architectures.
The important points to notice (compared to the Windows 95
architecture) are:
drivers (low level, MCIs...) are 32 bit and Unicode
the interfaces between kernel and user drivers has
changed, but it doesn't impact much Wine. Those
changes allow some good things (like kernel mixing,
where different apps share the audio hardware) and of
course bad things (like kernel mixing, which adds
latency).
Wine multimedia architecture
|
Kernel space | Client applications
|
| | | ^ ^ | | | |
| 16>| |<32 16>| |<32 16>| |<32 16>| |<32
| | | | | | | | |
| +------+ | | | | | | | |
| |32/16>| | | | | | | | |
| | v v v | | v v v v
| | +---------------+---+-------------+-------------+
| | | waveInXXX | | mciXXX | *playSound* |
| | | waveOutXXX | | | mmioXXX | WinMM.dll
| | | midiInXXX | | | timeXXX | 32 bit
| | | midiOutXXX | | | driverXXX |
| | | midiStreamXXX | | | | MMSystem.dll
| | | mixerXXX | | | | 16 bit
| | | auxXXX +---+ +---+ mmThread| |
| | | joyXXX | Call back | mmTask | |
| | +-----------+-----------+---------+-------------+
| | || ^ ^ | ^
| | 16>||<32 |<16>| 16>| |<16
| | vv |<32>| 32>v |<32
+---------+ | | +-------------+ +----------+
|HW driver|<------->| *.drv | | mci*.drv |
+---------+ | | +--------------+ +-----------+
| | | msacm.drv | | mciwave |
| | +--------------+ +-----------+
| | | midimap.drv | | mcimidi |
| | +-------------+ +-----------+
| | Low-level drivers | ... | MCI drivers
| | +----------+
| | |
| | |<32/16
| +-------------------------------+
|
From the previous drawings, the most noticeable differences are:
low-level drivers can either be 16 or 32 bit (in fact,
Wine supports only native wave and audio mappers).
MCI drivers can either be 16 or 32 bit
all built-in drivers (low-level and MCI) will be written as 32 bit
drivers
Wine's WinMM automatically adapts the messages to be sent to
a driver so that it can convert it to 16 or 32 bit
interfaces.
Low level layers
The low level drivers abstract the hardware specific features
from the rest of the multimedia code. Those are implemented with a
well defined set of APIs, as windows do.
Please note that native low level drivers are not currently supported
in Wine, because they either access hardware components or require
VxDs to be loaded; Wine does not correctly supports those two so far.
There are two specific low level drivers (msacm.drv for wave input/output,
midimap.drv for MIDI output only). These drivers (also present
in Windows) allow:
choosing one low level driver between many (we'll
discuss how the choice is made later on)
add the possibility to convert stream's format (ie ADPCM =>
PCM) (this is useful if the format required by the
application for playback isn't supported by the soundcard).
add the possibility to filter a stream (adding echo, equalizer...
to a wave stream, or modify the instruments that have to be
played for a MIDI stream).
Hardware-bound low level drivers
Each low lever driver has to implement at least one of the
following functionality, through the named function:
Waveform audio: out for playback, and in for
recording. MMSYSTEM and WINMM call the real low level
audio driver using the driver's
wodMessage and
widMessage functions which handle
the different requests.
MIDI (Musical Instrument Digital Interface): out for
playback, and in for recording. MMSYSTEM and WINMM
call the low level driver functions using the driver's
midMessage and the
modMessage functions.
Mixer: this allows setting the volume for each one of
the other functionnality (and also some specific
attributes, like left/right balance for stereo
streams...). MMSYSTEM and WINMM call the low level
driver functions using the
mxdMessage function.
Aux: this is the predecessor of the mixer
functionnality (introduced in Win 95). Its usage has
been deprecated in favor of mixer interfaces.
Wine currently supports the following (kernel) multimedia
interfaces.
Open Sound System (OSS) as supplied in the Linux and
FreeBSD kernels by 4Front
Technologies. The presence of this driver is
checked by configure (depends on the
<sys/soundcard.h> file). Source code resides in
dlls/winmm/wineoss.
Advanced Linux Sound Architecture (ALSA) as
supplied in the Linux kernel. Source code resides in
dlls/winmm/winealsa.
Analog RealTime Synthetizer (aRts): a
network server (and virtual mixer) used in the KDE project.
Network Audio Server (NAS): an
audio server.
Jack: a
low latency audio server.
AudioIO: the native Solaris audio interface.
The supported functionnalities per driver is as follows
(this table lists the available features of the products,
not exactly what's actually implemented on Wine):
Wine multimedia drivers' functionalities
Driver
Wave Out
Wave In
Midi Out
Midi In
Mixer (and Aux)
OSS
Yes
Yes
Yes
Yes
Yes
ALSA
Yes
Yes
Yes
Yes
Yes
aRts
Yes
Yes
No
No
Yes
NAS
Yes
Yes
No
No
Yes
AudioIO
Yes
Yes
No
No
Yes
Jack
Yes
Yes
No
No
Yes
Lots of listed drivers won't support Midi (in a short time)
because the exposed "Un*x" native interfaces don't. This
would require using some kind as software synthesis (as
Timidity), but we cannot incorporate as it's GPL'ed.
Wave mapper (msacm.drv)
The Wave mapper device allows to load on-demand audio codecs
in order to perform software conversion for the types the
actual low level driver (hardware). Those codecs are
provided through the standard ACM drivers in MSACM32.DLL.
Wave mapper driver implementation can be found in
dlls/winmm/wavemap/ directory. This
driver heavily relies on MSACM and MSACM32 DLLs which can be
found in dlls/msacm and
dlls/msacm32. Those DLLs load ACM
drivers which provide the conversion to PCM format (which is
normally supported by low level drivers). A Law, uLaw,
ADPCM, MP3... fit into the category of non PCM formats.
MIDI mapper (midimap.drv)
Midi mapper allows to map each one of 16 MIDI channels to a
specific instrument on an installed sound card. This allows
for example to support different MIDI instrument definitions
(XM, GM...). It also permits to output on a per channel
basis to different MIDI renderers.
A built-in MIDI mapper can be found in
dlls/winmm/midimap/. It partly provides
the same functionality as the Windows' one. It allows to
pick up destination channels: you can map a given channel to
a specific playback device channel (see the configuration
bits for more details).
Mid level drivers (MCI)
The mid level drivers are represented by some common API
functions, mostly mciSendCommand and
mciSendString. Wine implements several
MCI mid level drivers.
Wine MCI drivers
MCI Name
DLL Name
Role
Location
Comments
CdAudio
MciCDA.drv
MCI interface to a CD audio player
dlls/winmm/mcicda/
Relies on NTDLL CdRom raw interface (through
DeviceIoControl).
WaveAudio
MciWave.drv
MCI interface for wave playback and record
dlls/winmm/mciwave/
It uses the low level audio API.
Sequencer
MciSeq.drv
Midi Sequencer (playback)
dlls/winmm/mciseq/
It uses the low level midi APIs
AviVideo
MciAvi.drv
AVI playback and record
dlls/winmm/mciavi/
It rather heavily relies on MSVIDEO/MSVFW32 DLLs
pair to work.
The MCI Name column is the name of the MCI driver, as it is
searched in configuration. The DLL Name column is the name of
the DLL the configuration provides as a value. The name listed
here is the default one (see the configuration section for the
details).
Adding a new MCI driver is just a matter of writing the
corresponding DLL with the correct interface (see existing MCI
drivers for the details), and to provide the relevant setup
information for wine.inf
High level layers
WINMM (and MMSYSTEM)
The high level layers encompass basically the MMSYSTEM and
WINMM DLLs exported APIs. It also provides the skeleton for
the core functionality for multimedia playback and
recording. Note that native MMSYSTEM and WINMM do not
currently work under Wine and there is no plan to support
them (it would require to also fully support VxD, which is
not done yet).
WINMM and MMSYSTEM in Wine can handle both 16 bit and 32 bit
drivers (for low level and MCI drivers). It will handle all
the conversions transparently for the all the calls to WINMM
and MMSYSTEM, as it knows what the driver interface is (16
bit or 32 bit) and it manages the information sent
accordingly.
MCI drivers are seen as regular Wine modules, and can be
loaded (with a correct load order between builtin, native),
as any other DLL. Please note, that MCI drivers module names
must bear the .drv extension to be
correctly understood.
Multimedia timers are implemented with a dedicated thread,
run in the context of the calling process, which should
correctly mimic Windows behavior. The only drawback is that
the thread will appear the calling process if it enumerates
the running processes.
DSOUND
Wine also provide a DSound (DirectX) DLL with the proper
COM implementation.
Note that a Wine specific flag has been added to the
wodOpen function, so that the DSound
DLL can get a reference to a COM sound object from a given
WINMM wave output device. This should be changed in the
future.
MS ACM Dlls
Contents
The MSACM32 (and its 16 bit sibbling MSACM) provide a way to
map a given wave format to another format. It also provides
filtering capabilities. Those DLLs only implement the proper
switch between a caller and a driver providing the
implementation of the requested format change or filter
operation.
There's nothing specific in Wine's implementation compared
to Windows' one. Here's however a list of the builtin format
change drivers (there's no filter driver yet):
Wine ACM drivers
Name
Provides
imaadp32
IMA ADPCM (adaptative PCM)
msadp32
Microsoft's ADPCM (adaptative PCM)
msg711
Microsoft's G.711 (A-Law and µ-Law)
winemp3
Wine's MP3 (MPEG Layer 3), based on mpglib library
Note that Wine also supports native audio codecs as
well.
All builtin ACM drivers are 32 bit Unicode DLLs
Caching
The MSACM/MSACM32 keeps some data cached for all known ACM
drivers. Under the key
Software\Microsoft\AudioCompressionManager\DriverCache\<driver name>
, are kept for values:
aFormatTagCache which
contains an array of DWORD. There
are two DWORDs per cFormatTags
entry. The first DWORD contains a
format tag value, and the second the associated
maximum size for a WAVEFORMATEX structure.
(Fields dwFormatTag and cbFormatSize from
ACMFORMATDETAILS)
cFilterTags contains the number of tags supported by the driver
for filtering.
cFormatTags contains the number of tags support
by the driver for conversions.
fdwSupport (the same as the one returned from
acmDriverDetails).
The cFilterTags,
cFormatTags,
fdwSupport are the same values as the
ones returned from acmDriverDetails
function.
MS Video Dlls
Contents
The MSVFW32 (and its 16 bit sibbling MSVIDEO) provide
encode/decode video streams. Those DLLs only implement the
proper switch between a caller and a driver providing the
implementation of the requested format coding/decoding
operation.
There's nothing specific in Wine's implementation compared
to Windows' one. Here's however a list of the builtin
decoding drivers:
Wine VIDC drivers
Name
Provides
msrle32
Microsoft's RLE (Run-Length encoded)
msvidc32
Microsoft's Video-1
iccvid
Radius Cinepak Video Decoder
Note that Wine also supports native video codecs as well.
All builtin VIDC drivers are 32 bit Unicode DLLs
Multimedia configuration
Unfortunately, multimedia configuration evolved over time:
In the early days on Windows 3.x, configuration was
stored in system.in file, under
various sections ([drivers] for low
level drivers, [mci]
(resp. [mci32]) for 16 bit (resp. 32
bit) MCI drivers...).
With the apparition of the registry, in Windows 95,
configuration as been duplicated there, under the key
HKLM\System\CurrentControlSet\Control\MediaResources
Windows NT also adopted the registry, but decided to
store the configuration information under another key
than Windows 9x did.
HKLM\Software\Microsoft\Windows NT\CurrentVersion
And with a different layout of keys and values beneath
this key.
Currently, Wine tries to load first a driver (low-level or
MCI) from the NT registry settings. If it fails, it will try
the system.ini configuration.
An out-of-the-box configuration is provided in
wine.inf, and shall be stored in registry
and system.ini at Wine installation
time. It will setup correctly the MCI drivers' configuration
(as well as the wave and MIDI mappers). As the low-level
drivers depend on hardware, their setup will be handled by
winecfg.
Wine multimedia configuration scheme
Driver
Read from NT registry
Read from system.ini
Setup by wine.inf
Setup by winecfg
MCI drivers
Yes (1)
Yes (2)
Yes
No
Wave and MIDI mappers
Yes
No
Yes
No
Hardware-bound low level drivers
Yes
No
No
Yes
ACM and VIDC drivers (audio & video codecs)
No
Yes
Yes
No
This will allow most settings to be correctly loaded and
handled. However, it won't if an app tries to search directly
the registry for the actual configuration, as the three
potential configuration places may not be in sync.
It still lacks a correct installation scheme (as any
multimedia device under Windows), so that all the correct
keys are created in the registry. This requires an advanced
model since, for example, the number of wave out devices can
only be known on the destination system (depends on the
sound card driven by the OSS interface).
The following sections describe which type of information
(depending on the location) Wine's multimedia DLLs understand.
NT configuration
Under the
HKLM\Software\Microsoft\Windows NT\CurrentVersion
key, are stored the names of the DLLs to be loaded for each
MCI driver name:
"cdaudio"="mcicda.drv"
"sequencer"="mciseq.drv"
"waveaudio"="mciwave.drv"
"avivideo"="mciavi.drv"
"videodisc"="mcipionr.drv"
"vcr"="mcivisca.drv"
"MPEGVideo"="mciqtz.drv"
system.ini
Wine will read the MCI drivers from the
[mci] or [mci32]
section. Wine won't make any difference between the two.
Here's a sample configuration:
[mci]
cdaudio=mcicda.drv
sequencer=mciseq.drv
waveaudio=mciwave.drv
avivideo=mciavi.drv
videodisc=mcipionr.drv
vcr=mcivisca.drv
MPEGVideo=mciqtz.drv
ACM drivers' configuration is read (only so far) from the
system.ini (and setup at Wine
installation from the wine.inf file).
[drivers32]
MSACM.imaadpcm=imaadp32.acm
MSACM.msadpcm=msadp32.acm
MSACM.msg711=msg711.acm
MSACM.winemp3=winemp3.acm
Video (aka vidc) drivers' configuration is read (only so
far) from the system.ini (and setup at
Wine installation from the wine.inf
file).
[drivers32]
VIDC.MRLE=msrle32.dll
VIDC.MSVC=msvidc32.dll
VIDC.CVID=iccvid.dll
See also the configuration part of the User's Guide for
other information on low level drivers.
Per driver/DLL configuration
Midi mapper
The Midi mapper configuration is the same as on Windows
9x. Under the key:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Multimedia\MIDIMap
if the UseScheme value is not set, or
is set to a null value, the MIDI mapper will always use
the driver identified by the
CurrentInstrument value. Note: Wine
(for simplicity while installing) allows to define
CurrentInstrument as
#n (where n is a number), whereas
Windows only allows the real device name here. If
UseScheme is set to a non null value,
CurrentScheme defines the name of the
scheme to map the different channels. All the schemes are
available with keys like
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\MediaProperties\PrivateProperties\Midi\Schemes\%name_of_scheme%
For every scheme, under this key, will be a sub-key (which
name is usually a two digit index, starting at 00). Its
default value is the name of the output driver, and the
value Channels lists all channels (of
the 16 standard MIDI ones) which have to be copied to this
driver.
To provide enhanced configuration and mapping
capabilities, each driver can define under the key
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\MediaProperties\PrivateProperties\Midi\Ports\%driver_name%
a link to and .IDF file which allows
to remap channels internally (for example 9 -> 16), to
change instruments identification, event controllers
values. See the source file
dlls/winmm/midimap/midimap.c for the
details (this isn't implemented yet).