private static byte[] PacketizeSingleNAL(Span <byte> raw_nal, UInt32 rtp_timestamp) { // Put the whole NAL into one RTP packet. // Note some receivers will have maximum buffers and be unable to handle large RTP packets. // Also with RTP over RTSP there is a limit of 65535 bytes for the RTP packet. byte[] rtp_packet = new byte[RTPPacketUtil.HeaderLength + raw_nal.Length]; // 12 is header size when there are no CSRCs or extensions // Create an single RTP fragment bool rtp_marker = (raw_nal[0] & 0x1F) <= 5; RTPPacketUtil.WriteHeader(rtp_packet, rtp_version, rtp_padding, rtp_extension, rtp_csrc_count, rtp_marker, rtp_payload_type); UInt32 empty_sequence_id = 0; RTPPacketUtil.WriteSequenceNumber(rtp_packet, empty_sequence_id); RTPPacketUtil.WriteTS(rtp_packet, rtp_timestamp); UInt32 empty_ssrc = 0; RTPPacketUtil.WriteSSRC(rtp_packet, empty_ssrc); // Now append the raw NAL raw_nal.CopyTo(new Span <byte>(rtp_packet, 12, raw_nal.Length)); return(rtp_packet); }
private static void PacketizeNAL_FUA(ref List <byte[]> rtp_packets, Span <byte> raw_nal, UInt32 rtp_timestamp) { int start_bit = 1; int end_bit = 0; // consume first byte of the raw_nal. It is used in the FU header byte first_byte = raw_nal[0]; raw_nal = raw_nal.Slice(1); while (raw_nal.Length > 0) { int payload_size = Math.Min(RTPPacketUtil.MaxPayloadSize - 2, raw_nal.Length); if (raw_nal.Length - payload_size == 0) { end_bit = 1; } //for FU-A the marker is set when this is the last RTP packet bool rtp_marker = end_bit == 1; byte[] rtp_packet = new byte[RTPPacketUtil.HeaderLength + 2 + payload_size]; // 2 bytes for FU-A header. RTPPacketUtil.WriteHeader(rtp_packet, rtp_version, rtp_padding, rtp_extension, rtp_csrc_count, rtp_marker, rtp_payload_type); UInt32 empty_sequence_id = 0; RTPPacketUtil.WriteSequenceNumber(rtp_packet, empty_sequence_id); RTPPacketUtil.WriteTS(rtp_packet, rtp_timestamp); UInt32 empty_ssrc = 0; RTPPacketUtil.WriteSSRC(rtp_packet, empty_ssrc); // Now append the Fragmentation Header (with Start and End marker) and part of the raw_nal byte f_bit = 0; byte nri = (byte)((first_byte >> 5) & 0x03); // Part of the 1st byte of the Raw NAL (NAL Reference ID) byte type = 28; // FU-A Fragmentation rtp_packet[12] = (byte)((f_bit << 7) + (nri << 5) + type); rtp_packet[13] = (byte)((start_bit << 7) + (end_bit << 6) + (0 << 5) + (first_byte & 0x1F)); raw_nal.Slice(0, payload_size).CopyTo(new Span <byte>(rtp_packet, 14, payload_size)); raw_nal = raw_nal.Slice(payload_size); rtp_packets.Add(rtp_packet); start_bit = 0; } }
//TODO: reimplement these using Memory and Span<byte> public static List <byte[]> PacketizeSamples(Span <byte> smp, ulong tsMs) { List <byte[]> rtp_packets = new List <byte[]>(); double diffTs = 0; while (smp.Length > 0) { int dataLen = smp.Length > RTPPacketUtil.MaxPayloadSize ? RTPPacketUtil.MaxPayloadSize : smp.Length; byte[] packet = new byte[dataLen + RTPPacketUtil.HeaderLength]; Span <byte> packetData = new Span <byte>(packet, RTPPacketUtil.HeaderLength, dataLen); for (int i = 0; i < dataLen; i += 2) { packetData[i] = smp[i + 1]; packetData[i + 1] = smp[i]; } RTPPacketUtil.WriteHeader(packet, rtp_version, rtp_padding, rtp_extension, rtp_csrc_count, false, rtp_payload_type); UInt32 empty_sequence_id = 0; RTPPacketUtil.WriteSequenceNumber(packet, empty_sequence_id); RTPPacketUtil.WriteTS(packet, (UInt32)((tsMs + diffTs) * 48)); UInt32 empty_ssrc = 0; RTPPacketUtil.WriteSSRC(packet, empty_ssrc); rtp_packets.Add(packet); smp = smp.Slice(dataLen); diffTs += AudiolenRtpPackeMs; } return(rtp_packets); }