ich möchte für ein Hauptmenü als Hintergrund eine Animation abspielen. Diese liegt als MPEG vor. Nun dachte ich daran, diese via SMPEG über SDL zu laden, abzuspielen und zu rendern. Leider gibt es ein großes Problem: Wie soll gleichzeitig das Video flüssig gerendert werden und die while-Schleife, die für Events zuständig ist, ihren Dienst tun ? Entweder ruckelt das Video oder es werden keine Ereignisse abgefragt. Falls dazu einer eine Idee hat, wäre es sinnvoller diese hier zu posten.
Aber es geht hier eigentlich um etwas ganz anderes, das mich auch allgemein sehr stark interessiert. Welche Nachteile hat man im Fenstermodus in OpenGL in Vista gegenüber XP ? Welche Funktionen fehlen, was muss man beachten ? Ich bin nämlich schwer am überlegen, SDL+OpenGL statt SDL alleine zu nutzen. Das würde das ein oder andere Problem lösen, aber würden daraus auch neue Probleme unter Vista entstehen ? Ein Programm von mir funktioniert zum Beispiel unter Vista nicht. Es lädt eigentlich nur Texturen in einen Partikelmanager (glaube sogar der aus dem Tutorial) - schwarzer Bildschirm. Ich habe Vista nur auf dem Notebook installiert, mir ist es von daher fast egal, aber ich lege Wert darauf, dass auch andere das Programm möglichst nach Belieben verwenden können.
Der Verweis auf das Thema oben dient absolut nicht als Werbung. Es geht nebensächlich darum, das Forum weiterhin zu vervollständigen um viele Fragen mit Verweisen auf andere Themen oder im schlimmeren Fall mit einem Verweis auf die Suche zu beanworten, aber hauptsächlich dient der erste Teil dieses Posts als Einleitung, um Euch eine Vorstellung von meinem Problem zu ermöglichen - je besser die Vorstellung des Problems, desto besser die Lösung. Denn vielleicht sagt auch einer von Euch "Ach lass in dem Fall die Finger von OpenGL, mach lieber folgendes: [...]", was ich zwar nicht glaube, aber man kann nie wissen - ihr steckt sowieso voller Überraschungen
Das habe ich schon versucht. Leider ging das absolut in die Hose. Scheint so, als würde es nur bei mehreren Prozessorkernen was bringen. Denn bei meinem alten Hauptrechner wurden entweder die Events abgefragt oder das Video gerendert. Beides zusammen ging nicht, entweder ruckelte die Animation oder es wurden keine Ereignisse abgefragt. Im Extremfall ruckelt das Video und es werden keine Ereignisse abgefragt, dies ist aktuell der Fall. Ich möchte es präzisieren, denn eventuell habe ich auch nur einen Fehler gemacht.
Es gibt zwei Anzeigen. Die normale Anzeige und eine Anzeige für das Video als Zwischenspeicherungsort für SMPEG. Selbstverständlich muss SMPEG auch eine Variable bekommen, damit man es später noch kontrollieren kann. Flags hängt davon ab, ob Hardwareunterstützung besteht oder nicht. Da dies den Code nur unnötig in die Länge ziehen würde, lasse ich den Teil weg, wie sich Flags zusammensetzt.
Code:
var Anzeige : PSDL_Surface;// Abbild der Anzeige
VideoInfo : PSDL_VideoInfo;// Videoangaben
Flags :Cardinal;// Anzeigeeinstellungen
MPEG : PSMPEG;// Video
MPEGAnzeige : PSDL_Surface;// Videoanzeige
begin
[...] <-- Initialisierung von SDL, Zusammensetzung von Flags etc.sind weggekürzt.
// Fenster erzeugen
Anzeige := SDL_SetVideoMode(800,600,32, Flags);
// Zeichenfläche für Hintergrundanimation erstellen
if MPEG =nilthen// Datei konnte nicht geladen werden, Abbruch.
begin
Terminate;
Exit;
end;
end;
SMPEG verlangt eine Zuweisung auf eine Prozedur, die aufgerufen wird, wenn der nächste Frame fertig geladen wurde und es an der Zeit ist, ihn zu zeichnen.
Code:
function MovieUpdate(Surface : PSDL_Surface; X, Y :Integer; W, H :Cardinal):Pointer;cdecl;
Nun beginnt die Aufteilung in Threads. Erstmal dachte ich mir, wäre eine Prozedur sinnvoll, die sich nur um das Abspielen des Videos kümmert.
Code:
procedure PlayVideo;
begin
SMPEG_SetDisplay(MPEG, MPEGAnzeige,nil, MovieUpdate);// Anzeige setzen <-- hier wird die Zuweisung auf MovieUpdate gemacht.
SMPEG_EnableVideo(MPEG,1);// Videospur aktivieren
SMPEG_Play(MPEG);// Video abspielen
end;
Die Ereignissabfrage habe ich ebenfalls ausgelagert.
Code:
procedure Events;
begin
// Hauptschleife
while SDL_PollEvent(@Event)=1do// ...Fensterereignisse abholen und verarbeiten.
begin
case Event.Type_of
// Beenden des Programms
SDL_QUITEV:
begin
SDL_LockMutex(Mutex);
Fertig :=True;
SDL_UnLockMutex(Mutex);
end;
[...]
end;
end;
SDL_Flip(Anzeige);// Anzeige aktualisieren.
end;
Nun ist alles ausgelagert, also kann man die Threads erzeugen. Da Events bei SDL_QUITEV auf Fertig zugreift, muss der dazugehörige Speicherbereich gesichert werden. Dies ging noch bis hierhin relativ problemlos. Aber an folgendem Punkt hatte ich große Probleme alleine schon bei der Überlegung: Wie sorgt man dafür, dass einem das Programm nicht abschmiert ? So wie ich es verstanden habe, dürfte der Code in der Hauptprozedur der Projektdatei (.dpr/.lpr) der Hauptthread zugleich sein. Daher dachte ich an eine while-Schleife, die sich auf die Variable Fertig (ist vergleichbar mit der Variable Done in den meisten Quelltexten) bezieht und das Programm möglichst lange am Leben hält (so macht man es für gewöhnlich). Nur kostet genau diese Schleife nicht extrem viel Rechenleistung ? Wie gesagt: Es ruckelt die Hintergrundanimation und es werden keine Ereignisse abgefragt.
Code:
Mutex := SDL_CreateMutex;
ThreadE := SDL_CreateThread(@Events,nil);
ThreadV := SDL_CreateThread(@PlayVideo,nil);
whilenot Fertig do
begin
//
end;
SDL_WaitThread(ThreadE, Result);// Result ist eine einfache Integer-Variable - sicherstellen, dass die Threads fertig sind.
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Ich würde in die schleife noch ein sleep(10) setzen, um dem Betriebssystem explizit zu sagen: Hier passiert gerade garnix, du kannst andere Threads dran lassen.
Aber noch viel besser: Ich würde die Eventabfrage genau da mit reinsetzen. Anstatt im Hauptthread eine Schleife mit nix zu haben, würd ich da viel eher die Events abfragen. Auch hier übrigens: Sleep(10) wirkt Wunder (wenn keine Events mehr zu behandeln sind).
Ach: Warum deine Events nicht abgefragt werden, da hab ich so eine Vermutung. Kann es sein, dass du nur einmal alle Events abfragst (das ist deine While SDL_Pollevent...), danach die Surface flippst und dann ist der Thread auch schon zuende?
Übrigens sind die Pascal-Thread plattformunabhängig. Es lohnt sich vielleicht, die zu verwenden, ich finde die Handhabung zumindest viel besser.
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Jetzt wo Du es sagst, ist es klar. Unglaublich, wie einfach die Lösung doch ist. Dadurch ruckelt das Video jedoch leicht. Könnte man da noch was optimieren. Außerdem benötigt man kein Sleep - ein SDL_Delay macht das gleiche, aber das ist eigentlich unwichtig (eine Funktion weniger, die man aus der SysUtils in eine eigene Unit kopieren muss). Ansonsten ist das eine tolle Idee, vielen Dank!
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Hmm... Ansonsten fällt mir gerade nichts ein. Du könntest vielleicht die Priorität des Threads erhöhen.
Aber was anderes: Was hast du gegen SysUtils? Willst du eine sehr kleine Exe erzeugen oder was?
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.