Sunday, June 13, 2010

MediaPlayer Component

Getting JMC from JavaFX 1.3 to work within Sgine took a bit longer than I anticipated. In JavaFX 1.2 it was a simple matter of calling paintVideoFrame and using a BufferedImage to draw onto and then convert to a texture. Fortunately for performance in JavaFX 1.3 they changed to working with NIO buffers instead, but unfortunately that created a much bigger headache trying to figure out how to access and properly use it since there is absolutely no documentation and the source code is not freely available. However, after several days of poking around it has finally paid off. There are still some optimizations that should be done but on my machine I'm able to watch H.264 video at 4,000fps in synchronous mode (direct rendering in OpenGL) and 5,200fps in asynchronous mode (pushing data to the buffer in another thread via PBO).

Here's a screenshot of the working example:


Here's the source required to run the video:
package org.sgine.ui

import org.sgine.core.Resource

import org.sgine.render.Renderer
import org.sgine.render.scene.RenderableScene

import org.sgine.scene.GeneralNodeContainer
import org.sgine.scene.ext.ResolutionNode

object TestMediaPlayer {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(640, 480, "Test MediaPlayer")
  
  val scene = new GeneralNodeContainer() with ResolutionNode
  scene.setResolution(640, 480)
  
  val component = new MediaPlayer()
  val url = new java.net.URL("http://sun.edgeboss.net/download/sun/media/1460825906/1460825906_2956241001_big-buck-bunny-640x360.flv")
  component.source := Resource(url)
  scene += component
  
  r.renderable := RenderableScene(scene)
  
  component.play()
 }
}

As always the goal is to keep the API as simple as possible and hopefully 27 total lines of code is simplistic enough. :)

There's still much left to do as far as introspection and control of video playing as well as controls to allow user interaction with the player, but we've finally got a fast and reliable means of playing all popular audio and video formats and I will probably divert back to more important work for a while. :)

3 comments:

  1. hi, would you mind post more information about how to interpret the NIO of jmc?

    Regards
    peter

    ReplyDelete
  2. same,any more info about how to to it with nio? thxs

    ReplyDelete
  3. Well, in this case I have the advantage of being able to pass the buffered data directly to OpenGL as an image but you could do the same to generate a BufferedImage for use in Swing.

    Take a look at the source for MediaPlayer for more: http://code.google.com/p/sgine/source/browse/src/main/scala/org/sgine/ui/MediaPlayer.scala

    ReplyDelete

Scala Engine for high-performance interactive applications.