Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Fr Jul 18, 2025 08:02

Foren-Übersicht » Programmierung » OpenGL
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 6 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Vista im Fenstermodus
BeitragVerfasst: Mo Apr 06, 2009 21:35 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Okt 03, 2007 14:22
Beiträge: 388
Hi,

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 :)

Gruß
Nils


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Apr 07, 2009 05:39 
Offline
DGL Member

Registriert: Mo Mär 16, 2009 10:22
Beiträge: 26
Für das erste Problem würde ich zum Video-Abspielen einen eigenen Thread starten, der sich alleine um das Video kümmert.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Apr 07, 2009 09:35 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Okt 03, 2007 14:22
Beiträge: 388
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:
  1. var Anzeige      : PSDL_Surface;   // Abbild der Anzeige
  2.     VideoInfo    : PSDL_VideoInfo; // Videoangaben
  3.     Flags        : Cardinal;       // Anzeigeeinstellungen
  4.  
  5.     MPEG        : PSMPEG; // Video
  6.     MPEGAnzeige : PSDL_Surface; // Videoanzeige
  7. begin  
  8.   [...] <-- Initialisierung von SDL, Zusammensetzung von Flags etc. sind weggekürzt.
  9.   // Fenster erzeugen
  10.   Anzeige := SDL_SetVideoMode(800, 600, 32, Flags);
  11.   // Zeichenfläche für Hintergrundanimation erstellen
  12.   MPEGAnzeige := SDL_CreateRGBSurface(SDL_SWSURFACE or SDL_DOUBLEBUF, 756, 480, 32, ColorToMap(Anzeige, $FF0000), ColorToMap(Anzeige, $00FF00), ColorToMap(Anzeige, $0000FF), ColorToMap(Anzeige, $000000)); // Virtuelle Videoanzeige erstellen
  13.   // Hintergrundanimation laden
  14.   MPEG := SMPEG_new(PChar('.\data\bg.mpg'), nil, 0);
  15.   if MPEG = nil then // Datei konnte nicht geladen werden, Abbruch.
  16.   begin
  17.     Terminate;
  18.     Exit;
  19.   end;
  20. 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:
  1. function MovieUpdate(Surface : PSDL_Surface; X, Y : Integer; W, H : Cardinal ) : Pointer; cdecl;
  2. begin
  3.   SDL_BlitSurface(MPEGAnzeige, nil, Anzeige, PSDLRect(200, 0, MPEGAnzeige.w, MPEGAnzeige.h)); // Videoanzeige übertragen und...
  4.   SDL_Flip(Anzeige); // ...zeichnen.
  5. end;

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:
  1. procedure PlayVideo;
  2. begin
  3.   SMPEG_SetDisplay(MPEG, MPEGAnzeige, nil, MovieUpdate); // Anzeige setzen <-- hier wird die Zuweisung auf MovieUpdate gemacht.
  4.   SMPEG_EnableVideo(MPEG, 1); // Videospur aktivieren
  5.   SMPEG_Play(MPEG); // Video abspielen
  6. end;

Die Ereignissabfrage habe ich ebenfalls ausgelagert.
Code:
  1. procedure Events;
  2. begin
  3.   // Hauptschleife
  4.   while SDL_PollEvent(@Event) = 1 do // ...Fensterereignisse abholen und verarbeiten.
  5.   begin
  6.     case Event.Type_ of
  7.       // Beenden des Programms
  8.       SDL_QUITEV:
  9.       begin
  10.         SDL_LockMutex(Mutex);
  11.         Fertig := True;
  12.         SDL_UnLockMutex(Mutex);
  13.       end;
  14.       [...]
  15.     end;
  16.   end;
  17.   SDL_Flip(Anzeige); // Anzeige aktualisieren.
  18. 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:
  1. Mutex   := SDL_CreateMutex;
  2. ThreadE  := SDL_CreateThread(@Events, nil);
  3. ThreadV := SDL_CreateThread(@PlayVideo, nil);
  4. while not Fertig do
  5. begin
  6.   //
  7. end;
  8. SDL_WaitThread(ThreadE, Result); // Result ist eine einfache Integer-Variable - sicherstellen, dass die Threads fertig sind.
  9. SDL_WaitThread(ThreadV, Result);
  10. SDL_DestroyMutex(Mutex);


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Apr 07, 2009 10:37 
Offline
DGL Member
Benutzeravatar

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 networkmy 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


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Apr 07, 2009 16:40 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Okt 03, 2007 14:22
Beiträge: 388
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!


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Apr 07, 2009 18:05 
Offline
DGL Member
Benutzeravatar

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 networkmy 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


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 6 Beiträge ] 
Foren-Übersicht » Programmierung » OpenGL


Wer ist online?

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.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.008s | 15 Queries | GZIP : On ]