Aggiunta di altri codec video / supporto DVD a JavaFX 2.2

Aggiornare:

Dal momento che il lato multimediale di JFX è stato open source, ho esaminato me stesso ed è effettivamente ansible, ma richiede la modifica e la ricostruzione del sorgente JFX (sia parti Java che C). Il processo è descritto qui per chiunque voglia provatelo – aggiungo il supporto MKV in questo esempio, ma dovrebbe essere molto simile per altri plugin.

Il resto della domanda è quindi principalmente storico, ma lo lascerò qui per riferimento.

sfondo

Ho usato VLCJ finora per riprodurre video nella mia applicazione. Funziona, ma se ansible mi piacerebbe vedere se riesco a raggiungere un livello simile di supporto per codec comuni migrando a JavaFX e risparmiando un sacco di problemi con più VM e in modo simile a VLCJ che ha bisogno di riprodurre più video in modo affidabile. Non entrerò qui ma vedrò la mia risposta a questa domanda se sei interessato ai dettagli. C’è anche il problema della compatibilità multipiattaforma, funziona su Mac e Linux, ma non ho ancora capito come farlo visualizzare su Mac (credo che ci sia un po ‘di sicurezza per impedire a un processo di accedere a un altro nativo componenti, ma ancora una volta va oltre lo scopo di questa domanda).

Si riduce al fatto che, mentre funziona, è un sacco di manutenzione e problemi di lavoro con più macchine virtuali e il loro collegamento stabile se c’è un’altra soluzione che sarebbe più facile. VLC ha un livello di supporto piuttosto leggendario per giocare praticamente a tutto ciò che è il motivo per cui ci sono andato fino ad ora, e sarei interessato a vedere se posso ottenere un risultato simile in JavaFX – o almeno se può fornire i mezzi per farlo in modo multipiattaforma.

Ricerca

JavaFX 2.0 supporta video: ottimo! Ma al momento la linea ufficiale supporta “FLV contenente video VP6 e audio MP3”. C’è un modo per estendere questo per aggiungere supporto per più codec? Non c’è un codec difficile che mi piacerebbe supportare, è più un caso di quanti ne posso, quindi sto cercando un metodo estensibile per andare su quanto sopra.

Mi chiedevo se avrebbe riprodotto video per i codec installati in modo nativo sulla macchina e che semplicemente non si pubblicizza come tale (perché quella funzionalità ovviamente dipende dalla macchina e non dalla multipiattaforma.) Ma niente dado, ho provato un numero di formati comuni e rifiuta davvero di suonare qualcosa di diverso da ciò che afferma.

Guardando JavaFX 1.3 supporta anche altri codec dipendenti dalla piattaforma, a seconda di dove è installato . C’è un modo per ottenere questo comportamento con JavaFX 2? O è previsto per una successiva versione? Non sono stato in grado di trovare alcuna informazione su di esso sulla roadmap o commenti da Oracle a riguardo.

L’unica cosa che ho potuto trovare dalla ricerca estensiva è qui che implica che potrebbe essere ansible ma nessuno sembra sapere come. Sarei anche interessato a sapere se è basato su GStreamer perché tutti i formati supportati da GStreamer non sono inclusi di default?

In termini di riproduzione di DVD con JavaFX non ho assolutamente nulla, quindi presumo che sia solo un no-go al momento. Se qualcuno ha comunque idee o informazioni, sono tutto orecchie.

Altri approcci

Un approccio che mi chiedevo a metà potrebbe essere ansible è il crowbaring del jar JMC dal vecchio JavaFX come descritto qui e il tentativo di farlo funzionare insieme a JavaFX 2. Non credo che qualcuno abbia avuto fortuna con questo approccio o qualcosa di simile?

Tutte le cose falliscono, se qualcuno ha informazioni o collegamenti se / quando il supporto per codec aggiuntivi sarà supportato immediatamente, quindi sarei interessato a sentirlo anche. O se qualcuno ha dei dettagli di contatto per qualcuno in Oracle, potrei chiedere che sarebbe apprezzato! Ho desiderato ardentemente un supporto video decente in Java per un po ‘di tempo, e immagino che questo si riduce a cercare di capire se JavaFX è la risposta a questo, o solo un altro tentativo di mezzo cuore che non giocherà mai più di quello che fa al momento! Spero che non sia il secondo, ma devo ancora vedere molto per dimostrare che è così.

Credimi, sento e conosco la tua frustrazione. Ho riflettuto su questo per un po ‘, ma ho dovuto usare mezzi non diretti per risolvere i miei problemi.

Ci sono molti modi per aggirare questo, ognuno con limitazioni ma dipende da ciò che funziona per te:

  1. I documenti dicono che WebView funziona con HTML5, che riproduce i video supportati sulla piattaforma (anche se purtroppo non è flash). Se si utilizza una visualizzazione Web per riprodurre video per te, puoi provarlo. Puoi anche disegnare su di esso con altri nodes.

  2. Lettore VLC portatile! Se magari stai sviluppando una sorta di app per proiettore / regista e vuoi un video a schermo intero, puoi avere un lettore VLC portatile per riprodurre il video a schermo intero in una schermata con i suoi controlli nell’altra. Ha usato questa soluzione e funziona abbastanza bene per mac e windows. 🙂 L’unica cosa è che non puoi disegnare nodes sul video perché si tratta di un’app esterna, con solo l’illusione di video a schermo intero della tua app.

  3. Se hai bisogno di utilizzare la potenza del flash all’interno della tua applicazione javafx 2.0, usa un browser basato su swt (o qualcosa del genere Like the DJ Project se sei uno Swinger) poiché supporta tutte le funzionalità del tuo browser nativo.

Ora sono riuscito a compilare con successo il supporto MKV in JavaFX, e ci vuole un po ‘, ma non un grande sforzo anche sul livello nativo. Vedi qui per la discussione che lo circonda, e qui per il risultato presentato come una patch / biglietto JIRA.

Ho scritto qui una guida molto più completa sul processo che potrebbe interessare a chiunque stia cercando di seguire questa strada.

Quello che segue è la mia breve investigazione prima che effettivamente guardassi seriamente alla compilazione di altri supporti multimediali, anche se lo lascio qui per riferimento.

Ora che JFX8 è stato rilasciato ed è completamente open source, ho passato un po ‘di tempo a pensare a come questo potrebbe essere fatto, e se si potesse fare senza applicare patch al sorgente JFX. Sfortunatamente la risposta a quest’ultimo punto è un no quasi definito, almeno non senza orribili hack di manipolazione del bytecode. Potrei esaminarlo più praticamente in un secondo momento, ma documenterò quanto ho elaborato finora dalla fonte disponibile.

La magia inizia dal costruttore di Media , che è in definitiva il MediaException uscita di MediaException (con il flag MEDIA_UNSUPPORTED se si tenta di riprodurre un formato non supportato.) Da lì crea il Locator , il cui costruttore assicura che l’URL sia supportato. Il suo metodo init() viene quindi chiamato in un thread separato, che esegue un controllo di integrità sulla stringa dell’URL, legge il file, quindi procede per determinare quale sia il formato.

Il codice rilevante per questa parte del metodo è quindi:

 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; } 

Da questo possiamo vedere un primo tentativo “stupido” di catturare il contenuto del file in base al suo nome (questo è ciò che MediaUtils.filenameToContentType() fa.) Ci sono poi alcuni casi speciali per verificare diversi tipi di file wav, ma se che fallisce allora ricadiamo su un controllo più intelligente che guarda la firma del file vero e proprio. Entrambi questi controlli sono in MediaUtils . Quest’ultima verifica è molto più ampia e guarda ai primi pochi byte del file per vedere se può elaborare un formato in questo modo. Se non ci riescono, allora si mette in guardia e lancia l’eccezione che appare come la nostra temuta bandiera MEDIA_UNSUPPORTED .

Se il tipo è identificato correttamente, c’è ancora un altro ostacolo da superare: deve essere supportato dalla piattaforma corrente. Alcune piattaforms vengono caricate dynamicmente a seconda dell’ambiente, tuttavia GSTPlatform esiste sempre, quindi dovremmo inserire qui tutti i formati (universali) aggiuntivi. Questo è relativamente semplice, esiste un array CONTENT_TYPES che contiene semplicemente l’array di formati supportati.

Sfortunatamente la clonazione del repository JavaFX sembra non funzionare per il momento, altrimenti tenterei di metterne un po ‘in pratica. Ma al posto di quanto sopra, cosa deve effettivamente accadere per aggiungere supporto per ulteriori formati? In realtà non sembra estremamente difficile.

  1. In MediaUtils , è necessario aggiungere il supporto al metodo filenameToContentType() per gestire la nuova estensione di file. Questo è banale.

  2. Nella stessa class, è necessario aggiungere il fileSignatureToContentType() al metodo fileSignatureToContentType() per fileSignatureToContentType() il tipo di file in base alla sua firma. Questo è un po ‘più complesso, ma non ancora male. Questo potrebbe anche essere facoltativo, dal momento che il codice corrente sembra utilizzare questo come un fallback se il formato non è identificato correttamente (o del tutto) dall’estensione del file. Un elenco completo di firme dei file per diversi formati può essere trovato qui che dovrebbe aiutare con questo compito.

  3. In GSTPlatform, il nuovo tipo di contenuto deve essere aggiunto all’elenco dei tipi di contenuto supportati.

Sul lato Java delle cose, questo sembra essere tutto ciò che è necessario per farlo accettare il tipo di contenuto e almeno tentare di passarlo al livello nativo di Gstreamer .

Tuttavia, non sono esperto in GStreamer, quindi mentre sono consapevole che ci sono molti più formati in grado di gestire e riprodurre quello che JavaFX attualmente rifiuta, non sono sicuro di quanto esattamente abbiano rimosso questa capacità. Lo hanno sicuramente fatto nel livello Java sopra, ma potrebbero averlo fatto anche sul livello nativo di GStreamer – a questo punto non sono sicuro.

Presumo che abbiano apportato alcune modifiche a GStreamer per JFX8 – ma al momento non sono elencate nella pagina del progetto pertinente , quindi è abbastanza difficile capire esattamente cosa hanno cambiato per questa versione.

Il prossimo passo sarebbe quello di prendere il sorgente JFX8, build con le modifiche proposte sopra per un nuovo tipo di contenuto, e poi vedere quali errori (se ce ne sono) si verificano a livello nativo, quindi portarlo da lì.

E ora, Javafx2.1 supporta finalmente mp4 H.264, quindi ora dovresti andare bene senza le acrobazie postate sopra. 🙂

Il design dell’API non sembra supportare il rollover dei tuoi codec. Praticamente tutte le classi sono definitive (ad es. VideoTrack, Media, MediaPlayer ecc.). Suppongo che l’attuale decodifica video sia fatta con le classi interne al momento, il che significa che non c’è modo di ignorarle.

C’è un piano per Open Source JavaFX 2.0 , sospetto mentre ci avviciniamo al rilascio di JDK8. Speriamo che quando lo faranno possiamo vedere come risolvono i loro codec dal costruttore di Media(String source) e vediamo se possiamo collegarci in qualche modo.

Richieste di funzionalità aperte correnti per questo nel sistema di tracciamento bug di JavaFX:

  • JDK-8091656 Lista dei desideri per più supporto per il formato multimediale
  • I supporti JDK-8091755 dovrebbero supportare InputStream

Leggi le richieste di funzionalità collegate e i commenti associati su di esse per capire il loro stato corrente (o la loro mancanza 😉 per la versione di distribuzione JavaFX che stai utilizzando.

Nota: per l’API multimediale basata su InputStream, uno dei commenti successivi di uno sviluppatore JavaFX è “Propongo di considerare questo per JDK 10”, quindi suppongo che potrebbe essere una possibilità in futuro …

Inoltre, se non si è sicuri che JavaFX abbia attualmente un supporto integrato per un determinato tipo di codifica o meno, una panoramica completa delle codifiche multimediali e dei tipi di contenitori multimediali supportati viene fornita in javadoc per il pacchetto javafx.media (assicurarsi solo che rivedi la versione di javadoc che corrisponde alla tua versione di JavaFX).

Coloro che potrebbero essere interessati ad altre soluzioni per ottenere almeno un video da riprodurre da JavaFX, anche se si tratta di un tipo di media non supportato nativamente da JavaFX e non si vuole hackerare il supporto multimediale nativo JavaFX solo per ottenere il video in gioca, può anche vedere la mia risposta alla domanda correlata:

  • Riproduzione di HEVC h265 in un client JavaFX