제임스딘딘의
Tech & Life

수행 프로젝트 이력/참여자주도형 정보공유 시스템 [2011.12~2012.02]

자료조사(3) - VOIP

제임스-딘딘 2011. 11. 25. 11:36
VOIP(Voice Over IP)라는 것은 용어 해석그대로 IP를 통하여 사람의 보이스를 전달하는 것

환경 구성 
 - 리눅스 머신 (HUINS PXA255보드에서 작동하는 커널2.4x버젼)
 - HP의 PDA
 
역할  
 - HUINS PXA255보드는 PDA끼리의 연결을 위한 중앙서버역할
 - PDA는 VOIP를 위한 클라이언트 즉 단말기의 역할

설명
PDA자체의 CPU가 성능이 그리 좋지는 않다.
초창기에 OGG인코딩을 스트리밍하여 전송양을 줄여보려 했으나, 이는 오히려 인코딩/디코딩시에
시간이 더욱 소모되어 저사양의 PDA에서는 오히려 해가 될거라 판단했다.
그래서 RAW정보 자체를 그대로 전송하기로 결정하였다.
제한조건은 다음과 같다.
VOIP상에서 홀펀칭(STUN이라고도 불리운다.) 을 구현하려 했으나 실패한 관계로, PDA는 GLOBAL IP를 갖는다(모든단말), 혹은 모든단말이 같은 AP에 접속하여 같은 WAN-IP를 공유하는 라우터내에서 NAT로 등록된다라는 가정이다.

이런 가정하에 LOW LEVEL 함수를 통한 음성 정보 수집에 들어갔다. 기본적인 구성은
Visual C++ 6.0 Bible에 수록된 음성과 관련된 파트를 참조하여 작성을 하였다.

음성을 녹음받은후 데이터를 전송한다.
이 데이터는 메모리에 다중버퍼에 저장되고 이 버퍼에 데이터가 채워졌을경우 재생을 시작한다.

가장중요한건 지금부터다.

재생을 함에 있어 일반적으로 겪는 문제는 "뽂뽂뽁뽁....."거리는 소리가 들림에 있다.
버퍼링 사이즈를 무제한으로 길게 하면되지만 이는 현실적인 도피일뿐 근본적 해결이 아니다.

재생버퍼는 0.4초정조만을 재생하게끔 되어있기때문에 다음데이터를 불러올때 연결되지못해
끊기는 소리가 들림으로인해 뽂뽂거리는 소리가 들리는것이 원인이다.

이를 해결하기 위해서는 재생시에 더블버퍼링을 구현하여야한다.

C#으로 VOIP를 작성해본 사람이라면 C#이 내부적으로 다 처리해줌으로써 손쉽게 구현했었을것이다.(소스는 웹에 널리고 널렸다.)
하지만 C++로 직접 로우레벨 함수를 통해 제어하려다보니 이런것들도 일일이 다 컨트롤해야한다.


간단히 소개하자면,
재생버퍼에 다음재생할 부분을 미리 넣어둔다.
그리고 다음에 그 부분을 재생하는 것이 원칙이다.
이렇게하며 더블버퍼링이 구현되어 연속적으로 부드러운 음성재생이 가능하다.

방법은 이해했지만, 실질적으로 구현함에 있어 뜻대로 잘 구현이 되지 않을것

이로써 기본적 기능은 구현이 될것이다.
버퍼링 사이즈및 비트레이트 역시 전송딜레이에 큰 영향을 미친다. 우리팀은 이를 실험적 시도를 통하여 딜레이가 0.3초 정도밖에 되지않는 voip구현에 성공하였다. 이수치는 공개하지않겠다.

두번째는 서버측 기능이다.
클라이언트는 비정상 종료할수도있고, 정상종료할 수도있다.
이로인해, 서버는 리스트관리를 타이트하게 할 필요가있다.
이로인해 우리는 클라이언트에서 주기적인 Alive msg를 전송하고, 이 Alive msg가 도착하면
다음 Alive msg 전송시간까지 라이프 타임을 얻게한다. 이 라이프 타임이 다 소모되어 0이될때까지
Alive msg가 전송되지 않는다면 비정상 종료된 것이므로 강제로 리스트해제 등록을 해제하고 관련 리소스를 모두 해제하는 것이 우리가 구현한 중요부분이다.
이는 익셉션 핸들링을 서버에서도 처리해줌으로써 안정적인 작동을 가능하게 해주는 대목이다.