S3ldonPress

JMF in un applet

Qualche settimana fa lavorando alla mia tesi sono incappato in un problema che mi ha tenuto fermo per qualche giorno. Cercando in giro per la rete mi sono accorto che non è un problema di pochi ma di soluzioni praticamente non si vede traccia. Io dopo vari tentativi sono riuscito a risolvere. Vediamo di che si tratta.

JMF (Java Media Framework) è appunto un framework che permette di integrare vari media (per es. video e audio, ma anche streaming rtp) in applicazioni Java. Il primo problema che si incontra nell’utilizzo di JMF sta nel fatto che il supporto è stato abbandonato dalla Sun anni orsono e dunque JMF si presenta come un utile supporto per applicazioni multimediali ma allo stesso tempo è estremamente vecchio poichè i codec multimediali supportati risalgono all’età della pietra. Come spesso accade in questi casi è la comunità open source a farsi carico del problema. Infatti in giro si trovano varie soluzioni ed estensioni che permettono di utilizzare JMF con librerie native, per es. di utilizzare JMF con ffmpeg, ossia di essere in grado di leggere i più comuni formati e codec multimediali. Per il mio progetto la scelta è caduta su FOBS ma si potrebbe utilizzare tranquillamente anche FMJ. Una volta aggiunti i codec giusti a JMF mediante il JMFRegistry viene modificato il file jmf.properties che conterrà le informazioni per caricare i giusti codec. Bene, una volta fatto ciò non hanno più problemi ad utilizzare JMF con qualsivoglia media.

La mia necessità era di integrare il player che sto realizzando in un applet, all’interno di una pagina web. Ora, utilizzando Eclipse e avviando l’applet da lì non avevo nessun tipo di problema, tutto funzionava correttamente. Nel momento in cui però andavo ad integrare il codice dell’applet in una pagina html non funzionava una mazza. Perchè? Perchè l’applet non riusciva a caricare il giusto file jmf.properties e ne creava uno di default con i codec base di JMF. Come fare a far caricare la giusta configurazione? Dopo giorni, grazie anche e soprattutto all’aiuto e alla disponibilità di Werner, sono arrivato al dunque. Vediamo come. Come prima cosa occorre posizionare il file jmf.properties nello stesso path del file .class dell’applet. Dopodichè si può utilizzare la seguente classe,di cui riporto per intero il codice, per inizializzare correttamente JMF:

/* * Copyright 2009 Markus Koller *  * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at  *  *     http://www.apache.org/licenses/LICENSE-2.0 *  * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */

import java.io.IOException;import java.io.InputStream;import java.io.ObjectInputStream;import java.io.OptionalDataException;import java.net.URL;import java.util.HashMap;import java.util.Map;

import com.sun.media.util.Registry;

/** * Helps initializing JMF from a JMF.properties file not on the root of the classpath. * This also works for webstart! * @author Markus Koller */public class JMFInitializer {    public static void initJMF(URL url) throws IOException {        InputStream in = null;        try {            in = url.openStream();            if (in == null) {                throw new IllegalArgumentException("No such jmf properties file: " + url);            }             readJMFRegistry(in);        } finally {           if (in != null) {               try {                   in.close();               } catch (IOException e) {}           }        }    }

    private static void readJMFRegistry(InputStream ris) throws IOException {        ObjectInputStream ois = null;        try {            ois = new ObjectInputStream(ris);                int tableSize = ois.readInt();            int version = ois.readInt();            if (version > 200) {                System.err.println("Version number mismatch. There could be errors in reading the registry");            }            HashMap<String, Object> hash = new HashMap<String, Object>();            for (int i = 0; i < tableSize; i++) {                String key = ois.readUTF();                try {                     Object value = ois.readObject();                     hash.put(key, value);                } catch (ClassNotFoundException e) {                     throw new RuntimeException("Class not found for jmf registry entry", e);                } catch (OptionalDataException e) {                     throw new RuntimeException("Invalid jmf properties content", e);                }            }            for (Map.Entry<String, Object> entry : hash.entrySet()) {                 Registry.set(entry.getKey(), entry.getValue());             }        } finally {            if (ois != null) {                try {                    ois.close();                } catch (IOException e) {}            }        }     }}

 

Tale classe va richiamata nell’init() dell’applet prima di creare il player JMF in questo modo:

JMFInitializer.initJMF(this.getClass().getResource("jmf.properties"));

 

Bene ora l’applet inizializzerà correttamente JMF e caricherà i codec giusti dal file .properties. A questo punto potreste incappare in un altro problema, problema relativo alle restrizioni di sicurezza dell’applet. Infatti c’è da ricordare che un applet gode di restrizioni di sicurezza per evitare che applicazioni malevoli possano commettere atti impuri. Per evitare tali restrizioni è buona norma quella di firmare digitalmente l’applet. Per sapere come fare vi rimando a questa guida.

Se avete problemi non esitate a contattarmi e per quel che posso proverò a darvi una mano.

Algoritmi distribuiti

Ho aggiunto nell’area download del sito la mia ultima tesina universitaria. L’esame era di Sistemi Distribuiti e bisognava implementare due algoritmi distribuiti. Gli algoritmi implementati da me sono stati il Reliable Multicast ed il Two Phase Commit con Bully Election. Sono stati implementati in Java mediante l’utilizzo del tool DAJ. Nell’area download trovate documentazione e codice.

  • Meta

  • Archivi

  • Articoli recenti

  • Commenti recenti

  • Tag

  • Visitors Online

  • Blog sotto licenza Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License
    Creative Commons License