Trouble Parsing and Playing RTP VP8 Data in Node.js Using Siprec

114 Views Asked by At

Hello Stack Overflow community,

I'm attempting to develop a video recording application using Node.js. I'm trying to record and play back VP8 streams within RTP data sent over Siprec using UDP. However, it seems like I'm encountering issues either while parsing RTP packets or at some other step, and I'm unable to successfully extract, combine, and play the received packets as a video.

I've broken down my process into several steps:

RTP Parsing Saving Packets to a File Combining Packets Converting the Combined File Playback However, I'm facing issues in one of these steps. I either can't parse the payload correctly, or there might be some other problem that I'm not aware of.

Below, you can find some different functions I've tried:

[You can insert any code snippets or error messages you'd like to add here.]

I'm looking for assistance in resolving my issue. Thank you!

SDP Data:

Content-Type: application/sdp

v=0
o=MySiprecServer 672778243 713822205 IN IP4 192.168.0.205
s=SBC-Call
c=IN IP4 192.168.0.205
t=0 0
m=audio 8040 RTP/AVP 8 101
c=IN IP4 192.168.0.205
a=ptime:20
a=sendonly
a=label:1
a=mid:2
a=rtcp-mux
a=rtcp:8041 IN IP4 192.168.0.205
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15,16
m=audio 8045 RTP/AVP 8 101
c=IN IP4 192.168.0.205
a=ptime:20
a=sendonly
a=label:2
a=mid:3
a=rtcp-mux
a=rtcp:8046 IN IP4 192.168.0.205
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15,16
m=video 8000 RTP/AVP 96
c=IN IP4 192.168.0.205
a=rtcp:8001 IN IP4 192.168.0.205
a=mid:1
a=extmap:14 urn:ietf:params:rtp-hdrext:toffset
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:13 urn:3gpp:video-orientation
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendonly
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:96 VP8/90000
a=rtcp-fb:96 goog-remb
a=rtcp-fb:96 transport-cc
a=rtcp-fb:96 ccm fir
a=rtcp-fb:96 nack
a=rtcp-fb:96 nack pli
a=ssrc:4115522635 cname:Z2Ddcyd5sthBDaqs
a=label:3
m=video 8005 RTP/AVP 96
a=sendonly
a=rtpmap:96 vp8/90000
a=label:4
a=mid:4
a=rtcp-mux
a=rtcp:8006 IN IP4 192.168.0.205

this is my code attempt:

const fs = require('fs');
const path = require('path');
const dgram = require('dgram');
const server = dgram.createSocket('udp4');

function parseRtpPacket(buffer) {
    // RTP Header Fields
    const version = (buffer[0] >> 6) & 0x03;
    const padding = (buffer[0] >> 5) & 0x01;
    const extension = (buffer[0] >> 4) & 0x01;
    const csrcCount = buffer[0] & 0x0F;
    const marker = (buffer[1] >> 7) & 0x01;
    const payloadType = buffer[1] & 0x7F;
    const sequenceNumber = buffer.readUInt16BE(2);
    const timestamp = buffer.readUInt32BE(4);
    const ssrc = buffer.readUInt32BE(8);
  
    // Calculate the RTP header size
    let headerSize = 12 + 4 * csrcCount;
    
    // Check if there's an extension header
    if (extension === 1) {
      const extensionLength = buffer.readUInt16BE(headerSize + 2);
      headerSize += 4 + extensionLength * 4;
    }
  
    // VP8 Frame
    const vp8Frame = buffer.slice(headerSize);
  
    // Save to file (example)
    //fs.writeFileSync(`frame_${sequenceNumber}.bin`, vp8Frame);
  
    return {
      version,
      padding,
      extension,
      csrcCount,
      marker,
      payloadType,
      sequenceNumber,
      timestamp,
      ssrc,
      vp8Frame
    };
  }
  



const receivedData = JSON.parse(process.argv[2]);
const { Command, CallID, ChannelPort } = receivedData

console.log("Komut: " + Command + " CallID: " + CallID + " ChannelPort: " + ChannelPort);


if (Command == 'start') {

    // listen udp socket
    server.on('message', (msg, rinfo) => {
        const parsedPacket = parseRtpPacket(msg);
        console.log(`Received RTP packet from ${rinfo.address}:${rinfo.port}`);
        console.log(parsedPacket);
        const ssrc = parsedPacket.ssrc.toString();
        const sequenceNumber = parsedPacket.sequenceNumber.toString();

        const mainDirPath = path.join('calls', CallID.toString());
        const portDirPath = path.join(mainDirPath, ChannelPort.toString());

        if (!fs.existsSync(portDirPath)) {
            fs.mkdirSync(portDirPath);
        }

        // const filePath = path.join(ssrc, `${sequenceNumber}.bin`);
        const filePath = path.join(portDirPath, `${sequenceNumber}.bin`);
        fs.writeFileSync(filePath, parsedPacket.vp8Frame);

    });

    server.on('listening', () => {
        const address = server.address();
        console.log(`UDP Server listening on ${address.address}:${address.port}`);
    });

    // listen 5000 port
    server.bind(ChannelPort);

} else if (Command == 'stop') {
    console.log("stopped");
} else { }
0

There are 0 best solutions below