IT_etc/유용한 전산 지식들..

[펌] 인터넷 라디오 (Shoutcast Metadata Protocol)

JJun ™ 2015. 10. 5. 10:41



 출처: http://blog.naver.com/tjkim9393/70019516638




Shoutcast Server에 접속해서 MP3를 듣기위해서는 접속 규격대로 데이터를 주고 받아야 한다.

Shoutcast Stream은 MP3 Data에 Metadata가 붙어있는 형태로 Metadata를 적절히 추출해 내고
MP3 Stream을 MP3 Decoder로 전달해 주면 MP3 음악을 Server에 접속해서 들을 수 있다.

 

참고로 직접 주고 받는 Data를 보고 싶으면 Ethereal이라는 공개 소프트웨어를 PC에 설치한 후
Ethernet을 통해 주고 받는 모든 Packet을 볼 수 있다. 실제 구현시에도 이 툴을 사용해서 주고 받는 Packet을 보면서
그대로 옮겼다.


 



1. Shoutcast Stream Format

 우선 Shoutcast Data를 보면 다음 그림과 같다.

 



 

MP3 Data에 Metadata가 붙어있는 형태이다.

 


 


2. Connect to Server


보통 Shoutcast Server는 URL로 되어있다. 예를 들면 미인 방송국의 URL은 "miin.saycast.com"이다.

이 URL에 접속해서 streaming을 하고 있는 server의 ip와 socket 번호를 알아내야 한다.

URL에 대해 IP를 얻어서(DNS Request : GetHostByName) 해당 IP의 80 Port (HTTP Protocol)에 Request를 보낸다.

Request는 HTTP String으로 다음과 같이 보낸다.


2번째 라인의 Host: %s의 Parameter는 해당 URL String이다.

이 Request는 추후 실제 Streming server에 Metadata를 받기 위해서 다시 사용한다.


    static prog_char szReqStr[] = 

    {
        "GET / HTTP/1.0\r\n"
        "Host: %s\r\n"
        "User-Agent: WinampMPEG/5.09\r\n"
        "Accept: */*\r\n"
        "Icy-MetaData:1\r\n"
        "Connection: close\r\n"
        "\r\n"
    };



 Data caputre는 PC에서 Winamp로 miin방송국 Streaming Server Request를 하는 부분이다.

 



 

 


3. Get Streaming Server


앞의 Request에 대해 Server에서는 다음과 같은 응답 패킷을 보낸다. (HTTP Protocol만 보면 된다.)

HTTP/1.1 302 Found\r\n 라는 응답으로 시작되며 Data, Server, Location 정보등이 날라오게 된다.


이 중 Location 정보가 실제 Streaming Server의 주소가 되며 :8102는 포트 번호가 된다.

URL에 접속할 때마다 Streaming Server의 주소와 포트번호는 바뀔 수 있다.
(접속량에 따라 Server가 Connection을 분배하기 때문이다.)

이 그림에서는 sc07.saycast.com이 Streming Server의 URL이고 포트 번호는 8102가 된다.




 

 

4. Request Metadata

Streaming Server의 주소와 Port 번호를 알아냈으니 이제 접속해서 Steam의 Metadata를 얻어와야 한다.

Metadata를 얻기 위해 위에서 사용한 Request를 그대로 사용하되 Host의 파라미터를 위에서 얻은
Streaming Server의 URL을 사용한다.


    static prog_char szReqStr[] = 

    {
        "GET / HTTP/1.0\r\n"
        "Host: %s\r\n"
        "User-Agent: WinampMPEG/5.09\r\n"
        "Accept: */*\r\n"
        "Icy-MetaData:1\r\n"
        "Connection: close\r\n"
        "\r\n"
    };

 


80 Port가 아니어서 Protocol이 HTTP로 인식되지 않으니 Ethereal에서 오른쪽 버튼을 눌러 강제로 HTTP로 디코딩을 하면
다음과 같은 데이터를 보내는 것을 알 수 있다.




 

 


5. Interpret Response


위의 Request에 대해 Streaming Server는 다음과 같은 응답을 보낸다.

ICY 200 OK\r\n을 보낸 후 해당 Stream에 대한 정보를 보내게 된다.

각 field는 icy로 시작되며 각 field는 다음과 같은 의미이다.

 

Field

Meaning

icy-notice{n}

서버에서 공지사항을 보낼 때 사용

icy-name

방송국 이름

icy-genre

음악 장르

icy-url

방송국 Homepage URL

content-type

Metadata 뒤에 오는 Content Type

icy-br

Stream Bitrate

icy-pub

a switch to either allow the server to publish itself in the directory or not (1 meaning yes)

icy-metaint

Metadata의 Interval

 

icy-metaint가 바로 data가 반복되는 주기를 나타낸다.
이 만큼의 MP3 Data가 오고나서 metadata가 오게 된다.

아래 그림에서는 32768 byte만큼 MP3 데이터가 온 후에 metadata가 나오게 된다.

(icy-name을 이용하여 방송국 이름을 화면에 나타냈다.)




 

 


6. Interpret Metadata


icy-metaint만큼의 MP3 데이터가 온 후에 비로소 Metadata가 온다.

Metadata의 제일 첫 바이트는 실제 Meatadata의 크기로 이 값에 x16을 해서 Metadata Size로 사용한다.

따라서 Metadata < 4080 보다 작다. 이 Metadata를 Buffering해서 저장한 다음에 전부 다 받으면 Parsing을 해야 한다.

Metadata에는 현재 재생중인 곡의 Title이나 Stream URL과 같은 부가 정보가 오게 된다.


만약 Metadata Size byte가 0이면 Metadata가 없음을 나타낸다. 대부분 Metadata size가 0인 데이터가 온다.

Metadata는 접속을 했을 때 또는 재생중인 곡의 제목이 바뀔 때 날라오는 경우가 대부분이다.

재생중일때는 대부분 0인 Metadata가 온다. 아래 그림에서는 한글로 나온 제목이 "."으로 처리되어 보인다.

StreamTitle='xxxxxx' Field가 현재 재생중인 제목이다.

 



 
 
MP3 Data는 Buffering을 적절히(?) 시킨 후에 MP3 Decoder에 전달하면 된다.
 
VS1003 과 같은 Decoder를 사용시에는 DRQ Pin을 봐가면서 데이터를 전달해야 한다.
한꺼번에 받은 데이터를 모두 Writing을 시키면 Overflow가 나게 되서 소리가 끊기게 된다.
실제 Streaming 되는 Data는 Bitrate에 맞춰 전송이 되긴 하지만 
한 번에 받는 데이터의 크기 만큼 VS1003에 Write하지 못하기 때문에 일부 데이터를 Buffering 해야 한다.