Letzte Änderung: 2.11.97 von B. Tritsch
Zurück zum Index "PC- und MS-Windows-Support"
Multimedia spielt auf dem PC unter Windows eine immer größere Rolle. Daher sollen auch zu diesem Thema einige Überlegungen angestellt werden. Für eine multimediale Präsentation und Interaktion müssen z.B. folgende Ausgabegeräte unterstützt werden:
Für eine leistungsfähige Verarbeitung multimedialer Objekte wird man auf Dauer Multimedia Sub Units ähnlich den Floating Point Units benötigen, speziell für:
Im Hinblick auf die großen anfallenden Datenmengen von MM-Anwendungen bieten sich folgende Speichermedien an:
Bei sehr großen Datenmengen müssen MM-Datenbanken verwendet werden. Weiterhin fällt Kompressions/Dekompressions-Algorithmen (JPEG, MPEG, etc.) eine immer größere Bedeutung zu.
Eine erster Einstieg ist mit der Microsoft-Tandy-Initiative MPC (Multimedia PC) zu erreichen, die auf den MS-Windows-Standard aufbaut. Hierbei werden folgende zusätzlichen Komponenten unterstützt:
Einige wichtige Aspekte im Bezug auf Multimedia wurden von der MPC-Initiative jedoch etwas vernachlässigt:
Das Windows Multimedia Development Kit (MDK) erweitert Windows um etwa 150 MM-Funktionen. Diese umfassen folgende Spezifikationen:
Hierfür wird eine spezielle MMSYSTEM-Library mit dem MDK ausgeliefert. Das MDK ist inzwischen in jeder Standard-Entwicklungsumgebung für Windows enthalten.
Ein kleines Beispiel zeigt die Leistungsfähigkeit der MCI-Schnittstelle. Ein Fenster zur Ausgabe eines Videos kann mit einem einzigen High Level MCI-Aufruf erzeugt werden (MCIWndCreate). Die restlichen flankierenden Funktionen sind Standard oder zum Setzen der korrekten Videofenstergröße nötig. Letzteres wird über die Reaktion auf die Nachrichten MCIWNDM_NOTIFYPOS und MCIWNDM_NOTIFYSIZE bewerkstelligt.
#include <windows.h>
#include <vfw.h>
void SetClientRect(HWND hwnd, HWND hwndMCI)
{
RECT rect;
GetWindowRect(hwndMCI, &rect);
AdjustWindowRectEx(&rect, GetWindowLong(hwnd, GWL_STYLE),
FALSE, GetWindowLong(hwnd, GWL_EXSTYLE));
MoveWindow(hwnd, rect.left, rect.top, rect.right - rect.left,
rect.bottom - rect.top, TRUE);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case MCIWNDM_NOTIFYPOS:
case MCIWNDM_NOTIFYSIZE:
SetClientRect(hwnd, (HWND)wParam);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
HWND hwnd;
WNDCLASS wndClass;
if (hPrevInstance == NULL)
{
memset(&wndClass, 0, sizeof(wndClass));
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;
wndClass.hInstance = hInstance;
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndClass.lpszClassName = "HELLO";
if (!RegisterClass(&wndClass)) return FALSE;
}
hwnd = CreateWindow("HELLO", "HELLO",
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
NULL, NULL, hInstance, NULL);
SetClientRect(hwnd, MCIWndCreate(hwnd, hInstance, WS_VISIBLE |
WS_CHILD | MCIWNDF_SHOWALL |
MCIWNDF_NOTIFYSIZE |
MCIWNDF_NOTIFYPOS, lpCmdLine));
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
DispatchMessage(&msg);
return msg.wParam;
}
Die Timer-Funktionen betreffen die Behandlung der Zeitmessung. Die Zeit-Impulse kommen alle 54,95 ms (= 18,2 mal pro Sek.) vom Intel 8259-Timer-Baustein, der in jedem PC steckt. Durch ihn und mit Hilfe des Windows-Kern-Programms USER.EXE (bzw. USER32.EXE) wird regelmäßig die Nachricht WM_TIMER erzeugt, die sich einfach mit dem SPY beobachten läßt. Die Timer-Funktionen können nun diese WM_TIMER-Nachrichten weiterverarbeiten.
Für Windows bedeutet der Begriff Timer eine Ressource. Es können maximal 16 Timer gleichzeitig auf dem System existieren (unter Windows 3.1). Mit Hilfe der Timer-Funktionen können zeitliche Aktivitäten auch zwischen einzelnen Programmen gesteuert werden.
Genau koordinierte und definiert zeitabhängige Abläufe einzelner Prozesse sind in Multitasking-Systeme eine nicht triviale Aufgabe. Die grundlegende Funktionalität eines Timers wird mit der SetTimer-Funktion initialisiert. Timer für den Multimediabereich müssen mit deutlich erhöhter Genauigkeit realisiert werden. Daher existieren spezielle Timer-Funktionen für zeitkritische Multimediazwecke unter MS-Windows.
Die hochauflösenden Timer ändern die Programmierung des Timer-Bausteins, der dann in der Lage ist Interrupts mit einer Frequenz von 1000 Hz zu erzeugen. Die Multimedia-Erweiterung erlaubt zudem die Definition von Callback-Funktionen, die bei jedem Timer-Interrupt aufgerufen werden. Man muß diese Funktionen dann kurz und effektiv programmieren, um eine Überlastung des Systems zu verhindern. Normalerweise bedeutet dies, nur Daten in Memory-Bereichen zu speichern. Einige weitere Funktionen können ohne Bedenken innerhalb des Callbacks verwendet werden:
Die Benutzung eines hochauflösenden Timers ist recht einfach. Bevor der Timer gestartet wird, muß der entsprechende Timer-Service mit der Funktion timeBeginPeriod initialisiert werden. Der Timer wird dann mit der timeSetEvent-Funktion gestartet und mit der timeKillEvent-Funktion gestoppt. Wenn es keine weitere Verwendung für hochauflösende Timer gibt, wird deren Benutzung mit timeEndPeriod beendet.
Der Einsatz der genannten Funktionen in einem fragmentarischen Quellcode wird im folgenden aufgezeigt:
static UINT nTimerRes = 1, nTimerID; timeBeginPeriod(nTimerRes); nTimerID = timeSetEvent(nTimerRes, nTimerRes TimeCallback, (DWORD)(LONG far *) &lpSomeData, TIME_PERIODIC); if(nTimerID == NULL) MessageBox(hWnd, "Could not start Timer", "Message", MB_OK);
void CALLBACK _export TimeCallback(UINT nTimerID, UINT wMsg,
DWORD dwUser, DWORD dw1, DWORD dw2)
{
Callback: Hier wird etwas getan
}
Der Parameter dwUser des Callbacks beinhaltet dabei den vierten Parameter der timeSetEvent-Funktion.
Ein Hook (Haken, Öse) stellt eine Art Engpaß zwischen MS-Windows und einer Applikation dar, durch den fast alle ausgetauschten Nachrichten geleitet werden. Daher lassen sich an dieser Stelle leicht sogenannte Filter installieren, die bestimmte Nachrichtentypen abfangen und an vom Benutzer bestimmte Stellen weiterleiten.
Die meisten Filtertypen arbeiten systemweit (d.h. alle Nachrichten werden gefiltert) und müssen aus diesem Grund für Windows zu jedem Zeitpunkt verfügbar sein. Daher sind Filter in Form einer DLL-Funktion zu implementieren.