Estou usando o gstreamer para transmitir em um AppSink personalizado que imita o UdpSink. Estamos fazendo isso dessa forma para que possamos incorporar a escuta de alguns metadados em outras portas. Além disso, o estoque do UdpSink está quebrado. De qualquer forma, o vídeo foi transmitido com sucesso, mas os pacotes UDP parecem não estar empacotados corretamente. Estou me perguntando se perdi algum passo.
Aqui está meu pipeline de envio:
filesrc (mpeg TS file) ! displayQueue ! streamTee ! tsdemux ! decoder ! videosink
streamTee ! sendQueue ! udpSink (our custom one)
a extremidade receptora:
UdpSrc (custom) ! queue ! mpegtsdemux ! queue ! (mpegdecode || h264decode) ! ... ! videosink
A transmissão funciona. Mas parece muito frágil. Às vezes, simplesmente para. Existem muitos artefatos.
Então, tentei o VLC. Eu configurei-o para transmitir em unicast UDP. Funciona muito bem. Percebi que o VLC envia o vídeo de maneira diferente do meu pipeline. Usei o Wireshark para analisar os pacotes:
Protocolos usados: VLC: IP:UDP:MP2T
(e pacotes e todos os PET
outros PMT
tipos de coisas relacionadas ao TS)
Meu:IP:UDP:Data
Parece que o pipeline que estou usando está apenas enviando vídeo bruto por UDP sem qualquer correção de erros. o que estou perdendo? Os vídeos usados são .mpg
arquivos codificados em h264 ou mpeg.
Estou usando o gstreamer-java para programar os elementos UdpSink e UdpSrc personalizados, mas não consigo usar o gstreamer no console para testar, pois o estoqueO plugin UdpSink está quebrado. Tentei um pipeline simples em uma VM Linux e obtive um monte de pacotes semelhantes ao VLC:
gst-launch-0.10 -v videotestsrc ! mpeg2enc ! mpegtsmux ! udpsink host=192.168.2.100 port=1234
Responder1
Isso é apenas uma ideia, não estou muito familiarizado com o gstreamer, então não sei como filesrc
funciona, mas presumo que ele não entende MPEG-TS. O MPEG-TS exige que os pacotes cheguem em determinados limites (geralmente 188 bytes). Eu tentaria colocar seu tee depois do demux e depois adicionar um mpegtsmux antes do seu udpSink
.
Sei que isso dará mais trabalho do que o realmente necessário (demux apenas para mux novamente), mas garantirá que os pacotes estejam alinhados corretamente. Se funcionar e você precisar eliminar a sobrecarga, talvez seja necessário implementar uma fonte de arquivo mais inteligente.
Responder2
Você está perto. O plugin filesrc não sabe nada sobre o conteúdo do arquivo que está lendo. O GStreamer precisa saber que os dados são um fluxo de transporte para poder transmiti-los adequadamente. Embora o demuxing e o muxing do stream façam esse trabalho, há uma maneira melhor:
Source: gst-launch -v filesrc location=myvideo.ts ! tsparse set-timestamps=true ! udpsink host=192.168.2.100 port=1234
Dest: gst-launch udpsrc caps="video/mpegts, systemstream=(boolean)true, packetsize=(int)188" port=1234 ! tsdemux ! (video decoder) ! autovideosink
O plugin tsparse lê o stream e analisa informações sobre o stream. Ele também identifica sua saída como um fluxo de transporte. Isso por si só pode ser suficiente para suas necessidades de streaming, pois permite que o udpsink saiba que os dados estão em pacotes de 188 bytes. Do lado receptor, o tsdemux é necessário para analisar o fluxo de vídeo real. O elemento "set-timestamps" diz ao tsparse para definir carimbos de data e hora nos pacotes de saída para que o udpsink envie cada quadro no prazo, e não o mais rápido possível.
Você também pode usar rtpmp2tpay e rptmp2depay, que empacota os dados para envio do udpsink. Ele também define o nome da codificação como MP2T. Você pode tentar das duas maneiras.
Source: gst-launch -v filesrc location=myvideo.ts ! tsparse set-timestamps=true ! rtpmp2tpay ! udpsink host=192.168.2.100 port=1234
Dest: gst-launch udpsrc caps="application/x-rtp, systemstream=(boolean)true, packetsize=(int)188" port=1234 ! rtpmp2tdepay ! tsdemux ! (video decoder) ! autovideosink