\chapter{Descripción Informática}

Una vez que hemos explicado en los capítulos anteriores los requisitos
y las herramientas necesarias para la elaboración del proyecto, vamos
a explicar en este capítulo el software desarrollado en el
proyecto y cómo hemos abordado y resuelto los objetivos
principales. Para ello vamos a comenzar dando una visión general del
diseño y posteriormente se describirán sus detalles y la
implementación que se ha llevado a cabo en cada una de sus partes.

\section{Diseño global} \label{sec:diseno-global}

Como comentamos en el capítulo 2, el objetivo global del proyecto es
realizar una aplicación de vídeo vigilancia distribuida, robusta,
tolerante a fallos y que permita acceder a su contenido y
configuración a través de dispositivos móviles inteligentes. La
aplicación desarrollada es capaz de utilizar cámaras USB, inalámbricas
por radio-frecuencia e inalámbricas IP. La información recogida por
las cámaras es utilizada para analizar y detectar movimiento además de
poderse grabar a diferentes configuraciones de resolución, tasa de
fotogramas y formato. La información de las alarmas detectadas,
visualización de grabaciones, o visualización en directo por las
cámaras son tareas que se pueden realizar desde el dispositivo móvil
basado en \emph{Android}. La solución se ejecuta en dispositivos físicos
competitivos tanto por precio como por consumo de energía.

Siguiendo la línea marcada por la plataforma \emph{JDEROBOT}, se ha
resuelto el objetivo de este proyecto mediante la creación de
componentes que ofrecen cierta funcionalidad a través de sus
interfaces y la utilización de recursos nativos del sistema base,
\emph{GNU/Linux}. El diseño global de la aplicación se puede observar
en la figura \ref{fig:diseno-global}. En ella podemos observar los
diferentes componentes que ejecutan distribuidamente en una red de
ordenadores (componentes amarillos), el componente que ejecuta en el
dispositivo móvil (componente naranja) y el módulos del sistema
operativo (módulo azul). 


\begin{figure}[htbp]
\begin{center}
\includegraphics[height=12.0cm]{img/diseno-general}
\end{center}
\caption{Esquema global de la aplicación}
\label{fig:diseno-global}
\end{figure}

El funcionamiento global del sistema es el siguiente: Las imágenes
obtenidas por la cámara, que son gestionadas a bajo nivel por el
módulo \emph{vloopback}, llegan al componente \emph{CameraServer} que
es capaz de servirlas a través de su interfaz (tanto en modo
fotograma, como en modo \emph{streaming}). El componente \emph{Motion
  Detector} analiza las imágenes que le llegan del \emph{CameraServer}
para detectar si existe movimiento en la imagen. Si se detecta
movimiento, una alarma es enviada al componente \emph{Surveillance}, que es el
encargado de gestionar las alarmas y sus acciones. En este caso,
ordena al \emph{RecordingManager} realizar grabaciones en la cámara
donde se ha detectado movimiento. El \emph{RecordingManager} guarda la
información necesaria en la base de datos y notifica al
\emph{Recorder} que realice la grabacion física a un fichero en disco
de las imágenes recibidas de la cámara. Además el componente
\emph{Surveillance}, que gestiona la lógica de la aplicación, realiza
grabaciones de las cámaras contínuamente aunque no se notifique
alarma.
Por otro lado, el componente \emph{'MobileSecurity'} ejecuta en el entorno
del dispositivo móvil, en nuestro caso en Android. Este componente se
comunica con el componente \emph{'RecordingManager'} para obtener la
información de grabaciones, \emph{streaming} de los vídeos de grabación y
para generar alarmas desde el dispositivo móvil. Además, se comunica
con el componente \emph{'CameraServer'} para visualizar en tiempo real
y por \emph{streaming} la información recogida por las cámaras. La
utilización del dispositivo móvil en nuestro sistema nos permite
realizar una interacción remota con el sistema de tal modo que podemos
visualizar las cámaras de nuestra casa mientras estamos de vacaciones
en la montaña o de viaje fuera de nuestra ciudad.

\vspace{0.3cm}

A continuación se explica en detalle el funcionamiento de cada
componente del sistema de vídeo-vigilancia distribuido con detector de
alarmas de movimiento. Además se explicará el proceso de \emph{streaming} de
vídeo que ofrece el sistema.

\section{Obtención del vídeo}

La obtención del flujo de vídeo se realiza a través de las cámaras que
se detallaron en la apartado \ref{subsec:cameras}. En esta sección se
verán los problemas derivados al realizar varios accesos
simultáneamente a los dispositivos de vídeo y las soluciones
propuestas. Además se detallarán los componentes diseñados e
implementados.

La solución que se ha seleccionado debe permitir el acceso simultáneo
de varios procesos al flujo de vídeo, tal como muestra la figura
\ref{fig:diseno-video}. En los siguientes apartados se explicará la
esencia de la solución propuesta.

\begin{figure}[htbp]
\begin{center}
\includegraphics[height=5.0cm]{img/diseno-video}
\end{center}
\caption{Acceso simultáneo al flujo de vídeo}
\label{fig:diseno-video}
\end{figure}

\subsection{Componente \emph{CameraServer}}
\label{subsec:cameraserver}

El componente \emph{CameraServer} es el encargado de obtener la fuente
de vídeo del mayor número de dispositivos posibles. Estos dispositivos puede
ser físicos, como las cámaras, o pueden ser lógicos como flujos de
vídeo por internet, vídeos locales en fichero o fuente de prueba con patrones
(ruido estático, barras, colores, ...). Gracias a su interfaz definida
en \emph{ICE} (listado \ref{list:ejemplointerfazice}) conseguimos
unificar el \emph{API} y acceso a las imágenes, desde cualquier
aplicación con independencia de su localización (local o distribuida)
y de su lenguaje de programación. En la figura
\ref{fig:dise-cameraserver} se puede observar como gracias a la
interfaz que proporciona \emph{CameraServer}, varios componentes
pueden obtener imágenes de la cámara simultáneamente.

\begin{figure}[htbp]
\begin{center}
\includegraphics[width=0.8\textwidth]{img/cameraserver}
\caption{Vista de interacción de componentes con \emph{CameraServer}}
\label{fig:dise-cameraserver}
\end{center}
\end{figure}

Esto hace de \emph{cameraServer} un componente muy versátil,
permitiendo siempre obtener vídeo de casi cualquier fuente imaginable e
inyectarlo en nuestras aplicaciones mediante el interfaz
\emph{camera}. Dicha versatilidad proviene del uso del \emph{framework}
multimedia libre multiplataforma escrito en C, denominado
\emph{GStreamer}\footnote{http://es.wikipedia.org/wiki/GStreamer}. Hemos
optado por apoyarnos en bibliotecas consolidadas en el contexto
multimedia en vez de desarrollar nosotros unas específicas. Gracias a
la existencia de \emph{GStreamer}, que es software libre, ganamos
robustez, eficiencia, mantenimiento constante y código desarrollado
por expertos.

\emph{GStreamer} permite modelar \emph{pipelines} con los que manejar
diferentes elementos multimedia, desde su origen (cámaras reales, ficheros,
red, ...), pasando por su procesado (codificación/decodificación,
filtrado,...) hasta su destino (pantalla, fichero, red,
aplicación,...). Existen multitud de elementos que pueden acoplarse a
un pipeline, pudiendo crear complejos mecanismos de procesado
multimedia. En la figura \ref{fig:pipelinecameraserver} se puede
observar el \emph{pipeline} que genera este componente para obtener la imagen
final.

\begin{figure}[htbp]
\begin{center}
\includegraphics[width=0.8\textwidth]{img/pipelinecameraserver}
\caption{Pipeline Gstreamer usado en \emph{cameraServer}}
\label{fig:pipelinecameraserver}
\end{center}
\end{figure}

Este componente, que ya existía en la arquitectura de \emph{JDEROBOT},
se ha probado a fondo a lo largo de este proyecto y se le han añadido
funcionalidades avanzadas en cuanto a streaming se refiere. Para ello
fue necesario modificar ciertas partes del componente.

En primer lugar, se añadió al interfaz del componente métodos para
iniciar el streaming de la cámara (\emph{startCameraStreaming}), para parar
el \emph{streaming} de la cámara (\emph{stopCameraStreaming}) y para poder obtener
una miniatura en tiempo real del flujo de vídeo
(\emph{getThumb}). Todas ellas se pueden observar en el interfaz de la
figura \ref{camera-ice}

\begin{lstlisting}[language=c,float=htbp,caption=Interfaz ICE del
  componente cameraServer,label=camera-ice]

  /**
   * Camera interface
   */
  interface Camera extends ImageProvider
  {
    idempotent CameraDescription getCameraDescription();    
    string startCameraStreaming(int width, int height);    
    void stopCameraStreaming();    
    //! Return: bytes of thumb
    //null in other case
    ByteSeq getThumbCamera ();
  };
\end{lstlisting}


Para realizar el \emph{streaming} del dispositivo de vídeo nos ayudamos de la
herramienta \emph{VLC} (\cite{vlc}), que configurándola de la siguiente forma,
obtenemos un \emph{streaming} en tiempo real a 25fps y con una resolución de
320x240 píxeles.

\newpage
\begin{verbatim}
/usr/bin/vlc v4l2:///dev/video3
             -I dummy 
             --sout "#transcode{vcodec=mp4v,acodec=aac,width=320,height=240}:
                      rtp{dst=0.0.0.0,port=1234,
                          sdp=rtsp://193.147.51.113:8081/cameraB.sdp}"
\end{verbatim}


Durante todo el proyecto se han realizado pruebas en este componente,
ya que es la base de la obtención de las imágenes y vídeos, lo que ha
llevado al aumento de su eficiencia y ampliación de su
funcionalidad. En la tabla \ref{tabla:cameraserver} se pueden observar
algunas métricas interesantes sobre el código fuente de este
componente. A lo largo de este capítulo mostraremos tablas similares
para cada componente, donde se podrá ver el número de ficheros que lo
componen, número de líneas, la complejidad ciclomática de
\emph{McCabe} (Apéndice~\ref{apendiceA:mccabe}) y tiempo y coste
estimado según el modelo constructivo de costes de \emph{COCOMO}
(Apéndice~\ref{apendiceA:cocomo}).


\begin{table}[htbp]
\begin{center}
\footnotesize
\begin{tabular}{||l|p{7cm}||}
\hline
\hline
\bf{Número de ficheros} & 3  \\
\hline
\bf{Numero de líneas (C++)} &  508 \\
\hline
\bf{Complejidad ciclomática de McCabe} & cameraServer.cpp(31) gstpipeline.cpp(45) \\
\hline
\bf{Tiempo estimado de desarrollo (COCOMO)} & 2,66 meses  \\
\hline
\bf{Coste estimado de desarrollo (COCOMO)} & 13,268 \$  \\
\hline
\hline
\end{tabular}
\end{center}
\normalsize
\caption{Resumen de métricas de código del componente \emph{CameraServer}}
\label{tabla:cameraserver}
\end{table}

\subsection{Multiplexación del flujo de vídeo}

Una de las limitaciones que existen cuando se trabaja con dispositivos
de vídeo es que el kernel de Linux bloquea el acceso a dicho
dispositivo mientras exista un proceso utilizándolo. Esto es un
problema, ya que el sistema de video vigilancia debe ser capaz de
realizar varias acciones simultáneas con la misma cámara: analizar imagen,
grabar y realizar \emph{streaming}.

Para solucionar este inconveniente y disponer de multiplexación en el
flujo de vídeo de la cámara se ha utilizado el módulo
'vloopack'\footnote{http://www.lavrsen.dk/twiki/bin/view/Motion/VideoFourLinuxLoopbackDevice}. Este
módulo, que no se distribuye oficialmente en el kernel de Linux,
ofrece una solución ideal ya que permite que varios procesos accedan
al flujo de vídeo de la cámara simultáneamente. Como se puede observar
en la figura \ref{fig:vloopback} el módulo 'vloopback' crea dos
dispositivos virtuales (\emph{/dev/video1} y \emph{/dev/video2}). El
flujo de vídeo de la cámara (\emph{/dev/video0}) pasa directamente a
\emph{/dev/video1} a través de un único proceso. El módulo a su vez
transmite automáticamente el flujo de vídeo de \emph{/dev/video1} a
\emph{/dev/video2}, siendo este último no-bloqueante para los \emph{n}
procesos consumidores del flujo de vídeo. Esta configuración se
puede repetir por cada cámara del sistema que necesite multiplexar su
flujo de vídeo.

Además, esta solución nos permite un preprocesado mínimo antes de que
la señal llegue a nuestros procesos. Gracias a ello podemos hacer que
la resolución a la que llegue el flujo a los componentes sea una
determinada y no la que devuelve directamente la cámara.

\begin{figure}[htbp]
\begin{center}
\includegraphics[height=7.0cm]{img/vloopback}
\end{center}
\caption{Flujo de funcionamiento del módulo vloopback}
\label{fig:vloopback}
\end{figure}




\section{Componente \emph{Motion Detection}}

El objetivo de este componente es detectar movimiento en el flujo de
vídeo que se recibe desde un \emph{cameraServer} y notificar dicha
detección del movimiento al componente \emph{Surveillance}, que
realizará las grabaciones oportunas. Por tanto, el fichero de
configuración de este componente debe tener referencias al componente
\emph{cameraServer} y al componente \emph{Surveillance}, tal como se
muestra a continuación:

\begin{verbatim}
Motiondetection.Endpoints=default
Motiondetection.Camera.Proxy=cameraA:tcp -h 0.0.0.0 -p 9999
Motiondetection.Surveillance.Proxy=surveillance1:tcp -h 0.0.0.0 -p 9998
Motiondetection.UseUI=0
\end{verbatim}

El funcionamiento de este componente se basa en la petición de
imágenes constantemente al componente \emph{cameraServer}, para ser
analizadas y detectar movimiento en la imagen. Se utilizan dos
técnicas para detectar el movimiento. La primera de ellas se trata de
la diferencia de píxeles entre 2 imágenes consecutivas, por lo que
concluiremos que hay movimiento si esa resta supera un umbral
definido. La segunda técnica que utiliza es el flujo óptico, que
además de ofrecer la información de movimiento, calcula la magnitud y
orientación del mismo. Éste último se trata de un algoritmo más
complejo y costoso pero se obtienen mejores resultados y más
información. Se ha utilizado la implementación que posee la librería
de visión \emph{OpenCV}. La figura \ref{fig:clasesmotiondetection}
muestra un diagrama de las clases usadas en este componente.

\begin{figure}[htbp]
\begin{center}
\includegraphics[width=1.0\textwidth]{img/clasesmotiondetection}
\caption{Diagrama del componente \emph{motionDetection}}
\label{fig:clasesmotiondetection}
\end{center}
\end{figure}

Este componente, que ya existía en la arquitectura de \emph{JDEROBOT},
se ha probado más a fondo y se le ha añadido la integración con el
sistema de grabaciones, que es objetivo de este proyecto. En la tabla
\ref{tabla:motiondetection} se puede ver las métricas del código de
este componente.

\begin{table}[htbp]
\begin{center}
\footnotesize
\begin{tabular}{||l|l||}
\hline
\hline
\bf{Numero de ficheros} & 9  \\
\hline
\bf{Numero de líneas (C++)} &  703 \\
\hline
\bf{Complejidad ciclomática de McCabe} & 60  \\
\hline
\bf{Tiempo estimado de desarrollo (COCOMO)} & 3,03 meses  \\
\hline
\bf{Coste estimado de desarrollo (COCOMO)} & 18,661 \$  \\
\hline
\hline
\end{tabular}
\end{center}
\normalsize
\caption{Resumen de métricas de código del componente
  \emph{MotionDetection}}
\label{tabla:motiondetection}
\end{table}



\section{Sistema de Grabaciones}
\label{sec:grabaciones}

El sistema de grabaciones es una de las partes más importantes y
genuinas de este proyecto y en la que más tiempo se ha empleado para
su correcta implementación y funcionamiento. Este sistema es el
encargado de llevar la gestión y control de las grabaciones que se
realizan en el sistema y llevarlas a cabo obteniendo un fichero físico
de vídeo.

Esta parte del sistema se compone de tres componentes:
\emph{Survillance}, \emph{RecordingManager} y \emph{Recorder}. El
primero de ellos, \emph{Surveillance}, posee la lógica del
sistema. Es quien decide la duración de las grabaciones, cuándo
empezarlas y cuándo terminarlas, a qué resolución se realizan y sobre
qué dispositivo físico. El segundo componente, \emph{RecordingManager},
es el encargado de llevar un control lógico en base de datos de las
grabaciones que se están llevando a cabo y las que se hicieron en un
pasado. Es el encargado de servir la información de las grabaciones,
tanto sus datos específicos, como el \emph{streaming} de vídeo de las
mismas. Por último, el componente \emph{Recorder} es el encargado de
realizar la grabación individual a fichero desde el flujo que ofrece la
cámara. Una vista básica de la comunicación entre estos componentes se
puede ver en la figura \ref{fig:comun-grabaciones}

\begin{figure}[htbp]
\begin{center}
\includegraphics[height=4.0cm]{img/comun-grabaciones}
\end{center}
\caption{Vista básica del proceso de grabaciones}
\label{fig:comun-grabaciones}
\end{figure}

Una de las ideas de partir el sistema de grabaciones en varios
componentes, es que éstos puedan ejecutar en distintas máquinas y
puedan ser reutilizados en otras aplicaciones.
A continuación vamos a ver en detalle, la implementación y
características de cada componente que forma esta parte del sistema.

\subsection{Componente \emph{Surveillance}}
\label{subsec:surveillance}

La esencia de este componente es definir la lógica del sistema de
grabaciones. Este componente es imprescindible en el diseño ya que no
todos los sistemas de grabaciones tienen por qué comportarse de la misma
manera o tener las mismas especificaciones. Es en este componente, el
\emph{Surveillace}, donde se describen todas las características que
definen las grabaciones y es donde se configura la respuesta apropiada
a las alarmas generadas, unas veces será realizar grabaciones y otras
puede ser el envío automático de mensajes de texto (\emph{sms}). Tal
como se puede ver en la figura \ref{fig:dise-surveillance} el
componente \emph{Surveillance} ofrece una interfaz a todos los
posibles generadores de alarmas que existen en el sistema. Sólo cuando
se notifiquen las alarmas el \emph{Surveillance} inicia las
grabaciones pertinentes comunicándose con el interfaz del componente
\emph{RecordingManager}. Además dispone de una segunda función en el
sistema, que es el realizar grabaciones periódicas de un tiempo
definido por configuración y a baja resolución para recoger todo lo
sucedido en el escenario.  Es importante destacar que gracias a la
arquitectura distribuida de nuestro proyecto, cada componente puede
estar en una máquina física distinta.


\begin{figure}[htbp]
\begin{center}
\includegraphics[width=0.8\textwidth]{img/surveillance}
\caption{Vista de interacción de componentes con \emph{Surveillance}}
\label{fig:dise-surveillance}
\end{center}
\end{figure}


\begin{verbatim}
Surveillance.NRecordings=1

Surveillance.0.RecordingManager.Proxy=recordManager1:tcp -h 0.0.0.0 -p
9998

Surveillance.0.dirRecordings=/home/rocapal/tmp/recorder/
Surveillance.0.namePattern=video-XXXXXX
Surveillance.0.name=cameraA
Surveillance.0.protocol=v4l2
Surveillance.0.device=/dev/video2
Surveillance.0.width=320
Surveillance.0.height=240
Surveillance.0.fps=15
Surveillance.0.duration=10
\end{verbatim}

El fichero de configuración de \emph{Surveillance} se compone
inicialmente de un parámetro (\emph{NRecordings}) que indica cuántos procesos de grabación
van a existir, es decir, cuántas grabaciones queremos hacer a la
vez. Esta funcionalidad es muy potente y permite definir, en un mismo
componente, multitud de grabaciones y configuraciones sobre las
cámaras. Por ejemplo, se podrían realizar dos grabaciones de una misma
cámara, una de ellas a 320x240 @15fps y la segunda a 640x480 @25fps. Y
todo ello utilizando únicamente este componente. El segundo parámetro
que se muestra (\emph{RecordingManager}) define el proxy (la
dirección) donde hay que realizar las peticiones al
\emph{RecordingManager}.

\begin{lstlisting}[language=c,float=htb,caption=Código encargado de
  generar las peticiones de grabaciones,label=for-surveillance]

for (;;)
{  
  string new_name = generateFileName();
  jderobot::RecorderConfigPtr recConfig = new  jderobot::RecorderConfig();

  recConfig = readConfigRecording();
  recConfig->name = new_name;

  int recId = recManagerPrx->startRecording(recConfig);

  sleep(recConfig->duration);

  recManagerPrx->stopRecording(recId);
}
\end{lstlisting}

El resto de parámetros que se ven en el fichero de configuración
permiten definir características especificas de la grabación a
realizar. Por ejemplo, se puede definir el directorio donde se
guardarán los ficheros de video (parámetro
\emph{dirRecordings}). También se puede definir el patrón que tendrá
cada fichero de vídeo generado (parámetro \emph{namePattern}). Gracias
al parámetro \emph{name} definiremos el nombre de esta grabación en el
sistema. Y por último se detallan parámetros técnicos de grabaciones
como protocolo (parámetro \emph{protocol}), dispositivo físico de
vídeo (parámetro \emph{device}), resolución del vídeo (parámetros
\emph{width} y \emph{height}), flujo del vídeo (parámetro \emph{fps})
y la duración de la grabación en minutos (parámetro
\emph{duration}). Con toda esta información, el componente va
generando peticiones de comienzo y fin de grabación tal como se
observa en el listado \ref{for-surveillance}.

\subsubsection{Gestión de Alarmas}

Este componente también es el encargado de recibir las alarmas
generadas por el componente \emph{MotionDetection} y realizar las
acciones pertinentes en el sistema. En el caso concreto de este
proyecto, la notificación de una alarma conlleva el inicio de una
grabación inmediato en todas las cámaras durante un intervalo de 10
minutos y con una resolución de 320x240 @25fps. Es importante
comentar que esta es la configuración que hemos utilizado para este
proyecto, pero igualmente podríamos generar envíos de mensajes a
móviles, a correos electrónicos, activar alarma mediante hardware
domótico, etc.

Para dotar de esta funcionalidad al sistema es necesario configurar
al componente \emph{Surveillance} para que escuche peticiones
entrantes. Por ello, se incluyen las siguientes líneas en el archivo
de configuración del componente.

\begin{verbatim}
Surveillance.Endpoints=tcp -h 0.0.0.0 -p 9995
Surveillance.App.Name=surveillance1
\end{verbatim}

Además, es necesario generar un interfaz \emph{ICE} para que ambos
componentes (\emph{Surveillance} y \emph{MotionDetect}) puedan
comunicarse. El interfaz utilizado se compone de un único método,
\emph{notifyEvent}, que provee la información necesario de dónde (en
qué cámara) se ha producido la alarma.

\begin{lstlisting}[language=c,float=htb,caption=Interfaz ICE del
  componente surveillance,label=ice-surveillance]
module jderobot 
{
  interface Surveillance
  {
     //! Returns: 0 if all was ok
     //           -1 in other case 
    int notifyEvent (RecordingEvent recEvent);
  };
};
\end{lstlisting}

En la tabla \ref{tabla:surveillance} se puede ver las métricas sobre
el código de este componente. Es importante destacar la poca
complejidad ciclomática que presenta este componente (tabla
\ref{tabla:surveillance}). Una características común a todo el resto
de componentes, ya que gracias a la reutilización de código
\emph{FLOSS} conseguimos componentes eficaces, robustos y de poca
complejidad. Esto último permitirá que las tareas de mantenimiento
sean sencillas.

\begin{table}[htbp]
\begin{center}
\footnotesize
\begin{tabular}{||l|l||}
\hline
\hline
\bf{Numero de ficheros} & 1  \\
\hline
\bf{Numero de líneas (C++)} &  169 \\
\hline
\bf{Complejidad ciclomática de McCabe} & 18 \\
\hline
\bf{Tiempo estimado de desarrollo (COCOMO)} & 1,72 meses  \\
\hline
\bf{Coste estimado de desarrollo (COCOMO)} & 4,178 \$  \\
\hline
\hline
\end{tabular}
\end{center}
\normalsize
\caption{Resumen de métricas de código del componente                                                                                                                                    \emph{Surveillance}}
\label{tabla:surveillance}
\end{table}



\subsection{Componente \emph{Recorder}}
\label{subsec:recorder}

El componente \emph{Recorder} es el encargado de recibir las
peticiones de grabación y llevarlas a cabo generando un fichero de
video con las especificaciones adecuadas. Como se lleva comentando
durante todo el capítulo, los parámetros de grabación los establece el
componente \emph{Surveillance}, que a su vez realiza peticiones al
\emph{RecordingManager} y éste se las notifica al \emph{Recorder}. Por
tanto, este último es el encargado de llevar a cabo correctamente el
proceso de grabaciones y notificar los resultados al
\emph{RecordingManager}. En la figura \ref{fig:dise-recorder} se puede
ver una configuración posible con dos \emph{Recorder} en dos máquinas
distintas, y el \emph{RecordingManager} realizando peticiones de
grabaciones a través de los interfaces. Como se observa, es posible
configurar el componente \emph{Recorder} con tantas cámaras físicas
como se desee.

\begin{figure}[htbp]
\begin{center}
\includegraphics[width=0.8\textwidth]{img/recorder}
\caption{Vista de interacción de componentes con \emph{Recorder}}
\label{fig:dise-recorder}
\end{center}
\end{figure}

\newpage
La configuración de este componente es sencilla, como se puede ver más
abajo. Únicamente es necesario decirle el nombre que tendrá en nuestro
sistema, el \emph{endPoint} donde se atará para realizar las escuchas
y el \emph{provider} utilizado para realizar las grabaciones. Las
grabaciones se realizan utilizando herramientas del sistema. La
reutilización en este proyecto es muy importante, ya que gracias a la
reusabilidad y al \emph{FLOSS} se consigue llegar más lejos en los
desarrollos, con más calidad y se evita el \emph{``reinventar la rueda''}.

\begin{verbatim}
RecorderApp.Endpoints=tcp -h 0.0.0.0 -p 9997
RecorderApp.Recorder.Name=recorder1
RecorderApp.Recorder.Provider=vlc
\end{verbatim}


\begin{lstlisting}[language=c++,float=htpb,caption=Clase
  RecorderConfig,label=ice-recorder]
  class RecorderConfig
  {
    // Recording id;
    int id;
    // Recording name
    string name; 
    // Recording camera proxy
    string cameraProxy  
    // Protocol: v4l | v4l2 | cameraServer
    string protocol;
    // Device: /dev/video0 | proxy to cameraserver
    string device;
    // Height resolution
    string height;
    // Width resolution
    string width;
    // File system path
    string path;
    //! TimeStamp to begin
    Time beginTimeStamp;
    //! TimeStamp to end
    Time endTimeStamp;
    //! FrameRate of recording
    string frameRate;
    //! Seconds of recording
    string duration;
    //! Status
    // 0: In progress
    // 1: Finished
    // 2: Error
    int status;
  };
\end{lstlisting}

Ya que es necesario que otros componentes se comuniquen con éste, es
imprescindible definir una interfaz \emph{ICE}. Como se puede observar
en la definición del interfaz (\ref{ice-recorder}), existe una clase
llamada \emph{RecorderConfig} que guarda todos los datos necesarios
para realizar una grabación. Esta estructura es la que se utiliza en
la comunicación entre \emph{RecordingManager} y \emph{Recorder} para
llevar a cabo las grabaciones. En esta estructura se encuentran datos
importantes como el formato de la grabación, resolución, dispositivo
físico, directorio donde se debe guardar o la duración que debe tener
la grabación.

Además, se define un interfaz llamado \emph{Recorder} que se compone
de dos llamadas: \emph{startRecording} y \emph{stopRecording}. La
primera de ellas se utiliza para iniciar una grabación y es necesario
pasarle la configuración de la grabación mediante el parámetro
\emph{recConfig}. Esta llamada devuelve la misma estructura recibida
modificando el parámetro \emph{id}, asignándole un identificador único
si todo ha ido bien, y un \emph{-1} si ocurrió algún error. El segundo
método, \emph{stopRecording}, finaliza la grabación asignada al
identificador \emph{idRecording}. Más adelante se explicarán los
detalles de programación de estos métodos.

\begin{lstlisting}[language=c,float=htpb,caption=Interfaz ICE del
  componente Recorder,label=ice-surveillance]
  interface Recorder
  {
     //! Returns: ID of recording if all was ok
     //           -1 in other case
    ["ami"] RecorderConfig startRecording (RecorderConfig recConfig); 

    //! Returns: 0 if all was ok
    //           -1 in other case        
    int stopRecording (int idRecording);
  };
\end{lstlisting}

\subsubsection{Interacción con los componentes}

La interacción y comunicación con este componente se ha diseño de tal
manera que sea robusta a los fallos de grabaciones y sobre todo sea
consistente. Es un problema muy grave que el sistema diga que se está
grabando cuando no lo está haciendo, sobre todo si se trata de un
sistema de seguridad crítico.

En la figura \ref{fig:diagrama-recorder} se muestra el diagrama de
secuencia que siguen los componentes \emph{RecordingManager} y
\emph{Recorder} para realizar una grabación. El primer paso lo realiza
el \emph{RecordingManager} iniciando una grabación utilizando el
método \emph{startRecording} mediante una llamada asíncrona (en el
siguiente sub-apartado de implementación se explicará con detalle el
mecanismo utilizado para llamadas asíncronas). El componente
\emph{Recorder} recibe la petición de iniciar una grabación y genera
un hilo de ejecución con el \emph{provider} de grabación
correspondiente. Cuando el hilo de ejecución ha comenzado a grabar
correctamente, y sólo en este momento, se envía un mensaje de
confirmación al \emph{Recorder} que propaga hasta el
\emph{RecordingManager}. En este momento, el identificador que recibe
el \emph{RecordingManager} es un identificador único para el manejo de
esta grabación. Pasado el tiempo de grabación, que se define en el
fichero de configuración, el \emph{RecordingManager} decide parar la
grabación y por tanto utiliza el método \emph{stopRecording} junto con
el identificador correspondiente. El \emph{Recorder} finaliza el
hilo de grabación y propaga la respuesta hasta el
\emph{RecordingManager} para notificar que la grabación finalizó
correctamente.

Es importante destacar que el método \emph{startRecording} devuelve
como identificador el número de proceso que arranca en el sistema
operativo para realizar la grabación. Este número puede no ser único,
ya que puede repetirse dentro de la misma máquina y además la
configuración del sistema permite tener varios componentes
\emph{Recorder} en varias máquinas distintas. Por lo que no podemos
asegurar que ese identificador sea único en nuestro sistema de
grabaciones. Veremos más adelante cómo solucionamos este problema en
el componente \emph{RecordingManager}.

\begin{figure}[htbp]
\begin{center}
\includegraphics[height=10.0cm]{img/diagram-recorder}
\end{center}
\caption{Diagrama de secuencia del componente \emph{Recorder}}
\label{fig:diagrama-recorder}
\end{figure}

Si por cualquier motivo ocurre un error entre los pasos \emph{2} y
\emph{3} (figura \ref{fig:diagrama-recorder}), \emph{Recorder}
devolvería un error al \emph{RecordingManager} para notificarlo al
sistema y dar a conocer que una grabación no se ha podido iniciar. De
igual modo, si ocurriese un error una vez iniciada la grabación (por
ejemplo, falta de espacio en disco duro, o desconexión de la cámara),
el hilo de ejecución de grabación lo detectaría y se lo notificaría al
\emph{Recorder}, que a su vez lo propagaría para comunicar que una
grabación terminó antes de lo esperado.

Quizás éste sea el componente más crítico en el sistema, ya que es el
encargado de realizar las grabaciones en última instancia, generando
el fichero de vídeo en el sistema de almacenamiento. Este componente
es, desde luego, el que más tiempo ha llevado de diseño, desarrollo y
pruebas de todos los que componen el sistema.

\subsubsection{Implementación}

Este componente contiene varios puntos importantes de implementación
que merecen una explicación detallada.

El primer punto se trata de implementar de manera asíncrona la llamada
de \emph{startRecording}. Es necesario que esta llamada sea asíncrona
ya que \emph{ICE}, aunque permite hilos de ejecución dentro de una
interfaz, no retorna la llamada hasta que todos los hilos de ejecución
hayan terminado. Esto supone un problema ya que si un componente
llamase a \emph{startRecording}, éste no retornaría hasta que tanto la
grabación como su hilo de ejecución terminasen. Para solucionar este
problema hemos utilizado el modelo de programación asíncrona que nos
ofrece \emph{ICE}, el \emph{Asynchronous Method Invocation
  (AMI)}. \emph{AMI} nos provee de mecanismos para que el hilo de
ejecución que realiza la llamada no se quede bloqueado esperando la
respuesta. En la parte del servidor, en nuestro caso \emph{Recorder},
el uso de \emph{AMI} es transparente a la implementación, ya que lo
único que hay que hacer es definir el interfaz de la llamada de la
siguiente manera:

\begin{verbatim}
["ami"] RecorderConfig startRecording (RecorderConfig recConfig);
\end{verbatim}

En la parte cliente, la que realiza la llamada (en este caso
\emph{RecordingManager}), sí es necesario modificar código y
prepararlo para cuando llegue la respuesta asíncrona del método
definido como \emph{AMI}. Esta parte se verá con más detalle en la
implementación del componente \emph{RecordingManager}.

El segundo punto importante de implementación de este componente es el
que trata de la realización de grabaciones a bajo nivel. Como ya se ha
comentado, se utilizan herramientas del sistema \emph{GNU/Linux} para
realizar las grabaciones, tales como \emph{ffmpeg}, \emph{mencoder} o
\emph{vlc}. En el futuro es de esperar que se agreguen más
herramientas o métodos para realizar grabaciones, por ello se ha
diseñado de tal forma que sea fácilmente escalable el sistema. Como se
puede ver en la figura \ref{fig:clases-recorder} el componente
\emph{Recorder} sabe manejar clases de tipo \emph{GenericRecorder} que
proveen una interfaz para acceder a toda la información de grabaciones
(comenzar, parar, estado, ...). Como se observa, actualmente hay dos
clases que heredan de la clase genérica, \emph{deviceRecorder} y
\emph{imageRecorder}. La primera de ellas se encarga de grabar
directamente del dispositivo físico utilizando diferentes
\emph{providers} (\emph{ffmpeg}, \emph{mencoder}, \emph{vlc}). La
segunda de ellas se encarga de grabar utilizando una secuencia de
imágenes que obtiene del componente \emph{CameraServer} (funcionalidad
utilizada \cite{smarugan10}). Gracias a este diseño de clases
es fácil integrar una nueva herramienta de grabación de dispositivos
físicos (se incorporaría a \emph{deviceRecorder}) o integrar un nuevo
sistema de grabaciones (se crearía una nueva clase que heredase de
\emph{GenericRecorder}).

\begin{figure}[htbp]
\begin{center}
\includegraphics[height=9.0cm]{img/clases-recorder}
\end{center}
\caption{Diagrama de clases del componente \emph{Recorder}}
\label{fig:clases-recorder}
\end{figure}

Por último, se puede ver en el listado \ref{list:code-startRecording} el
código del método startRecording, donde dependiendo de la
configuración seleccionada utilizará el protocolo \emph{video for
  linux} para realizar la grabación o utilizará el protocolo que
utiliza el interfaz de \emph{cameraServer}. Concretamente, para este
proyecto hemos utilizado el protocolo \emph{video for linux} y por
tanto hemos usado la clase \emph{deviceRecorder} que ofrece varios
\emph{providers} para realizar las grabaciones, tal como se observa en
el listado \ref{list:code-deviceRecorder}

\begin{lstlisting}[language=c++,float=htbp,caption=Código del método
  startRecording,label=list:code-startRecording]
virtual jderobot::RecorderConfigPtr startRecording(
                     const jderobot::RecorderConfigPtr& recConfig,
 				     const Ice::Current& c)
{
	jderobot::RecorderConfigPtr rec = new jderobot::RecorderConfig();
	GenericRecorder* myRecorder = NULL;
	// Initialize and launch the Recorder
	if ( (recConfig->protocol).find(RECORDING_PROTOCOL_V4L) !=
         std::string::npos) {
	  // V4L & V4L2 protocol
	  myRecorder = new deviceRecorder (context,recConfig,mProvider);
	  myRecorder->startRecording();
	}
	else if ( (recConfig->protocol).
              compare(RECORDING_PROTOCOL_CAMERASERVER) == 0)	{
	  // cameraServer Protocol
	  myRecorder = new imageRecorder (context,recConfig,
                                      RECORDING_PROVIDER_MENCODER);
	  myRecorder->startRecording();
	}
	// The recorder is saved in a list.
	if (myRecorder != NULL) {
	  IceUtil::Mutex::Lock sync(listMutex);
	  recList.push_back(myRecorder);
	  
	  jderobot::RecorderConfigPtr rec = new jderobot::RecorderConfig();
	  rec = recConfig;
	  rec->id = myRecorder->getId();
	  return rec;
	}
	else {
	  context.tracer().error("Impossible initialize the recorder!");
	  rec = recConfig;
	  rec->id = -1;
	  return rec;
	}
}
\end{lstlisting}


\begin{lstlisting}[language=c++,float=htbp,caption=Código de la clase
  deviceRecorder,label=list:code-deviceRecorder]
int deviceRecorder::doRecording() {
	getContext().tracer().info ( "starting recording: Path = " +
				 getConfig()->path + " - FrameRate = " +
				 getConfig()->frameRate + " fps - " + " - device: " + 
                 getConfig()->device );
	if (getProvider() == RECORDING_PROVIDER_FFMPEG)	{
		std::string v4lVersion, resolution;
		
		char *parmList[] = generateCommand(RECORDING_PROVIDER_FFMPEG);

		// Execute command
		execv("/usr/bin/ffmpeg", parmList);
	}
	else if (getProvider() == RECORDING_PROVIDER_MENCODER)	{
		std::string v4lVersion;
		char *parmList[] = generateCommand(RECORDING_PROVIDER_MENCODER);

		execv("/usr/bin/mencoder", parmList);
	}
	else if  (getProvider() == RECORDING_PROVIDER_VLC)	{
		std::string v4lConfig, vlcTranscode;

		char *paramList[] = generateCommand(RECORDING_PROVIDER_VLC);
		execv("/usr/bin/vlc", paramList);
	}
	else {
		getContext().tracer().error ("Recording Provider Unknow!");
		return -1;
	}
}
\end{lstlisting}

La tabla \ref{tabla:recorder} muestras las métricas sobre el código de
este componente. Al igual que los anteriores componentes muestra una
complejidad de código baja.

\begin{table}[htbp]
\begin{center}
\footnotesize
\begin{tabular}{||l|p{5cm}||}
\hline
\hline
\bf{Número de ficheros} & 8  \\
\hline
\bf{Numero de líneas (C++)} & 552   \\
\hline
\bf{Complejidad ciclomática de McCabe} & deviceRecorder.cpp(8) 
imageRecorder.cpp(19) genericRecorder.cpp(5) recorder.cpp(16)\\
\hline
\bf{Tiempo estimado de desarrollo (COCOMO)} & 2,75 meses  \\
\hline
\bf{Coste estimado de desarrollo (COCOMO)} & 14,477 \$  \\
\hline
\hline
\end{tabular}
\end{center}
\normalsize
\caption{Resumen de métricas de código del componente
  \emph{Recorder}}
\label{tabla:recorder}
\end{table}


\subsection{Componente \emph{RecordingManager}}
\label{subsec:recordingManager}

El componente \emph{RecordingManager} tiene vital importancia en el
aspecto de gestión de las grabaciones. Es el encargado de llevar el
control de qué grabaciones se hacen, cuáles se han llevado a cabo
bien, cuáles mal, y servir la información necesaria para visualizar
dichas grabaciones. En este proyecto, \emph{Surveillance} se comunica
con \emph{RecordingManager} para la petición de grabaciones, tanto
regulares, como de alarmas. También el componente que ejecuta en el
móvil habla con el componente \emph{RecordingManager} para pedir
información sobre las grabaciones y el \emph{streaming} de los
vídeos. En la figura \ref{fig:dise-recordingmanager} se puede ver la
estructura que tiene el sistema de grabaciones en cuanto a componentes
y máquinas donde ejecutan dichos componentes.

\begin{figure}[htbp]
\begin{center}
\includegraphics[width=1.0\textwidth]{img/recordingmanager}
\caption{Vista de interacción de componentes con \emph{RecordingManager}}
\label{fig:dise-recordingmanager}
\end{center}
\end{figure}


La configuración de este componente es sencilla. Como se puede ver a
continuación, únicamente es necesaria la información sobre su nombre en
el sistema y el \emph{endPoint} donde estará escuchando peticiones y
la referencia al proxy del componente \emph{Recorder}. Además, se
especifica también la dirección que se utilizará para realizar el streaming
(\emph{StreamingUri}).

\begin{verbatim}
RecordingSrv.Endpoints=tcp -h 0.0.0.0 -p 9998
RecordingSrv.Recording.Id=recordManager1
RecordingSrv.StreamingUri=rtsp://193.147.51.113:8081/video
RecordingSrv.Recorder.Proxy=recorder1:tcp -h 0.0.0.0 -p 9997 
\end{verbatim}


El componente \emph{RecordingManager} implementa un interfaz algo más
extensa que los otros componentes (listado
\ref{list:interface-recordingManager}) ya que ofrece bastante más
funcionalidad y es el centro lógico de las grabaciones. Esta
funcionalidad la podemos separar en tres grupos: gestión de
grabaciones, gestión de alarmas y streaming de los vídeos.

La primera de estas funcionalidades, \texttt{gestión de grabaciones}, posee
dos métodos para la creación de grabaciones: \emph{startRecording} y
\emph{stopRecording}. Para comenzar una grabación se llamará a
\emph{startRecording} lo que generará una nueva entrada en la base de
datos de grabaciones y se realizará una llamada al componente
\emph{Recorder} para que comience a grabar en disco. Del mismo modo,
cuando se llame a \emph{stopRecording} se detendrá el proceso de
grabación del componente \emph{Recorder} y se actualizará el estado
correspondiente de la grabación en la base de datos. Además, el
interfaz dispone de varios métodos para consultar las grabaciones
realizadas en el sistema. El primero de estos métodos es
\emph{getRecordings} que pasándole un rango de enteros, nos devuelve
las grabaciones que se encuentran en dicho rango. El segundo de ellos,
\emph{getRecordingsByDate}, permite hacer lo mismo pero filtrando las
grabaciones por fecha, muy útil para realizar búsquedas
rápidamente. Por último, el interfaz provee el método
\emph{getThumbRecording} que devuelve la imagen del primer segundo de
la grabación. Esta funcionalidad es muy útil para mostrar todas las
grabaciones en un listado y simplemente por la imagen inicial
distinguir las grabaciones.

La segunda de las funcionalidades que este componente provee es la
\texttt{gestión de alarmas}. En el interfaz de este componente se
define la clase \emph{RecordingEvent} (listado
\ref{list:recorder-event}) que recoge todos los parámetros importantes
de una alarma: identificador, tipo (sistema o alarma), quién lo
produce, sobre qué recurso, una imagen asociada y un comentario. El
interfaz ofrece varios métodos para establecer Alarmas. En este
proyecto es el componente \emph{Surveillance} quien se encarga de
recoger las alarmas notificadas por \emph{Detection Motion} y añadir
la lógica de qué hacer cuando se recibe una alarma. En nuestro
proyecto, la acción ejecutada cuando se recibe una alarma es generar
una grabación en la cámara donde se produjo dicha alarma. Cuando esto
ocurre, el \emph{RecordingManager} recibe un \emph{setEvent} sobre una
grabación en concreto y por tanto se queda almacenada la relación
entre grabaciones y alarmas. Gracias al método
\emph{getEventsOfRecording} podemos consultar las alarmas asociadas a
una grabación determinada del sistema.

Por último, este interfaz dispone del método \emph{startStreaming}
que permite abrir una conexión de streaming mediante \emph{RTSP} para
poder visualizar la grabación en un dispositivo móvil o un
ordenador. Más adelante se detallará la implementación de esta
funcionalidad.


\begin{lstlisting}[language=c++,float=htbp,caption=Clase RecorderEvent,label=list:recorder-event]

//! A sequence of recordings
sequence<RecorderConfig> RecordingSequence;

//! Description of the recording's event
class RecordingEvent
{
    //! Identifier of event
    int id;
    //! Type of event
    string type;
    //! TimeStamp of event
    Time timeStamp;
    //! What producer the alarm
    string producer;
    //! Resource from the alarm
    string resource;
    //! Path to image
    string pathImage; 
    //! Image associated to event
    ByteSeq image;    
    //! Comment
    string comment; 
};

\end{lstlisting}

\begin{lstlisting}[language=c++,float=htbp,caption=Interfaz
  RecordingManager,label=list:interface-recordingManager]

//! A sequence of events/alarms of the recording
sequence<RecordingEvent> EventSequence;

interface RecordingManager
{
    //! Returns the list of recordings
    idempotent RecordingSequence getRecordings(int from, int elems);
    //! Returns the list of recordings by date
    // Format Date = "YYYY-MM-DD" - "2010-05-28"
    idempotent RecordingSequence getRecordingsByDate (string date, 
                                                      int from, 
                                                      int elems);
    //! Return the event list of recording
    EventSequence getEventsOfRecording (int recordingId);
    //! Set an alarm event
    int setEvent (RecordingEvent recEvent, int recordingId);
    //! Get event
    RecordingEvent getEvent (int eventId);
    //! Start recording
    int startRecording (RecorderConfig recConfig);
    //! Returns: 0 if all was ok
    //           -1 in other case        
    int stopRecording (int recordingId);
    //! Return: url to listen the streaming
    //null in other case
    string startStreaming (int id); 
    //! Return: bytes of thumb
    //null in other case
    ByteSeq getThumbRecording (int id);
};
\end{lstlisting}


\subsubsection{Streaming}

El \emph{streaming} consiste en hacer una distribución de vídeo y/o
audio. Esta distribución puede ser de 1 a 1, o de 1 a muchos. La palabra
\emph{streaming} se refiere a emitir un flujo de vídeo y/o audio en
continuo, no se puede ir hacia atrás, ni hacia delante. Sólo es
posible visualizar lo que se emite en ese momento. Es muy útil para realizar
conferencias o visualizar contenido multimedia sin tener que descargar
el archivo completo.

El streaming que realiza este componente se basa en \emph{RTSP (Real
  Time Streaming Protocol)}. \emph{RTSP} es un protocolo de flujo de
datos en tiempo real que establece y controla uno o muchos flujos
sincronizados de datos. Es un protocolo no orientado a conexión,
aunque también puede ir encima de \emph{TCP}. En la mayoría de las
ocasiones se utiliza \emph{TCP} para los datos de control y \emph{UDP}
para los datos de audio y video, tal como muestra la figura
\ref{fig:udp-rtsp}. Este protocolo tiene las siguientes propiedades:

\begin{itemize}
  \item Extensible: nuevos parámetros y métodos puede ser fácilmente
    añadidos al protocolo.
  \item Seguro: reutiliza mecanismos de seguridad web
    (\emph{TSL}). Todas las fórmulas de autenticación de \emph{HTTP}
    son directamente aplicables.
  \item Es independiente del protocolo de transporte, se puede
    utilizar sobre \emph{UDP} y \emph{TCP}.
  \item Puede controlar dispositivos de grabación y reproducción como
    las cámaras \emph{IP-RTSP}
  \item Es ideal para aplicaciones profesionales ya que soporta
    resolución de fotogramas mediante marcas temporales para permitir la
    edición digital.
\end{itemize}


\begin{figure}[htbp]
\begin{center}
\includegraphics[height=4.0cm]{img/Udp_rtsp}
\end{center}
\caption{Comunicación básica del protocolo \emph{RTSP}}
\label{fig:udp-rtsp}
\end{figure}


El componente \emph{RecordingManager} realiza \emph{streaming} de todas las
grabaciones realizadas mediante el método
\emph{startStreaming} utilizando el protocolo \emph{RTSP}. Cuando se
llama a este método el componente levanta un servidor de streaming
generado con la herramienta \emph{vlc} que permite conectar varios
clientes para la visualización de la grabación. Para levantar el
servidor \emph{streaming} utilizamos el siguiente comando:

\newpage
\begin{verbatim}
/usr/bin/vlc -vvv path_fichero_grabación
             --play-and-exit 
             -I dummy 
             --sout '#transcode{vcodec=mp4v,acodec=aac,width=320,height=240}:
                      rtp{dst=0.0.0.0,port=1234,
                      sdp=rtsp://193.147.51.113:8081/video}'
\end{verbatim}


\subsubsection{Base de datos}

Como se ha comentado anteriormente, toda la gestión de grabaciones se
lleva en la base de datos. Se ha utilizado el motor de \emph{MySQL}
para generar las tablas y relaciones necesarias. En la base de datos
se guardan todos los datos relevantes de una grabación exceptuando los
ficheros de vídeo e imágenes, que se guardan directamente en el
sistema de ficheros (únicamente se guardan las referencias a los
\emph{paths} absolutos).

Como puede observarse en la figura \ref{fig:diseno-bbdd} el diseño de
la base de datos se compone de 4 tablas: en una se guarda toda la
información referente a las grabaciones
(\emph{recording\_recordings}), en otra se guarda toda la información
referente a alertas (\emph{recording\_events}), en la tercera se
guarda qué alertas pertenecen a qué grabaciones
(\emph{event\_recordings}) y por último en la tabla
\emph{recording\_type\_events} se define los tipos de alarmas
existentes (de sistema y alarma generada por componente). Las alarmas
generadas por el sistema son aquellas que hacen referencia a
notificaciones generales como falta de espacio en disco duro, error
de conexión de red, falta de memoria, etc. Las alarmas generadas por
componentes, son alarmas específicas que puede lanzar cualquier
componente del sistema como desconexión de la cámara, detección de
movimiento, límite de conexiones permitidas por un componente, etc.

Gracias a que utilizamos una base de datos centralizada para llevar el
control y gestión de las grabaciones, podemos asignar un identificador
único e universal a cada grabación. Este identificador único es el
identificador auto-incremental que disponemos en la tabla
\emph{recording\_recordings} de la base de datos. De esta manera
convertimos los identificadores locales que provienen de los
componentes \emph{Recorders} a identificadores universales que se
ofrecen a los componentes que realizan peticiones sobre las
grabaciones realizadas, como por ejemplo el componente
\emph{Surveillance}.


\begin{figure}[htbp]
\begin{center}
\includegraphics[height=5.0cm]{img/diseno-bbdd}
\end{center}
\caption{Diseño de la base de datos de grabaciones}
\label{fig:diseno-bbdd}
\end{figure}


\subsubsection{Implementación}

Este componente posee varias características importantes que merecen
ser detalladas y explicadas.

Como ya se vió en el apartado \ref{subsec:recorder}, la llamada
\emph{startRecording} que realiza el componente
\emph{RecordingManager} al interfaz del \emph{Recorder} es una llamada
asíncrona porque era necesario que retornara la llamada aunque se
estuviera lanzando y haciéndose la grabación. Es en este componente
\emph{RecordingManager} donde es necesario programar correctamente el
método asíncrono para esperar la confirmación del comienzo de la
grabación. \emph{ICE} nos provee una llamada nueva para funciones
asíncronas, esta nueva llamada lo que hace es no quedarse bloqueada en
ningún momento y retornar lo antes posible. A su vez, se define una
nueva clase que será la que recibirá la respuesta cuando esté lista y
preparada.

Entrando más en el código, se puede observar en el listado
\ref{list:start-recording} cómo se llama al método
\emph{startRecording\_async} (que retornará siempre con un valor fijo)
pasándole como parámetro una instancia de la clase
\emph{AMI\_Recoder\_startRecordingI} (que es la que obtendrá el
resultado final de la operación). Como es necesario que el
\emph{startRecording} del interfaz del \emph{RecordingManager} sea
bloqueante, utilizamos el paso de mensajes mediante \emph{pipes} para
sincronizar la llamada con el resultado que devuelve el
\emph{Recorder}. En el listado \ref{list:async-metodo} se puede
observar cómo se define la clase y se implementa el método
\emph{ice\_response}. Este método se ejecutará cuando la respuesta
haya sido devuelta y por tanto lo que se hace es escribir en el \emph{pipe}
el identificador de la grabación, lo que hará que desbloquee la
ejecución del código del listado \ref{list:start-recording}. Este
flujo de interacción se puede observar en la figura
\ref{fig:startRecording-async}.

\begin{figure}[htbp]
\begin{center}
\includegraphics[height=7.0cm]{img/startRecording-async}
\end{center}
\caption{Proceso de sincronización para el comienzo de una grabación.}
\label{fig:startRecording-async}
\end{figure}


\begin{lstlisting}[language=c++,float=htbp,caption=Método
  startRecording de RecordingManager,label=list:start-recording]

virtual Ice::Int startRecording(const jderobot::RecorderConfigPtr& recConfig, 
                                const Ice::Current&)
{
   recLog = initRecordingHandler();
   jderobot::AMI_Recorder_startRecordingPtr cb = 
          new AMI_Recoder_startRecordingI;

   getRecorderProxy()->startRecording_async(cb, recConfig);
   int pid_rec;
   // Read the PID
   read (descPipe[0], &pid_rec, sizeof(int));
   recConfig->id = pid_rec;
   // Log recording
   int recordingId = recLog->startRecording(recConfig);
   return recordingId;
}
\end{lstlisting}

\begin{lstlisting}[language=c++,float=htbp,caption=Método asíncrono
  que recoge la información,label=list:async-metodo]

// Private class to obtain the response of recording
class AMI_Recorder_startRecordingI: 
                  public jderobot::AMI_Recorder_startRecording
   {
     public:
         virtual void ice_response
                 (const jderobot::RecorderConfigPtr& recConfig)
         {
             int rec_id = recConfig->id;
             write (descPipe[1],&rec_id, sizeof(int));
         }
         virtual void ice_exception(const Ice::Exception& ex)
         {
             try {
               ex.ice_throw();
             } catch (const Ice::LocalException&e) {
                 std::cerr << "recorderfailed: " << e << std::endl;
             }
          }
    };
\end{lstlisting}

\newpage
La segunda característica importante de implementación que queremos
destacar es la generación de fotogramas o \emph{vista previa} de los
vídeos de las grabaciones. Es una funcionalidad muy útil ya que
podemos generar fotogramas o imágenes a partir del vídeo para mostrar más
rápidamente de qué grabación se trata. Esta funcionalidad permite
realizar una reproducción mostrando 1 fotograma cada segundo, por
ejemplo, lo que resulta muy útil en configuraciones de sistemas donde
la velocidad de la red no sea elevada. Además incluimos una marca
temporal en la misma imagen como se puede observar en la figura
\ref{fig:thumb-fecha}.


\begin{figure}[htbp]
\begin{center}
\includegraphics[height=5.0cm]{img/thumb-fecha}
\end{center}
\caption{Vista previa del vídeo con fecha y hora incrustada}
\label{fig:thumb-fecha}
\end{figure}

Esta funcionalidad se consigue gracias a la reutilización y mezcla de
varias herramientas del sistema \emph{GNU/Linux}, concretamente
\emph{ffmpeg} y \emph{convert}. A continuación se muestra el comando:

\begin{verbatim}
       ffmpeg -i path_video_grabacion 
              -r 1 -t 00:00:01 thumb.jpg 
       &&
       convert thumb.jpg 
               -draw "text 190,235 '16:44:54 - 15/05/2010'" 
               thumb.png
\end{verbatim}

En la tabla \ref{tabla:recordingmanager} se pueden ver las métricas de
código fuente de este componente. Al ser un componente importante, ya que
todos los mensajes de grabaciones pasan por él, la complejidad de sus
archivos aumenta levemente.

\begin{table}[htbp]
\begin{center}
\footnotesize
\begin{tabular}{||l|p{5cm}||}
\hline
\hline
\bf{Número de ficheros} & 3  \\
\hline
\bf{Numero de líneas (C++)} & 520  \\
\hline
\bf{Complejidad ciclomática de McCabe} & recordingserver.cpp(30) recordingLog.cpp(32)\\
\hline
\bf{Tiempo estimado de desarrollo (COCOMO)} & 2,69 meses  \\
\hline
\bf{Coste estimado de desarrollo (COCOMO)} & 13,597 \$  \\
\hline
\hline
\end{tabular}
\end{center}
\normalsize
\caption{Resumen de métricas de código del componente                                                                                                                                    \emph{RecordingManager}}
\label{tabla:recordingmanager}
\end{table}

\newpage
\subsection{Formatos}

Los ficheros de vídeo pueden estar codificados en varios formatos
(DIVX, mpeg, Ogg, ...). Para la grabación de vídeos hemos realizado
diferentes pruebas con varias herramientas y codecs, todos ellos
disponibles en el sistema operativo \emph{GNU/Linux}. Es importante
seleccionar la solución que mejor se adecúe al sistema, que
pasa por aquella que permita reducir al máximo el espacio en disco
obteniendo la máxima calidad posible y gastando el mínimo porcentaje
de proceso en el sistema. La calidad de la grabación es el parámetro
que más peso tiene en esta ecuación ya que es necesario que las
imágenes sean nítidas y se pueda identificar claramente las personas u
objetos en la imagen.

En la tabla \ref{tabla:comparacion-grabaciones} se puede ver las
diferentes opciones que se han utilizado y sus
configuraciones. Finalmente y basándonos en los requisitos comentados
anteriormente nos decantamos por utilizar \emph{VLC}. Es importante
destacar que los datos obtenidos en esta tabla sobre el porcentaje de
\emph{CPU} se hicieron sobre la arquitectura \emph{Pico-ITX} descrita
en el apartado \ref{subsec:picoitx}.

\begin{table}[htbp]
\begin{center}
\footnotesize
\begin{tabular}{||l|l|l|l|l|l||}
\hline
\hline
Herramienta & Codec & Resolución & FrameRate & MB por minuto & Carga
CPU \\
\hline
\hline
ffmpeg & mpeg & 320x240 & 15 & 4,8 & 41\% \\
\hline
ffmpeg & mpeg & 320x240 & 25 & 7,5 & 43\% \\
\hline
mencoder & mpeg & 320x240 & 15 & 5,2 & 43\% \\
\hline
mencoder & mpeg & 320x240 & 25 & 8,6 & 49\% \\
\hline
\bf{vlc} & \bf{mpeg} & \bf{320x240} & \bf{15} & \bf{4,2} & \bf{39\%} \\
\hline
\bf{vlc} & \bf{mpeg} & \bf{320x240} & \bf{25} & \bf{7,1} & \bf{44\%} \\
\hline
\hline
\end{tabular}
\end{center}
\normalsize
\caption{Tabla comparativa de configuraciones de grabación.}
\label{tabla:comparacion-grabaciones}
\end{table}


\section{Dispositivo Móvil: Componente \emph{MobileSecurity}}
\label{sec:movil}

La última parte importante del sistema se trata del dispositivo móvil
o \emph{smartphone}. Como ya se comentó en el apartado de requisitos
(\ref{sec:requisitos}), una parte importante del sistema ejecutará en
el dispositivo móvil, más concretamente en un dispositivo móvil basado
en \emph{Android}.

Es necesario destacar la gran integración que se ha podido realizar en
el dispositivo móvil de todas las funcionalidades que requería gracias
al uso del \emph{middleware} distribuido \emph{ICE}. Todos los
componentes anteriormente descritos están programados en \emph{C} y
\emph{C++} y corren sobre un arquitectura \emph{i486}. En el
dispositivo móvil se programa utilizando \emph{JAVA} bajo una
arquitectura \emph{MIPS}. Pero todo esto es transparente para la
programación gracias a la utilización de \emph{ICE}, que permite
interoperar a los componentes abstrayéndolos de su arquitectura y
lenguaje.

\begin{figure}[htbp]
\begin{center}
\includegraphics[width=0.75\textwidth]{img/mobilesecurity}
\caption{Vista de interacción de componentes con \emph{MobileSecurity}}
\label{fig:dise-mobilesecurity}
\end{center}
\end{figure}


En los siguientes apartados se va a describir la funcionalidad que se
ha integrado en el dispositivo móvil a través del componente
\emph{MobileSecurity}, como el \emph{streaming} en directo de
las cámaras, la visualización con miniaturas, el \emph{streaming} de las
grabaciones, el listado de grabaciones, el acceso al listado y la visualización
de alarmas, y por último se detallará la detección de cara que se
realiza en el dispositivo móvil. En la figura
\ref{fig:dise-mobilesecurity} se puede ver la interacción que realiza
este componente con \emph{CameraServer} para obtener el
\emph{streaming} de la cámara y con \emph{RecordingManager}, para
obtener \emph{streaming} de los vídeos e información de las grabaciones.

\subsection{Streaming en directo}
\label{subsec:streaming}

Uno de los retos más ambiciosos de este proyecto es el utilizar el
\emph{smartphone} no sólo como un mero visor del sistema, sino como un
visor inteligente y por qué no, como un generador de información. Una
de las características que hacen a este sistema muy usable es la
posibilidad de ver en tiempo real las cámaras del sistema en el
\emph{smartphone}. Ver las cámaras en tiempo real da una información
muy valiosa del sistema, ya que en cualquier momento se puede acceder
a ver qué está ocurriendo y confirmar las alarmas recibidas, o
simplemente observar el entorno que se vigila.

Como se puede observar en la figura \ref{fig:cams-streaming} el
interfaz principal de la aplicación muestra todas las cámaras
disponibles en el sistema, en nuestro caso sólo hay dos. Si accedemos
a verlas por \emph{streaming}, nos aparecerá la pantalla que se
observa en la figura \ref{fig:streaming1}, donde se muestran las
miniaturas de lo que se está viendo en ese momento de las cámaras,
además de uno de los flujos de vídeo en tiempo real. El interfaz
mostrado en la figura \ref{fig:streaming1} permite intercambiar la
visión de las cámaras únicamente pulsando sobre la miniatura
correspondiente.


\begin{figure}[htbp]
\begin{center}
\subfigure[]{\label{fig:cams-streaming}\includegraphics[height=8.0cm]{img/cams-streaming}}
\hspace{0.3cm}
\subfigure[]{\label{fig:streaming1}\includegraphics[height=8.0cm]{img/streaming1}}
\end{center}
\caption{Cámaras disponibles en el sistema(a) y streaming de una de ellas(b)}
\label{fig:streaming}
\end{figure}

\newpage
El flujo de vídeo se transmite mediante el protocolo \emph{RTSP}, como
ya vimos anteriormente. El vídeo mostrado tiene una resolución de
320x240 píxeles y se transmite a un ritmo de 25\emph{fps}. Aunque el
vídeo es mostrado con un flujo continuo y real en el dispositivo
móvil, tiene un desfase de 4 segundos con la realidad. Estos segundos
de latencia son a causa de obtener el flujo de la cámara, convertirlo
al formato adecuado, enviarlo por la red y mostrarlo en el
dispositivo. Las pruebas realizadas nos dicen que estos segundos son
casi despreciables ya que lo importante es ver el vídeo de una manera
suave, continua y sin saltos. Es importante destacar que conseguimos
un flujo contínuo del vídeo a 320x240 utilizando la conexión
\emph{WIFI} del teléfono móvil. Para conexiones \emph{3G} es necesario
bajar la resolución del vídeo hasta 160x120 píxeles para conseguir un
flujo contínuo del vídeo.

Para mostrar un vídeo en el dispositivo móvil basado en Android es
necesario que éste venga en un formato determinado. Este formato es
\emph{MPEG-4 SP (simple profile)}. Como ya vimos en el apartado
\ref{subsec:cameraserver}, es el componente \emph{cameraserver} quien
se encarga de configurar correctamente el envío del vídeo en este
formato mediante el uso de la herramienta \emph{VLC}.

En cuanto a la implementación se refiere, se utiliza el widget
\emph{VideoView} para reproducir el flujo de vídeo que viene a través
del \emph{streaming} que se define, como puede observarse en el listado
\ref{list:layout-videoview}. Además el código encargado de actualizar
el \emph{streaming} de las cámaras se puede ver en el listado
\ref{list:layout-updatestream}.

\begin{lstlisting}[language=xml,float=htbp,caption=Definición layout
  con un videoview,label=list:layout-videoview]

<?xml version=''1.0'' encoding=''utf-8''?>
<LinearLayout
    xmlns:android=''http://schemas.android.com/apk/res/android''
    android:orientation=''vertical''
    android:layout_width=''match_parent''
    android:layout_height=''match_parent''
    >
    <VideoView
        android:id=''@+id/surface_view''
        android:layout_width=''320px''
        android:layout_height=''240px''
    />
</LinearLayout>
\end{lstlisting}



\begin{lstlisting}[language=java,float=htbp,caption=Método encargado
  de actualizar el streaming de las cámaras,label=list:layout-updatestream]
private void updateStreaming()
{
   String streamingURI = null;
   Ice.Communicator communicator = Ice.Util.initialize();
   Ice.ObjectPrx base = communicator.stringToProxy(proxysCamera[indexProxy]);
 
   if (base == null)
       Log.e("Main","Could not create proxy");
   else {
       vprx = CameraPrxHelper.checkedCast(base);
       if (vprx == null)
           Log.e("Main", "Invalid proxy");
       else
           streamingURI = vprx.startCameraStreaming();
    }
   	SystemClock.sleep(1000);
    myvideo = (VideoView)findViewById(R.id.videoview);
    myvideo.setVideoURI( Uri.parse(streamingURI));
    myvideo.setSoundEffectsEnabled(false);
    myvideo.setOnErrorListener(this);

    try
    {
        myvideo.setMediaController(new MediaController(this));
        myvideo.start();
    }
    catch (Exception e)
    {
        Log.e("Error = ",e.getMessage());
    }
}
\end{lstlisting}

\newpage
\subsection{Grabaciones}
\label{subsec:grabaciones}

La segunda funcionalidad que puede realizarse desde el componente \emph{MobileSecurity}
es la gestión y visualización de grabaciones. En la mayoría de los
sistemas de video vigilancia, las tareas de administración de grabaciones
o simplemente visualizarlas tienen que realizarse típicamente desde PC's
situados en las oficinas. En este proyecto se presenta una solución
donde desde el dispositivo móvil, y por tanto desde cualquier
localización, es posible acceder al listado de grabaciones, a sus
características y a sus vídeos correspondientes.

El listado de grabaciones se muestra de diez en diez, tal como se
observa en la figura \ref{fig:recordings1}. El listado se realiza dentro del widget genérico
\emph{ListView} que permite crear un contenedor donde se muestra una
imagen inicial de la grabación, el nombre de la misma, y datos
técnicos junto con la fecha. Además, a la derecha de cada posición de
la lista aparece un símbolo que nos indica si la grabación está en
curso (circulo verde), si la grabación se realizó correctamente (un
\emph{tick} verde) o si hubo algún problema en la grabación (una aspa
roja). 

Además, también se permite realizar búsquedas concretas por fecha de
las grabaciones, tal como se muestra en la figura
\ref{fig:recordings-date}. Esta funcionalidad, unida a la imagen
previa del vídeo, resulta muy útil para localizar grabaciones dentro
del sistema de una manera rápida y sencilla.


\begin{figure}[htbp]
\begin{center}
\subfigure[]{\label{fig:recordings1}\includegraphics[height=5.5cm]{img/recordings1}}
\hspace{0.3cm}
\subfigure[]{\label{fig:recordings-date}\includegraphics[height=5.5cm]{img/recordings-by-date}}
\end{center}
\caption{Listado de grabaciones (a) y búsqueda por fecha (b)}
\label{fig:recordings}
\end{figure}


Como ya se ha comentado, la lista de grabaciones permite visualizar
diez de ellas por pantalla. Esta decisión se ha tomado en favor de la
usabilidad de la aplicación en un teléfono móvil de casi 4 pulgadas
con pantalla táctil. Pero es de suponer que existan numerosos
registros de grabaciones, muchas más que 10 desde luego. Por ello, se
ha diseñado e implementado una característica innovadora que permite
desplazarse a las siguientes diez grabaciones, mediante un gesto
realizado con el dedo sobre la pantalla táctil del
\emph{smartphone}. Como se puede observar en la sucesión de imágenes
de la figure \ref{fig:gesture-recordings}, cuando arrastramos el dedo por la
pantalla generando un movimiento de izquierda a derecha, el sistema lo
detecta y realiza una petición de las siguientes diez grabaciones
disponibles en el sistema. Del mismo modo, si el recorrido del dedo se
realiza de derecha a izquierda, el sistema devolverá las 10
grabaciones anteriores.


\begin{figure}[htbp]
\begin{center}
\subfigure[]{\label{fig:gesture-recordings1}\includegraphics[height=5.5cm]{img/gesture-recordings}}
\hspace{0.3cm}
\subfigure[]{\label{fig:gesture-recordings2}\includegraphics[height=5.5cm]{img/gesture-recordings2}}
\hspace{0.3cm}
\subfigure[]{\label{fig:recordings3}\includegraphics[height=5.5cm]{img/recordings3}}
\end{center}
\caption{Gesto con el dedo (a), carga de nuevas grabaciones (b) y
  visualización de grabaciones (c)}
\label{fig:gesture-recordings}
\end{figure}


\subsubsection{Streaming de grabaciones}

A parte de poder consultar datos técnicos de las grabaciones como el
nombre, fecha, estado, resolución o ritmo del vídeo, es posible
visualizar mediante \emph{streaming} las grabaciones realizadas por el
sistema. De un modo similar a como se visualiza el vídeo en tiempo
real de la cámara que se describió en el apartado
\ref{subsec:streaming}, podemos visualizar el vídeo grabado en el
dispositivo móvil (tal como se muestra en la
figura~\ref{fig:streaming-recording}).


Las grabaciones se mostrarán en la resolución y \emph{framerate} al
que han sido grabados. Por tanto podrán verse grabaciones a 320x240
@15fps o 320x240 @25fps.

\begin{figure}[htbp]
\begin{center}
\includegraphics[height=6.0cm]{img/streaming-recording}
\end{center}
\caption{\emph{Streaming} de una grabación}
\label{fig:streaming-recording}
\end{figure}


\subsection{Alarmas}

Las alarmas de movimiento son una funcionalidad importante que es
necesario integrar en el móvil, ya que resulta de gran utilidad
observar las alarmas producidas en cualquier instante y desde
cualquier localización (tal como se puede ver en la
figura~\ref{fig:list-alarms}).

Existen dos maneras de acceder a las alarmas desde el móvil. La
primera de ellas es bajo demanda, accediendo al apartado de alarmas
veremos toda la información relativa a ellas
(figura~\ref{fig:list-alarms}). La segunda forma es mediante un aviso
automático en la barra de notificaciones de \emph{Android}, tal como
se observa en la figura~\ref{fig:notify-alarms}.



\begin{figure}[htbp]
\begin{center}
\subfigure[]{\label{fig:list-alarms}\includegraphics[height=5.5cm]{img/alarms}}
\hspace{0.3cm}
\subfigure[]{\label{fig:notify-alarms}\includegraphics[height=5.5cm]{img/notify-alarm}}
\end{center}
\caption{Listado de alarmas (a) y notificación automática de las mismas (b)}
\label{fig:alarms}
\end{figure}

Las alarmas generadas por movimiento llevan asociada al menos una
grabación de la cámara que detecta el movimiento. Aunque si existen
más cámaras en el sistema, la alarma tendrá asociadas tantas
grabaciones como cámaras existan. Concretamente este proyecto dispone
de dos cámaras en su configuración, por lo que a la hora de visualizar
las alarmas se ha implementado un sistema de visualización avanzada
para poder mostrar las dos grabaciones a la vez, tal como muestra la
figura~\ref{fig:streaming-2recording}.

\begin{figure}[htbp]
\begin{center}
\includegraphics[height=6.0cm]{img/streaming-2recording}
\end{center}
\caption{\emph{Streaming} de dos grabaciones de una alarma.}
\label{fig:streaming-2recording}
\end{figure}

\subsection{Detección de caras}
\label{subsec:face-detect}

El dispositivo móvil se usa en este sistema para algo más que un mero
visualizador. Además de su utilidad como visor, hemos introducido una
funcionalidad (a modo de prototipo) de análisis y detección de caras
sobre el flujo de vídeo en directo de las cámaras del sistema.

Tal como se observa en la figura~\ref{face-detect}, el sistema es
capaz de detectar caras en tiempo real (un máximo de 20), sobre el
flujo de vídeo de las cámaras existentes. Esto permite a un usuario
del sistema visualizar en tiempo real el escenario y automáticamente
detectar caras. En futuros prototipos se podría enviar automáticamente
la información de la cara y generar una alarma desde el
dispositivo móvil.

\begin{figure}[htbp]
\begin{center}
\includegraphics[height=6.0cm]{img/face-detect}
\end{center}
\caption{Detección de cara en el teléfono móvil.}
\label{fig:face-detect}
\end{figure}

Para realizar el análisis de la imagen y detectar las caras se ha
utilizado parte de la librería de \emph{Android} que provee métodos para
realizar estas operaciones. Concretamente se puede ver el código en el
bloque \ref{face-detect}.

\begin{lstlisting}[language=java,float=htpb,caption=Método de
  detección de caras,label=face-detect]

public void detect (Bitmap bitmap)
{
   bm = bitmap;
      
   BitmapFactory.Options bfo = new BitmapFactory.Options();
   bfo.inPreferredConfig = Bitmap.Config.RGB_565;
              
   picWidth = bm.getWidth();
   picHeight = bm.getHeight();
                      
   arrayFaces = new FaceDetector( picWidth,
   picHeight, NUM_FACES );
   arrayFaces.findFaces(bm, getAllFaces);
                              
   for (int i = 0; i < getAllFaces.length; i++)
   {
      getFace = getAllFaces[i];
      try {
         PointF eyesMP = new PointF();
         getFace.getMidPoint(eyesMP);
         eyesDistance[i] = getFace.eyesDistance();
         eyesMidPts[i] = eyesMP;                 
      }
                    
      catch (Exception e)
      {
         eyesMidPts[i] = null;
         Log.e(``Face'', i + `` is null'');
      }
   }
}
\end{lstlisting}

\newpage
En la tabla \ref{tabla:mobilesecurity} se puede ver las métricas sobre
el código del componente \emph{MobileSecurity}. A diferencia de los otros componentes,
éste esta programado en varios lenguajes (\emph{java} y \emph{xml}
principalmente) y debido a las líneas que tiene es el componente que
más coste temporal y de desarrollo nos ha llevado (según \emph{COCOMO}).

\begin{table}[htbp]
\begin{center}
\footnotesize
\begin{tabular}{||l|p{5cm}||}
\hline
\hline
\bf{Número de ficheros} & 8  \\
\hline
\bf{Numero de líneas } & java: 12258 (97.70\%), xml: 284 (2.26\%) y
sh: 5 (0.04\%)  \\
\hline
\bf{Tiempo estimado de desarrollo (COCOMO)} & 9,57 meses  \\
\hline
\bf{Coste estimado de desarrollo (COCOMO)} & 384,688 \$  \\
\hline
\hline
\end{tabular}
\end{center}
\normalsize
\caption{Resumen de métricas de código del componente
  \emph{MobileSecurity}}
\label{tabla:mobilesecurity}
\end{table}







