Come riprodurre, registrare e transcodificare un video col proprio telefono cellulare, utilizzando le API J2ME.
Introduzione
I video sul telefono cellulare sono diventati una realtà . Riprodurre un video che abbiamo scaricato o trasportato sul telefono è una funzionalità offerta da tutti i dispositivi di terza generazione.
E? interessante tuttavia capire come si possa riprodurre un video localizzato su di un server o magari in streaming. Vedremo come queste funzionalità siano offerte dalle MMAPI mentre le AMMS ci consentono di settare la camera del telefono per realizzare riprese di alta qualità e di effettuare transcodifiche.
Riproduzione di un video con MMAPI
Analogamente a quanto visto per le foto, i due oggetti principali di cui abbiamo bisogno per la riproduzione o la registrazione di un video sono Player e Canvas o Form: Player per accedere al flusso video e Canvas o Form per la visualizzazione sul display.
Ricordiamo che se utilizziamo una Canvas tutte le operazioni relative alla riproduzione vanno implementate in una classe che estende Canvas e viceversa se utilizziamo un Form.
Abbiamo già visto, a proposito dell?audio, quali sono gli stati in cui un Player può transitare e gli eventi che tali transizioni possono generare.
Il Player lo si ottiene tramite un Manager e un locator nel quale viene specificata in sintassi URI la locazione del video:
Player player = Manager.createPlayer("http://myserver/video.mpg");
La codifica video supportata dipende ovviamente dal dispositivo. La maggior parte dei telefoni ad oggi supporta il formato 3gpp, basato su MPEG-4 e definito dal Third Generation Partnership Project.
Oltre al protocollo http, il file video può essere locale, può essere contenuto in un InputStream, oppure per i dispositivi che consentono lo streaming il video si può ricevere via RTP (Real Time Protocol) secondo questa sintassi:
"rtp://" address [ ":" port ] [ "/" type ]
Ad esempio:
rtp://220.2.2.2:7777/video
Se il dispositivo non supporta la riproduzione di quel particolare tipo di video viene lanciata una MediaException. Mentre se il file non è disponibile viene lanciata una IOException.
E? necessario poi che il Player sia nello stato realized per ottenere le risorse di cui ha bisogno per la riproduzione:
player.realize ( );
Per visualizzare il video sul display del telefono utilizziamo il VideoControl:
VideoControl videoControl = (VideoControl)(player.getControl("VideoControl"));
A questo punto inizializziamo il VideoControl secondo la modalità con cui vogliamo che il flusso ripreso venga visualizzato. Nel caso in cui volessimo utilizzare una Canvas avremo:
videoControl.initDisplayMode(VideoControl.USE_DIRECT_VIDEO,this);
Se invece vogliamo utilizzare un Form:
Item item = (Item) videoControl.initDisplayMode(GUIControl.USE_GUI_PRIMITIVE, null); append(item);
Ora basta avviare il Player e rendere visibile sul display il video:
player.start();videoContro.setVisible(true);
A parte la semplice visualizzazione è sicuramente utile realizzare un vero e proprio player (nel suo significato reale), in cui si possa mettere in pausa la riproduzione, ricominciarla, cambiarne il volume e la velocità . Quanto descritto di seguito è ovviamente valido anche nel caso di riproduzione audio.
Abbiamo visto come avviare la riproduzione, metterla in pausa è banale:
public void pausa(){try {player.stop();} catch (MediaException me) {}}
Per avviare la riproduzione dal punto in cui ci si era fermati basta ristartare il Player:
public void continua(){try {player.start();} catch (MediaException me) {}}
Per riavviare la riproduzione dall?inizio occorre modificare il punto di partenza temporale:
public void riavvia(){try {player.setMediaTime(0);player.start();} catch (MediaException me) {}}
Se vogliamo rendere ?muta? la riproduzione dobbiamo far ricorso a VolumeControl:
public void mute(){try {VolumeControl vc = (VolumeControl) player.getControl("VolumeControl");cc.setMute(true);} catch (Exception me) {}}
Analogamente per ripristinare il volume:
public void unmute(){try {VolumeControl vc = (VolumeControl)player.getControl("VolumeControl");vc.setMute(false);} catch (Exception me) {}}
Se invece si desiderasse cambiare il volume a proprio piacimento si potrebbe utilizzare un TextField o una Gauge per impostare il valore (che va da 0 a 100) per poi settarlo in questo modo:
public void setVolume(int level){try {VolumeControl vc = (VolumeControl) player.getControl("VolumeControl");vc.setLevel (level);} catch (Exception me) {}}
Possiamo anche decidere di cambiare la velocità di riproduzione. Ricordando che il metodo setRate(int millirate) di RateControl utilizza come parametro un valore in ?millipercentuale? (vedi articolo https://www.mokabyte.it/2005/06/j2me_multimedia-2.htm), per raddoppiare la velocità di riproduzione avremo:
public void raddoppiaVelocita(){try {RateControl rc = (RateControl) player.getControl("RateControl");rc.setRate (200000);} catch (Exception me) {}}
Ovviamente il dispositivo deve supportare l?aumento o la diminuzione di velocità . Per conoscere quali sono le velocità minima e massima di riproduzione basta utilizzare i metodi getMinRate( ) e getMaxRate( ) di RateControl.
Registrazione di un video con MMAPI
Per descrivere l?implementazione della registrazione di un video, pensiamo alla situazione di uso reale.
Possiamo pensare che, una volta avviata l?applicazione, essa ci mostri ciò che la telecamera riprende. La pressione di un tasto (ad esempio con label ?Registra video?) avvierà la registrazione, mantenendo attiva la vista della camera e la pressione di ?Stop registrazione? ci permetterà di interromperla.
Come già visto per la cattura di una foto, per connettere l?applicazione al dispositivo camera del telefono costruiamo il Player in questo modo:
Player player = Manager.createPlayer("capture://video?widht=640&height=480");
Il formato del video catturato in questo caso è 640×480 e la codifica è quella di default per il dispositivo. Le varie opzioni di codifica utilizzabili sono le stesse descritte a proposito della cattura di una foto.
Se il dispositivo non supporta la cattura video con le caratteristiche richieste viene lanciata una MediaException.
A questo punto in modo identico a quanto visto per la riproduzione (in effetto andiamo a riprodurre ciò che la camera riprende) si ha:
player.realize ( );videoControl = (VideoControl)(player.getControl("VideoControl"));videoControl.initDisplayMode(VideoControl.USE_DIRECT_VIDEO,this);player.start();videoControl.setVisible(true);
Vediamo ora ciò che succede quando si preme il tasto relativo alla voce ?Registra video?. Nel metodo CommandAction avremo:
if (c == recordCommand) {recordVideo();}
Il metodo recordVideo ( ) innanzitutto rimuove il comando ?Registrazione video? ed aggiunge ?Stop registrazione?. Successivamente chiede al Player il Control di tipo RecordControl ed inizia la memorizzazione dei dati su un ByteArrayOutputStream:
public void recordVideo() {removeCommand(captureCommand);removeCommand(recordCommand);addCommand(stopRecordCommand);rc = (RecordControl)player.getControl("RecordControl");output = new ByteArrayOutputStream();rc.setRecordStream(output);rc.startRecord();}
L?unica azione che possiamo ora intraprendere è ?Stop registrazione?:
if (c == stopRecordCommand) {stopRecording();}
Il metodo stopRecording ( ) interrompe la registrazione e trasferisce i dati da un ByteArrayOutputStream ad un ByteArray:
public void stopRecording () {try {rc.commit();ByteArray videoData = output.toByteArray();} catch (MediaException me){. . .} catch (IOException ioe) {. . .}}
Una volta registrato il video si può salvarlo su file system utilizzando le File Connection API, per poi riguardarlo o uploadarlo su di un server.
Gestione video con AMMS
Le AMMS non implementano un modo alternativo per la riproduzione e la registrazione di un video. Queste operazioni avvengono allo stesso modo descritto per le MMAPI.
La differenza risiede nella possibilità di regolare la camera del telefono per effettuare una ripresa quanto migliore e personalizzata possibile.
I controlli disponibili sono stati già descritti nell?articolo sulle foto e sono: CameraControl, ZoomControl, ExposureControl, FocusControl.
Vediamo nello specifico alcuni metodi di CameraControl relativi ai video e perciò tralasciati nel precedente articolo:
- int[] getSupportedVideoResolutions ( ): restituisce le risoluzioni video supportate come coppia (larghezza, altezza). Ad esempio se la camera supporta le risoluzioni 1024×768 e 640x 580, il risultato sarà un array di interi [1024, 768, 640, 480].
- void setVideoResolution(int index): imposta la risoluzione video. Il parametro ?index? indica la coppia restituita da getSupportedVideoResolutions( ): ?0? indica la prima coppia, ?1? la seconda e così via.
- int getVideoResolution( ): restituisce la risoluzione video corrente sotto forma di intero che indica la coppia restituita da getSupportedVideoResolutions( ): ?0? indica la prima coppia, ?1? la seconda e così via.
AMMS fornisce anche la possibilità di cambiare il formato video utilizzando VideoFormatControl.
Per far questo dobbiamo prima di tutto creare un MediaProcessor attraverso un GlobalManager e inizializzarlo:
MediaProcessor processor = GlobalManager.createMediaProcessor("video/mpeg");InputStream inputStream = // InputStream che contiene il video mpegOutputStream outputStream = // OutputStream che conterrà il video di outputprocessor.setInput(inputStream);processor.setOutput(outputStream);processor.start():
I formati di video che si possono settare sono presenti nella tabella di figura 1.
Vediamo come cambiare il formato del video mpeg su cui abbiamo prima costruito il MediaProcessor, in H.263:
VideoFormatControl videoFormat = (VideoFormatControl)processor.getControl("javax.microedition.media.control.VideoFormatControl");videoFormat.setFormat("video/h263");processor.complete();
Conclusioni
In questo articolo abbiamo visto come riprodurre e registrare un video in J2ME.
Queste operazioni possono risultare molto utili per realizzare un VideoBlog, oppure un?applicazione di infotainment nella quale si voglia dare all?utente la possibilità di visualizzare dei video in modalità embedded.
Bibliografia
[1]
http://jcp.org/en/jsr/detail?id=234