# Videos abspielen etc.



## erxx (28. Dez 2009)

Hallo liebe Gemeinde,

Wie ich bereits in meinem ersten beitrag hier geschrieben habe bin ich noch ein blutiger Anfänger was JAVA angeht.

Jedenfalls gilt es nun in einem Frame ein Video abzuspielen. Es soll jedoch möglich sein je nach Gegebenheiten innerhalb von einer Reihe von Videos eines auszusuchen was dann abgespielt wird. Das heisst der benutzer soll keinerlei Einfluss auf die Wahl des Videos haben sondern nur Play/Pause/Stop (evtl. Lautstärke).

Meine Frage hierzu ist nun ob ich das nun mit JMF oder jVLC oder eventuell mit etwas völlig anderem umsetzen soll. Das Einbinden soll dabei möglichst einfach sein, aber effektiv.

Kleine Neben"frage":

Bei der Pfadauswahl zur Videodatei (da das Programm auf mehreren Plattformen funktionieren soll) erstelle ich im Arbeitsverzeichnis ein Ordner vid (/dist/vid) und hau dort die videos rein so dass im Listing die Pfadangabe der Videos etwa so aussieht: System.getProperties("user.dir") + "/" + dateiname1;

Was mich daran wieder stutzig macht ist das "/" da es ja bei Windows ein \ ist...

Gibt sicherlich eine bessere Möglichkeit?!


Vielen Dank 

Grüsse


----------



## Guybrush Threepwood (28. Dez 2009)

zur Frage mit dem Dateipfad: Nimm lieber File.Separator statt "/". Da wird dann das richtige Zeichen eingesetzt. Zum Mediaplayer kann ich Dir leider keinen endgültigen Tipp geben. Es gibt mehrere Projekte, aber was jetzt am Besten ist - keine Ahnung.


----------



## faetzminator (28. Dez 2009)

Hier noch eine Anmerkung zu Guybrush Threepwood's Post, das wird dir in dem Zusammenhang weiterhelfen: System (Java Platform SE 6)


----------



## erxx (29. Dez 2009)

Danke euch für die Antworten. Das hat mir bereits etwas weitergeholfen.

Hat vielleicht jemand ein konkretes Beispiel um ein Video in einem Frame abzuspielen ?


----------



## Kr0e (2. Jan 2010)

Ja, nimm JMC, DAs sind die Java Media Classes...

Ist zur Zeit die beste Lösung fürs Abspielen bei Java. Ist noch in einem inoffiziellen Stadium, aber kommt mit JDK 7 offiziell raus.

Wie du daran kommst, ist hier beschrieben:

(Ist aus einem anderen Forum kopiert, deshalb Englisch)

Hi,
thanks for the replies Smiley

I think it would be the best to write a small tutorial about JMC. The rest (Drawing a BufferedImage to ImageGraphics)
is nothing special.

Because JMC is officially not part of the jdk, there is no documentation about these classes. I read a lot about JMC and finally i was able to create a simple MediaPlayer.

1. At first you'll need the JMC files. The files consist of a jmc.jar file, which is used for every OS and a few dynamic library files. (On windows they are called *.dll)

How can i get these files ?

Download and install JavaFX SDK 1.2. After installation switch to the install folder and enter the directory "lib/desktop".

Now you will see a lot of files. You need the jmc.jar file and the particular dll files (On mac and linux these files have another extension)

The names of the files: jmc.dll, msvcp71.dll, msvcr71.dll

Now you have everything to create a very fast media application. If your java application runs on Windows, the DirectShow codecs are used, on Mac the Core library and on Linux the GStreamer library... You do not have to care about compiling new codecs... I think the library will be released offcially in JDK 7!

To use the classes in your java application you have to add the files to your buildpath.



How can i create a simple media application ?

It's easier than you think! The following code shows a simple implementation of a MediaPlayer:

Code:

public class MediaPlayer implements VideoRendererListener {

    private MediaProvider prov; //This is the most important class!

    private VideoRenderControl renderer; //It's a interface to control the rendering

    private Graphics2D g2;

    public MediaPlayer(File path, Graphics2D g2) {
        this.g2 = g2;
        prov = new MediaProvider(path.toURI());
    	renderer = prov.getControl(VideoRenderControl.class);		
    	renderer.addVideoRendererListener(this);       
    }

    @Override
    public void videoFrameUpdated(VideoRendererEvent arg0) {
	if(g2 != null)
		renderer.paintVideoFrame(g2, new Rectangle(0, renderer.getFrameSize().height,
                                                                                         getWidth(),  getHeight()));		
    }	
}


It could be happen that the MediaProvider says that the media file is invalid... Check your path! Empty spaces are restricted!

Now you can draw a video on a Graphics2D object! So you are ready! To access the track control or sound control, you can easily use prov.getControl(VideoRenderControl.class); You must replace VideoRenderControl in this case with the control type you need. The package com.sun.media.jmc.control contains all control interfaces...

Ok, i hope i could help to intergrate the new Java Media Classes! They are very powerful and should be used instead of JMF for simple playback!!
Chris





Das sollte dir helfen...

Gruß,

Chris


----------



## erxx (2. Jan 2010)

Danke erstmal für deine Antwort. Jedoch habe ich in der Zeile ein Problem:

renderer.paintVideoFrame(g2, new Rectangle(0, renderer.getFrameSize().height,
getWidth(), getHeight()));


will er vom obenstehenden Code Beispiel nicht annehmen. 

internal error, cannot instantiate Rectangle(int,int,int,int) at java.awt.Rectangle to ()



```
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package audiovideo;


import com.sun.media.jmc.MediaProvider;
import com.sun.media.jmc.control.VideoRenderControl;
import com.sun.media.jmc.event.VideoRendererEvent;
import com.sun.media.jmc.event.VideoRendererListener;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.io.File;



public class MediaPlayer implements VideoRendererListener {

private MediaProvider prov; //This is the most important class!

private VideoRenderControl renderer; //It's a interface to control the rendering

private Graphics2D g2;

public void MediaPlayer(File path, Graphics2D g2) {
    this.g2 = g2;
    prov = new MediaProvider(path.toURI());
    renderer = prov.getControl(VideoRenderControl.class);
    renderer.addVideoRendererListener(this);
}

@Override
public void videoFrameUpdated(VideoRendererEvent arg0) {
    if(g2 != null)
        renderer.paintVideoFrame(g2, new Rectangle(0, renderer.getFrameSize().height,
getWidth(), getHeight()));
}
}
```


----------



## Kr0e (2. Jan 2010)

Upps, mein Fehler!

getHeight() und getWidth gibt es ja garnicht in dieser Klasse!
Musst sie ersetzen durch JFrame oder JPanel.getWidth/getHeight

Nimm am besten folgenden Codeabschnitt, damit gewährleitest du, dass das Video korret skaliert wird:


```
JPanel panel;
        Graphics2D ig = (Graphics2D)panel.getGraphics(); //Das musst du iwo anders aufrufen ;)

	@Override
	public void videoFrameUpdated(VideoRendererEvent arg0) {
		float ratio = vrc.getFrameSize().height / (float)vrc.getFrameSize().width;
		
		int diff = ( panel.getHeight() - Math.round(ratio * panel.getHeight())) / 2; 
		

		vrc.paintVideo(ig,
				new Rectangle(0, 0, vrc.getFrameSize().width, vrc.getFrameSize().height)
				,				
				new Rectangle(0, diff, panel.getWidth(), Math.round(ratio * panel.getHeight())));
	}
```


----------



## erxx (3. Jan 2010)

Ich befürchte dass meine java Kenntnisse noch nicht ausreichen um das Komplett nachzuvollziehen.
Jedenfalls wird nun das vrc nicht erkannt.


ich habe auch diesen code gefunden
jedenfalls erkennt er dort das JMediaPlayer nicht, 

import com.sun.media.jmc.JMediaPlayer macht da Probleme da das JMediaPlayer in dem package nicht existiert bei mir.


01.package test;
02. 
03.import java.io.File;
04. 
05.import javax.swing.JFrame;
06. 
07.import com.sun.media.jmc.JMediaPlayer;
08. 
09.public class TestJMC {
10. public static void main(String[] args) throws Exception {
11.  JFrame frame = new JFrame("Testing JMC"); {
12.   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
13.   frame.setSize(800, 600);
14.    
15.   JMediaPlayer player = new JMediaPlayer(new File("trailer_1080p.mov").toURI()); {
16.    frame.add(player);
17.   }
18.    
19.   frame.setVisible(true);
20.  }
21. }
22.}


----------



## Kr0e (3. Jan 2010)

Hi, sry... Mann, ich mach aber auch doofe FEhler in der Eile 

Dein Code kann nicht klappen. Der ist für JMC1.1 ausgelegt.. (JavaFX 1.1)

Einfach vrc durhc arg0 ersetzen. Tut mir Leid. Hätte ich sehen müssen....
vrc ist das Event!

Gruß,
Chris


----------



## erxx (3. Jan 2010)

Danke für deine Antworten

arg0.paintVideo existiert jedoch auch nicht :/


----------



## Kr0e (4. Jan 2010)

Ok, jetzt weiß ichs wieder:

vrc ist in der Tat nicht der Parameter... vrc ist ein VideoRenderControl...
So kommst du dran: (Einfach )


```
//Extract the render control
		VideoRenderControl vrc = prov.getControl(VideoRenderControl.class); //prov ist dein Media Provider!!
		vrc.addVideoRendererListener(this); //"This" ist auf die eigene Instanz der Klasse bezogen, die den "VideoRendererListener" implementiert!
```

In deinem Code weiter oben, wo nur getHeight und getWidth nicht erkannt wurde... Da war das schon richtig umbenannt!
Da hies es "renderer" vrc gibt es in dem Code den ich dir geschickt hab dann natürlich nicht... Da musse dann "renderer" und nicht
vrc nehmen ...
Nun sollte es gehen. vrc ist ein VideoRenderControl. Damit kann man zeichnen. arg0 braucht man garnicht. Ist schon ne Weile her gewesen.

Gruß,

Chris

PS:
Weil ich dir hier nur Fragmente gebe, nochmal zum Schluss einen vollständigen Player:


```
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
 
package audiovideo;
 
 
import com.sun.media.jmc.MediaProvider;
import com.sun.media.jmc.control.VideoRenderControl;
import com.sun.media.jmc.event.VideoRendererEvent;
import com.sun.media.jmc.event.VideoRendererListener;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.io.File;
 
 
 
public class MediaPlayer implements VideoRendererListener {
 
private MediaProvider prov; //This is the most important class!
 
private VideoRenderControl renderer; //It's a interface to control the rendering
 
private Graphics2D ig;

private JPanel panel;
 
public void MediaPlayer(File path, JPanel panel) {
    ig = panel.getGraphics();
    this.panel = panel;
    prov = new MediaProvider(path.toURI());
    renderer = prov.getControl(VideoRenderControl.class);
    renderer.addVideoRendererListener(this);
}
 
@Override
public void videoFrameUpdated(VideoRendererEvent arg0) {
        float ratio = renderer.getFrameSize().height / (float)renderer.getFrameSize().width;
        
        int diff = ( panel.getHeight() - Math.round(ratio * panel.getHeight())) / 2; 
        
 
        renderer.paintVideo(ig,
                new Rectangle(0, 0, renderer.getFrameSize().width, renderer.getFrameSize().height)
                ,               
                new Rectangle(0, diff, panel.getWidth(), Math.round(ratio * panel.getHeight())));

}
```

SO!, Jetzt sollte es aber klappen. Lass dich nicht entmutigen, es macht Sinn sich diese Lib jetzt shconmal anzueignen.
Bald ist sie Teil vom JDK

Jetzt aber gut nacht


----------



## erxx (4. Jan 2010)

Herzlichen Dank,

Ich musste jedoch noch ein paar kleinere änderungen vornehmen bei den imports sowie in Zeile 32 und 52-54 damit netbeans nicht meckert, ist das noch so okay ?


```
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package audiovideo;


import com.sun.media.jmc.MediaProvider;
import com.sun.media.jmc.control.VideoRenderControl;
import com.sun.media.jmc.event.VideoRendererEvent;
import com.sun.media.jmc.event.VideoRendererListener;
import java.awt.Graphics2D;

import java.awt.Rectangle;
import java.io.File;
import javax.swing.JPanel;



public class MediaPlayer implements VideoRendererListener {

private MediaProvider prov; //This is the most important class!

private VideoRenderControl renderer; //It's a interface to control the rendering

private Graphics2D ig;

private JPanel panel;

public void MediaPlayer(File path, JPanel panel) {
    ig = (Graphics2D) panel.getGraphics();
    this.panel = panel;
    prov = new MediaProvider(path.toURI());
    renderer = prov.getControl(VideoRenderControl.class);
    renderer.addVideoRendererListener(this);
}

@Override
public void videoFrameUpdated(VideoRendererEvent arg0) {
        float ratio = renderer.getFrameSize().height / (float)renderer.getFrameSize().width;

        int diff = ( panel.getHeight() - Math.round(ratio * panel.getHeight())) / 2;


        renderer.paintVideo(ig,
                new Rectangle(0, 0, renderer.getFrameSize().width, renderer.getFrameSize().height)
                ,
                new Rectangle(0, diff, panel.getWidth(), Math.round(ratio * panel.getHeight())));

}
    public static void main(String[] args) {

    }
}
```


----------



## Kr0e (4. Jan 2010)

Ist in Ordnung so! Ich habe die Zusammenstellung jetzt nicht mehr mit NetBeans gemacht.. Haben sich wohl ein paar Fehler eingeschlichen... Also es funktioniert ?


----------



## erxx (4. Jan 2010)

Lässt sich kompilieren, jedoch habe ich grad keine Ahnung wie ich das richtig aufrufe.

Bisher habe ich in meinem Projekt immer so gearbeitet dass ich Funktionen über Class.Funktion(Parameter...) aufgerufen habe dies geht aber in diesem Fall nicht.

Wie wäre denn ein konkretes Beispiel um mit dem Code ein Video abzuspielen?


----------



## Kr0e (4. Jan 2010)

Selbstverständlich,

du musst beim Parameter "prov" (Oben in der Class definiert) einfach .play() aufrufen! NAtürlich vorher die Klassen erstellen..

new MediaPlayer(File, JPanel) für File und JPanel musst du jetzt selbst sorgen 

Btw: Der Pfad darf nicht LEerzeichen enthalten.. Das ist noch wichtig!

EDIT: Wäre das vlt. etwas für diE FAQ ?


----------



## erxx (4. Jan 2010)

Also das File leg ich zB in ner anderen Klasse fest

```
File f = new File(System.getProperty("user.dir") + File.separator + "test.avi");
```
Genau so wie das Panel was ich per Drag an Drop in die Form schmeiße.


Wie übergebe ich denn nun die beiden Daten an den Player?


Bzw. wie meinst du ich muss die Klassen noch erstellen ^^?

Tut mir leid aber hab nun grad noch weniger Durchblick... Für mich ist das Gebiet noch Neuland und muss mich da erstmal zurecht finden


----------



## Kr0e (4. Jan 2010)

Meinst du Java im allgemeinen oder was jetzt ?

Also wie du die übergibst bzw erstellst...

Da du offensichtlich mit dem GUI-Builder Matisse arbeitest, werde ich das dementsprechend erklären:

Mach z.b. noch einen Button, Doppelclick druff, dann sollte sich iwas "onButtonClicked" mäßiges erstellen..

Dort schreibst du dann z.b. rein :

MediaPlayer m = new MediaPlayer(f, jPanel1);

Den Namen vom Panel hab ich jetzt geraten, der sollte aber stimmen sofern es das einzige Panel bei deinem Programm ist, ansonsten halt jPanel2 usw.. Musse halt mal schauen wie das heißt.. "f" ist ja das File das du erstellt hast...

Da du nun auch noch das Video starten willst, musst du in den Konstruktor vom MediaPlayer noch eine letzte Zeile einfügen.

public void MediaPlayer(File path, JPanel panel) {
    ig = (Graphics2D) panel.getGraphics();
    this.panel = panel;
    prov = new MediaProvider(path.toURI());
    renderer = prov.getControl(VideoRenderControl.class);
    renderer.addVideoRendererListener(this);

   //WICHTIG
   prov.play(); //Das startet nun das Video
}

Ich weiß garnciht, ob der Konstruktor ne Exception schmeißt, ich meine aber nicht.

Gruß,
Chris

PS: Dein Pfad könnte unter Umständen probleme geben... "user.dir" hat evt. Leerzeichen... Ich denke da grad an WIndows
"C:/Dokumente und Einstellngen/usw"

Fürn Test, kopier dein Video einfach nach C:/test.avi und dann dementsprechend : new File ("C:/test.avi") ...
Achja, ist nich schlimm, dass das Neuland ist, jeder fängt mal klein an. Aber vlt. brauchst du noch ein paar basics ?!


----------



## erxx (4. Jan 2010)

Vielen Dank werde ich gleich mal ausprobieren.

Naja meine Kenntnisse reichen immerhin schonmal aus um ein Funktionstüchtiges Lernprogramm (Brüche) zu erstellen welches oft gemachte Fehler beim Schüler ausfindig macht.  Ist mit Sicherheit schonmal etwas awer die Klassen usw machen mir noch einige Schwierigkeiten da ich gerade aus der Delphi Welt komme.

Edit:

also in meiner Klasse runIt habe ich nun 


```
private void jButton1MouseClicked(java.awt.event.MouseEvent evt) {
        // TODO add your handling code here:
        File f = new File(System.getProperty("user.dir") + File.separator + "test.avi");
        MediaPlayer m = new MediaPlayer(f, jPanel1);
    }
```

Wobei mir das zweite MediaPlayer bei 
	
	
	
	





```
MediaPlayer m = new MediaPlayer(f, jPanel1);
```
 unterstrichen wird. 

```
Cannot Find Symbol 
Symbol: constructor MediaPlayer(java.io.File,javax.swing.JPanel)
location: class audiovideo.MediaPlayer
```



Hier meine Form mit meinem Panel:

```
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * Video.java
 *
 * Created on 04.01.2010, 16:08:10
 */

package audiovideo;

import java.io.File;

/**
 *
 * @author erxx
 */
public class Video extends javax.swing.JFrame {

    /** Creates new form Video */
    public Video() {
        initComponents();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 457, Short.MAX_VALUE)
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 334, Short.MAX_VALUE)
        );

        jButton1.setText("jButton1");
        jButton1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jButton1MouseClicked(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 34, Short.MAX_VALUE)
                .addComponent(jButton1)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addGroup(layout.createSequentialGroup()
                        .addGap(20, 20, 20)
                        .addComponent(jButton1)))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>

    private void jButton1MouseClicked(java.awt.event.MouseEvent evt) {
        // TODO add your handling code here:
        File f = new File("F:\test.avi");
        //new File(System.getProperty("user.dir") + File.separator + "test.avi");
        MediaPlayer m = new MediaPlayer(f, jPanel1);
    }

    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Video().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify
    private javax.swing.JButton jButton1;
    private javax.swing.JPanel jPanel1;
    // End of variables declaration

}
```


und hier die MediaPlayer.java


```
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package audiovideo;


import com.sun.media.jmc.MediaProvider;
import com.sun.media.jmc.control.VideoRenderControl;
import com.sun.media.jmc.event.VideoRendererEvent;
import com.sun.media.jmc.event.VideoRendererListener;
import java.awt.Graphics2D;

import java.awt.Rectangle;
import java.io.File;
import javax.swing.JPanel;



public class MediaPlayer implements VideoRendererListener {

private MediaProvider prov; //This is the most important class!

private VideoRenderControl renderer; //It's a interface to control the rendering

private Graphics2D ig;

private JPanel panel;


public void MediaPlayer(File path, JPanel panel) {
//    File f = new File(System.getProperty("user.dir") + File.separator + "test.avi");
//    path = f;
//    panel = runIt.jPanel1;
    ig = (Graphics2D) panel.getGraphics();
    this.panel = panel;
    prov = new MediaProvider(path.toURI());
    renderer = prov.getControl(VideoRenderControl.class);
    renderer.addVideoRendererListener(this);

    prov.play();
}

@Override
public void videoFrameUpdated(VideoRendererEvent arg0) {
        float ratio = renderer.getFrameSize().height / (float)renderer.getFrameSize().width;

        int diff = ( panel.getHeight() - Math.round(ratio * panel.getHeight())) / 2;


        renderer.paintVideo(ig,
                new Rectangle(0, 0, renderer.getFrameSize().width, renderer.getFrameSize().height)
                ,
                new Rectangle(0, diff, panel.getWidth(), Math.round(ratio * panel.getHeight())));

}
    public static void main(String[] args) {

    }

}
```


----------



## Kr0e (4. Jan 2010)

Der "Konstruktor" ist kein Konstruktor... 

public VOID MediaPlayer(File path, JPanel panel) { //Mach das void raus. Dann sollte es klappen, In Java haben Konstruktoren keinen Rückgabewert! 
//    File f = new File(System.getProperty("user.dir") + File.separator + "test.avi");
//    path = f;
//    panel = runIt.jPanel1;
    ig = (Graphics2D) panel.getGraphics();
    this.panel = panel;
    prov = new MediaProvider(path.toURI());
    renderer = prov.getControl(VideoRenderControl.class);
    renderer.addVideoRendererListener(this);

    prov.play();
}


Wie gesagt, ich habe den Code ohne Editor gemacht... Da können sich kleine Fehler einschleichen


----------



## erxx (4. Jan 2010)

Ach die Fehler sind kein Problem 

Bin ja froh dass mir überhaupt einer weiter hilft!

Jedenfalls schreibt er nun da ich das void weggemacht habe, folgendes:


```
com.sun.media.jmcimpl.plugins.javapeer.MediaPlayer is abstract; cannot be instantiated
```


Edit:


jetzt funzt es jedoch erhalte ich beim ausführen des Buttons:


```
Exception in thread "AWT-EventQueue-0" java.lang.UnsatisfiedLinkError: com.sun.media.jmcimpl.plugins.directshow.DShowEngine.ndsInit()Z
        at com.sun.media.jmcimpl.plugins.directshow.DShowEngine.ndsInit(Native Method)
        at com.sun.media.jmcimpl.plugins.directshow.DShowEngine.nInit(DShowEngine.java:234)
        at com.sun.media.jmcimpl.plugins.directshow.DShowProvider$1.run(DShowProvider.java:206)
        at java.security.AccessController.doPrivileged(Native Method)
        at com.sun.media.jmcimpl.plugins.directshow.DShowProvider.init(DShowProvider.java:182)
        at com.sun.media.jmcimpl.plugins.directshow.DShowProvider.canPlay(DShowProvider.java:247)
        at com.sun.media.jmcimpl.PeerManager.getPlayerPeer(PeerManager.java:78)
        at com.sun.media.jmc.MediaProvider.setSource(MediaProvider.java:561)
        at com.sun.media.jmc.MediaProvider.<init>(MediaProvider.java:169)
        at audiovideo.MediaPlayer.<init>(MediaPlayer.java:38)
        at audiovideo.Video.jButton1MouseClicked(Video.java:90)
        at audiovideo.Video.access$000(Video.java:20)
        at audiovideo.Video$1.mouseClicked(Video.java:55)
        at java.awt.AWTEventMulticaster.mouseClicked(AWTEventMulticaster.java:253)
        at java.awt.Component.processMouseEvent(Component.java:6266)
        at javax.swing.JComponent.processMouseEvent(JComponent.java:3255)
        at java.awt.Component.processEvent(Component.java:6028)
        at java.awt.Container.processEvent(Container.java:2041)
        at java.awt.Component.dispatchEventImpl(Component.java:4630)
        at java.awt.Container.dispatchEventImpl(Container.java:2099)
        at java.awt.Component.dispatchEvent(Component.java:4460)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574)
        at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4247)
        at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
        at java.awt.Container.dispatchEventImpl(Container.java:2085)
        at java.awt.Window.dispatchEventImpl(Window.java:2475)
        at java.awt.Component.dispatchEvent(Component.java:4460)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
```


----------



## Kr0e (5. Jan 2010)

Das ist schonmal ein guter Fehler xD Wenigstens klappt es jetzt soweit.
Der Fehler besagt, dass JMC die nativen dlls nicht gefunden hat. Anscheinend hsat du
die JMC Klassen richtig deinem Classpath hinzugefügt, sonst würde es garnicht kompiliert werden.
Aber die JMC Java Klassen benötigen quasi eine externe Bibliothek, um zu funktionieren.... (Die sind ebenfalls in dem Ordner wo auch die jmc.jar war)

In meiner kleinen Beschreibung weiter oben, sind die dlls aufgelistet die du brauchst.
Du musst deinem Programm jetzt noch sagen, wo er nach nativen (Also OS - abhängigen) Libs suchen soll.
Da du NetBeans verwendest, hier die Erklärung:

Rechtsklick auf den Namen von deinem Projekt, "Properties bzw. Eigenschaften", Dann in der Kategorieliste links die Rubrik "Run bzw. Ausführen" anklicken. Nun siehst du unter anderem ein Textfeld mit der Bezeichnung "VM Options". Da kannst du jetzt ziemlich viele Dinge reinschreiben. Du brauchst aber nur folgendes für dein Problem:

-Djava.library.path=lib

Dieser Pfad besagt, dass die VM im Projektordner im Ordner "lib" nach nativen dll Dateien suchen soll. Kannste jetzt je nachdem wo 
deine Sachen sind abändern.

Damit sollte es gehen... 

Gruß,

Chris


----------



## erxx (5. Jan 2010)

FUNZT !!!
Die Dlls hatte ich mit kopiert aber er wusste halt nicht wo die sind ^^ aber nun gehts ja !


Herzlichen Dank !

Leider scheint das Bild etwas zu ruckeln oder sagen wir besser es hat den Anschein nicht sehr flüssig abzulaufen.

Wo genau kann ich denn nun das Bild selbst skalieren und Steuerungen wie Play/Pause hinzufügen ?


----------



## Kr0e (5. Jan 2010)

Hi, skalieren in der "videoFrameUpdated" Methode, dort wo ich das auch getan hab.
Halt dich am besten an mein Beispiel was die Anpassung angeht... Sonst passiert es shcnell, dass das bild zwar korrekt skaliert ist, aber iwo am Rand des JPanel abgespielt wird... 

renderer.paintVideo(Graphics, Rectangle, Rectangle) Diese Methode erwartet als 2ten Parameter das Rectangle des Frames das reinkommt. (Deswegen auch new Rectangle(0, 0, renderer.getFrameSize().width, renderer.getFrameSize().height))
Wir wollen ja schließlich das gesamte Frame, das reinkommt, auch darstellen!
Der dritte Parameter sagt, wo dieses Frame dann gezeichnet werden soll auf deinem JPanel. Eines ist noch wichtig:
Man kann das Video quasi nicht "falsch" skalieren. DAs Video wird IMMER von JMC im richtigen Seitenverhältnis gezeichnet!
Deswegen meine etwas umständliche Art das Rectangle zu bestimmen. Aber dafür ist es immer in der Mitte (Zumindest bei mir)

Zum Punkt "es ruckelt"... Verrate mir doch bitte deine Hardware... JMC ist im allgemeinen langsamer als native Player wie WMP oder VLC... Ich habe z.b. einen Intel Q 8300... Bei mir komm ich nie über 5% aus Auslastung...

Aber bei meinem alten AMD 3500+ Kam ich locker mal auf 65 - 70... Da muss man etwas Nachsicht mit Java haben...

Achja, welches Format schaust du dir an ? Irgendwelche hardcore Codec 1080p oder so brauchen natürlich mehr als DIVX oder XVID...


Gruß,
Chris

EDIT:

Pause ist ähnlich wie play() Mit dem MediaProvider "prov"!

Im Konstruktor rufst du ja prov.play() auf, Das kannste im Prinzip auch lassen... Mach für den prov ne Getter Methode rein,
und sag dann bei deinen Buttons:

MediaPlayer m = new MediaPlayer(File, JPanel);
m.getProvider().play() bzw. m.getProvider().pause();

"getProvider" gibt einfach nur die private Variable "prov" zurück vom MediaPlayer...


----------



## erxx (5. Jan 2010)

> Zum Punkt "es ruckelt"... Verrate mir doch bitte deine Hardware... JMC ist im allgemeinen langsamer als native Player wie WMP oder VLC... Ich habe z.b. einen Intel Q 8300... Bei mir komm ich nie über 5% aus Auslastung...



Intel Core2Duo 8400
2GB RAM DDR2
EVGA TX260



> Achja, welches Format schaust du dir an ? Irgendwelche hardcore Codec 1080p oder so brauchen natürlich mehr als DIVX oder XVID...



Normale Xvid 170MB gross... bei ner Dauer von 20 Min


----------



## Kr0e (5. Jan 2010)

Das ist sehr merkwürdig. Ich glaube nicht, dass es an der Hardware liegt.. hmm

Da bin ich leider überfragt... Ansonsten versuchs mal mit einer anderen Datei oder auf einem anderen Rechner (Nur um sicher zu gehen.)

Da die genutzten Codecs nativ sind, sollte es ansich ruckelfrei laufen...
Hast du schonmal irgendein codec pack installiert für Windows ?

Um JMC zu nutzen, hab ich bei mir K-Lite windows codecs runtergeladen.. Damit lief das dann.
Ich hatte erst nur DIVX. Problem war, dass das Video nicht aufs JPanel geziechnet wurde, sondern in einem neuen divx player
gestartet wurde...


----------



## erxx (5. Jan 2010)

Also es ruckelt nicht wirklich, es ist nur dass das Video nicht flüssig zu laufen scheint... :S

Ich hab nunmal  K Lite Codec Pack x64 installiert.

übrigends .pause() stoppt das Bild aber nicht den Ton


----------



## Kr0e (5. Jan 2010)

Hm, sehr merkwürdig. Mir sagen dir Probleme von denen du erzählst leider ncihts


----------



## erxx (5. Jan 2010)

ich hab irrtümlicherweise 2mal play aufgerufen ... jetzt habe ich alledrings das problem dass pause garnicht wirkt ^^

ausserdem ist das video bei mir nicht richtig skaliert, die höhe scheint zu kurz bzw die länge zu lang


----------



## Kr0e (5. Jan 2010)

Schau dir nochmal die Methode an, wo du "zeichnen" lässt. Vlt. hab ich da irgendein rechenfehler gemacht. Hab das noch nicht getestet... 

Zu der Sache mit pause() keine Ahnung. Bei mir hält er dann an. Vlt. irgendein anderer FEhler ?


----------



## erxx (5. Jan 2010)

Ist denn die Grösse des Panels egal ? 


Edit :Ausserdem werden die Videos die abgespielt werden nachher im Arbeitsverzeichnis abgelegt in dem aber dann Leerzeichen drin sein könnten... gibt es dafür denn keine Lösung ?


----------



## Kr0e (5. Jan 2010)

Mir ist bislang keine bekannt. Vlt. fehlt mir auch Wissen über die Klasse URL und URI... Man übergibt an den MediaProvider schließlich eine URI... Wenn die nun irgendwie speziell Leerzeichen makiert oder so.. könnte ich mir vorstellen, dass auch Leerzeichen möglich sind. Falls du dafür ne Lösung findest, sag bitte bescheid.

Wieso ist die Größe des Panels egal ?


```
@Override
public void videoFrameUpdated(VideoRendererEvent arg0) {
        float ratio = renderer.getFrameSize().height / (float)renderer.getFrameSize().width;
 
        int diff = ( panel.getHeight() - Math.round(ratio * panel.getHeight())) / 2;
 
 
        renderer.paintVideo(ig,
                new Rectangle(0, 0, renderer.getFrameSize().width, renderer.getFrameSize().height)
                ,
                new Rectangle(0, diff, panel.getWidth(), Math.round(ratio * panel.getHeight())));
 
}
```

Du benutzt doch da panel.getWidth() und panel.getHieght()


----------



## erxx (5. Jan 2010)

Werde mich dann mal nach ner Lösung zum Problem umschauen.


Ja stimmt habe es auch kurz nach dem posten bemerkt... Mal sehen ob ich das Problem mit dem Stoppen erstmal gelöst bekomme.

Danke dir für deine Geduld 


Edit: 

Hier ist was zum Thema Leerzeichen, ich versuch mich mal dran

Sonderzeichen umwandeln - Java @ tutorials.de: Forum, Tutorial, Anleitung, Schulung & Hilfe

Hab mal bezüglich des Thema bisschen rumgewerkelt und versucht die Leerzeichen bzw die + durch %2B zu ersetzen und als sich herausgestellt hat dass dies nicht funktionierte habe ich versucht einen escape leerzeichen zu übergeben... aber das wird immer als leerzeichen erkannt und in ein plus umgewandelt...


vllt noch wer ne idee ?


```
private static String getEnc(File path) {
       
      String pathStr = path.getPath().substring(3, path.getPath().length()); // Rest des Pfades ohne Laufwerk
      String drive = path.getPath().substring(0, 3); //Laufwerk
      String[] parsed = new String[20];
      String[] result = pathStr.split("\\\\"); // aufsplitten bei \
      String fullPath = drive;

      for(int i=0; i<result.length; i++) {
          try {
            parsed[i] = URLEncoder.encode(result[i], "UTF-8"); //parsen
            } catch(UnsupportedEncodingException uee) {
                uee.printStackTrace();
            }
          if(i == result.length-1) { //nach dateiname kein \ mehr
              fullPath = fullPath + parsed[i];
          } else {
          fullPath = fullPath + parsed[i] + File.separator; }
          fullPath = fullPath.replaceAll("\\%2B", "\\\\b");
          System.out.println(result[i] + "\n");
          System.out.println(parsed[i] + "\n");
          System.out.println(fullPath);

      }
//     encFile.resolve(fullPath);
//     encFile.toURL();
//     encFile.

     return fullPath;
   }
```


----------



## erxx (8. Jan 2010)

kann gelöscht werden


----------



## erxx (13. Jan 2010)

Hallo,

Das Fenster mit dem Video Player startet nur in der IDE, wenn ich jedoch die JAR-Datei ausführe wird nur dieses eine Fenster nicht geöffnet...

Woran könnte es liegen ?!

Edit:

Ich denke dass es daran liegt dass das JAR-File nicht auf den Ordner mit den DLLs zugreift oder sie zumindest nicht findet/laden kann und das nur beim kompilieren in der IDE funzt.


----------



## tuxedo (11. Feb 2010)

Hast du das mit dem ruckeln in den Griff bekommen?

Bastel selbst gerade ein wenig mit JMC. 

Da hier eigentlich direkt auf DirectShow aufgebaut wird sollte das in Java doch genauso schnell laufen wie außerhalb Java. 

Wenn JMC läuft kann ich mein auf DirectShow aufbauendes ActiveX Control das ich mittels SWT-Ole-Bridge mit Java benutze endlich entsorgen. Aber solange das Video in Java nicht genauso flüssig läuft wie in WMP oder VLC bringt's das nicht.

Die videoFrameUpdated() Methode hab ich schon gecheckt. Die braucht zwischen 2 und 4ms. Das sollte nicht das Nadelöhr sein. Kann darin sogar ein Sysout laufen lassen ohne dass es schlimmer wird.

Hier mein Sample-Code (bis auf die URL direkt lauffähig, nicht so wie die hier zusammengestückelten Codefragmente  ).


```
import java.net.URISyntaxException;
import javax.swing.JFrame;

import com.sun.media.jmc.MediaProvider;
import com.sun.media.jmc.control.VideoRenderControl;
import com.sun.media.jmc.event.VideoRendererEvent;
import com.sun.media.jmc.event.VideoRendererListener;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.net.URI;

public class MediaPlayer implements VideoRendererListener {

    private JFrame myFrame = new JFrame("MediaPlayer");
    private MediaProvider prov; //This is the most important class!
    private VideoRenderControl renderer; //It's a interface to control the rendering
    private Graphics2D g2;

    public MediaPlayer() throws URISyntaxException {

        myFrame.setLocationRelativeTo(null);
        myFrame.setSize(800, 600);
        myFrame.setVisible(true);


        this.g2 = (Graphics2D) myFrame.getContentPane().getGraphics();;
        prov = new MediaProvider(new URI("axrtpm://192.168.190.90/mpeg4/1/media.amp"));
//        prov = new MediaProvider(new URI("file:///C:/TheKnack.mpg"));
        renderer = prov.getControl(VideoRenderControl.class);
        renderer.addVideoRendererListener(this);

        System.out.println("Running ...");
    }

    @Override
    public void videoFrameUpdated(VideoRendererEvent arg0) {
        long start = System.nanoTime();
        float ratio = renderer.getFrameSize().height / (float)renderer.getFrameSize().width;

        int diff = ( myFrame.getHeight() - Math.round(ratio * myFrame.getHeight())) / 2;

        renderer.paintVideo(g2,
                new Rectangle(0, 0, renderer.getFrameSize().width, renderer.getFrameSize().height),
                new Rectangle(0, diff, myFrame.getWidth(), Math.round(ratio * myFrame.getHeight())));

        long stop = System.nanoTime();
        System.out.println((stop-start)/1000000);
    }

    public void play() {
        prov.setRepeating(true);
        prov.play();
    }

    public static void main(String[] args) throws URISyntaxException {
        System.out.println("Starting ... java.library.path="+System.getProperty("java.library.path"));
        MediaPlayer mediaPlayer = new MediaPlayer();
        mediaPlayer.play();
    }
}
```


----------



## tuxedo (26. Feb 2010)

Das ruckeln hab ich wegbekommen. Der Trick: In der 
	
	
	
	





```
videoFrameUpdated
```
 Methode im VideoRendererListener ist es "pöhse" direkt zu zeichnen. Stattdessen einfach ein 
	
	
	
	





```
repaint
```
aufrufen und in 
	
	
	
	





```
paintComponent
```
zeichnen.

Mein aktuelles sample


```
// JMCMediaPlayerSample 

import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;


import java.net.URI;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import com.sun.media.jmc.MediaProvider;

import com.sun.media.jmc.control.AudioControl;
import com.sun.media.jmc.control.VideoRenderControl;

import com.sun.media.jmc.event.VideoRendererEvent;
import com.sun.media.jmc.event.VideoRendererListener;

public class JMCMediaPlayerSample extends JFrame {

    MediaProvider mp;

    public JMCMediaPlayerSample(String mediaURI) {
        super("JMCMediaPlayerSample: " + mediaURI);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        try {
            mp = new MediaProvider(new URI(mediaURI));
            mp.setRepeating(true);
            mp.setRate(0.01d);
            
        } catch (Exception e) {
            System.out.println("Error opening media: " + e.toString());
            System.exit(1);
        }

        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        panel.add(new MediaPanel(mp), BorderLayout.CENTER);
        panel.add(createControlPanel(), BorderLayout.SOUTH);
        mp.play();

        setContentPane(panel);

        pack();
        setVisible(true);
    }

    public JPanel createControlPanel() {
        JPanel panel = new JPanel();

        JButton btnPlay = new JButton("Play");
        ActionListener alPlay = new ActionListener() {

            public void actionPerformed(ActionEvent ae) {
                mp.play();
            }
        };
        btnPlay.addActionListener(alPlay);
        panel.add(btnPlay);

        JButton btnPause = new JButton("Pause");
        ActionListener alPause = new ActionListener() {

            public void actionPerformed(ActionEvent ae) {
                mp.pause();
            }
        };
        btnPause.addActionListener(alPause);
        panel.add(btnPause);

        JButton btnStop = new JButton("Stop");
        ActionListener alStop = new ActionListener() {

            public void actionPerformed(ActionEvent ae) {
                mp.pause();
                mp.setMediaTime(0.0);
            }
        };
        btnStop.addActionListener(alStop);
        panel.add(btnStop);

        JCheckBox cbMute = new JCheckBox("Mute");
        ChangeListener clMute = new ChangeListener() {

            public void stateChanged(ChangeEvent ce) {
                JCheckBox cb;
                cb = (JCheckBox) ce.getSource();
                AudioControl ac;
                ac = mp.getControl(AudioControl.class);
                ac.setMute(cb.isSelected());
            }
        };
        cbMute.addChangeListener(clMute);
        panel.add(cbMute);

        panel.add(new JLabel("Duration: " + mp.getDuration()));

        return panel;
    }

    public static void main(final String[] args) {
        if (args.length != 1) {
            System.err.println("usage: java JMCMediaPlayerSample mediaURI");
            return;
        }

        Runnable r = new Runnable() {

            public void run() {
                new JMCMediaPlayerSample(args[0]);
            }
        };
        EventQueue.invokeLater(r);
    }
}

class MediaPanel extends JPanel {

    private AlphaComposite ac1 = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f);
    private AlphaComposite ac2 = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f);
    private Dimension frameSize;
    private Font font = new Font("Verdana", Font.BOLD, 20);
    private VideoRenderControl vrc;

    MediaPanel(MediaProvider mp) {
        vrc = mp.getControl(VideoRenderControl.class);
        if (vrc == null) {
            System.err.println("no video renderer control");
            System.exit(-1);
        }
        frameSize = vrc.getFrameSize();
        System.out.println("Framesize: "+frameSize);
        VideoRendererListener vrl;
        vrl = new VideoRendererListener() {

            public void videoFrameUpdated(VideoRendererEvent vre) {
                repaint();
            }
        };
        vrc.addVideoRendererListener(vrl);
        setPreferredSize(new Dimension(frameSize.width, frameSize.height));
    }

    protected void paintComponent(Graphics g) {

        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

//        g2d.setComposite(ac1);
        vrc.paintVideo(g2d,
                new Rectangle(0, 0, frameSize.width, frameSize.height),
                new Rectangle(0, 0, getWidth(),getHeight()));

        g2d.setComposite(ac2);
        g2d.setColor(Color.yellow);

        
        g2d.fillOval(getWidth()/2-50,getHeight()/2-50, 100, 100); // center

        g2d.setFont(font);
        g2d.setPaint(Color.red);
        g2d.drawString("My alpha transparent test overlay", 50, 50);
    }
}
```

Einfach mit Copy&Paste in die IDE ziehen, JMC.jar in den Classpath werfen und die jmc.dll in den lib path aufnehmen. Fertig. 

Sogar overlays mit Alpha-Blending gehen 1a.

Einziges Manko:

Das Ding braucht immernoch >5-10% mehr CPU für unsere Netzwerkstreams als der WindowsMediaPlayer *grml*

Kein Plan wo die CPU Last herkommt...

- Alex


----------



## Kr0e (26. Feb 2010)

Hallo Tuxedo,
freut mich, dass du das Ruckeln in den Griff bekommen hast. Bei mir braucht das sowieso etwas länger zu zeichnen, da ich in eine OpenGL Textur rendere was erheblichen Overhead verursacht, da die Bildformate erst konvertiert werden müssen. Die 5-10% mehr CPU Last halte ich schon für verdammt gut.

Ich bin mir jetzt nicht 100% sicher, aber der WMP z.B. rendert doch nicht mit GDI oder ?
Ich glaube der nutzt directdraw mit directplay für die Dekodierung... (Korrigiere mich, falls ich falsch liege!)
Sprich die Visualisierung des Frames geht vlt. ein wenig schneller...

An der Dekodierung dürfte es meiner Ansich nach auch nicht liegen. Du könntest das auch mit OpenGL vlt. beschleunigen, aber bisher kann man nicht direkt den FrameBuffer des Videos auslesen, da es noch nicht implementiert ist (Ist mir mal aufgefallen, als ich mal den Sourcecode davon durchstöbert hab) Ab JDK 7 wird sich das hoffentlich ändern. JMC ist ja offiziel noch garnicht für Java released. Ich habs ja wie beschrieben (Wie du ja auch^^) aus dem JavaFX Paket extrahiert... die basteln da wohl noch dran rum.

Ich löse das Problem zur Zeit so, dass ich quasi in ein bufferedImage rendere und dieses dann in eine OpenGL Texture kopiere. Das bringt allerdings wie gesagt mehr Overhead. Solange du in der Übergangsphase (Vorrausgesetzt SUN hält sich an ihr Versprechen ) mit 10-5% mehr CPU leben kannst, würde ich JMC durchaus verwenden.

In der PM sagtest du was von 32 gleichzeitig abgespielten Videos (bzw. Streams), Ich konnte mit der OpenGL Variante 8 gleichzeitig abspielen, danach war es nicht mehr zumutbar. Die normale Java2D Impl. schafft bei mir locker 15 (Ich hab keinen allzu schnellen Pc)  DivX Videos. Allerdings merkt man das dann schon...^^ Nachdem du die Repaint-Geschichte gelöst hast, konntest du schon testen, ob 30 Videos funktionieren bei dir (bzw. Firma) ?

Gruß,
Chris


----------



## tuxedo (1. Mrz 2010)

Hi,

der WMP renderet selbst gar nicht. Er baut intern den Filtergraph auf und gibt dem Graphen ein Window-Handle in das der entsprechende VideoRenderer (per Default der Video Renderer 7, in meinem Fall "forciert" der "Video Mixing Renderer 9") hineinzeichnet/rendert. 

Ob der Renderer dann GDI/GDI+ oder sonst was benutzt: Kein Plan. 

Wenn ich das rendern/zeichnen des Video komplett weglasse (repaint() ausklammern), dann kostet's noch genausoviel CPU. Von daher kann es nicht am Zeichnen liegen. Es muss irgendwie zwischen dem dekodieren und dem ansteuern mit Java liegen. Ich werd' das ganze nochmal versuchen zu profilen. Vielleicht komm ich damit dahinter ...

Das ganze on OpenGL zu verlagern: Das wäre eine Idee. Aber da wie gesagt das abschalten des Zeichnens keine besserung bringt, würde OpenGL ja auch nix bringen. Denn OpenGL setzt ja erst nach dem dekodieren, bzw. erst beim zeichnen an.

Das mit dem BufferedImage wird für mich dann später auch relevant. Damit lassen sich nämlich recht einfach solche Features wie "Video wird von anderen Fenster gerade verdeckt und ist nicht sichtbar, aber in einem ToolTop an einer bestimmten Stelle sieht man das Video noch" basteln. Also wie in Vista oder Win7 oder wie in Linux mit Compiz/Beryl ... Sowas wollen Kunden sehen/haben 

Was mir persönlich noch sorgen macht ist die Lizenz ... Bisher bastle ich ja nur mit JMC um Vergleiche anzustellen. Aber ich hoffe dass Sun/Oracle hier mal bald etwas an der aktuellen Lizenzsituation ändert. 

Nochmal zum Performance-Problem: Hab im Sun-Forum auch nochmal gepostet. Vielleicht springen da ja Experten rum die ne klare Ansage machen können ?!

--> JavaFX Application Development - Videorendering via JMC: Slower than native?!

Gruß
Alex


----------



## Kr0e (1. Mrz 2010)

Die Sache mit der Lizenz stört mich auch erheblich. Mal schauen wann Sun endlich mal JDK7 rausbringt.
Da gitbs ja noch ganz andere Leckerbissen  -> JWebPane!!

Alles in allem ist Multimedia noch sone Sache bei Java. Ich würde einfach vermuten dass der geringe Overhead (Das lag doch bei dir jetzt alles in einem Bereich < 10% oder ?) einfach dadurch zustande kommt, dass es eben native ist. Vlt. sind die nativen Wrapperklassen auch noch nciht ausgereift von JMC. Ich meine du bewegst dich ja in einem extrem kleinen "Overheadbereich". Ich finde es ehrlich gesagt verblüffend dass es überhaupt so gut funktioniert!

Gruß,
Chris


----------



## tuxedo (1. Mrz 2010)

Hab eben vor der Mittagspause noch ne kleine Besprechung mit unserem DirectShow Experten gehabt.

Unser Fazit:

JMC scheint intern sowas wie einen renderless playback-mode des VideoRenderers auf dem Filtergraphen zu unterstützen. Dabei klinkt sich JMC direkt in der Renderprozess ein und nimm allem anschein nach die Frames die es zu rendern gilt direkt auf in einen entsprechenden Buffer. Dann wird auf Java Seite das VideoFrameUpdated Event ausgelöst und im paintComponent() dann dieser Puffer nach dem aktuellen Frame befragt und mit Java-OnBoard Mitteln auf das Frame gezeichnet. 

In meinem AxctiveX Control Fall läuft das anders: Da wird dem Renderer das Window Handle, die Offset-Position und Größe des Ausgaberechtecks mitgeteilt. Jedesmal wenn ein Frame dekodiert wurde wird dieser direkt in den Speicherbereich dieses Windows für dieses Rechtecks geclippt. 

Im JMC Fall hat man hier einen gewissen Overhead durch das umkopieren der Frames in den Buffern etc. Desweiteren hat man den Nachteil, dass das Zeichnen der Frames vom Takt im FIltergraphen entkoppelt ist: Du bietest nur Frames an und hoffst dass irgendwann mal irgendwer die Frames holt und zeichnet. Speziell im Broadcast- und Television Markt wird so ein Verfahren wohl nicht akzeptiert werden. Da geht's um jedes Frame. Da darf nix gedroppt werden und da müssen die zeitlichen Abstände zwischen den Frames passen. Mit dieser Indirektion hebelt man das natürlich komplett aus. 

Auf ausreichend schnellen Maschinen mag es zwar gehen: Aber garantieren kann man das mit diesem Ansatz nicht. 

Für den Consumer-Markt ist es auch völlig unerheblich ob nun ein Video mit 2-5% CPU last oder mit 10-15%CPU Last läuft. Hauptsache es läuft und die CPU hat nebenher noch Platz für andere Sachen. Use-Cases wie >16 Videos gleichzeitig sind da eher nicht der Fall. 

Ich denke ich werde mein ActiveX Control mal zu einer normalen DLL Umbauen und da noch die Funktionalität, wie sie JMC bietet (Event bei neuen Frames + getriggertes zeichnen der Frames) einbauen. Entweder ich seh dann den gleichen Performance-Verlust, oder es läuft besser. Und wenn's besser läuft muss ich immer noch die Sache mit dem Broadcast- und Television Markt analysieren. Die Chancen stehen aber nach diesen Erkenntnissen jetzt schon nicht gut.

Naja, mal schauen. Warte auch noch auf Antwort aus dem Sun-Forum.

- Alex


----------



## Kr0e (1. Mrz 2010)

Hmm, dann müsste die Performance also unterschiedlich auf unterschiedlichen OSs sein, oder ?. Unter Linux wird ja z.B. GStreamer zur Dekodierung verwendet. Oder auf Mac direct "Core". Oder ist diese Verhalten dann demnach unabhängig vom Dekoder?

Noch eine Frage! Wenn das mit dem "renderless" stimmt, müsste dann nciht eigentlcih die Auslastung fast 0 sein wenn man nicht rendert ? (Was ja bei dir nicht der Fall war...)


----------



## tuxedo (1. Mrz 2010)

Naja. Wenn JMC auf LInux mit GStreamer auch das Konzept des VideoBuffer-umkopierens verfolgt, dann ist da die CPU Last ebenfalls höher. 

Ich hab das mit einer lokalen MPEG2 File sogar mal ausprobiert. Und ja, es hat auch hier mehr Ressourcen benötigt.

Lass dich nciht vom Namen "renderless" täuschen. renderless heisst in dem zusammenhang nur, dass der VideoRenderer Filter im DirectShow Filtergraph nicht direkt für's rendern zuständig ist. Stattdessen gibt man ihm ein Stück Code das er dann zum rendern einsetzt. Ist vielleicht vergleichbar mit einem Plugin-System: Der letztendliche "Rendering" mechanismus lässt sich austauschen. 

Gerendert wird aber in jedem Fall. Der Hauptaufwand liegt auch nicht im Rendern (anzeigen), sonder, je nach Stream, mit sicherheit beim dekodieren. 

- Alex


----------



## maximal2011 (29. Mrz 2011)

Sorry, dass ich diesen Beitrag nochmal ausgrabe aber ich habe ein Problem mit dem auf der 1. bzw. 2. Seite genannten Beispiel. Undzwar gibt mir die folgende Methode einen Fehler:


```
renderer.paintVideo(ig,
                new Rectangle(0, 0, renderer.getFrameWidth(), renderer.getFrameHeight())
                ,
                new Rectangle(0, diff, panel.getWidth(), Math.round(ratio * panel.getHeight())));
```

Die paintVideo Methode existiert leider nicht (Cannot find Symbol. usw.). Auch autoComplete von renderer gibt mir keine passende Methode an. Der Rest scheint alles erkannt zu werden und zu funktionieren. Lediglich diese paintVideo Methode gibt es nicht. Wie kann ich das Video trotzdem in meinem JPanel anzeigen lassen?

Vielen Dank.


----------

