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 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 audio_data = new List(); 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; } } }