# JMF Events MediaPlayer



## Timbo23 (15. Mai 2010)

Hallo zusammen,

ich arbeite gerade an meiner Diplomarbeit, bei der ich einen *MediaPlayer* (Java Media Framework) verwende.
Es geht jetzt darum, in das aktuelle Bild etwas zu zeichnen. Das habe ich realisiert indem ich mir die GetGraphics() - Methode des MediaPlayers verwende und dann einen Kreis darauf zeichne:

mediaPlayer = Manager.createRealizedPlayer( mediaURL );
// get the components for the video and the playback controls
             video = mediaPlayer.getVisualComponent();

             controls = mediaPlayer.getControlPanelComponent();
             if ( video != null )
                  add(video, BorderLayout.CENTER); // add video component to Panel

             if ( controls != null )
               add( controls, BorderLayout.SOUTH ); // add controls to Panel

             // hier erfolgt dann das Zeichnen des Kreises
            Graphics g = video.getGraphics();
    	  //super.paintComponent(g);
   	   	g.drawOval(0, 0, 10, 10);​
Das Ganze funktioniert wunderbar, jetzt müsste ich nur bei jedem neuen Bild den Kreis anpassen (soll eine Ballerkennung werden, die sich ständig an den veränderten Ball anpasst.)

Die Frage ist, wie der *MediaPlayer* die *Änderung eines Bildes* registriert. Hierzu bräuchte ich ein *Event*, welches mir zurückgibt, wenn das nächste Bild geladen ist. Ich habe schon einige Events beim MediaPlayer ausprobiert, aber leider war nichts passendes dabei. Wäre toll, wenn ihr mir helfen könntet.

Danke im Voraus.

Timo


----------



## Kr0e (16. Mai 2010)

Du willst auf die Frames im einzelnen reagieren ? Wie gut sind deine Kenntnisse über JMF ?
Du kannst einen eigenen Renderer schreiben. Is im Prinzip ein Interface dass Methode wie "onNextFrame" enthält.
Du kansnt dann in dem Fall von einem Renderer einfach ableiten z.b. vom Java2DRenderer und die jeweilige Methode überschreiben.
Der Name der Methode muss jetzt nich genau stimmen. Ich hab mich vor 2 Jahren mal mit JMF beschäftigt...
ODER du schreibst einen eignen Controller und rufst Player.addController auf. Wenn spezielle Fragen bleiben, einfach posten 

Gruß,
Chris

PS: Wie regelst du das mit der Bilderkennung ? (Aus reiner Neugier und interessant für ein ähnlcihes Projekt von mir)
Nur ne grobe Erläuterung wenns möglich wäre


----------



## Timbo23 (16. Mai 2010)

Hallo Chris,

ja genau, ich möchte nach jedem Frame einen Kreis auf das verwendete Panel zeichnen.
Deshalb muss ich ja dann wissen, wann ein neues Bild geladen wurde und darauf entsprechend reagieren.
Meine Kenntnisse in JMF sind nicht so berauschend. Deshalb würde mich interessieren was Du für die beste und noch wichtiger schnellste Lösung hälst, eigener Renderer oder den Controller überschreiben?

Ich hatte mir bisher folgendes überlegt: Ich baue einen Timer ein, der die entsprechende Framerate des Videos abbildet. Wenn Player gestartet dann alle 1/24s (Framerate) ein Bild weiter springen. Beim MediaPlayer in Java gibt es ja die entsprechende Funktion seek(). Denke aber, dass das eventuell Probleme mit der Performance geben könnte. Muss ich denke ich mal ausprobieren. Es scheint mir aber, dass deine Lösungen wohl eher Sinn machen!?

Das mit Bilderkennung, bei mir eine Ballerkennung ist ein Mix aus Farberkennung (zusammen mit der Bayes-Decision Theorie) und der Hough-Transformation (vorher ist noch eine Kantenerkennung mittels Canny-Edge) vorgesehen. 

Solltest du hier mehr Infos benötigen kein Problem.
Danke schon mal für den ersten Denkanstoss.  

Timo


----------



## Kr0e (16. Mai 2010)

Hallo,

nachdem ich mich jetzt nochmal etwas mehr mit JMF beschäftigt hab, fiel mir wieder ein, dass es der ControllerListener war...


```
Player p = null; //Schon klar, dass null nciht gültig ist xD
        p.addControllerListener(new ControllerListener() {

            public void controllerUpdate(ControllerEvent ce) {
             if(ce instanceof ....) {
               //Hier dann neu berechnen   
             }
        });
```

So, jetzt weiß ich allerdings nichtmehr wie genau das Event hieß.... Ich kann dir aber sagen, dass alle möglichen Events im Paket
javax.media.* sind. Meine Vermutung ist, dass es das MediaTimeSetEvent sein könnte. Oder evt das TransitionEvent. Leider schlecht dokumentiert. Falls es nciht klappt, kannst du ein wenig "Reverse engineering" bertreiben ^^ Lass dir mit System.out.println (ce.getClass()) Einfach mal alle Events die eintrudeln ausgeben. Das Event, das andauernd reinkommt sollte dann das Richtige sein... Viel Erfolg 

Gruß,
Chris

PS: Danke, deine Stichpunkte bzg. Bilderkennung waren hilfreich für weitere Quellen.


----------



## Timbo23 (17. Mai 2010)

Hallo Chris,

ja da hattest Recht, das Event heisst tatsächlich javax.media.MediaTimeSetEvent.
Das Problem das ich jetzt habe, ist, dass das Event immer nur bei Bedienung der Suchleiste bekomme.
Die habe ich mir mit 
controls = mediaPlayer.getControlPanelComponent();
geholt und eingebunden. 
Ein Event findet von sich aus, also wenn der MediaPlayer abspielt, nicht statt. Was mach ich da falsch?
Danke für deinen erneuten Denkanstoss.

Beste Grüße
Timo


----------



## Kr0e (17. Mai 2010)

Hi, ähm... Ich befürchte langsam, dass du wirklich nicht um den Renderer rumkommst. Allerdings musst du bedenken, dass ein eigener Renderer erst bei JMFRegistry eingetragen werden muss. Ich würde einfach folgendes machen:
Wie du shcon anfangs vorgeschlagen hast, wäre vermutlcih ein Timer in der Framerate das einfachste.
Du brauchst auch nicht immer seek() zu machen... Einfach alle 24 ms oder wie auch immer deine Berechnung neudurchführen, in dem du mit getVisualComponent() das Image nimmst. Damit kannst du ja dann quasi deine Berechnungen machen. Ich hatte gehofft, dass es ein Event gibt, das ständig ausgeführt wird... Scheint dann aber wohl nicht der Fall zu sein.. 

Weiterhin viel Erfolg

Gruß,
Chris


----------



## Timbo23 (17. Mai 2010)

Hallo Chris,

also die Variante mit dem Timer hab ich mittlerweile umgesetzt. Funktioniert soweit ganz gut , bis auf das Flackern des Kreises, der den Ball markieren soll. Aber soweit schon mal ganz gut. Das mit dem Renderer check ich noch nicht so ganz. Hab mich mal im Netz umgeschauen und nach diesem 2DRenderer geschaut. Muss aber ehrlich gestehen, dass ich nicht so recht weiß, wo ich da ansetzen soll und wie das Zusammenspiel der Komponenten dann funktionieren soll. Wenn du da vielleicht noch einen Link für mich hättest oder ne kleine Anleitung wäre super. Nochmals vielen Dank für die Hilfe soweit, damit kann Ich trotz des kleinen Schönheitsfehlers wunderbar leben :toll: 

Timo


----------



## Kr0e (17. Mai 2010)

Das Flackern des Balls entsteht durch das ungebufferte Rendern von Java2D. OpenGL nutzt dafür Backbuffer.. Sprich ein Bild wird komplett neu gezeichnet und nicht wie bei Java2D die linke Hälfte des Kreises, dann erfolgt ein Refresh der einen Hälfte des Monitors und dann ein 2ter Refresh wobei diesmal der Ball aber schon weiter gezogen ist und nicht mehr zur linken Seite passt. In Java kann man das Problem leicht umgehen mit DoubleBufferung, allerdings hab ich keine Ahnung, wie das bei getVisualComponent() nachträglich eingerichtet werden kann...


Aus einem Oracle Forenbeitrag hab ich das gefunden:

Manager.setHint(Manager.LIGHTWEIGHT_RENDERER, new Boolean(true));

Link: Java Media Framework - Drawing over a video

Vlt. findest du noch weitere Sachen wenn du bei Google nach "jmf draw over video" suchst oder so ... Das Flackern sollte aber lösbar sein... Viele Java Mediaplayer könnnen auch Text (Z.B. den Namen des Videos) über dem Video anzeigen ohne Flackern...

Gruß,
Chris


----------



## Timbo23 (19. Mai 2010)

Hallo Chris,

das ist ein schönes Beispiel, was auch eigentlich gut funktioniert.
Die Sache ist nur die, dass dieses "GlassPane" über  das Ganze Frame läuft und wenn es aktiv ist, alle anderen Bedienmöglichkeiten deaktiviert. Gibt es eine Möglichkeit das GlassPane auf einen Bereich oder bei mir speziell das Video zu beschränken? Das ganze ist bei mir mit dem Borderlayout aufgeteilt.
Links ist das Ordnerverzeichnis und rechts das Video sowie die Suchleiste (siehe Bild):

http://www.dasrundemussinseckige.eu/bild_layout.png

Danke für deine Mühen.

Gruß Timo


----------

