Skip to content

[Proposal] SE-00003: Session Description Protocol Handling for AES67 Stream Interoperability #16

Description

@N3v1

Proposal Title

Session Description Protocol Handling for AES67 Stream Interoperability

Proposal ID

SE-00003

Author

Nevio Hirani

Motivation

The libAES67 project aims to provide a robust, standards-compliant implementation of AES67, the interoperability standard for high-performance audio over IP. One of the most crucial aspects of AES67-based systems is their ability to advertise and consume real-time audio streams using well-defined metadata. This metadata is encapsulated in the Session Description Protocol (SDP), which is specified in RFC 4566 and referenced throughout the AES67 standard, particularly in Annex B.

In AES67 environments, SDP is used to describe the essential characteristics of an RTP stream, such as the media type, payload type, encoding format, sampling rate, number of channels, multicast address, port number, synchronization source, and reference clock information. Interoperability between systems depends on the ability to accurately parse, validate, and generate these SDP descriptions.

At present, libAES67 does not support any form of SDP handling. This limits its ability to automatically participate in audio networking workflows that rely on SIP, SAP, RTSP, or any form of stream announcement or discovery. It also restricts the library’s utility when used alongside commercial and open-source AES67 endpoints, many of which announce their RTP streams using SDP via multicast, unicast, or API-based mechanisms.

Adding comprehensive support for SDP will enable libAES67 to parse incoming stream descriptions, validate them for AES67 compliance, and generate outbound SDP announcements for broadcasting or unicast publication. This feature will improve the interoperability of libAES67 with other AES67 systems, simplify its integration into complex network topologies, and lay the groundwork for future support of session negotiation protocols such as SIP or RTSP.

Specification

The proposed SDP subsystem for libAES67 will provide a robust set of data structures, parsing logic, validation routines, and generation utilities written in C, fully aligned with the subset of SDP required by the AES67 standard. The purpose of this module is to allow the library to consume raw text-based SDP messages and transform them into structured, validated representations that can be used by other core components such as the RTP receiver and transmitter.

Each SDP session describes one or more RTP media streams and is essential for interoperation in broadcast or streaming contexts, especially when operating with other AES67-compliant devices. The parser must support all session and media-level SDP lines relevant to AES67, including:

  • v= protocol version
  • o= session name
  • c= connection data (unicast/multicast IP)
  • t= timing
  • m= media description (typically audio)
  • a= attributes, including rtpmap, ptime, ts-refclk, mediaclk

The validator must check for AES67 conformance, ensuring RTP/AVP is used, the clock rate is 48000 Hz, encoding is either L16 or L24, and the number of channels is compliant (1–8). The presence and format of PTP-based clock references must also be verified in accordance with RFC 7273.

v=0
o=- 2890844526 2890842807 IN IP4 192.168.1.100
s=AES67 Audio Session
c=IN IP4 239.255.0.1/32
t=0 0
m=audio 5004 RTP/AVP 96
a=rtpmap:96 L24/48000/2
a=ptime:1
a=ts-refclk:ptp=IEEE1588-2008:00-1D-C1-FF-FE-12-34-56:0
a=mediaclk:direct=0

The above example demonstrates a typical AES67 SDP description, highlighting the essential lines and attributes that the parser and generator will handle to ensure compliant audio stream configuration and synchronization.

Finally, the generator must be able to serialize a validated session structure into a correctly formatted SDP message that is suitable for multicast SAP advertisement or SIP/RTSP negotiation.

System Integration & Stream Flow

SDP handling integrates at both control and stream setup layers. The typical AES67 stream lifecycle involves the following:

+------------------+      SDP (SAP/SIP)       +------------------+
| AES67 Transmitter| -----------------------> | AES67 Receiver   |
| RTP Session Init |                          | Parse & Join RTP |
+------------------+                          +------------------+

                +---------------------------------------------+
                |       aes67_sdp_parse()  + validation       |
                |       aes67_sdp_generate()                  |
                +---------------------------------------------+

In a transmitting context, the application generates an aes67_sdp_session_t using metadata from the configured stream. This is serialized into a string via aes67_sdp_generate() and transmitted via SAP or embedded in SIP/RTSP. On the receiver side, the incoming SDP text is parsed via aes67_sdp_parse() into an aes67_sdp_session_t, validated via aes67_sdp_validate(), and passed to the RTP subsystem to establish the stream.

Proposed Design

The SDP module will be implemented entirely in C and will be located under the src/sdp.c path within the libAES67 codebase. It will expose a clean public API and define a comprehensive set of internal data structures for representing SDP sessions, media descriptions, session attributes, and reference clock information. All public functions and types defined by this module will follow the established aes67_ prefix convention used across the library.

At the core of the design is the aes67_sdp_session_t structure, which serves as the in-memory representation of an entire SDP document. This structure will contain fields for session-level metadata such as the protocol version, origin, session name, connection information, and timing. Additionally, it will include a dynamically allocated list of aes67_sdp_media_t elements, each representing a single m= line and its associated attributes. This model allows the library to support multiple media streams per session, although AES67 typically uses only one.

The parsing subsystem will be responsible for transforming raw SDP text into an aes67_sdp_session_t instance. It will iterate over the input line by line, identify each line’s type based on its prefix, and populate the corresponding fields in the data structures. Because SDP has a hierarchical format in which some attributes are session-wide and others are media-specific, the parser must correctly differentiate and associate each attribute with the appropriate scope.

Once parsed, the resulting structure will be passed to a validation routine that checks for both syntactic correctness and semantic compliance with AES67. This includes ensuring the use of the correct RTP profile (RTP/AVP), verifying that the sample rate is set to '48000 Hz', and confirming that the encoding format is either L16 or L24. The number of channels must also fall within the acceptable AES67 range of 1 to 8. Moreover, the validator will examine clock-related attributes such as ts-refclk and mediaclk to ensure that the reference clock format matches the PTP-based specification defined in RFC 7273.

On the transmission side, the library will offer a generator function capable of producing a complete SDP string from a filled-in aes67_sdp_session_t. This function must ensure that all fields are correctly ordered, newline characters are standardized, and required attributes are included. The output of this generator will be suitable for use in various signaling and announcement protocols common in AES67 deployments.

In particular, the generated SDP data must be compatible with SAP (Session Announcement Protocol), SIP (Session Initiation Protocol), and RTSP (Real-Time Streaming Protocol). Each of these protocols makes use of SDP for different purposes: SAP broadcasts SDP announcements over multicast to advertise available audio streams; SIP embeds SDP in signaling messages to negotiate RTP sessions; RTSP returns SDP in response to client requests to describe media resources. The implementation must therefore ensure that the produced SDP output is formatted correctly for consumption in any of these contexts and adheres to the expectations of each protocol’s parser.

To support this flexibility, the module will also include utilities for handling RTP payload types, formatting and parsing reference clock attributes, and possibly extending support for future AES67-related attributes as the standard evolves. The end goal of this design is to provide a minimal yet complete SDP subsystem that enables seamless integration with AES67-compatible devices and infrastructure.

Required Types and Functions

To support this specification, libAES67 should define:

Core Data Types

  • aes67_sdp_session_t: Represents a full SDP session including origin, timing, connection info, and media entries.
  • aes67_sdp_origin_t: Models the o= line: session owner/creator and session ID/version.
  • aes67_sdp_connection_t: Represents the c= line: IP address, TTL, and network type.
  • aes67_sdp_timing_t: Holds the t= line: start and stop time of the session.
  • aes67_sdp_bandwidth_t: Optional b= bandwidth modifiers (e.g., AS, CT).
  • aes67_sdp_media_t: Models the m= media line with port, protocol, payloads, and attributes.
  • aes67_sdp_attribute_t: Represents a= attributes like rtpmap, ptime, ts-refclk, etc.
  • aes67_sdp_codec_t: Holds codec information parsed from rtpmap or payload type fields.
  • aes67_sdp_ptime_t: Holds packetization time (ptime) information.
  • aes67_sdp_mediaclk_t: Parses and stores mediaclk: attribute values.
  • aes67_sdp_clockref_t: Parses and stores ts-refclk: attribute values (PTP clock format).

Enumerations

  • aes67_sdp_media_type_t: Enumerated types of media (e.g., AUDIO, VIDEO).
  • aes67_sdp_proto_t: Enumerated transport protocols (e.g., RTP/AVP).
  • aes67_sdp_attr_type_t: Enumerated known attribute types like rtpmap, ptime, ts-refclk.
  • aes67_clockref_type_t: Specifies the type of reference clock (ptp, ntp, etc.).
  • aes67_mediaclk_type_t: Defines clock distribution type (direct, sender, etc.).
  • aes67_sdp_parse_result_t: Used to indicate parsing or validation outcomes (OK, INVALID, UNSUPPORTED, etc.)
  • aes67_sdp_codec_format_t: Classifies codec formats (L16, L24, OPUS, etc.).

SDP Lifecycle Functions

  • aes67_sdp_parse(const char* sdp_text, aes67_sdp_session_t* out): Parses raw SDP text into a structured aes67_sdp_session_t object.
  • aes67_sdp_validate(const aes67_sdp_session_t* session): Verifies that a parsed session complies with AES67, including codec, channel count, and clock format.
  • aes67_sdp_generate(const aes67_sdp_session_t* session, char* out_text, size_t max_len): Serializes a session back into SDP-compliant text.
  • aes67_sdp_free(aes67_sdp_session_t* session): Frees memory allocated for dynamic arrays or strings within the session.

Attribute, Codec, Media Utilities

  • aes67_sdp_attribute_find(const aes67_sdp_media_t*, const char* key): Returns the attribute matching a key name in a given media section.
  • aes67_sdp_attribute_copy(...): Performs a safe copy between two attribute structs.
  • aes67_sdp_media_add_attribute(...): Adds or replaces a new attribute line under a specific media section.
  • aes67_sdp_codec_equals(const aes67_sdp_codec_t*, const aes67_sdp_codec_t*): Compares two codecs for equality in encoding, clock, and channels.
  • aes67_sdp_get_payload_type(const aes67_sdp_media_t*): Returns the RTP payload number for the media description.
  • aes67_sdp_payload_type_to_codec(int pt, aes67_sdp_codec_t* out): Maps an integer payload type to a codec struct (e.g., 96L24/48000/2).
  • aes67_sdp_codec_to_payload_type(const aes67_sdp_codec_t* codec): Maps a codec struct back to a dynamic or static payload type number.

Clock Handling Functions

  • aes67_sdp_parse_clockref(const char* line, aes67_sdp_clockref_t* out): Parses the ts-refclk line into structured clock reference info.
  • aes67_sdp_parse_mediaclk(const char* line, aes67_sdp_mediaclk_t* out): Parses the mediaclk line and determines clock mode.
  • aes67_sdp_is_ptp_clock(const char* ref)AES67_IS_PTP_CLOCK: Boolean helper that returns true if the clock string uses a PTP format.
  • aes67_sdp_format_clockref(const aes67_sdp_clockref_t*, char* out, size_t len): Converts a structured clockref into a textual a=ts-refclk: line.
  • aes67_sdp_format_mediaclk(const aes67_sdp_mediaclk_t*, char* out, size_t len): Converts a mediaclk struct into a valid a=mediaclk: SDP attribute.

Line & Field Formatters

  • aes67_sdp_origin_to_string(const aes67_sdp_origin_t*, char* out, size_t len): Converts an origin struct into an o= line.
  • aes67_sdp_connection_to_string(const aes67_sdp_connection_t*, char* out, size_t len): Converts a connection struct into a c= line.
  • aes67_sdp_media_to_string(const aes67_sdp_media_t*, char* out, size_t len): Converts a single media section into full m= and a= block.
  • aes67_sdp_session_to_string(const aes67_sdp_session_t*, char* out, size_t len): Serializes the entire session into a human-readable SDP block.

Parsing Internals & Debug

  • aes67_sdp_parse_line(const char* line, char* type_out, char* value_out): Splits one SDP line into its type character and value string.
  • aes67_sdp_is_multicast(const aes67_sdp_connection_t*): Returns true if the c= address is in a multicast range (224.x or ff::/8).
  • aes67_sdp_is_valid_clock_format(const char* value): Lightweight syntax check for ts-refclk and mediaclk.
  • aes67_sdp_normalize_line_endings(char* text): Ensures all SDP line endings follow \n or \r\n consistently.
  • aes67_sdp_dump(const aes67_sdp_session_t*, FILE* out): Prints debug information for a parsed session (e.g., in test suite).
  • aes67_sdp_error_to_string(aes67_sdp_parse_result_t): Converts error codes into readable strings for debugging and logging.

Advanced Utilities

  • aes67_sdp_clone_session(const aes67_sdp_session_t* src, aes67_sdp_session_t* dst): Performs a deep copy of a full session, including attributes and media.
  • aes67_sdp_strip_session_fields(aes67_sdp_session_t* session): Removes optional or dynamic fields before SDP re-serialization.
  • aes67_sdp_append_attribute(aes67_sdp_media_t* media, const char* key, const char* value): Safely appends an attribute to a media section, growing storage if needed.

Compatibility Flags

  • aes67_sdp_profile_t: Enumeration for SDP behavior: AES67_PROFILE_STRICT, AES67_PROFILE_FRIENDLY, AES67_PROFILE_CORRECTIVE

Constants & Macros

  • AES67_CLOCK_RATE: Specifies the fixed clock rate for AES67 audio RTP streams.
  • AES67_CHANNELS_MIN: Minimum number of audio channels permitted in AES67.
  • AES67_CHANNELS_MAX: Maximum number of audio channels permitted.
  • AES67_MAX_MEDIA: Maximum number of m= media blocks in a single SDP session.
  • AES67_MAX_ATTR_LEN: Maximum combined length of an SDP a= line (key + value).
    alue.
  • AES67_SDP_LINE_MAX: Maximum character length of a single SDP line. Used for safe parsing and buffer allocation.
  • AES67_SDP_ATTR_KEY_MAXLEN: Maximum number of characters for the attribute key in a= lines.
  • AES67_SDP_ATTR_VALUE_MAXLEN: Maximum number of characters for the attribute value in a= lines.
  • AES67_SDP_MAX_LINES: Upper bound on number of lines in a single SDP description. Prevents runaway parsing or malformed blobs.
  • AES67_DEFAULT_SESSION_NAME: Used for the s= field if no session name is provided.
  • AES67_SDP_VERSION: SDP protocol version.
  • AES67_SDP_NETWORK_TYPE: Network type used in o= and c= lines.
  • AES67_SDP_ADDRESS_TYPE: Address type used in o= and c= lines.
  • AES67_SDP_MEDIA: Media type used in m= lines.
  • AES67_IS_MULTICAST_ADDR(ip): Macro that evaluates whether an IPv4 address is multicast. Checks if the first byte is in 224.0.0.0/4.
  • AES67_IS_MULTICAST_ADDR_V6(ip6): Returns true if the provided IPv6 address string falls within the ff00::/8 range, indicating an IPv6 multicast address as defined by RFC 4291 §2.7.
  • AES67_IS_PTP_CLOCK(ref): Returns true if a ts-refclk attribute value begins with ptp=, as per RFC 7273.

Affected Layer

sdp

Alternatives Considered

None

Impact

Adding SDP handling to libAES67 will greatly improve interoperability with AES67-compliant systems and popular AoIP technologies like Dante and Ravenna. It enables seamless parsing and generation of SDP messages for stream discovery and session negotiation via SAP, SIP, and RTSP.

This feature ensures AES67 compliance through validation of codec, clock, and channel parameters, enhancing robustness. It also provides a strong foundation for future extensions such as SIP call control and RTSP media browsing.

References

Additional Notes

This proposal is part of a larger effort to enhance AES67 interoperability; feedback and contributions are welcome.

Is there an existing proposal for this?

  • I have searched the existing proposals

Metadata

Metadata

Assignees

Labels

P3Blocking or urgentcompilance: interopWorks with third-party AES67 systemscompilance: sdpSDP-related spec conformancelayer: apiPublic-facing C API (headers, symbols)layer: buildBuild system (CMake, Makefiles, flags)layer: sdpSDP parsing, generationplatform: crossAffects all or multiple platformsplatform: linuxAffects Linux-specific codeplatform: macosAffects macOS-specific codeplatform: windowsAffects Windows-specific codetype: featureNew functionality to be added

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions