-
-
Save corelmax/9f5c3593cf4314b3337eca5efee2a9a8 to your computer and use it in GitHub Desktop.
Relay a Dante multicast stream to AES67. This assumes the AES67 device is synced to the same PTP master, as no PTP timestamping is done (timestamp from Dante is copied to AES67 RTP packet)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const dgram = require('dgram'); | |
const client = dgram.createSocket({ type: 'udp4', reuseAddr: true }); | |
const sdp = require('./sdp'); | |
//config | |
const addr = '10.10.1.100'; | |
const danteMulticast = '239.255.220.221'; | |
const aes67Multicast = '239.69.1.122'; | |
const samplerate = 48000; | |
const channels = 2; | |
const encoding = 'L24'; | |
const name = 'Dante Multicast Relay'; | |
const sessID = Math.round(Date.now() / 1000); | |
const sessVersion = sessID; | |
const ptpMaster = '08-00-00-ff-fe-00-00-1f:0'; | |
//rtp specific vars | |
var seqNum = 0; | |
client.on('listening', function() { | |
client.addMembership(danteMulticast, addr); | |
client.setMulticastInterface(addr); | |
}); | |
client.on('message', function(buffer, remote) { | |
//read values from buffer | |
var channelCount = buffer.readUInt8(0); | |
var timestampSeconds = buffer.readUInt32BE(1); | |
//bytes 6 and 7 seem to be always 0x00, maybe reserved bytes | |
var timestampMedia = buffer.readUInt16BE(7); | |
var pcmData = buffer.slice(9); | |
//calculate media timestamp for rtp | |
var timestampRTP = ((timestampSeconds * samplerate) + timestampMedia) & 0xffffffff; | |
//create RTP header | |
var rtpHeader = Buffer.alloc(12); | |
rtpHeader.writeUInt16BE(0x8061, 0); | |
rtpHeader.writeUInt16BE(seqNum, 2); | |
rtpHeader.writeInt32BE(timestampRTP, 4); | |
rtpHeader.writeUInt32BE(0xaf12af34, 8); | |
//create and send RTP packet | |
var rtpBuffer = Buffer.concat([rtpHeader, pcmData]); | |
client.send(rtpBuffer, 5004, aes67Multicast); | |
//increase seqnum | |
seqNum = (seqNum + 1) % 65536; | |
}); | |
client.bind(4321); | |
sdp.start(addr, aes67Multicast, samplerate, channels, encoding, name, sessID, sessVersion, ptpMaster); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var dgram = require('dgram'); | |
var socket = dgram.createSocket({ type: 'udp4', reuseAddr: true }); | |
var constructSDPMsg = function(addr, multicastAddr, samplerate, channels, encoding, name, sessID, sessVersion, ptpMaster){ | |
var sapHeader = Buffer.alloc(8); | |
var sapContentType = Buffer.from('application/sdp\0'); | |
var ip = addr.split('.'); | |
//write version/options | |
sapHeader.writeUInt8(0x20); | |
//write hash | |
sapHeader.writeUInt16LE(0xefef, 2); | |
//write ip | |
sapHeader.writeUInt8(parseInt(ip[0]), 4); | |
sapHeader.writeUInt8(parseInt(ip[1]), 5); | |
sapHeader.writeUInt8(parseInt(ip[2]), 6); | |
sapHeader.writeUInt8(parseInt(ip[3]), 7); | |
var sdpConfig = [ | |
'v=0', | |
'o=- '+sessID+' '+sessVersion+' IN IP4 '+addr, | |
's='+name, | |
'c=IN IP4 '+multicastAddr+'/32', | |
't=0 0', | |
'a=clock-domain:PTPv2 0', | |
'm=audio 5004 RTP/AVP 96', | |
'a=rtpmap:96 '+encoding+'/'+samplerate+'/'+channels, | |
'a=sync-time:0', | |
'a=framecount:48', | |
'a=ptime:1', | |
'a=mediaclk:direct=0', | |
'a=ts-refclk:ptp=IEEE1588-2008:'+ptpMaster, | |
'a=recvonly', | |
'' | |
]; | |
var sdpBody = Buffer.from(sdpConfig.join('\r\n')); | |
return Buffer.concat([sapHeader, sapContentType, sdpBody]); | |
} | |
exports.start = function(addr, multicastAddr, samplerate, channels, encoding, name, sessID, sessVersion, ptpMaster){ | |
sdpMSG = constructSDPMsg(addr, multicastAddr, samplerate, channels, encoding, name, sessID, sessVersion, ptpMaster); | |
socket.bind(9875, function(){ | |
socket.setMulticastInterface(addr); | |
socket.send(sdpMSG, 9875, '239.255.255.255', function(err){}); | |
}); | |
setInterval(function(){ | |
socket.send(sdpMSG, 9875, '239.255.255.255', function(err){}); | |
}, 30*1000); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment