Java Media Framework

 

Tutorial

 

Índice
Introducción
Conceptos básicos
Ejemplo 1
Reproducción
Ejemplo 2
Procesamiento
Ejemplo 3
   

Procesamiento de contenidos multimedia:


En esta página

Se presentará el procesador como medio para realizar transformaciones a los contenidos multimedia, enviarlos en una sesión rtp a través de internet, capturarlos de una webcam o un micrófono y muchas más.

¿Qué diferencia a un procesador de un reproductor?

Un procesador no es más que un tipo especializado de reproductor (player) que permite controlar el procesamiento que se hace sobre la fuente de datos que recibe a su entrada. Un procesador tambien proporciona a su salida la fuente de datos procesada.

Así un Processor recibe a su entrada un flujo de datos multimedia, que representamos como una DataSource de entrada, y produce un nuevo flujo de datos multimedia correspondiente a la entrada procesada y que representamos como una DataSource de salida.

Grafico 1 - Esquema de funcionamiento de un Processor


El flujo de datos de entrada al procesador puede proceder de:

  1. Una URL, que puede localizar: archivos multimedia locales o archivos multimedia alojados en servidores remotos.
  2. Una sesión RTP.
  3. Una captura de audio y/o video

A su vez el flujo de datos procesados puede ser:

  1. Almacenado en un archivo
  2. Transmitido den tiempo real a través de Internet mediante RTP.
  3. Reproducido.

Construyendo un procesador

El método createManager() de la clase Manager devuelve un Processor. El flujo Multimedia de entrada al Processor es un argumento de createProcessor(), puede consistir en una DataSource, un MediaLocator o una URL.

Tabla 1 - Creación de un Processor. Métodos createProcessor() de la clase Manager
Processor createProcessor (DataSource dataSource)
Procesor createProcessor (MediaLocator sourceLocator)
Processor createProcessor (java.net.URL sourceURL)


Java Media Framework también permite la creación de un Processor, directamente en estado Realized, mediante el método createRealizedProcessor de la clase Manager.

Tabla 2 - Creación de un Processor. Método createRealizedProcessor, clase Manager
Processor createRealizeProcessor (ProcessorModel modelo)


Este método recibe como argumento un objeto ProcessorModel en el que se detalla el procesamiento que va a efectuar el Processor. De esta forma establecemos las opciones de procesamiento directamente al crear el Processor, en el siguiente apartado profundizaremos acerca de la creación de los ProcessorModels. Nótese además que se crea un Processor directamente en estado realizado.

Especificando las opciones de procesamiento

Un flujo de datos MultiMedia pude contener una o más pistas (Tracks) multiplexadas. Por ejemplo, dicho flujo MM, puede ser demultiplexado en dos pistas diferentes, una de audio y otra de video.

Grafico 2 - Demultiplexación/Multiplexación de pistas por parte de un Processor


Los estados de un Processsor son muy similares a los de un Player (Estados de un Player). Cuando un Processor se encuentra en estado Realized, podemos llamar al método getTrackControls() para obtener sendos objetos TrackControl para cada una de las pistas contenidas en el flujo de datos MM. Estos objetos permiten especificar el procesamiento que se va a efectuar sobre cada una de las pistas.

Listado 1 - Ejemplo de obtención de los TrackControls de las pistas de un Processor
      ...      
      controlPista = processor.getTrackControls();
//Obtencion de los formatos de salida soportados para cada pista for (int i = 0; i < controlPista.length; i++) {
Format[] formatosPista = controlPista[i].getSupportedFormats();
if (controlPista[i].getFormat() instanceof AudioFormat){
formatosAudio = formatosPista;
formatoAudioActual = controlPista[i].getFormat();
} else if (controlPista[i].getFormat() instanceof VideoFormat){
formatosVideo = formatosPista;
formatoVideoActual = controlPista[i].getFormat();
}
} ... (Continua en listado 3)
Codigo fuente completo de ProcesamientoJMF.java


Existen dos formas fundamentales de especificar el procesamiento que se va a llevar a cabo en un Processor:

  • Usar un ProcessorModel al construir el Processor. Un objeto ProcessorModel contiene información acerca de:
    • El flujo MultiMedia de entrada
    • El formato de salida de cada una de las pistas
    • El descriptor de contenido de la salida (ContentDescriptor), que indica el formato global de la salida del Processor (por ejemplo: archivo quicktime, datos RAW, datos RTP ...)
Listado 2 - Ejemplo de uso de un Processor Model para especificar opciones de procesamiento
    ...
    //Descriptor de contenido de la salida
    descContenido = new ContentDescriptor(ContentDescriptor.RAW);
... //Formatos de salida de cada una de las pistas formatos[0] = new AudioFormat(formatoAudio);
formatos[1] = new VideoFormat(formatoVideo); ... //Creacion del Processor en estado realizado mediante //un ProcessorModel try {
procesador = Manager.createRealizedProcessor(new ProcessorModel( dataSourceOrigen, formatos,descContenido));
}
catch (Exception ex) {
System.err.println(ex);
} ...
Codigo fuente completo de ProcesamientoJMF.java
  • Una vez obtenidos los TrackControls correspondientes a cada pista. Llamar al método setFormat() en cada TrackControl para especificar el formato de salida de cada pista (en la práctica formato de salida del video y del audio). Se debe establecer también el descriptor de contenido de la salida del Processor llamando al método setOutputContentDescriptor del Processor.
Listado 3 - Ejemplo de uso de TrackControls para establecer opciones de procesamiento
(Continúa al listado 1)
  ...  
  public boolean setFormatoVideo(VideoFormat formato) {
controlPista[0].setFormat(formato);
controlPista[0].setEnabled(true);
}
return exito;
} ...
Codigo fuente completo de ProcesamientoJMF.java

 

Destino para los datos procesados

Los destinos posibles para los datos multimedia de salida de un procesador son:

  • Reproducción: Recordemos que un Processor no es más que un tipo especializado de Player. Por lo tanto podemos obtener el componente visual correspondiente al contenido reproducido así como el componente de control y de esta forma reproducir el contenido multimedia en nuestro equipo como si de un Player se tratase.
  • Almacenamiento en un archivo: Podemos almacenar la salida de un procesador en un archivo utilizando el siguiente procedimiento:

1. Obtener la DataSource de salida del procesador llamando al método getDataOutput() de éste

2. Construir un DataSink cuyo cometido es escribir la salida del procesador en un archivo de nuestro sistema. Para ello llamamos al método Manager.createDataSink al que pasamos como parámetro la DataSource de (1) y un MediaLocator que especifique el nombre y localización del archivo, devuelve un objeto tipo DataSink

3. Llamar a open() del objeto DataSink, devuelto en (2)

4. Llamar a start() del objeto DataSink

5. Iniciar el procesamiento de los datos multimedia llamando al método start() del Processor

Una vez se produzca un evento EndOfMediaEvent u otro que indique el final del procesamiento:

6. Llamar al método stop() del Processor para finalizar el procesamiento

7. Llamar al método close() del Processor

8. Llamar al método close() en el DataSink

Listado 4 - Ejemplo de almacenamiento en un archivo de la salida de un Processor
...
public void guardarContenidoMM(DataSource fuente, String destino){
System.out.println(destino);
try {
mlrDest = new MediaLocator(new URL(destino));
}
catch (Exception ex) {
System.out.println(ex);
}
try {
filewriter = Manager.createDataSink(fuente, mlrDest);
System.out.println(filewriter);
filewriter.addDataSinkListener(this);
}
catch (NoDataSinkException ex) {
System.out.println(ex);
}
System.out.println(filewriter);
try {
filewriter.open();
}
catch (SecurityException ex1) {
}
catch (IOException ex1) {
}
try {
filewriter.start();
}
catch (IOException ex2) {
}
} ...
Codigo fuente completo de ProcesamientoJMF.java

  • Por último la salida de un Processor también puede servir de entrada a otro Processor o Player

 

 

     

Copyright Universidad de Málaga 2003