Aggiunta di altri codec video / supporto DVD a JavaFX 2.2


Aggiornamento:

Poiché il lato multimediale di JFX è stato open source, ho esaminato questo da solo ed è davvero possibile, ma richiede la modifica e la ricostruzione del sorgente JFX (sia parti Java che C.) Il processo è descritto qui per chiunque voglia avere un go - aggiungo il supporto MKV in quell'esempio, ma dovrebbe essere molto simile per altri plugin.

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

Contesto

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

Si riduce al fatto che mentre funziona, è un sacco di manutenzione e problemi lavorare con più macchine virtuali e collegarle stabilmente se c'è un'altra soluzione che sarebbe più facile. VLC ha un livello di supporto abbastanza leggendario per giocare praticamente qualsiasi cosa, motivo per cui sono andato con esso finora, 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-grande! Ma al momento la linea ufficiale è che supporta "FLV contenente video VP6 e audio MP3". C'è un modo per estendere questo per aggiungere il supporto per più codec? Non c'è codec difficile che mi piacerebbe supportare, è più un caso di quanti più posso, quindi sto cercando un metodo estensibile per fare quanto sopra.

Mi chiedevo se avrebbe riprodotto video per i codec installati nativamente sulla macchina e che semplicemente non si pubblicizza come tale (perché quella funzionalità ovviamente dipende dalla macchina e non è multipiattaforma.) Ma senza dadi, ho provato un certo numero di formati comuni e si rifiuta davvero di giocare a qualcosa di diverso da quello che afferma.

Di 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 è pianificato per una versione successiva? Non sono stato in grado di trovare alcuna informazione su di esso sulla roadmap o alcun commento da Oracle a riguardo.

L'unica cosa che ho potuto trovare dalla ricerca estensiva è qui il che implica che potrebbe essere possibile, 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 qualche idea o informazione, sono tutto orecchie.

Altri approcci

Un approccio che mi chiedevo potrebbe essere possibile è il crowbarring del barattolo JMC dal vecchio JavaFX come descritto qui e cercando di ottenere che lavora al fianco di JavaFX 2. Suppongo che nessuno abbia avuto fortuna con questo approccio o qualcosa di simile?

Tutte le cose falliscono, se qualcuno ha informazioni o collegamenti su se / quando il supporto per codec aggiuntivi sarà supportato fuori dalla scatola, allora sarei interessato a sentire anche questo. O se qualcuno ha qualche dettaglio di contatto per qualcuno a Oracle potrei chiedere che sarebbe anche apprezzato! Ho desiderato un supporto video decente in Java per un po ' di tempo, e immagino cosa sia questo si riduce a sta cercando 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 è il caso.

Author: Community, 2011-11-16

5 answers

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 problema, ognuno con limitazioni ma dipende da cosa funziona per te:

  1. I documenti dicono che WebView funziona con HTML5, che riproduce video supportati sulla piattaforma (anche se purtroppo non flash). Se l'utilizzo di una webview per riprodurre video funziona per te, puoi provarlo. Si può anche disegnare su di esso con altri nodo.

  2. Lettore VLC portatile! Se forse stai sviluppando una sorta di app proiettore/regista e vuoi un video a schermo intero, puoi far riprodurre il video a schermo intero a un lettore VLC portatile con i suoi controlli nell'altro. Utilizzato questa soluzione e funziona abbastanza bene per Mac e Windows. :) L'unica cosa è che non puoi disegnare nodi sul video in quanto è un'app esterna, con solo l'illusione del video a schermo intero della tua app.

  3. Se avete mai bisogno di utilizzare il potenza di flash all'interno dell'applicazione javafx 2.0, quindi utilizzare un browser basato su swt (o qualcosa di simile al progetto DJ se sei uno Swinger) in quanto supportano tutte le funzionalità del browser nativo.

 10
Author: Glstunna, 2011-11-27 00:06:29

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

Ho scritto una guida molto più completa sul processo qui che potrebbe essere di interesse per chiunque voglia seguire questa strada.

Cosa segue è la mia breve indagine prima di aver seriamente esaminato la compilazione di altri supporti multimediali, anche se lo lascerò qui per riferimento.

Ora che JFX8 è stato rilasciato ed è completamente open source, ho passato un po ' di tempo a guardare come questo potrebbe essere fatto, e se potrebbe essere fatto senza patch il sorgente JFX. Sfortunatamente la risposta a quest'ultimo punto è un no quasi definitivo, almeno non senza orribili hack di manipolazione del bytecode. Potrei indagare più praticamente in un secondo momento, ma documenterò ciò che ho elaborato finora dalla fonte disponibile.

La magia inizia dal Media constructor, che è in definitiva dove il MediaException salta fuori da (con il flag MEDIA_UNSUPPORTED se si tenta di riprodurre un formato non supportato.) Da lì crea il localizzatore , il cui costruttore assicura che l'URL sia supportato. Il metodo init() viene quindi chiamato in un thread separato, che esegue un controllo di integrità la stringa URL, legge il file, quindi procede per cercare di capire qual è il formato.

Il codice pertinente 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" è fatto per afferrare il contenuto del file in base al suo nome (questo è ciò che fa MediaUtils.filenameToContentType().) Ci sono poi alcuni casi speciali per il controllo di diversi tipi di file wav, ma se ciò fallisce, ricorriamo a un controllo più intelligente che esamina la firma effettiva del file. Entrambi questi controlli sono in MediaUtils . Quest'ultimo controllo è molto più esteso e esamina i primi byte del file per vedere se può elaborare un formato in questo modo. Se non può, allora esce e lancia l'eccezione che poi salta fuori 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 piattaforme vengono caricate dinamicamente a seconda dell'ambiente, tuttavia il GSTPlatform esiste sempre, quindi avremmo bisogno di mettere tutti i formati aggiuntivi (universali) qui. Questo è relativamente semplice, esiste un array CONTENT_TYPES che contiene solo l'array di formati supportati.

Sfortunatamente la clonazione del repository JavaFX sembra fallire per me al momento, altrimenti tenterei di mettere in pratica qualcosa di questo. Ma al posto di quanto sopra, cosa deve effettivamente accadere per aggiungere il supporto per ulteriori formati? In realtà non sembra enormemente difficile.

  1. In MediaUtils , il supporto deve essere aggiunto al metodo filenameToContentType() per gestire la nuova estensione del file. Questo è banale.

  2. Nella stessa classe, il supporto deve essere aggiunto al metodo fileSignatureToContentType() per elaborare il tipo di file in base alla sua firma. Questo è un po ' più complesso, ma ancora non troppo male. Questo potrebbe anche essere facoltativo, poiché il codice corrente sembra usarlo solo come fallback se il formato non è identificato correttamente (o del tutto) da l'estensione del file. Un elenco completo di firme di file per diversi formati può essere trovato qui che dovrebbe aiutare con questa attività.

  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 Gstreamer nativo livello.

Tuttavia, non sono esperto in GStreamer, quindi mentre sono consapevole che ci sono molti altri formati che può gestire e riprodurre che JavaFX attualmente rifiuta, non sono sicuro di come esattamente hanno rimosso questa capacità. L'hanno sicuramente fatto nel livello Java sopra, ma potrebbero averlo fatto anche a 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 elencati su la pagina del progetto pertinente , quindi è piuttosto difficile capire esattamente cosa hanno cambiato per questa versione.

Il passo successivo sarebbe quello di afferrare il sorgente JFX8, costruire con le modifiche proposte sopra per un nuovo tipo di contenuto, e quindi vedere quali errori (se presenti) si verificano a livello nativo, quindi prenderlo da lì.

 8
Author: Michael Berry, 2014-03-27 16:13:33

E ora, Javafx2.1 supporta finalmente mp4 H. 264, quindi ora dovresti essere a posto senza le acrobazie sopra pubblicate. :)

 6
Author: Glstunna, 2012-03-27 23:19:52

Il design dell'API non sembra avere il supporto per il rolling dei propri codec. Praticamente tutte le classi sono definitive (ad esempio VideoTrack, Media, MediaPlayer ecc.). Presumo che la decodifica video effettiva sia attualmente eseguita con classi interne, il che significa che non c'è modo di sovrascriverle.

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

 5
Author: Bringer128, 2011-11-25 06:12:20

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

Leggere 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 si sta utilizzando.

Nota, per l'API multimediale basata su InputStream, una delle i commenti di uno sviluppatore JavaFX sono "Propongo di considerare questo per JDK 10", quindi immagino che potrebbe essere una possibilità in futuro...

Si noti inoltre, se non si è sicuri che JavaFX abbia attualmente il supporto integrato per un determinato tipo di codifica o meno, una panoramica completa delle codifiche dei supporti supportati e dei tipi di contenitori multimediali è fornita in javadoc per javafx.media package (assicurati solo di rivedere la versione di javadoc che corrisponde alla tua versione di XavaFX).

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 supporto non supportato nativamente da JavaFX e non si desidera hackerare il supporto multimediale nativo JavaFX solo per far riprodurre il video, possono anche vedere la mia risposta alla domanda correlata:

 2
Author: jewelsea, 2018-01-30 00:32:36