Apresentação
Este artigo explora diversas maneiras de obter, exibir e gravar vídeos utilizando um CoM ou SoM (Computer on Module ou System on Module) otimizado para aplicações sensíveis a custo e que não possui enconder/decoder de vídeo por hardware.
Aplicação de Câmeras em Sistemas Linux Embarcado
Dizem que uma imagem vale mais que mil palavras, talvez por isso a utilização de câmeras em sistemas embarcados tem crescido muito nos últimos anos. Elas são utilizadas nas mais diversas situações, entre elas:
- Monitoramento por um operador remoto: exemplos desta aplicação são os circuitos de TV fechados onde um operador monitora o ambiente (provavelmente a portaria de seu prédio tem um) ou mesmo monitoramento de cidade pela polícia;
- Gravação de vídeo de segurança: sistemas de monitoramento podem ou não gravar vídeo, muitos sistemas não possuem um operador monitorando o sistema o tempo todo, eles apenas realizam a gravação para obter provas em caso de algum evento;
- Monitoramento automático com análises através de ferramentas de visão computacional: nestes sistemas, um software realiza o processamento da imagem para extrair informações mais complexas. Entre eles estão os radares e alguns sistemas de monitoramento de tráfego em cidades;
- Utilização como um sensor: diversos sistemas de diagnóstico clínico são baseados em análise de imagem da amostra, outro exemplo são vitrines inteligentes em lojas que identificam algumas características do usuário para oferecer o marketing específico.
Hardware utilizado
Usaremos os módulos Colibri VF61 da empresa Toradex que possuem processadores Vybrid da Freescale, que são processadores dual core heterogêneo (ARM Cortex-A5 + ARM Cortex-M4). Além do processador o módulo conta com 256 MB RAM e 512 MB Flash. Neste artigo estaremos utilizando apenas o Cortex-A5. É possível fazer várias atividades com vídeo e câmeras nesses processadores mesmo eles não possuindo hardware específico para isso. Outras informações e instruções sobre o módulo Colibri VF61 podem ser encontradas no site da Toradex na seção de desenvolvedores.
As câmeras utilizadas foram uma Logitech HD 720p, um módulo de câmera USB mjpeg genérica e uma câmera IP da D-Link modelo DCS-930L.
A imagem linux do módulo utilizado para este artigo possui um ambiente de área de trabalho chamado LXDE. Utilizaremos também um framework chamado GStreamer, que é amplamente usado no desenvolvimento de aplicações de multimídia. O GStreamer provê o serviço de multimídia de aplicativos, como editores de vídeo, streaming de mídia e media players. É utilizada uma série de plugins que faz com que o GStreamer funcione com as mais diversas bibliotecas de mídia, como MP3, ffmpeg e outras. Entre esses plugins encontram-se elementos de entrada e saída, filtros, codecs e outros mais.
Instalando os pacotes necessários
Nos módulos Colibri VF61 é necessário a instalação do GStreamer, Video4Linux2 e também alguns pacotes adicionais. Para isso, execute os seguintes comandos no terminal do módulo:
opkg update opkg upgrade opkg install gst-plugins-base-meta gst-plugins-good-meta gst-ffmpeg
Agora com o comando gst-inspect você pode vizualizar os plugins e elementos instalados anteriormente. Abaixo alguns exemplos de plugins e elementos instalados.
Um pouco sobre Pipelines e seus elementos
Com base no Manual de Desenvolvimento de Aplicação do GStreamer no capítulo 3, um elemento é a mais importante classe de objetos do GStreamer. Usualmente cria-se uma corrente de elementos conectados e os dados percorrem por essa estrutura. Um elemento tem função específica que pode ser leitura de dados de um arquivo, decodificação de dados ou sua exibição na tela. Elementos colocados juntos como uma corrente denomina-se uma pipeline, que pode ser utilizada para uma tarefa específica, por exemplo reprodução ou captura de vídeo. Por padrão o GStreamer contém uma vasta coleção de elementos, tornando possível o desenvolvimento de uma grande variedade de aplicações de mídia. Ao longo desse artigo iremos usar algumas pipelines e esclarecer um pouco sobre alguns elementos.
Abaixo temos uma ilustração de uma pipeline de um player ogg básico, contendo um demuxer e dois ramos, um para áudio e outro para vídeo.
Exibindo vídeo padrão de teste
Para exibir um vídeo padrão de teste utilizamos a pipeline a seguir:
gst-launch videotestsrc ! autovideosink
O autovideosink é um elemento que detecta automaticamente uma saída de vídeo. O elemento videotestsrc é usado para gerar um vídeo de teste em uma variedade de formatos e pode ser controlado com a propriedade “pattern”.
gst-launch videotestsrc pattern=snow ! autovideosink
Exibindo vídeo de uma WebCam
Ao inserir uma WebCam no módulo ela deve ser encontrada em /dev/videox podendo x ser 0, 1, 2 e assim por diante, dependendo do número de câmeras conectadas ao módulo.
Para visualização do vídeo da WebCam em tela cheia utilize a pipeline a seguir:
gst-launch v4l2src device=/dev/video0 ! ffmpegcolorspace ! ximagesink
A seguir se encontra um vídeo mostrando a fluidez de exibição da webcam em modo tela cheia:
Video 4 Linux é uma API e driver framework de captura e reprodução de vídeo que suporta vários tipos de câmeras USB e outros dispositivos. v4l2src é um elemento do plugin video4linux2 que lê frames de um dispositivo video4linux2, que no nosso caso é uma webcam.
O elemento ffmpegcolorspace é um filtro utilizado para converter frames de vídeo entre uma grande variedade de formatos de cor.
O ximagesink é um elemento videosink padrão baseado no desktop X.
Podemos ver com o comando top a memória e processamento da CPU utilizados pelo gstreamer ao exibir uma câmera.
top - 16:32:37 up 4:36, 2 users, load average: 0.83, 0.28, 0.13 Tasks: 72 total, 1 running, 70 sleeping, 0 stopped, 1 zombie Cpu(s): 69.3%us, 7.1%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 23.6%si,0.0%st Mem: 235188k total, 107688k used, 127500k free, 0k buffers Swap: 0k total, 0k used, 0k free, 61232k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1509 root 20 0 39560 8688 6400 S 77.9 3.7 0:16.83 gst-launch-0.10 663 root 20 0 17852 8552 4360 S 19.7 3.6 4:12.32 X 1484 root 20 0 2116 1352 1144 R 1.3 0.6 0:00.80 top
É possível também exibir o vídeo com algumas propriedades como tamanho e outras. Os parâmetros width, height, framerate podem ser ajustados de acordo com as configurações suportadas pela câmera. Execute as pipelines a seguir para câmeras 1, 2 ou 3 respectivamente (no caso, 3 câmeras estão conectadas no módulo), para visualizar o vídeo de cada webcam num formato 320×240 ou especifique o formato desejado.
gst-launch v4l2src device=/dev/video0 ! 'video/x-raw-yuv,width=320,height=240,framerate=30/1' ! ffmpegcolorspace ! ximagesink
gst-launch v4l2src device=/dev/video1 ! 'video/x-raw-yuv,width=320,height=240,framerate=30/1' ! ffmpegcolorspace ! ximagesink
gst-launch v4l2src device=/dev/video2 ! 'video/x-raw-yuv,width=320,height=240,framerate=30/1' ! ffmpegcolorspace ! ximagesink
top - 16:50:22 up 4:54, 2 users, load average: 0.49, 0.27, 0.29 Tasks: 71 total, 1 running, 69 sleeping, 0 stopped, 1 zombie Cpu(s): 29.2%us, 3.7%sy, 0.0%ni, 59.4%id, 0.0%wa, 0.0%hi, 7.7%si,0.0%st Mem: 235188k total, 105416k used, 129772k free, 0k buffers Swap: 0k total, 0k used, 0k free, 60336k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1530 root 20 0 37380 6420 4744 S 28.2 2.7 0:03.43 gst-launch-0.10 663 root 20 0 16956 7796 3584 S 8.4 3.3 5:19.25 X 1521 root 20 0 2116 1348 1144 R 1.3 0.6 0:01.31 top
Exibindo duas janelas simultâneas
Também é possível exibir duas câmeras simultaneamente. A pipeline seguinte foi testada usando uma câmera Logitech HD 720p e um módulo de câmera mjpeg genérica.
gst-launch v4l2src device=/dev/video0 ! 'video/x-raw-yuv,width=320,height=240,framerate=30/1' ! ffmpegcolorspace ! ximagesink v4l2src device=/dev/video1 ! 'video/x-raw-yuv,width=320,height=240,framerate=30/1' ! ffmpegcolorspace ! ximagesink
A seguir se encontra um vídeo mostrando a fluidez de exibição de duas webcams simultaneamente:
top - 17:15:53 up 5:20, 2 users, load average: 1.38, 0.42, 0.30 Tasks: 72 total, 1 running, 70 sleeping, 0 stopped, 1 zombie Cpu(s): 90.5%us, 4.6%sy, 0.0%ni, 4.6%id, 0.0%wa, 0.0%hi, 0.3%si, 0.0%st Mem: 235188k total, 106892k used, 128296k free, 0k buffers Swap: 0k total, 0k used, 0k free, 60612k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1613 root 20 0 54624 7380 5260 S 64.8 3.1 0:34.12 gst-launch-0.10 663 root 20 0 17260 8100 3888 S 25.6 3.4 6:16.56 X 1619 root 20 0 2116 1344 1140 R 1.3 0.6 0:00.43 top
Gravando vídeo
Para gravar um vídeo em formato mp4 utilizamos a seguinte pipeline:
gst-launch --eos-on-shutdown v4l2src device=/dev/video0 ! 'video/x-raw-yuv,width=640,height=480,framerate=30/1' ! ffmpegcolorspace ! ffenc_mjpeg ! ffmux_mp4 ! filesink location=video.mp4
O comando –eos-on-shutdown é usado para finalizar o arquivo corretamente. O elemento ffenc_mjpeg é um codificador para o formato mjpeg. ffmux_mp4 é um muxer para o formato mp4.
O elemento filesink indica que os dados provenientes do source v4l2 devem ser armazenados em um arquivo e não são exibidos no elemento ximagesink. Pode também ser especificado o path de destino do arquivo.
Para analisar a qualidade do vídeo gravado pelo módulo, você pode vizualisar o mesmo no video a seguir:
top - 17:35:51 up 5:40, 2 users, load average: 0.46, 0.17, 0.27 Tasks: 72 total, 1 running, 70 sleeping, 0 stopped, 1 zombie Cpu(s):79.3%us, 8.1%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 12.6%si, 0.0%st Mem: 235188k total, 109740k used, 125448k free, 0k buffers Swap: 0k total, 0k used, 0k free, 59884k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1626 root 20 0 48976 11m 6376 S 97.4 4.9 0:21.11 gst-launch-0.10 1629 root 20 0 2116 1312 1108 R 1.0 0.6 0:00.26 top 729 root 20 0 56320 9248 7544 S 0.6 3.9 1:37.39 lxpanel
Playback de vídeo
Para visualizar o vídeo anteriormente gravado, utilizamos a seguinte pipeline:
gst-launch filesrc location=video.mp4 ! qtdemux name=demux demux.video_00 ! queue ! ffdec_mjpeg ! ffmpegcolorspace ! ximagesink
Neste caso o vídeo source é proveniente de um filesrc, ou seja, o vídeo é buscado de um arquivo e não de um dispositivo de vídeo como uma WebCam. Esse vídeo foi anteriormente codificado utilizando mjpeg por isso utilizamos o decoder ffdec_mjpeg para decodificar o vídeo.
top - 17:41:55 up 5:46, 2 users, load average: 0.55, 0.31, 0.28 Tasks: 73 total, 1 running, 71 sleeping, 0 stopped, 1 zombie Cpu(s):46.9%us, 1.6%sy, 0.0%ni, 51.5%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 235188k total, 105660k used, 129528k free, 0k buffers Swap: 0k total, 0k used, 0k free, 59688k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1645 root 20 0 51220 9108 6180 S 38.0 3.9 0:02.88 gst-launch-0.10 663 root 20 0 17852 8572 4360 S 8.5 3.6 7:24.88 X 1635 root 20 0 2116 1308 1104 R 0.7 0.6 0:01.08 top
Playback de vídeo via HTTP
Para visualizar um vídeo de uma dada URL utilizamos a seguinte pipeline:
gst-launch souphttpsrc location=https://upload.wikimedia.org/wikipedia/commons/4/4b/MS_Diana_genom_Bergs_slussar_16_maj_2014.webm ! matroskademux name=demux demux.video_00 ! queue ! ffdec_vp8 ! ffmpegcolorspace ! ximagesink
Souphttpsrc é um elemento que recebe dados como cliente, pela rede, via HTTP. Neste caso a propriedade location recebe uma URL que contém um arquivo de vídeo ao invés de um arquivo em seu computador.
Note que o decoder ffdec_vp8 foi utilizado para decodificar o formato webm.
top - 17:54:09 up 1 min, 2 users, load average: 1.14, 0.47, 0.17 Tasks: 73 total, 1 running, 71 sleeping, 0 stopped, 1 zombie Cpu(s):46.5%us, 3.0%sy, 0.0%ni, 50.2%id, 0.0%wa, 0.0%hi, 0.3%si, 0.0%st Mem: 235188k total, 78356k used, 156832k free, 0k buffers Swap: 0k total, 0k used, 0k free, 34372k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 767 root 20 0 61412 9548 6548 S 41.9 4.1 0:15.63 gst-launch-0.10 665 root 20 0 16752 7488 3516 S 6.9 3.2 0:03.17 X 777 root 20 0 2116 1308 1100 R 1.0 0.6 0:00.09 top
Streaming de vídeo da Webcam via TCP
É também possível fazer streaming de vídeo dos módulos VF61 para um computador rodando linux.
IP VF61 = 192.168.0.8
IP Ubuntu = 192.168.0.7
Execute a seguinte pipeline no terminal do módulo VF61:
gst-launch v4l2src device=/dev/video1 ! video/x-raw-yuv,width=320,height=240 ! ffmpegcolorspace ! ffenc_mjpeg ! tcpserversink host=192.168.0.7 port=5000
Execute a seguinte pipeline no terminal do host:
gst-launch tcpclientsrc host=192.168.0.8 port=5000 ! jpegdec ! autovideosink
Note que deverão ser alterados os respectivos endereços IP. Para verificar o endereço IP, execute o comando ifconfig no terminal.
No link a seguir se encontra um vídeo demonstrando o exemplo acima:
Usando uma câmera Logitech HD 720p obtivemos o seguinte desempenho:
top - 17:58:26 up 5 min, 2 users, load average: 0.73, 0.59, 0.29 Tasks: 71 total, 1 running, 69 sleeping, 0 stopped, 1 zombie Cpu(s):68.9%us, 3.1%sy, 0.0%ni, 27.7%id, 0.0%wa, 0.0%hi, 0.3%si, 0.0%st Mem: 235188k total, 78684k used, 156504k free, 0k buffers Swap: 0k total, 0k used, 0k free, 34596k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 787 root 20 0 52140 8548 5404 S 66.0 3.6 0:22.98 gst-launch-0.10 791 root 20 0 2116 1352 1148 R 1.0 0.6 0:00.30 top 16 root 20 0 0 0 0 S 0.7 0.0 0:00.30 kworker/u2:1
Câmera IP D-Link e módulo VF61
Exibindo vídeo da Câmera IP
Neste exemplo foi utilizado uma câmera IP da D-Link modelo DCS-930L. A câmera foi configurada para fazer streaming de vídeo codificado num formato JPEG com uma resolução de 320×240 em 15 frames por segundo e uma qualidade média de JPEG. O rendimento da placa difere de acordo com as configurações de streaming da câmera IP.
Para exibir o vídeo da camera IP use a seguinte pipeline no terminal do módulo:
gst-launch -v souphttpsrc location='https://192.168.0.200/video.cgi' is-live=true ! multipartdemux ! decodebin2 ! ffmpegcolorspace ! ximagesink
A seguir se encontra um vídeo demonstrando o desempenho do exemplo acima:
top - 14:42:41 up 55 min, 2 users, load average: 0.32, 0.35, 0.34 Tasks: 71 total, 1 running, 69 sleeping, 0 stopped, 1 zombie Cpu(s):28.2%us, 2.0%sy, 0.0%ni, 69.2%id, 0.0%wa, 0.0%hi, 0.7%si, 0.0%st Mem: 235188k total, 80780k used, 154408k free, 0k buffers Swap: 0k total, 0k used, 0k free, 37536k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 774 root 20 0 38752 7772 5684 S 25.2 3.3 12:58.18 gst-launch-0.10 662 root 20 0 16804 7748 3708 S 3.6 3.3 1:54.36 X 728 root 20 0 56320 9352 7648 S 0.7 4.0 0:17.68 lxpanel
Gravando câmera IP
É possível também gravar o vídeo da câmera IP com o módulo VF61, utilizando a seguinte pipeline:
gst-launch --eos-on-shutdown -v souphttpsrc location='https://192.168.0.200/video.cgi' is-live=true ! multipartdemux ! decodebin2 ! ffmpegcolorspace ! ffenc_mjpeg ! ffmux_mp4 ! filesink location=stream.mp4
Para analisar a qualidade do vídeo você poderá acessá-lo a seguir:
Com a resolução da câmera em 320×240, 15 frames por segundo e média qualidade JPEG, obtivemos o seguinte desempenho:
top - 16:32:25 up 2:45, 2 users, load average: 0.13, 0.05, 0.05 Tasks: 73 total, 1 running, 71 sleeping, 0 stopped, 1 zombie Cpu(s): 39.1%us, 2.0%sy, 0.0%ni,57.9%id, 0.0%wa, 0.0%hi, 1.0%si, 0.0%st Mem: 235188k total, 86156k used, 149032k free, 0k buffers Swap: 0k total, 0k used, 0k free, 40904k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 924 root 20 0 45500 9272 5996 S 40.1 3.9 0:17.81 gst-launch-0.10 927 root 20 0 2116 1308 1104 R 1.0 0.6 0:00.38 top 728 root 20 0 56320 9352 7648 S 0.7 4.0 0:48.61 lxpanel
Streaming TCP de IP para IP
Neste exemplo será feito streaming de vídeo da câmera IP para o módulo VF61 onde esse irá fazer novamente streaming para outro endereço IP.
A pipeline seguinte foi executada no terminal do módulo VF61:
gst-launch --eos-on-shutdown -v souphttpsrc location='https://192.168.0.200/video.cgi' is-live=true ! multipartdemux ! decodebin2 ! ffmpegcolorspace ! ffenc_mjpeg ! tcpserversink host=192.168.0.12 port=5000
top - 17:24:18 up 3:37, 2 users, load average: 0.88, 0.52, 0.30 Tasks: 72 total, 1 running, 70 sleeping, 0 stopped, 1 zombie Cpu(s):95.1%us, 2.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 2.9%si, 0.0%st Mem: 235188k total, 86876k used, 148312k free, 0k buffers Swap: 0k total, 0k used, 0k free, 39828k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1074 root 20 0 56520 10m 6108 S 97.2 4.8 1:00.96 gst-launch-0.10 1079 root 20 0 2116 1340 1136 R 1.0 0.6 0:00.08 top 728 root 20 0 56320 9352 7648 S 0.7 4.0 1:02.93 lxpanel
Para visualizar o streaming de dados proveniente do módulo em um computador rodando Linux utilizamos a pipeline a seguir:
gst-launch tcpclientsrc host=192.168.0.8 port=5000 ! jpegdec ! autovideosink
Abaixo uma tabela comparativa de CPU e memória RAM do módulo em cada teste realizado.
|
Teste Realizado |
%CPU |
%MEM |
|
Exibindo vídeo de uma Webcam |
28.2 |
2.7 |
|
Exibindo vídeo de duas Webcams |
64.8 |
3.1 |
|
Gravando vídeo |
97.4 |
4.9 |
|
Playback de vídeo |
38.0 |
3.9 |
|
Playback de vídeo via HTTP |
41.9 |
4.1 |
|
Streaming de vídeo via TCP |
66.0 |
3.6 |
|
Exibindo vídeo câmera IP |
25.2 |
3.3 |
|
Gravando vídeo câmera IP |
40.1 |
3.9 |
|
Streaming câmera IP para outro IP |
97.2 |
4.8 |
Conclusão
A duração das atividades realizadas neste artigo, desde a pesquisa teórica e estudo de vários elementos do Gstreamer, pode levar alguns dias. Uma das dificuldades encontradas, é que não há documentação do Gstreamer específica para cada caso. Entretanto, há uma vasta gama de exemplos pela internet, os quais provavelmente necessitam de adaptações. Por isso, pode ser necessário que o leitor realize várias pesquisas, assim como foi feito para realização deste artigo. Foi necessário uma estratégia de tentativa e erro para a construção das pipelines e encontrar elementos do Gstreamer compatíveis com as configurações desse artigo.
Os processadores da Freescale Vybrid VF61 podem, muitas vezes, atender a várias necessidades com respeito à mídia e processamento de vídeo, mesmo não possuindo hardware específico para tais tarefas. Ficamos realmente surpresos com o desempenho desse processador ao realizar atividades com vídeo e imagem. Quando projetos embarcados são sensíveis a custo, e não vão realizar tarefas que demandem um grande processamento de vídeo, os processadores Vybrid VF61 são uma ótima opção. Já quando há necessidade de um alto processamento de vídeo com uma melhor performance, indicamos processadores como o iMX6, também da Freescale, que tem hardware específico de vídeo.
Referências e Links adicionais:
– https://www.toradex.com/pt_br/computer-on-modules/colibri-arm-family/freescale-vybrid-vf6xx
– https://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/index.html
– https://developer.toradex.com/knowledge-base/webcam-(linux)
– https://developer.toradex.com/knowledge-base/video-playback- (linux)#Video_Playback_on_Vybrid_Modules
– https://en.wikipedia.org/wiki/GStreamer
– https://pt.wikipedia.org/wiki/Codec
– https://pt.wikipedia.org/wiki/Codec_de_v%C3%ADdeo
– https://gstreamer.freedesktop.org/data/doc/gstreamer/0.10.36/manual/manual.pdf
– Fonte da Figura 2: https://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/images/simple-player.png
– Fonte da Figura 9: https://www.premiumstore.com.br/images/product/DCDLDCS930L_1.jpg







Ótimo artigo! Obrigado por compartilhar essas informações.
Bem legal, os VF61 vão cair como uma luva em minha aplicação.
Obrigado.
Olá Rodrigo, temos o VF61 em estoque.Se quiser pode ligar para o nosso escritório.
Fico feliz pelo artigo ter te ajudado!
Opa, já tenho três módulos VF61 e Violas, agora vou iniciar testes e desenvolvimento.
muito bom. qualquer dúvida estamos aqui pra dar suporte
Bem proveitoso, obrigado.
Excelente artigo! Parabéns.