收到的音乐流数据包中有丢失帧的时候,可以通过 control port 发送 resendTransmit 的 request 给iPhone,iPhone收到后会将帧在 response 中补发回来。
SETUP rtsp://192.168.1.150/1561243076001349804 RTSP/1.0
Transport: RTP/AVP/UDP;unicast;mode=record;timing_port=55703;control_port=56616
CSeq: 4
DACP-ID: 4CB06073C86450D8
Active-Remote: 2937221397
User-Agent: AirPlay/373.9.1
图2-2 SETUP报文
W5500EVB回复的响应报文中的server_port, server port 用来传输音频流数据包
RTSP/1.0 200 OK
CSeq: 4
Apple-Jack-Status: connected; type=analog
Transport: RTP/AVP/UDP;unicast;mode=record;timing_port=56461;events;control_port=51196;server_port=55641
Session:DEADBEEF
图2-3 SETUP响应报文
SETUP数据包确定音频流传输方式与传输端口号后,iPhone就开始发送音频数据到W5500EVB指定的server_port 55641端口,W5500EVB接收音频数据,通过解密过程后,我们会得到AAC编码的音频数据,播放器播放AAC数据还需要对其进行解码,话不多说,直接通过部分代码来说明音频解密过程。
1 int decode_audio_data(unsigned char *data, unsigned short
2 datalen, int use_seqnum)
3 {
4 unsigned short seqnum;
5 raop_buffer_entry_t entry;
6 int encryptedlen;
7 AES_CTX aes_ctx;
8 int outputlen;
9 /* Check packet data length is valid */
10 if (datalen < 12 || datalen > 1472) {
11 return -1;
12 }
13 /* Get correct seqnum for the packet */
14 if (use_seqnum) {
15 seqnum = (data[2] << 8) | data[3];
16 }
17 /* Update the raop_buffer entry header */
18 entry.flags = data[0];
19 entry.type = data[1];
20 entry.seqnum = seqnum;
21 entry.timestamp = (data[4] << 24) | (data[5] << 16) |
22 (data[6] << 8) | data[7];
23 entry.ssrc = (data[8] << 24) | (data[9] << 16) |
24 (data[10] << 8) | data[11];
25 entry.available = 1;
26 /* Decrypt audio data */
27 encryptedlen = (datalen-12)/16*16;
28 AES_set_key(&aes_ctx, aeskey, aesiv, AES_MODE_128);
29 AES_convert_key(&aes_ctx);
30 memset(packetbuf,0,sizeof(data));
31 AES_cbc_decrypt(&aes_ctx, &data[12], (uint8*)packetbuf,
32 encryptedlen);
33 memcpy(packetbuf+encryptedlen, &data[12+encryptedlen],
34 datalen-12-encryptedlen);
35 /* Decode ALAC audio data */
36 outputlen = audio_buffer_size;
37 alac_decode_frame(&alac, (uint8*)packetbuf ,audiobuf,
38