Como forçar um processo a transmitir por UDP em vez de TCP?

4

Estou executando um processo ffserver em uma máquina Linux, a fim de obter streaming de vídeo via ffmpeg . No entanto, há um atraso no streaming de vídeo. No arquivo de configuração ffserver eu defino Port 8090 .

Comando netstat -tulnap me dá isto:

root@beagleboard:/etc# netstat -tulnap
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             Stat                                                                             e       PID/Program name
tcp        0      0 0.0.0.0:68                  0.0.0.0:*                   LIST                                                                             EN      654/pump
tcp        0      0 0.0.0.0:111                 0.0.0.0:*                   LIST                                                                             EN      662/portmap
tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LIST                                                                             EN      698/dropbear
tcp        0      0 0.0.0.0:8090                0.0.0.0:*                   LIST                                                                             EN      744/ffserver
tcp        0     52 192.168.1.104:22            192.168.1.111:10838         ESTA                                                                             BLISHED 724/dropbear
udp        0      0 0.0.0.0:514                 0.0.0.0:*                                                                                                            703/syslog-ng
udp        0      0 0.0.0.0:111                 0.0.0.0:*                                                                                                            662/portmap
udp        0      0 0.0.0.0:60628               0.0.0.0:*                                                                                                            709/avahi-daemon: r
udp        0      0 0.0.0.0:5353                0.0.0.0:*                                                                                                            709/avahi-daemon: r

Como você pode ver, o processo ffserver usa o protocolo tcp para transmitir e suspeito que essa seja a razão do atraso do streaming de vídeo. Como posso forçar o processo a usar o protocolo udp? Devo mudar de porto?

    
por dempap 07.03.2014 / 17:22

3 respostas

22

Você não pode simplesmente forçar um programa a usar o UDP em vez do TCP, sem reescrever partes do próprio programa. Esses protocolos são muito diferentes para serem intercambiáveis.

  • O TCP é orientado por fluxo (o receptor vê tudo como um fluxo contínuo na ordem exata em que o emissor o envia); O UDP é orientado por datagrama (cada datagrama é enviado em um pacote separado e pode até ser reordenado).

  • O TCP tem controle de fluxo, portanto, o remetente (ou o sistema operacional do remetente) sabe exatamente o quão rápido deve enviar dados sem ultrapassar o link ou afetar significativamente outras conexões. O UDP não faz nada disso - um programa mal "forçado" pode começar a enviar gigabytes de dados por segundo sobre o UDP, independentemente da velocidade do link.

  • O TCP tem retransmissão, portanto, se um pacote for descartado no meio (por exemplo, porque a rede está sobrecarregada ou tem outros problemas), ele será reenviado. Se o protocolo depender de um transporte confiável e você forçá-lo a passar pelo UDP, a conexão pode morrer completamente assim que pelo menos um único pacote for perdido. (E os pacotes serão perdidos; veja os pontos # 1 e # 2 acima.)

por 07.03.2014 / 18:11
6

Como outros já mencionaram, UDP e TCP são protocolos fundamentalmente diferentes.

No entanto, se você precisar transportar dados por UDP em vez de TCP, você pode usar uma ferramenta de retransmissão como socat . Você pode configurar o socat para escutar uma conexão TCP e encaminhar o conteúdo do fluxo TCP como um fluxo UDP para outro host. Se o outro host estiver esperando o tráfego TCP, você poderá usar outra instância do relé para converter de volta para TCP. Isso removerá o comportamento de repetição e confirmação do link de host para host. Novas tentativas e acks ainda estarão presentes entre a ferramenta de retransmissão local e o aplicativo local, mas é improvável que você veja novas tentativas em um link de loopback local.

No entanto, é improvável que isso resolva seu problema de atraso. Se seu aplicativo é construído para usar TCP em vez de UDP, ele pode não ser tolerante com pacotes descartados, caso em que esse hack pode causar um comportamento instável.

    
por 07.03.2014 / 20:00
3

A menos que você esteja usando conexões realmente lentas, seu problema de atraso provavelmente se deve ao seu codec de vídeo.

Para compactar vídeo com eficiência, você terá que usar codificações preditivas (consulte este artigo na Wikipedia ).

As codificações preditivas basicamente calculam imagens de imagens anteriores ou posteriores. Isso tem as seguintes implicações:

  1. Se você usar muitos quadros P (calculados a partir de quadros anteriores), você terá um atraso antes que a exibição do vídeo seja iniciada , porque o cliente precisa aguardar o próximo quadro de vídeo completo (I-frame). No entanto, depois que o fluxo for estabelecido, você poderá assistir ao vídeo sem atraso.

  2. Se você usar quadros B (calculados a partir de imagens anteriores e posteriores), haverá um atraso muito grande: além do atraso inicial acima, o cliente precisa aguardar o próximo quadro I para iniciar a reprodução a partir do último quadro I. Isso introduzirá o atraso (o cliente reproduz o vídeo visivelmente depois dos registros do servidor / envia-o, geralmente muitos segundos). Se você estiver codificando o vídeo em tempo real, você também terá um atraso do servidor - ele precisará aguardar que o próximo quadro I envie tudo a partir do quadro I anterior.

Para a maioria dos codecs, você pode ajustar o uso de quadros B e P de acordo com suas necessidades, no entanto, há um atraso de compensação versus eficiência de compactação

Se você tiver largura de banda suficiente, você também pode usar um codec sem quadros B / P, como MJPEG

Outro motivo para um atraso seria armazenar em buffer no lado do player, para que você não tenha distorções se houver uma transmissão de rede nervosa. Muitos players de vídeo permitem ajustar os tamanhos do buffer.

    
por 07.03.2014 / 21:57