4.8 Camera
4.8.4 ROS-Service associati alla camera
59
il quale si riferisce alla posizione del buffer corrente all’interno della coda di input.
Parallelamente, nel momento in cui vengono acquisiti dei nuovi dati dalla camera e viene chiamata la callback: onNewRawImage, all’interno di CameraActivity; questa a sua volta invocherà un metodo chiamato: encode, della classe H264Encoder. All’in-terno di quest’ultimo si verifica se nella mappa availableInputBuffers è presente al-meno una entry, in tal caso viene selezionata la al-meno recente tra quelle presenti. Do-podiché, i dati relativi all’immagine (ricevuti come parametro dal metodo: encode), una volta convertiti grazie all’istanza della classe NV21Convertor, introdotta in prece-denza, vengono inseriti all’interno del buffer prelevato dalla mappa. Dopodiché, quest’ultimo verrà nuovamente inserito all’interno della coda di input dell’encoder per poter essere elaborato.
Una volta terminata la fase di elaborazione, i nuovi dati codificati vengono inseriti in un buffer di uscita, rendendoli disponibili nella coda di output. A questo punto viene chiamato il metodo onOutputBufferAvailable definito all’interno dell’oggetto Media-Codec.Callback. In questo metodo viene eseguita la pubblicazione sul topic ROS: /de-viceName/android/camera/video/x264, attraverso un publisher specializzato per l’uti-lizzo dei messaggi: x264_video_transport/X264Packet.
L’utilizzo di questa soluzione ha consentito di migliorare notevolmente la qualità dello stream video, portando a risultati superiori sia rispetto al caso compressed che alla precedente versione realizzata con FFMPEG.
Uso congiunto con il package x264_video_transport
Come anticipato nel capitolo precedente, x264_video_transport, oltre ad introdurre al-cuni aggiornamenti riguardanti le funzioni FFMPEG utilizzate nel package:
x264_image_transport; è stato pensato per garantire una maggiore compatibilità e un supporto aggiuntivo rispetto all’esigenze dell’applicazione Android. Come si è visto, attraverso i ROS-service, l’utente può modificare a run-time una serie di parametri legati alla camera, uno di questi è la risoluzione. Quest’ultima rappresenta il parametro più critico sia dal punto di vista del publisher che da quello del subscriber; in quanto richiede che tanto l’encoder quanto il decoder, nel momento in cui essa cambia, deb-bano essere prima bloccati e riconfigurati e solo a questo punto potranno essere riav-viati. Un altro ROS-service che richiede il supporto del package x264_video_transport per il suo funzionamento è quello relativo alla rotazione delle immagini. Infatti, mentre nel caso compressed, questa operazione viene fatta direttamente sul dispositivo (con tutti gli svantaggi che comporta), nel caso “x264” è stato possibile spostare questa fase all’interno del codice relativo al subscriber.
60
L’utilizzo di questi servizi può essere utile in quelle situazioni in cui l’utente vuole intervenire sul comportamento dell’applicazione. In questo caso, attraverso i ROS-service è possibile intervenire sulla qualità delle immagini trasmesse o modificare la loro risoluzione; questo può essere utile ad esempio in quelle situazioni in cui la banda a disposizione è bassa, e per favorire una trasmissione più fluida o con minor latenza, può essere necessario ridurre entrambi questi parametri. Inoltre, è possibile: ruotare le immagini, passare dalla camera posteriore a quella anteriore e attivare il flash.
Per fare ciò, tra gli attributi della classe CameraActivity, è necessario definire delle implementazioni specializzate dell’interfaccia: ServiceResponseBuilder. Ognuna di queste include il metodo: “build”, il quale riceve due parametri secondo la classica coppia: Request-Response. Infatti, il primo parametro è associato alla richiesta del client, in base alla quale si potrà variare lo stato dell’applicazione. A sua volta, l’esito di questa operazione determinerà il valore della risposta, che verrà inserita all’interno del secondo parametro. Quest’ultimo sarà inoltrato nuovamente verso il client.
Una volta definita l’implementazione di uno specifico ServiceResponseBuilder, quest’ultimo dovrà essere assegnato a un server, affinché il ROS-Service ad esso as-sociato diventi operativo. Questa operazione viene svolta all’interno della classe Mo-nitoring (durante la configurazione dell’istanza CameraActivity) utilizzando il metodo newServiceServer (appartenente alla classe ConnectedNode). Anche in questo caso, il metodo accetta due parametri: il primo è una stringa contenente il nome del ROS-Service che si sta creando, il secondo è l’oggetto ROS-ServiceResponseBuilder associato ad esso. Di seguito verranno presentati i vari servizi definiti all’interno dell’applicazione:
rotateImage
questo servizio consente di modificare l’angolo di rotazione dell’immagine visualiz-zata attraverso il topic, rispetto all’orientamento originale della camera. Il servizio mo-difica il valore dell’attributo: angle, definito all’interno della classe CameraActivity.
Anche in questo caso gli effetti del servizio variano a seconda della modalità di tra-sporto utilizzata per la trasmissione delle immagini.
Nel caso del tipo compressed, come si è già visto, l’attributo angle viene utilizzato come parametro per la funzione responsabile della rotazione dell’oggetto di tipo Bit-map associato all’immagine. Nel caso x264 il valore dell’attributo angle viene inserito all’interno di un omonimo campo all’interno del messaggio x264Packet, questo campo verrà poi utilizzato dal subscriber definito nel package x264_video_transport per ese-guire la rotazione.
L’ultima soluzione porta notevoli vantaggi in termini di frame-rate e latenza rispetto a quella utilizzata nel caso compressed 8, in quanto essa demanda l’esecuzione della ro-tazione al subscriber. Quest’ultimo disponendo normalmente di una maggiore potenza
8 al quale non è stato possibile applicare la stessa soluzione in quanto questa richiederebbe la modifica del messaggio standard: sensor_msgs/CompressedImage, oltreché del subscriber ad esso associato, definito nel package: image_transport_plugins, rendendoli incompatibili con le versioni preesistenti.
A questo punto chiunque volesse utilizzare l’applicazione dovrebbe anche scaricare la versione modi-ficata del plugin.
61
di calcolo oltreché di librerie più adatte, sarà in grado di eseguire l’operazione più velocemente, evitando che questa possa avere un impatto sulle performance.
setQuality
Questo servizio consente di modificare, in fase di esecuzione, la qualità delle immagini trasmesse, attraverso l’utilizzo dell’attributo: quality, appartenente alla classe Came-raActivity. I valori che questo campo può assumere sono compresi tra 1 e 99 e suo significato varia a seconda del tipo di trasporto utilizzato in un dato momento.
Se si considera il tipo compressed, l’attributo quality consente di modificare il para-metro di quantizzazione utilizzato durante la compressione nel formato JPEG. Mentre, se si sta utilizzando la modalità di trasporto x264, il parametro quality rappresenta un coefficiente, compreso zero e uno, utilizzato per regolare il valore del parametro: Me-diaFormat.KEY_BIT_RATE, specificato durante la configurazione del codec H.264.
Quest’ultimo parametro consente di impostare il cosiddetto: “target bitrate”, ovvero un valore di soglia che i dati in uscita dall’encoder non possono superare, perciò sulla base di quest’ultimo i singoli frame risulteranno più, o meno compressi. L’attributo quality consente di variare il valore di questo parametro da un minimo uguale a zero9 a un massimo di 7 Mbps.
setResolution
Attraverso questo servizio è possibile modificare la risoluzione delle immagini tra-smesse. Per fare ciò è necessario rilasciare la fotocamera ed eventualmente bloccare l’esecuzione dell’encoder H.264. Successivamente utilizzando il metodo getSuppor-tedPreviewSizes, è possibile ottenere la lista delle risoluzioni supportate dalla camera attualmente selezionata. Poiché l’ordine degli elementi nella lista non è noto a priori, è necessario stabilire un criterio di ordinamento. Perciò si è deciso di ordinare le varie risoluzioni in modo decrescente.
A questo punto il client può decidere se aumentare o diminuire la risoluzione, inviando rispettivamente i valori 1 o -1. Seguirà la risposta del server. Questa sarà costituita da una stringa che conterrà il nuovo valore utilizzato, seguito dall’elenco di tutte le riso-luzioni supportate, ordinate secondo il criterio descritto sopra.
switchCamera
Consente di modificare la camera utilizzata selezionandone un’altra tra quelle dispo-nibili, per fare ciò è necessario rilasciare tutte le risorse acquisite relative alla camera, in quanto generalmente non saranno più valide e il loro possesso in determinati casi impedisce l’acquisizione da parte della nuova camera selezionata. Se l’operazione va a buon fine, il servizio restituisce una stringa che può variare in base al numero di fotocamere disponibili sul dispositivo, nel caso in cui fosse presente solo una sola
9 Il valore effettivo del bitrate medio in uscita, ovviamente non potrà mai essere zero; in questo caso viene applicata la massima compressione possibile nei limiti consentiti dall’immagine.
62
camera, viene comunicato all’utente che non è possibile selezionarne un'altra, nel caso più comune in cui son presenti due fotocamere: il metodo restituisce “front” o “back”
a seconda di quale viene selezionata. Infine, nel caso in cui le fotocamere siano più di due, viene restituito il valore dell’attributo: camera_id, ovvero un intero che partendo da zero rappresenta il numero associato alla camera selezionata.