Maneira moderna de transmitir H.264 a partir da câmera Raspberry

16

Eu adquiri a câmera Pi B + e Pi e agora estou tentando encontrar a configuração mais eficiente (baixa CPU) e de menor latência para transmitir vídeo codificado em H.264 da câmera para o meu servidor doméstico.

Eu li o seguinte:

  1. http://pi.gbaman.info/?p=150

  2. http://blog.tkjelectronics.dk/2013/06/how-to-stream-video-and-audio-from-a-raspberry-pi-with-no-latency/comment-page-1/#comments

  3. http://www.raspberrypi.org/forums/viewtopic.php?p=464522

(Todos os links usam gstreamer-1.0 de deb http://vontaene.de/raspbian-updates/ . main.)

Muito foi feito nesse sentido nos últimos anos.

Originalmente, tínhamos que canalizar a saída raspividpara gst-launch-1.0(consulte o link 1).

Então (link 2) foi criado o driver oficial V4L2, que agora é padrão, e permite obter diretamente os dados sem um cano, usando apenas o gstreamer (veja especialmente o post de towolf »sábado, 07 de dezembro de 2013 15:34 no link 2):

Remetente (Pi): gst-launch-1.0 -e v4l2src do-timestamp=true ! video/x-h264,width=640,height=480,framerate=30/1 ! h264parse ! rtph264pay config-interval=1 ! gdppay ! udpsink host=192.168.178.20 port=5000

Receptor: gst-launch-1.0 -v udpsrc port=5000 ! gdpdepay ! rtph264depay ! avdec_h264 ! fpsdisplaysink sync=false text-overlay=false

Se bem entendi, as duas formas usam a GPU para decodificar o H264, mas a última é um pouco mais eficiente, pois não precisa passar pelo kernel mais uma vez, pois não há canal entre os processos envolvidos.


Agora eu tenho algumas perguntas sobre isso.

  1. Essa última ainda é a maneira mais recente de obter com eficiência o H264 da câmera? Eu li sobre gst-omx, o que permite pipelines gstreamer como ... video/x-raw ! omxh264enc ! .... Isso faz algo diferente de apenas usar video/x-h264ou pode até ser mais eficiente? Qual é a diferença?

  2. Como descubro qual plugin de codificação do gstreamer é realmente usado quando uso o video/x-h264 ...pipeline? Parece apenas especificar o formato que eu quero, em comparação com as outras partes do pipeline, onde nomeio explicitamente o componente (código) (como h264parseou fpsdisplaysink).

  3. Em esta resposta ao link de 1 Mikael Lepistö menciona "Tirei um filtro passa desnecessária de streaming de lado" , o que significa que ele cortar o gdppaye gdpdepay. O que esses fazem? Por que eles são necessários? Posso mesmo tirá-los?

  4. Ele também menciona que, especificando caps="application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)96"parâmetros para o udpsrclado receptor, ele pode iniciar / retomar a transmissão no meio da transmissão. O que esses limites alcançam, por que essas escolhas específicas, onde posso ler mais sobre eles?

  5. Quando faço o que é sugerido nas perguntas 3 e 4 (adicionando caps, soltando gdppaye gdpdepay), a latência do meu vídeo fica muito pior (e parece estar se acumulando, a latência aumenta com o tempo e, após alguns minutos, o vídeo para)! Por que poderia ser isso? Gostaria de obter a latência obtida com o comando original, mas também tenho o recurso de poder ingressar no fluxo a qualquer momento.

  6. Eu li que o RTSP + RTP geralmente usa uma combinação de TCP e UDP: TCP para mensagens de controle e outras coisas que não devem ser perdidas, e UDP para a transmissão de dados de vídeo real. Nas configurações acima, estou realmente usando isso ou apenas usando UDP? É um pouco opaco para mim se o gstreamer cuida disso ou não.

Eu apreciaria qualquer resposta para até uma dessas perguntas!

nh2
fonte
A idéia de que o uso de um pipe |cria qualquer problema nesse contexto é uma peça incrível da BS. Você já tentou algum raspivid | cvlcmétodo? Eu não tenho a câmera há muito tempo ou muito tempo para brincar com ela, mas usá-la para produzir um fluxo http (visível no linux na outra extremidade com vlc) parece funcionar bem.
goldilocks
@ goldilocks Eu não estou dizendo que o pipe é um "problema", apenas que não é necessário e tem alguma sobrecarga, assim como em cat file | grep ...vez de grep ... file. O canal adiciona outra camada de cópia de e para o kernel, que é facilmente mensurável, especialmente em dispositivos com pouca largura de banda de memória. Se o gstreamer pode ler diretamente do arquivo do dispositivo, por que não usá-lo? Com relação à sua raspivid | cvlcsugestão: eu estava usando isso antes de mudar para a solução baseada no gstreamer, ela tem até 3 segundos a mais de latência do que o gstreamer (não sei por quê).
nh2 10/01
Sim, definitivamente tem alguma latência. WRT o pipe, meu argumento sobre o "contexto" é que isso não pode ser um gargalo aqui - a E / S da rede terá ordens de magnitude mais lentas, etc. Você está certo, porém, isso pode adicionar um pouco à CPU Tempo. Só não apostaria muito; executar isso em resolução total cvlcusa ~ 45%, mas apenas passar por um tubo com essa taxa de dados (lembrando novamente, o tubo não está diminuindo sua velocidade ) mal moveria a agulha, eu acho. Como <5%. Não é totalmente insignificante, se você quiser fazer isso de forma tão eficiente quanto possível, é claro ...
goldilocks
... Só não quero que mais ninguém leia isso tenha a impressão de que o uso de um canal aqui pode ser responsável por problemas de latência ou outros problemas. Isso é um arenque vermelho. Ou eu posso estar errado;)
goldilocks
Se você procura eficiência, inclua o uso total observado da CPU para vários métodos com taxas de resolução / quadro específicas. O único que eu tentei é o raspivid | cvlcúnico e isso é 40-50%. As pessoas podem responder melhor a uma pergunta que as desafia a melhorar uma figura específica. No momento, você está perguntando muito por que, sem explicar por que cada um é significativo.
goldilocks

Respostas:

8

As opções:

  1. raspivid -t 0 -o - | nc -k -l 1234

  2. raspivid -t 0 -o - | cvlc stream:///dev/stdin --sout "#rtp{sdp=rtsp://:1234/}" :demux=h264

  3. cvlc v4l2:///dev/video0 --v4l2-chroma h264 --sout '#rtp{sdp=rtsp://:8554/}'

  4. raspivid -t 0 -o - | gst-launch-1.0 fdsrc ! h264parse ! rtph264pay config-interval=1 pt=96 ! gdppay ! tcpserversink host=SERVER_IP port=1234

  5. gst-launch-1.0 -e v4l2src do-timestamp=true ! video/x-h264,width=640,height=480,framerate=30/1 ! h264parse ! rtph264pay config-interval=1 ! gdppay ! udpsink host=SERVER_IP port=1234

  6. uv4l --driver raspicam

  7. picam --alsadev hw:1,0

Coisas a considerar

  • latência [ms] (com e sem solicitar ao cliente que deseje mais fps que o servidor)
  • CPU ociosa [%] (medida por top -d 10)
  • Cliente CPU 1 [%]
  • RAM [MB] (RES)
  • mesmas configurações de codificação
  • mesmos recursos
    • audio
    • reconectar
    • Cliente independente do SO (vlc, webrtc, etc)

Comparação:

            1    2    3    4    5    6    7
latency     2000 5000 ?    ?    ?    ?    1300
CPU         ?    1.4  ?    ?    ?    ?    ?
CPU 1       ?    1.8  ?    ?    ?    ?    ?
RAM         ?    14   ?    ?    ?    ?    ?
encoding    ?    ?    ?    ?    ?    ?    ?
audio       n    ?    ?    ?    ?    y    ?
reconnect   y    y    ?    ?    ?    y    ?
any OS      n    y    ?    ?    ?    y    ?
latency fps ?    ?    ?    ?    ?    ?    ?
user1133275
fonte
1
Por que todos os valores nesta tabela " ?"?
Larsks 19/03/19
@larsks porque ninguém se importa em teste e preencha os dados sobre este 'wiki comunidade'
user1133275
6

A única maneira moderna de transmitir o H264 para um navegador é com UV4L : sem latência, sem configuração, com áudio opcional, áudio / vídeo bidirecional opcional. Sem molho GStreamer mágico, ainda é possível estender seu uso.

prinxis
fonte
Como eu quero transmitir para o meu servidor e potencialmente para smartphones, a transmissão para um navegador não é um requisito. Além disso, o navegador pode colocar restrições extras nele (por exemplo, sem RTSP, potencialmente sem TCP, a menos que você use o WebRTC, mas isso é complicado). Mas o UV4L ainda parece promissor. Você poderia criar um link para um local onde eu possa ler sobre como usá-lo / obter os dados para transmissão pela rede?
nh2 15/01/16
Puta vaca, acho que achei a página de exemplo ... essa coisa parece capaz de fazer tudo ! RTMP, RTSP, streaming HTTPS, WebRTC, "Detecção de objetos em tempo real e rastreamento de objetos + Detecção de rosto" - que diabos? Cada um com alguns sinalizadores de linha de comando simples para uv4l? Meu pipeline de gstreamer parece bastante desatualizado agora! Mal posso esperar para testar como está a latência!
nh2 15/01/16
1
Ah, não, é uma fonte fechada :( Isso a desqualifica para o uso de vigilância em casa que eu tinha em mente :(
nh2 15/01/16
suporta WebRTC, WebRTC bidirecional. latência é ~ 200ms de áudio / vídeo, áudio menos provavelmente
prinxis
@ nh2, o link parece estar quebrado, você tem algum local atualizado para essa página de exemplo?
precisa
1

1.) h264es transmitido pela rede (apenas amostra)

no servidor:

raspivid -v -a 524 -a 4 -a "rpi-0 %Y-%m-%d %X" -fps 15 -n -md 2 -ih -t 0 -l -o tcp://0.0.0.0:5001

no cliente:

mplayer -nostop-xscreensaver -nolirc -fps 15 -vo xv -vf rotate=2,screenshot -xy 1200 -demuxer h264es ffmpeg://tcp://<rpi-ip-address>:5001

2.) mjpeg transmitido pela rede (apenas amostra)

no servidor:

/usr/local/bin/mjpg_streamer -o output_http.so -w ./www -i input_raspicam.so -x 1920 -y 1440 -fps 3

no cliente:

mplayer -nostop-xscreensaver -nolirc -fps 15 -vo xv -vf rotate=2,screenshot -xy 1200 -demuxer lavf http://<rpi-ip-address>:8080/?action=stream

tudo isso funciona mesmo em um RPi Zero W (configurado como servidor)

sparkie
fonte
Ei, obrigado pela resposta, o que sample onlysignifica?
nh2 15/12/17
Eu queria dizer 'é apenas um exemplo'. Você pode adaptar isso às suas necessidades.
Sparkie