Como transmitir MPEG-TS por UDP?

Como transmitir MPEG-TS por UDP?

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 PEToutros PMTtipos 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 .mpgarquivos 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 filesrcfunciona, 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

informação relacionada