Video auf Imagegadget mittels MCI

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Benutzeravatar
Morty
Beiträge: 268
Registriert: 22.10.2004 07:20
Wohnort: Erfurt
Kontaktdaten:

Video auf Imagegadget mittels MCI

Beitrag von Morty »

Hi,

ist schwer hierfür eine geeignete Überschrift zu finden.
Und zwar habe ich ein Fenster mit einem großen ImageGadget (800x600).
Jetzt will ich auf genau diesem ein Movie abspielen lassen.
Mit den von PB hauseigenen Befehlen ging das recht gut, diese Befehle sind aber im Framebereich zu ungenau, deswegen musste ich auf die Variante mit

Code: Alles auswählen

mcisendstring_()
umsteigen.

Hier stellt es sich aber durchaus als Problem dar, das Videosignal auf das Imagegadget zu legen.
Der Schlüssel müsste irgendwo hier liegen:

Code: Alles auswählen

mciSendString_("WINDOW MPG1 HANDLE " +Str(WindowID(0)), 0, 0, 0)
mciSendString_("PUT MPG1 DESTINATION AT" + Str(50) + " " + Str(118) + " " + Str(800) + " " + Str(600), 0, 0, 0)
vorher hab ich natürlich den MPG Film mittels

Code: Alles auswählen

res.l=mciSendString_("OPEN "+Chr(34)+File.s+Chr(34)+" TYPE "+stream_type.s+" ALIAS MPG1",0,0,0) 

geladen.
Hab auch schon viel rum probiert mit Hilfe der MSDN, aber nichts passendes gefunden.

Selbst das Video nur auf die gleichen Koordinaten zu setzen und abzuspielen geht nicht, da flakerts nur kurz. Ich denke mal da refreshed er das Fenster stellt es über dem Video wieder dar.

Boah, ich hoffe ihr verzweifelt nicht mit meiner Beschreibung.

Thanx,
Morty
DNA
Beiträge: 40
Registriert: 25.02.2006 23:54

Beitrag von DNA »

ist zwar schon länger her die Frage, hab aber mal ein Beispiel gefunden und das in PB umgesetzt. Hab es mit einer wmv getestet und funktioniert auch.

Code: Alles auswählen

;######################################################################################

Global OpenAlias.b = #False
#StdAlias = "TmpAlias"

; ermitteln aller Dateitypen, die mit den MCI-Treibern abgespielt werden sollen
Procedure.s GetMciFileTypes()
  Protected result.l    = 0
  Protected memIndex.l  = 0
  Protected Retval.s    = ""
  Protected Buffer.s    = Space(255)
  Protected FileTypes.s = ""
  Protected count.l     = 0
  
  ; erst mal alle Dateitypen ermitteln
  result = GetProfileString_("mci extensions", #Null, "*.*", Buffer, Len(Buffer))

  While PeekS(@Buffer + memIndex) <> ""
    FileTypes = FileTypes + PeekS(@Buffer + memIndex) + "#"
    If PeekS(@Buffer + memIndex) <> ""
      count = count + 1
    EndIf
    memIndex = memIndex + Len(PeekS(@Buffer + memIndex)) + 1
  Wend

  ; jetzt die dazugehörigen Treiber identifizieren
  Retval = "Alle Dateien (*.*)" + "|" + "*.*"
  
  For i = 1 To count
    Buffer = Space(256)
    res = GetProfileString_("mci extensions", StringField(FileTypes,i,"#"), #Null, Buffer, Len(Buffer))
    Retval = Retval +  "|" + Left(Buffer, res) + " (*." + StringField(FileTypes,i,"#") + ")|" + "*." + StringField(FileTypes,i,"#")
  Next

  ProcedureReturn Retval
EndProcedure

; ermitteln eines Treibers für einen entsprechenden Dateityp
Procedure.s GetSingleType(Extension.s)
  Protected result.l
  Protected Buffer.s = Space(255)
 
  result = GetProfileString_("mci extensions", Right(Extension, 3), "NotFound", Buffer, Len(Buffer))
  ProcedureReturn Left(Buffer, result)
EndProcedure

; Fehlercode für einen erfolglosen Aufruf ermitteln
Procedure ErrMsg(Errorcode.l)
  Protected result.l = 0
  Protected Buffer.s = Space(256)
 
  ; kein Fehler
  If Errorcode <> 0
    ; Fehler in einer MessageBox ausgeben
    result = mciGetErrorString_(Errorcode, Buffer, Len(Buffer))
    MessageRequester("Fehler " + Str(Errorcode), Buffer)
  EndIf
EndProcedure

; schließen eines MCI-Treibers
Procedure Mci_Close()
  If OpenAlias
    mciSendString_("close " + #StdAlias, 0, 0, 0)
    OpenAlias = #False
  EndIf
EndProcedure

; öffnet eine Datei, sofern nicht eine andere noch geöffnet ist
Procedure Mci_Open(FileName.s, Handle.l)
  Protected Buffer.s = Space(256)
  Protected result.l = 0
  
  If OpenAlias
    Mci_Close()
  EndIf
  
  OpenAlias = #True
 
  ; ermittelt den Dos-Pfadnamen, ist erforderlich weil MCI Treiber Leerstellen als Separator interpretieren
  result = GetShortPathName_(FileName, Buffer, Len(Buffer))
  FileName = Left(Buffer, result)
 
  ; öffnet ein Gerät und eine Multimedia-Datei
  ErrMsg(mciSendString_("open " + FileName + " type " + GetSingleType(FileName) + " alias " + #StdAlias, 0, 0, 0))
 
  ; falls das Medium ein Video ist, die PictureBox als Anzeige verwenden
  mciSendString_("window " + #StdAlias + " handle " + Str(Handle), 0, 0, 0)
 
  ; Zeitformat wählen, das wir abfragen wollen
  mciSendString_("Set " + #StdAlias + " Time Format Milliseconds", 0, 0, 0)
EndProcedure

; starten der Wiedergabe von Position 0 aus
Procedure Mci_Play()
  If OpenAlias
    ErrMsg(mciSendString_("play " + #StdAlias + " from 0", 0, 0, 0))
  EndIf
EndProcedure

; stoppen der Wiedergabe
Procedure Mci_Stop()
  If OpenAlias
    mciSendString_("stop " + #StdAlias, 0, 0, 0)
  EndIf
EndProcedure

; ermitteln der aktuellen Abspielposition
Procedure.l Mci_GetPos()
  Protected Pos.s = Space(256)
  
  If OpenAlias 
    mciSendString_("status " + #StdAlias + " position", Pos, Len(Pos), 0)
    ProcedureReturn Val(Pos) ;, InStr(1, Pos, vbNullChar) - 1)
  EndIf
EndProcedure

;######################################################################################

Enumeration
  #Fenster
  #Btn_laden
  #Btn_play
  #Btn_stop
  #Img_Video
  #Zeit
EndEnumeration

#IDTIMER_MAIN = 33

; abfragen der aktuellen Abspielposition
Procedure aktuelle_Zeit()
  Protected Seconds.l, Minutes.l, Hours.l
 
  ; Millisekunden in ein Stunden:Minuten:Sekunden-Format umrechnen
  Seconds = Mci_GetPos() / 1000
  Hours = (Seconds - (Seconds % 60)) / 60 / 60
  Minutes = (Seconds - (Hours * 60) - (Seconds % 60)) / 60
  Seconds = Seconds - (Hours * 60 * 60) - (Minutes * 60)
 
  ; Zeitformat im Labelfeld ausgeben
  SetGadgetText(#Zeit, RSet(Str(Hours), 2, "0") + ":" + RSet(Str(Minutes), 2, "0") + ":" + RSet(Str(Seconds), 2, "0"))
EndProcedure

Procedure lade_Mediafile(Handle.l)
  Protected File$ = OpenFileRequester("Multimediadatei Öffnen", "", GetMciFileTypes(), 0)
  Mci_Open(File$, Handle)
EndProcedure

If OpenWindow(#Fenster, 0, 0, 400, 400, "MCI Beispiel...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  If CreateGadgetList(WindowID(#Fenster))
    
    TextGadget(#Zeit, 10, 14, 50, 20, "")
    ButtonGadget(#Btn_laden, 60, 10, 100, 20, "öffnen")
    ButtonGadget(#Btn_play, 170, 10, 100, 20, "play")
    ButtonGadget(#Btn_stop, 280, 10, 100, 20, "stop")
    ImageGadget(#Img_Video, 10, 40, 380, 350, #Null)
  EndIf
  
  SetTimer_(WindowID(#Fenster), #IDTIMER_MAIN, 500, @aktuelle_Zeit())
  
  Repeat
    Event = WaitWindowEvent()

    Select Event
      Case #PB_Event_Gadget
        Select EventGadget()
          Case #Btn_laden
            lade_Mediafile(GadgetID(#Img_Video))
          Case #Btn_play
            Mci_Play()
          Case #Btn_stop
            Mci_Stop()
        EndSelect
    EndSelect

  Until Event = #PB_Event_CloseWindow
  
  KillTimer_(WindowID(#Fenster), #IDTIMER_MAIN)
EndIf

Mci_Close()

End
Benutzeravatar
dige
Beiträge: 1245
Registriert: 08.09.2004 08:53

Re: Video auf Imagegadget mittels MCI

Beitrag von dige »

Morty hat geschrieben:Mit den von PB hauseigenen Befehlen ging das recht gut, diese Befehle sind aber im Framebereich zu ungenau, deswegen musste ich auf die Variante mit

Code: Alles auswählen

mcisendstring_()
umsteigen.
Was ist denn damit gemeint?
"Papa, ich laufe schneller - dann ist es nicht so weit."
DNA
Beiträge: 40
Registriert: 25.02.2006 23:54

Beitrag von DNA »

Was auch immer damit gemeint wurde, der vorteil hier ist, dass man nicht solche probleme beim abspielen hat, wie die PB-Befehle.
Wenn ich z.B. eine wmv abspiele im openscreen und das bei einer auflösung von mind. 1024x768, dann spielt PB mit seinen Befehlen zwar das Video ab, aber ich sehe dann nicht das gesamte Video, dafür sieht man einen Teil vom Desktophintergrund.
Versuch grad das mit der Api so hinzubekommen, dass ich das ganze auch in Sprites darstellen kann, aber da öffnet der mir jedesmal ein neues fenster :cry:

Falls also jemand hier eine Lösung hat, nur her damit. Ich selbst bin mit der API-Hilfe nicht weit gekommen.
Benutzeravatar
Thalius
Beiträge: 476
Registriert: 17.02.2005 16:17
Wohnort: Basel / Schweiz

Beitrag von Thalius »

also mit den PB internen befehlen ist das ganz easy mit den Sprites.

Hast du mal nen Screenshot wie das Movie Beispiel bei dir aussieht ?
Sind bei dir irgendwelche speziellen codecpacks installiert. DX Version und aktuelle Grafiktreiber ?
Der Vorteil zu MCI ist halt - dass die PB Befehle Hardware-Beschleunigung ( Overlay oder DX über ein 3D Sprite ) nutzen.

Cheers,
Thalius
"...smoking hash-tables until until you run out of memory." :P
Antworten