2010-11-19 2 views
2

우리는 Silverlight 위에 오디오 - 비디오 공동 작업 응용 프로그램을 구현했으며이를 조정하려고합니다. 우리가 겪고있는 문제 중 하나는 패킷이 드롭 될 때마다 스트림 대기 시간이 증가한다는 것입니다. 즉, 패킷 손실을 감지하고 요청한 다음 재전송 패킷을 다시 기다려야합니다. 물론, 이것은 우리 오디오 스트림의 일관성으로 지옥을 재생합니다. (가능한 경우 UDP로 전환하지만 Silverlight는 해당 브라우저를 지원하지 않으며 Nagle 알고리즘도 비활성화 했으므로 일반적으로 전송할 byte [] 배열을 제출하는 즉시, 그것은 하나의 패킷으로 전송되었고, TCP 패킷 크기! = 제출 된 데이터의 양을 알고 있지만 Nagle 알고리즘을 사용하지 않도록 설정 한 상태는 가까운 것입니다. 적응 형 지터 버퍼가 있으므로 수는입니다. 패킷을 잃어 버렸지 만 TCP/IP를 통해 손실 된 패킷은 버퍼링해야 할 오디오의 양을 크게 늘려 대기 시간을 증가시킵니다.TCP를 통해 전송 된 실시간 미디어 스트림에서 손실 된 패킷의 영향을 최소화하는 가장 좋은 방법은 무엇입니까?

그래서 우리는 패킷을 보내는 방법을 최적화하려고합니다. 드롭 된 패킷의 영향을 줄이십시오. 현재 구현하려는 여러 가지 경쟁 솔루션이 있습니다.

(1) 패킷을 더 크게 만들 수 있습니다. 현재 우리는 동일한 TCP 스트림을 통해 큰 (~ 1024 바이트 비디오) 패킷과 작은 (~ 70 바이트 오디오) 패킷의 혼합을 보냅니다. 그러나 오디오 및 비디오 데이터를 함께 다중화 할 수 있습니다 (예 : 여유가있을 때마다 오디오 데이터에 일부 비디오 데이터를 첨부). 이렇게하면 개별 패킷이 다소 커지지 만 총 패킷 수는 줄어 듭니다.

(2) 오디오와 비디오를 두 개의 분리 된 TCP 스트림으로 분리 할 수 ​​있습니다. 즉, 패킷 손실로 인해 비디오 스트림이 정지 된 경우 오디오 스트림이 중단되지 않으며 반대의 경우도 마찬가지입니다. 물론 오버 헤드가 약간 증가하고 전송 된 패킷의 전체 수를 줄이지는 못합니다.

(3) 오디오를 여러 개의 별도 TCP 스트림으로 역 다중화 한 다음 먼 쪽에서 재구성 할 수 있습니다. 이것은 효과적으로 단일 UDP 스타일의 패킷 전달을 "허위"로 만들 수 있습니다. 우리가 8 개의 오디오 스트림을 가지고 있고 그 중 하나가 패킷 손실로 인해 정지 되었다면, 다른 스트림은 여전히 ​​제 시간에 데이터를 전달할 수 있습니다. 우리가해야 할 일은 오디오 패킷의 1/8을 처리하는 것입니다 스톨 된 하천이 다시 잡힐 때까지는 사용할 수 없습니다. 물론 이상적은 아니지만, 스트림 전체가 멈추고 손실 된 패킷이 다시 전송 될 때까지 패킷을 재생할 수없는 것보다 더 좋은 경험이 될 수 있습니다.

이러한 가능성에 대한 의견이 있으십니까? 다른 제안? 아니면 우리는 세 가지 모두를 코딩하고 테스트해야합니까?

+0

MTU는 옵션 1에 영향을 미칩니다. 클라이언트와 서버 간의 가장 작은 MTU만큼 빠릅니다. –

+0

동의 함 - 패킷을 너무 크게 만들 수 없습니다. 현재 페이로드를 1024 바이트로 제한하고 있지만 MTU 문제없이 최대 1500 바이트까지 올라갈 수 있다고 생각합니다. –

답변

0

이 응용 프로그램은 인터넷을 통해 사용됩니까? 인터넷 품질로 인해 손실 된 패킷의 이유는 무엇입니까? 그렇다면 가능한 한 내결함성을 유지하도록 응용 프로그램을 개발하는 것 이외에 인터넷 회로가 허용 가능한 품질인지 확인해야 할 수도 있습니다. 좋은 인터넷 회선은 현재 0.1 % 이상의 패킷 손실을 가져서는 안됩니다. Packet Loss 도구를 사용하여 인터넷 회선 및 ISP를 테스트 할 수 있습니다. 자유롭게 사용하면 도움이됩니다.

+0

예, 인터넷을 통해 사용됩니다.그러나 수천명의 소비자 (희망에 따라)가 인터넷 연결을 완전히 통제 할 수있는 품질로 사용될 것입니다. 물론 패킷이 손실 될 수있는 많은 이유가 있습니다. 가난한 WiFi 연결에서 로컬로, 과부하가 걸린 라우터, 여기 저기로 20 개의 홉이있는 곳, 버퍼에서 어딘가에 비트를 튀기는 우주선 등이 있습니다. –

1

Nagle 알고리즘을 다시 활성화하면 (i) TCP가 자신의 결정보다는 경로 MTU에 따라 최대 크기의 버퍼를 보내도록합니다. (ii) 오디오 및 비디오 패킷을 피기 백 (piggybacking)하는 제안 (1)을 수행하십시오. (iii) 총 패킷 수를 줄이십시오. Nagle 알고리즘이 있거나없는 포화 TCP 연결의 정상 상태 성능은 동일하므로 초기 창 채우기를 제외하고는 아무 것도 잃지 않습니다.

가능한 최대 소켓 전송 버퍼도 실행해야합니다. 가능한 한 최소 128k 또는 이중 또는 4 배로 설정하십시오. 또한 소켓을 연결하기 전에 소켓 수신 버퍼> 64k를 설정해야 TCP 수신 핸드 셰이크 동안 창 크기 조정에 대한 정보를 얻을 수 있기 때문에 은 최대한 버퍼를 수신해야합니다.

+0

Nagle 알고리즘을 다시 활성화 할 때의 문제점은 많은 지연 시간을 추가 할 가능성이 있다는 것입니다. 이는 우리가 최소화하려고 시도하는 것입니다. 오디오 및 비디오 데이터를 모두 포함하는 스트림에서는 대기 시간이 너무 길어 지지만 80 바이트 오디오 메시지 만 포함하는 스트림에서는 전체 패킷을 채우기에 충분한 메시지를 대기열에 넣기보다 오래 걸립니다 . –

0

포장 마차를 일으키는 패킷 손실을 어떻게 확인 했습니까?

스트림을 분리하면 많은 도움이 될 것이라고 생각하지 않습니다. 오디오/비디오를 동기화 상태로 유지하는 데 더 많은 문제가있을 것입니다.

어떤 방법을 사용하든간에 패킷을 재전송해야하는 TCP/IP에 의해 제한됩니다. 내가 조사 할 가장 큰 일은 TCP 스택이 서버이고 클라이언트가 고급 옵션을 사용할 수 있는지 여부입니다. 나는 특별히 Selective Acknowledgements와 Fast retransmissions를 언급하고있다. (모든 최신 OS에는 기본적으로 이것들이 있어야한다.) 빠른 재전송은 누락 된 것으로 감지되면 클라이언트가 손실 된 패킷을 매우 빠르게 요청하게되며 선택 승인을 통해 서버는 스트림의 누락 부분 만 재전송합니다.

그러나 궁극적으로 단일 패킷 손실을 용인 할 수없는 경우 충분히 큰 지터 버퍼를 사용하지 않는 것처럼 들립니다. 또한 응용 프로그램이 tcp 스택에 데이터를 보내는 데 사용되는 타이밍에서 일관성있는 것이 아닐 수도 있습니다. 나는 패킷 캡처를하고 네트워크에서 무슨 일이 벌어지고 있는지 잘 알고, 거기에서 무엇을 할 수 있는지 살펴볼 것이다.

+0

간헐적 인 패킷 손실은 나에게 상당히 설득력있는 것으로 보일지라도이 시점에서 가설에 지나지 않는다고 고백 할 것입니다. 알아 두어야 할 사항은 오디오 스트림이 멈추는 경우입니다. 즉, 애플리케이션이 1-2 초 동안 알림을받지 못합니다. 보류중인 데이터에 대해 알려면 많은 패킷의 데이터로 구성됩니다. 간헐적 인 패킷 손실을 제외하고는 내 머리 꼭대기에서 다른 시나리오를 설명 할 수 없다고 생각합니다. –

+0

또한 지터 버퍼와 관련하여 예, 지터 버퍼를 더 크게 만드는 것은 간단합니다. 그러나 지터 버퍼는 가능한 한 작게 유지하려고합니다. 대기 시간을 도입하는 것이기 때문입니다. 지터 버퍼가 1-2 초 분량의 "스톨 (stall)"을 처리 할 수있을만큼 충분히 클 때 대화에서 1-2 초의 대기 시간을 유발하여 상당히 혼란 스럽습니다. 지금 우리가하고있는 일은 지연을 경험하자마자 지터 버퍼를 크기를 올린 다음 대기 시간이 더 이상 눈에 띄지 않을 때까지 천천히 크기를 줄이는 것입니다 (때때로 프레임을 버림으로써). –

0

초에 @Kevin Nisbet이 버퍼에 있습니다 (불행히도). UDP 대신 TCP를 사용하는 경우 버퍼는 누락 된 바이트에 대해 서버가 알리고 클라이언트에 도달하는 데 필요한만큼 커야합니다.

TCP는 순서가 지정된 스트림으로 응용 프로그램에 데이터를 전달하므로 패킷이 손실되면 스택은 누락 된 바이트를보고하는 ack가 서버로 보내지고 처리되고 바이트가 도착할 때까지 추가 바이트를 응용 프로그램에 전달할 수 없습니다 클라이언트에. 한편 앱을 계속 실행하는 유일한 방법은 버퍼입니다. 가공을 포함하여 왕복 여행에 얼마나 걸립니까?

선택적인 Ack가 없으면 손실 된 바이트 뒤에 수신 된 모든 것이 쓸데없고 재전송해야합니다. 클라이언트는 수신 된 마지막 바이트를 확인하고 서버는 그 시점부터 모든 것을 다시 재전송해야합니다.

Selective Ack를 사용하면 적어도 서버는 누락 된 청크를 보내야하지만 스택은 청크가 도착하기를 기다려야합니다. 지금까지받은 데이터는 앱에 제공 할 수 없으며 누락 된 부분을 채울 수 없습니다. 그것은 UDP가하는 것입니다. 어쩌면 당신은 MS에 글을 써야합니다 ...

네트워크 측면에서 볼 때, 나는 같은 내용의 여러 사본을 보내는 것에 대해 약간의 말을 씁니다. 애플리케이션에 대역폭이 충분합니까? 어쩌면 중복성 (FEC 또는 유사)의 일종의 중복성이 콘텐츠를 복제하는 것보다 낫습니다. 게다가 패킷 손실이 발생할 수있는 경우 네트워크에서 더 많은 트래픽을 발생시키는 것이 현명하지 않을 것이라고 생각합니다. 컴퓨터가 반이중으로 작동합니까? :-D

+0

관찰 해 주셔서 감사합니다. 정적 인 대형 버퍼의 문제점은 대화에 대기 시간을 추가한다는 것입니다. 이는 성가 시거나 혼란 스럽습니다. 현재 트래픽이 얼마나 안정적인지에 따라 크기가 (빠르게) 증가하거나 (느리게) 감소하는 동적 버퍼를 사용하고 있습니다. 또한 옵션 3에서 동일한 데이터의 여러 복사본을 보내지 않을 것입니다. 우리는 역 다중화합니다. 즉, 한 세트의 오디오 샘플을 하나의 TCP 스트림으로 보냅니다. 다음 세트는 다음 TCP 스트림으로 보내지는데, 아마도 일종의 중복/FEC 데이터가 데이터에 추가되어 있습니다 (제안한대로). –

관련 문제