Sprite und Movie in Threads

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Sven
Beiträge: 374
Registriert: 23.09.2004 12:01

Sprite und Movie in Threads

Beitrag von Sven »

Ich möchte von einem Programm aus zwei WindowedScreens erzeugen. Geht nicht, weil nur in Screen möglich. Also hab ich das mal mit Threads probiert, und da passieren komische Sachen:

1. Im Gegensatz zur Angabe in der Hilfe gehen Sprites auch in Threads. Dabei ist egal, wo das InitSprite steht, ob im Hauptprogramm oder im Thread.

2. Leider geht trotzdem ohne OpenGL nur ein Screen. Mit OpenGL wird ein zweiter Screen geöffnet, die Ausgabe ist aber kryptisch, könnte auch am falschen OpenGL-Treiber liegen.

3. InitMovie geht nur, wenn es im ersten aufgerufenen Thread steht, dann aber bei beiden Threads. Steht InitMovie im Hauptprogramm, geht in den Threads kein PlayMovie, wird zwar geladen, aber dann als nicht existent gemeldet.

Code: Alles auswählen

UseJPEGImageDecoder()

Procedure Video1(xo)
  If InitSprite() <> 0
    Debug "Sprite init"
  EndIf
  If InitMovie() <> 0
    Debug "Movie init"
  EndIf
  
  If OpenWindow(1, xo, 50, 340, 340, "Video 1", #PB_Window_BorderLess)
    If OpenWindowedScreen(WindowID(1), 10, 10, 320, 320, 0, 0, 0)
      LoadSprite(0, "bild.jpg")
    EndIf
    
      If LoadMovie(1, "sound.mp3") <> 0
        Debug "Movie geladen"
        If IsMovie(1)
          PlayMovie(1, WindowID(1))  ;Abspielen starten
        Else
          Debug "Kein Movie"
        EndIf
      EndIf
  EndIf

  direction = 1

  Repeat
    Repeat
      Event1 = WindowEvent()
    Until Event1 = 0
    
    ClearScreen(RGB(0,0,0))
    ClipSprite(0, 0, 0, x, x)
    DisplaySprite(0, x, 100)
    DisplaySprite(0, x, x)
    DisplaySprite(0, 300-x, x)
  
    x + direction
    If x > 300 : direction = -1 : EndIf   ; moving back to the left with negative value
    If x < 0   : direction =  1 : EndIf   ; moving to the right with positive value
      
    FlipBuffers()       ; Inverse the buffers (the back become the front (visible)... and we can do the rendering on the back 
    Delay(10)

  Until Quit1
EndProcedure

Procedure Video2(xo)
  If OpenWindow(2, xo, 50, 340, 340, "Video 2", #PB_Window_BorderLess)
    If LoadMovie(2, "sound.mp3") <> 0
      Debug "Movie geladen"
      If IsMovie(2)
        PlayMovie(2, WindowID(2))  ;Abspielen starten
      Else
        Debug "Kein Movie"
      EndIf
    EndIf
  EndIf

  direction = 1

  Repeat
    Repeat
      Event2 = WindowEvent()
    Until Event2 = 0 ; Quit the event loop only when no more events are available
    
    Delay(10)
    
  Until Quit2
EndProcedure

CallDebugger

  If OpenWindow(0, 50, 50, 340, 400, "Gadget and sprites!", #PB_Window_SystemMenu | #PB_Window_SizeGadget)
    ButtonGadget(1, 10,  10, 100, 25, "Grab input")
    ButtonGadget(2, 120,  10, 100, 25, "Button 2")
    ButtonGadget(3, 230,  10, 100, 25, "Button 3")
    TextGadget  (4, 10, 40, 300, 30, "Press 'F1' to ungrab keyboard and mouse")
  EndIf
  
td1 = CreateThread(@Video1(), 400)

Delay(2000)

td2 = CreateThread(@Video2(), 750)

  Repeat
    Event = WaitWindowEvent()
    Select Event
      Case #PB_Event_CloseWindow
        Quit = 1
    EndSelect 
     
  Until Quit

KillThread(td1)
KillThread(td2)

End
Fragen:

1. Warum muss InitMovie im Thread stehen, bei InitScreen ist es egal?

2. Gibt es eine Chance, dass jeder Thread einen WindowedScreen öffnen und darin Sprites anzeigen kann?

3. Andere Idee, wie ich von einem Programm aus zwei Screens mit Bildern versorgen kann? Soll für eine Steuerung von zwei Beamern sein, mit unterschiedlichen Inhalten.

Achso, "Threadsichere Exe" ist aktiviert.
Benutzeravatar
Vermilion
Beiträge: 1846
Registriert: 08.04.2006 16:00
Computerausstattung: Apple iMac (2010) & HP Notebook
Wohnort: Heidekreis

Beitrag von Vermilion »

(1) 1. Nur weil das jetzt so weit geht, heißt das noch lange nicht, dass es gut ist das so zu benutzen, es ist eine Empfehlung, und solange man nicht weiß, wie PureBasic intern damit arbeitet, ist es wohl besser darauf zu achten.
Die Init-Funktionen müssen wohl nicht zwangsmäßig am Programmanfang stehen, da sie wohl vielleicht nur dazu dienen, anzugeben, was beim Kompilieren gelinkt werden soll, was ich allerdings bezweifle.

(1) 2. Was soll den heißen "trotz ohne OpenGL"? Mit OpenGL geht nur ein Screen, oder wie?
Könnte wirklich an einem schlecht installierten Treiber liegen. Hatte ich früher auch mal. Z.B. lauter schwarze Punkte auf ein mal auf den Texturen in einem Spiel, etc.
Kommt vielleicht auch davon, dass man DirectX und OpenGL Screen auf ein mal offen hat.

(2) 2. Du hast die Hilfe gelesen, wenn du nur noch drüber nachdenken würdest, hättest du die Antwort bereits von alleine gekriegt: Nein. /:->
Benutzeravatar
dige
Beiträge: 1245
Registriert: 08.09.2004 08:53

Beitrag von dige »

Ich glaub Sprites und Threads ist keine gute Idee, da wirst Du früher
oder eher schneller an Grenzen und unlösbare Probleme kommen,
zumal die MovieLib(DX9) noch nicht mal Bugfrei ist.

Am besten ist es Deinem Player 2x zu starten (über Parameter gesteuert)
und die beiden Prozesse über SharedMemory synchronisieren..
"Papa, ich laufe schneller - dann ist es nicht so weit."
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

im Englischen Forum hatte netmaestro mal n snippet veröffentlicht,
wie man direkt über API zwei WindowedScreens öffnet.

damit wäre aber noch lange nicht die Frage geklärt, wie die verwaltet werden sollen:
auf welchen Screen soll sich denn dann ein DisplaySprite beziehen?

der Vorschlag von Dige ist immer noch am praktikabelsten, zwei Instanzen des
selben Programms laufen haben, aber trotzdem würde ich mich auch da nicht drauf verlassen,
dass beide unabhängig von einander fehlerfrei jede ihren eigenen Screen anzeigen können.

PB unterstützt ausdrücklich nicht mehrere Screens und Sprites in Threads,
damit rumzuexperimentieren ist also eine Lotterie.
du könntest dich auf jede Funktion deines Programms nur verlassen,
wenn du sie an der Maschine schreibst, wo sie nachher auch laufen soll.


... müssen es denn überhaupt Screens sein?
an animierten Images kannst du so viele Instanzen vom selben thread aus erstellen wie du lustig bist.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Sven
Beiträge: 374
Registriert: 23.09.2004 12:01

Beitrag von Sven »

>> Init-Funktionen müssen wohl nicht zwangsmäßig am Programmanfang stehen

hat mich nur verwirrt, dass es mal nur geht, wenn es im Thread steht, dann aber auch für den zweiten Thread, obwohl es dort nicht steht (gibt nen Fehler, dass nur einmal aufgerufen werden darf.

>> Was soll den heißen "trotz ohne OpenGL"?

Ohne openGL, also DXirgendwas, geht nur ein Screen. Der Versuch einen zweiten mittels zweiten Thread zu öffnen, endet mit diversen Memory-Fehlern.

Mit OpenGL gehen zwei Screens, pro Thread einer, aber mit verwüsteter Anzeige.

>> Du hast die Hilfe gelesen

Die Hilfe scheint offensichtlich an der Stelle unvollständig zu sein. Außerdem will ich was machen, was so häufig nicht gebraucht wird, da gehe ich nicht davon aus, dass das die Hilfe abdeckt.
Sven
Beiträge: 374
Registriert: 23.09.2004 12:01

Beitrag von Sven »

>> selben Programms laufen haben, aber trotzdem würde ich mich auch da nicht drauf verlassen,
dass beide unabhängig von einander fehlerfrei jede ihren eigenen Screen anzeigen können.

Hab schon probiert, würde gehen, aber ich muss die Inhalte während der Laufzeit vom Hauptprogramm steuern können. Nur Parameterübergabe ist also nicht.

Shared Mem hab ich noch nicht drüber nachgedacht, wie geht das? Im Prinzip würde mir reichen, wenn ich einen String im Steuerprogramm irgendwo hin schreibe, und sich das Videoprogramm den abholt.

Über Netzwerkfunktionen müsste das auch gehen, dummerweise hab ich davon keien Ahnung.

>> damit rumzuexperimentieren ist also eine Lotterie.

Ich weiss, aber das Leben ist ein Spiel ;-)

>> an animierten Images kannst du so viele Instanzen

Bilder in Echtzeit überblenden, Zoomen, Videos auf Sprite abspielen (wegen Ein-Ausblenden), und das Ganze mit Full-HD-Auflösung? Auf einem Image?

Ich möchte das gern vom Hauptprogramm unabhängig laufen lassen, weil:
- Wenn sich der Videothread aufhängt, wegen korrupten Video, soll das Hauptprogramm weiterlaufen und im Idealfall den Videothread killen und neu starten.
- Wenn mehrere Cores vorhanden, soll die Rechenleistung für Video1 und Video2 und Hauptprogramm verteilt werden.
Benutzeravatar
Vermilion
Beiträge: 1846
Registriert: 08.04.2006 16:00
Computerausstattung: Apple iMac (2010) & HP Notebook
Wohnort: Heidekreis

Beitrag von Vermilion »

Bilder in Echtzeit überblenden, Zoomen, Videos auf Sprite abspielen (wegen Ein-Ausblenden), und das Ganze mit Full-HD-Auflösung? Auf einem Image?
Mit Sprite bist du da auch nicht besser dran, wenn solltest du Sprite3D benutzen (falls du das nun nicht meintest). Mit PureBasic ist ja ein Beispiel mitgeliefert, wenn ich mich nicht irre, bei dem das Video auf das Sprite3D gerendert wird. Ein- und Ausblenden mit Sprite wäre auch nicht sehr leistungsfähig, weil man dafür auf die SpecialFX Befehle zugreifen muss, welche die CPU benutzen (das ist ganz schön langsam, im Vergleich zu Hardware-beschleunigter (GPU) Darstellung).
Wenn sich der Videothread aufhängt, wegen korrupten Video, soll das Hauptprogramm weiterlaufen und im Idealfall den Videothread killen und neu starten.
Wäre wohl etwas neues. Bisher sind diverse Abspielprogramme immer abgestürzt, wenn sie nicht einfach gemeldet haben, dass etwas nicht stimmt, um danach ihre Tätigkeit zu beenden.
Aber wozu den Videothread killen und neu starten, wenn die Datei doch sowieso reif für den Papierkorb ist? Wenn die Wiedergabe von vorne gestartet wird, wird alles wieder an derselben Stelle zu Grunde gehen.
Wenn mehrere Cores vorhanden, soll die Rechenleistung für Video1 und Video2 und Hauptprogramm verteilt werden.
Wenn du mehrere Instanzen des Programmes hättest, sollte das Betriebssystem das schon von alleine machen. Aber wenn es sich ohnehin um Hardware-beschleunigte Wiedergabe handelt, dann ist Threading nicht unbedingt nützlich, da die GPU hauptsächlich benutzt wird, und nicht die CPU.
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

>> Bilder in Echtzeit überblenden, Zoomen, Videos auf Sprite abspielen (wegen Ein-Ausblenden), und das Ganze mit Full-HD-Auflösung? Auf einem Image?

:mrgreen: davon hast du aber auch keinen mucks gesagt.

es war nur die Rede von zwei Screens, und da muss die Rückfrage erlaubt sein, ob du Overkill betreibst.

denn "einfache" Präsentationen ohne solchen Kokkolores kann man wunderbar mit 30FpS auf Images machen.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Sven
Beiträge: 374
Registriert: 23.09.2004 12:01

Beitrag von Sven »

Idee zur Datenübergabe:

Ich reserviere im Main einen Speicherbereich und bekomme die Adresse zurück.

Ich rufe das Videoprogramm auf und übergebe die Adresse.

Ich reserviere einen zweiten Speicherbereich.

Ich rufe das Videoprogramm zum zweiten Mal auf und übergebe Adresse 2.

Die Videoprogramme holen sich an der Adresse ihre Init-Infos ab und zeigen den Kram an.

Würde das so gehen? Wie kann ich feststellen, ob sich eines der Videoprogramme festgefahren oder verabschiedet hat?
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

ganz so einfach ist es nicht, weil getrennte Prozesse nicht ohne weiteres auf Memory von anderen Prozessen zugreifen können.

daswegen das Stichwort "SharedMemory" das dige gegeben hat:
es gibt die Möglichkeit, über API gemeinsamen Speicher zu reservieren,
es gibt auch noch weitere Möglichkeiten für Prozesse zu kommunizieren,
aber bei den Meisten bist du wirklich auf API angewiesen.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Antworten