java video javafx codec vlcj

Agregar otros códecs de video/soporte de DVD a JavaFX 2.2



codec vlcj (5)

Créeme, siento y conozco tu frustración. He reflexionado sobre esto por un tiempo, pero tuve que usar medios poco claros para resolver mis problemas.

Hay muchas maneras de evitar esto, cada una con limitaciones, pero depende de lo que funcione para usted:

  1. Docs dice que WebView funciona con HTML5, que reproduce videos compatibles con la plataforma (aunque lamentablemente no es flash). Si el uso de una vista web para reproducir un video funciona para usted, puede probar esto. Incluso puedes dibujar sobre él con otros nodos.

  2. Reproductor VLC portátil! Si tal vez está desarrollando algún tipo de aplicación de proyector / director y desea un video de pantalla completa, puede hacer que el reproductor VLC portátil reproduzca el video en pantalla completa en una pantalla y los controles en la otra. Usé esta solución y funciona bastante bien para mac y windows. :) Lo único es que no puedes dibujar nodos en el video, ya que es una aplicación externa, con solo la ilusión de un video de pantalla completa de tu aplicación.

  3. Si alguna vez necesitas utilizar el poder del flash en tu aplicación javafx 2.0, entonces usa un navegador basado en swt (o algo así como el Proyecto DJ si eres un Swinger) ya que son compatibles con todas las funciones de tu navegador nativo.

Actualizar:

Dado que el lado de los medios de JFX ha sido de código abierto, he investigado esto por mí mismo y es realmente posible, pero requiere cambiar y reconstruir la fuente de JFX (partes de Java y C). El proceso se describe here para cualquier persona que quiera tener un ir - agrego soporte MKV en ese ejemplo, pero debería ser muy similar para otros complementos.

El resto de la pregunta es, por lo tanto, principalmente histórico, pero lo dejaré aquí como referencia.

Fondo

He estado usando VLCJ hasta ahora para reproducir video en mi aplicación. Funciona, pero si es posible, me gustaría ver si puedo lograr un nivel de soporte similar para los códecs comunes al migrar a JavaFX y evitarme muchos problemas con varias máquinas virtuales, por lo que VLCJ necesita reproducir múltiples videos de manera confiable. No voy a entrar aquí, pero vea mi respuesta a this pregunta si está interesado en los detalles. También está el problema de la compatibilidad multiplataforma, funciona bien en Mac y Linux, pero aún no he descubierto cómo hacer que se muestre en Mac (creo que existe cierta seguridad para evitar que un proceso obtenga acceso a otro nativo componentes, pero de nuevo eso está más allá del alcance de esta pregunta.)

Se reduce al hecho de que, si bien funciona, requiere mucho mantenimiento y problemas para trabajar con varias máquinas virtuales y para unirlas de manera estable si hay otra solución que sería más fácil. VLC tiene un nivel de soporte bastante legendario para reproducir casi cualquier cosa, por eso lo he hecho hasta ahora, y me gustaría ver si puedo obtener un resultado similar en JavaFX, o al menos si puede Proporcionar los medios para hacerlo de manera multiplataforma.

Investigación

JavaFX 2.0 soporta video - ¡genial! Pero en este momento la línea oficial es que admite "FLV que contiene video VP6 y audio MP3". ¿Hay alguna forma de extender esto para agregar compatibilidad con más codecs? No hay ningún códec duro que me gustaría apoyar, es más un caso de tantos como puedo, así que estoy buscando un método extensible para abordar lo anterior.

Me pregunté si reproduciría video para los códecs instalados de forma nativa en la máquina y que simplemente no se anunciará como tal (porque esa funcionalidad obviamente depende de la máquina y no es multiplataforma). Pero no dados, he intentado un número de formatos comunes y realmente se niega a jugar otra cosa que no sea lo que dice.

Al observar JavaFX 1.3, también es compatible con otros códecs dependientes de la plataforma, dependiendo de dónde esté instalado . ¿Hay alguna manera de obtener este comportamiento con JavaFX 2? ¿O está planeado para un lanzamiento posterior? No he podido encontrar ninguna información sobre él en la hoja de ruta ni ningún comentario de Oracle al respecto.

Lo único que pude encontrar en la búsqueda extensa está here que implica que puede ser posible pero nadie parece saber cómo hacerlo. También me gustaría saber si está basado en GStreamer, ¿por qué todos los formatos compatibles con GStreamer tampoco están incluidos de forma predeterminada?

En cuanto a la reproducción de DVD con JavaFX, no tengo absolutamente nada en ninguna parte, así que supongo que no hay nada por el momento. Si alguien tiene alguna idea o información, soy todo oídos.

Otros enfoques

Uno de los enfoques en los que me estaba preguntando es posible: sacar el frasco de JMC del antiguo JavaFX como se describe here e intentar que funcione junto con el JavaFX 2. ¿No creo que alguien haya tenido suerte con ese enfoque o algo similar?

Todas las cosas fallan, si alguien tiene alguna información o enlaces sobre si el soporte para códecs adicionales se admitirá de forma inmediata, también me interesaría saberlo. O si alguien tiene algún tipo de información de contacto de alguien en Oracle, ¡puedo pedirle que también se lo agradezca! He estado anhelando un soporte de video decente en Java por algún tiempo, y supongo que esto se reduce a tratar de averiguar si JavaFX es la respuesta a esto, o simplemente otro intento a medias que nunca jugará más de lo que es. lo hace en este momento! Espero que no sea lo último, pero todavía tengo que ver mucho para demostrar que ese es el caso.


El diseño de la API no parece tener soporte para rodar tus propios códecs. Casi todas las clases son finales (por ejemplo, VideoTrack, Media, MediaPlayer, etc.). Supongo que la decodificación de video real se realiza con clases internas en el presente, lo que significa que no hay forma de anularlas.

Hay un plan para Open Source JavaFX 2.0 , sospecho que a medida que nos acercamos al lanzamiento de JDK8. Esperemos que cuando hagan esto podamos ver cómo resuelven sus códecs desde el constructor de Media(String source) y ver si podemos conectarnos de alguna manera.


Las solicitudes de funciones abiertas actuales para esto en el sistema de seguimiento de errores de JavaFX:

Lea las solicitudes de funciones vinculadas y los comentarios asociados sobre ellas para comprender su estado actual (o la falta de ellas ;-) para la versión de distribución de JavaFX que está utilizando.

Tenga en cuenta que, para la API de medios basada en InputStream, uno de los comentarios posteriores de un desarrollador de JavaFX es "Propongo que consideremos esto para JDK 10", por lo que creo que puede ser una posibilidad en el futuro ...

También tenga en cuenta que si no está seguro de si JavaFX actualmente tiene soporte incorporado para un tipo de codificación determinado o no, en javadoc para el paquete javafx.media se proporciona una descripción general completa de las codificaciones de medios compatibles y los tipos de contenedores de medios (solo asegúrese de que revisa la versión del javadoc que coincide con su versión de JavaFX).

Aquellos que puedan estar interesados ​​en otras soluciones para al menos obtener un video para reproducir desde JavaFX, incluso si se trata de un tipo de medios que JavaFX no admite de forma nativa y usted no desea piratear el soporte de medios JavaFX nativo solo para que su video llegue a juego, también puede ver mi respuesta a la pregunta relacionada:


Y ahora, Javafx2.1 finalmente es compatible con mp4 H.264, por lo que ahora debería ser bueno sin los trucos publicados anteriormente. :)


Ahora he logrado compilar el soporte MKV en JavaFX con éxito, y requiere algo de esfuerzo, pero no mucho esfuerzo en la capa nativa también. Consulte here para ver la discusión que lo rodea, y here para ver el resultado enviado como un parche / boleto JIRA.

He escrito una guía mucho más completa sobre el proceso here que puede ser de interés para cualquier persona que quiera seguir este camino.

Lo que sigue es mi breve investigación antes de que realmente considerara seriamente la compilación de otros medios de comunicación, aunque lo dejo aquí como referencia.

Ahora que JFX8 ha sido lanzado y es completamente de código abierto, he dedicado un poco de tiempo a ver cómo se puede hacer esto, y si se podría hacer sin parchear la fuente JFX. Desafortunadamente, la respuesta a este último punto es un no casi definitivo, al menos no sin trucos de manipulación de bytecodes horribles. Puedo analizar esto más prácticamente en una fecha posterior, pero documentaré lo que he trabajado hasta ahora de la fuente disponible.

La magia comienza desde el constructor de Medios , que es, en última instancia, desde donde MediaException la MediaException (con el indicador MEDIA_UNSUPPORTED si intentas reproducir un formato no compatible). Desde allí, crea el Locator , cuyo constructor garantiza que la URL sea compatible. A continuación, se llama al método init() en un subproceso independiente, que realiza algunas comprobaciones de cordura en la cadena de URL, lee el archivo y luego trata de averiguar cuál es el formato.

El código relevante para esta parte del método es así:

if (scheme.equals("file") || scheme.equals("jar")) { InputStream stream = getInputStream(uri); stream.close(); isConnected = true; contentType = MediaUtils.filenameToContentType(uriString); // We need to provide at least something } if (isConnected) { // Check whether content may be played. // For WAV use file signature, since it can detect audio format // and we can fail sooner, then doing it at runtime. // This is important for AudioClip. if (MediaUtils.CONTENT_TYPE_WAV.equals(contentType)) { contentType = getContentTypeFromFileSignature(uri); if (!MediaManager.canPlayContentType(contentType)) { isMediaSupported = false; } } else { if (contentType == null || !MediaManager.canPlayContentType(contentType)) { // Try content based on file name. contentType = MediaUtils.filenameToContentType(uriString); if (Locator.DEFAULT_CONTENT_TYPE.equals(contentType)) { // Try content based on file signature. contentType = getContentTypeFromFileSignature(uri); } if (!MediaManager.canPlayContentType(contentType)) { isMediaSupported = false; } } } // Break as connection has been made and media type checked. break; }

A partir de esto, podemos ver que se realiza un primer intento "tonto" para capturar el contenido del archivo en función de su nombre (esto es lo que hace MediaUtils.filenameToContentType() .) Hay algunos casos especiales para verificar diferentes tipos de archivos wav, pero si eso falla, luego recurrimos a una comprobación más inteligente que analiza la firma real del archivo. Ambas verificaciones están en MediaUtils . Esta última verificación es mucho más extensa y examina los primeros bytes del archivo para ver si puede trabajar en un formato de esa manera. Si no puede, entonces rescata y lanza la excepción que luego aparece como nuestra temida bandera MEDIA_UNSUPPORTED .

Sin embargo, si el tipo se identifica correctamente, todavía hay otro obstáculo que superar: tiene que ser compatible con la plataforma actual. Algunas plataformas se cargan dinámicamente según el entorno, sin embargo, la GSTPlatform siempre existe, por lo que tendríamos que poner aquí cualquier formato adicional (universal). Esto es relativamente simple, existe una matriz CONTENT_TYPES que solo contiene la matriz de formatos compatibles.

Desafortunadamente, la clonación del repositorio de JavaFX parece estar fallando para mí en este momento, de lo contrario intentaría poner algo de esto en práctica. Pero en lugar de lo anterior, ¿qué debe suceder realmente para agregar soporte para formatos adicionales? En realidad no parece muy difícil.

  1. En MediaUtils , el soporte debe agregarse al método filenameToContentType() para manejar la nueva extensión de archivo. Esto es trivial.

  2. En la misma clase, es necesario agregar soporte al método fileSignatureToContentType() para calcular el tipo de archivo según su firma. Esto es un poco más complejo, pero no está tan mal. Esto incluso puede ser opcional, ya que el código actual solo parece usar esto como un respaldo si el formato no se identifica correctamente (o no se identifica) con la extensión del archivo. Una lista completa de firmas de archivos para diferentes formatos se puede encontrar here que debería ayudar con esta tarea.

  3. En GSTPlatform, el nuevo tipo de contenido debe agregarse a la lista de tipos de contenido admitidos.

En el lado de Java de las cosas, esto parece ser todo lo que es necesario para que acepte el tipo de contenido y al menos intente transmitirlo a la capa nativa de Gstreamer .

Sin embargo, no soy un experto en GStreamer, así que aunque estoy consciente de que hay muchos más formatos que puede manejar y reproducir que JavaFX actualmente rechaza, no estoy seguro de cómo han eliminado exactamente esta capacidad. Definitivamente lo han hecho en la capa Java de arriba, pero también pueden haberlo hecho en el nivel nativo de GStreamer; en este momento no estoy seguro.

Supongo que han hecho algunos cambios en GStreamer para JFX8, pero en este momento no aparecen en la página del proyecto correspondiente , por lo que es bastante difícil averiguar qué han cambiado exactamente para esta versión.

El siguiente paso sería tomar el código fuente de JFX8, compilar con los cambios propuestos anteriormente para un nuevo tipo de contenido, y luego ver qué errores (si los hay) ocurren en el nivel nativo, luego tomarlo desde allí.