Files
2025-08-19 12:45:50 +02:00

137 lines
5.2 KiB
C#

using System;
using System.Collections.Generic;
namespace Inspectron.HawkEye.RTSP
{
// This class handles the AAC-hbd (High Bitrate) Payload
// It has methods to process the RTP Payload
// (c) 2018 Roger Hardiman, RJH Technical Consultancy Ltd
/*
RFC 3640
3.3.6. High Bit-rate AAC
This mode is signaled by mode=AAC-hbr.This mode supports the
transportation of variable size AAC frames.In one RTP packet,
either one or more complete AAC frames are carried, or a single
fragment of an AAC frame is carried.In this mode, the AAC frames
are allowed to be interleaved and hence receivers MUST support de-
interleaving.The maximum size of an AAC frame in this mode is 8191
octets.
In this mode, the RTP payload consists of the AU Header Section,
followed by either one AAC frame, several concatenated AAC frames or
one fragmented AAC frame.The Auxiliary Section MUST be empty. For
each AAC frame contained in the payload, there MUST be an AU-header
in the AU Header Section to provide:
a) the size of each AAC frame in the payload and
b) index information for computing the sequence(and hence timing) of
each AAC frame.
To code the maximum size of an AAC frame requires 13 bits.
Therefore, in this configuration 13 bits are allocated to the AU-
size, and 3 bits to the AU-Index(-delta) field.Thus, each AU-header
has a size of 2 octets.Each AU-Index field MUST be coded with the
value 0. In the AU Header Section, the concatenated AU-headers MUST
be preceded by the 16-bit AU-headers-length field, as specified in
section 3.2.1.
In addition to the required MIME format parameters, the following
parameters MUST be present: sizeLength, indexLength, and
indexDeltaLength.AAC frames always have a fixed duration per Access
Unit; when interleaving in this mode, this specific duration MUST be
signaled by the MIME format parameter constantDuration.In addition,
the parameter maxDisplacement MUST be present when interleaving.
For example:
m= audio 49230 RTP/AVP 96
a= rtpmap:96 mpeg4-generic/48000/6
a= fmtp:96 streamtype= 5; profile-level-id= 16; mode= AAC-hbr;config= 11B0; sizeLength= 13; indexLength= 3;indexDeltaLength= 3; constantDuration= 1024
The hexadecimal value of the "config" parameter is the AudioSpecificConfig(), as defined in ISO/IEC 14496-3.
AudioSpecificConfig() specifies a 5.1 channel AAC stream with a sampling rate of 48 kHz.For the description of MIME parameters, see
section 4.1.
*/
public class AACPayload
{
public uint ObjectType = 0;
public uint FrequencyIndex = 0;
public uint ChannelConfiguration = 0;
// Constructor
public AACPayload(String config_string)
{
/***
5 bits: object type
if (object type == 31)
6 bits + 32: object type
4 bits: frequency index
if (frequency index == 15)
24 bits: frequency
4 bits: channel configuration
var bits: AOT Specific Config
***/
// config is a string in hex eg 1490 or 0x1210
// Read each ASCII character and add to a bit array
BitStream bs = new BitStream();
bs.AddHexString(config_string);
// Read 5 bits
ObjectType = bs.Read(5);
// Read 4 bits
FrequencyIndex = bs.Read(4);
// Read 4 bits
ChannelConfiguration = bs.Read(4);
}
public List<byte[]> Process_AAC_RTP_Packet(byte[] rtp_payload, int rtp_marker) {
// RTP Payload for MPEG4-GENERIC can consist of multple blocks.
// Each block has 3 parts
// Part 1 - Acesss Unit Header Length + Header
// Part 2 - Access Unit Auxiliary Data Length + Data (not used in AAC High Bitrate)
// Part 3 - Access Unit Audio Data
// The rest of the RTP packet is the AMR data
List<byte[]> audio_data = new List<byte[]>();
int ptr = 0;
while (true) {
if (ptr + 4 > rtp_payload.Length) break; // 2 bytes for AU Header Length, 2 bytes of AU Header payload
// Get Size of the AU Header
int au_headers_length_bits = (((rtp_payload[ptr] << 8) + (rtp_payload[ptr + 1] << 0))); // 16 bits
int au_headers_length = (int)Math.Ceiling((double)au_headers_length_bits / 8.0);
ptr += 2;
// Examine the AU Header. Get the size of the AAC data
int aac_frame_size = (((rtp_payload[ptr] << 8) + (rtp_payload[ptr+1] << 0)) >> 3); // 13 bits
int aac_index_delta = rtp_payload[ptr+1] & 0x03; // 3 bits
ptr += au_headers_length;
// extract the AAC block
if (ptr + aac_frame_size > rtp_payload.Length) break; // not enough data to copy
byte[] aac_data = new byte[aac_frame_size];
System.Array.Copy(rtp_payload, ptr, aac_data, 0, aac_frame_size);
audio_data.Add(aac_data);
ptr += aac_frame_size;
}
return audio_data;
}
}
}