{"id":13418187,"url":"https://github.com/tschiemer/aes67","last_synced_at":"2026-04-04T23:38:18.176Z","repository":{"id":49769836,"uuid":"328144919","full_name":"tschiemer/aes67","owner":"tschiemer","description":"Framework for AES67 targeting embedded devices // WORK IN PROGRESS","archived":false,"fork":false,"pushed_at":"2023-02-24T15:20:06.000Z","size":920,"stargazers_count":57,"open_issues_count":1,"forks_count":4,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-07-31T22:41:45.946Z","etag":null,"topics":["aes67","ravenna","rtp","sap","sdp"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tschiemer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-01-09T11:59:51.000Z","updated_at":"2024-07-06T11:08:19.000Z","dependencies_parsed_at":"2024-10-26T14:06:37.607Z","dependency_job_id":"18751f20-673e-4849-b041-64afa5d91937","html_url":"https://github.com/tschiemer/aes67","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tschiemer%2Faes67","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tschiemer%2Faes67/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tschiemer%2Faes67/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tschiemer%2Faes67/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tschiemer","download_url":"https://codeload.github.com/tschiemer/aes67/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243681024,"owners_count":20330152,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aes67","ravenna","rtp","sap","sdp"],"created_at":"2024-07-30T22:00:59.440Z","updated_at":"2026-04-04T23:38:18.140Z","avatar_url":"https://github.com/tschiemer.png","language":"C","funding_links":[],"categories":["C"],"sub_categories":[],"readme":"# aes67\nFramework for AES67 targeting embedded devices.\n\nWORK IN PROGRESS\n\nDesigned in particular to be employed on embedded devices and thus not relying on dynamic memory allocation (although optionally possible where meaningful), tight control over memory usage, no dependencies on external libraries, in particular as few hardware/library abstractions are used as possible - the framework will have to be adapted according to needs.\n\nComponents are intended to be as minimal as possible to allow for essential AES67 operations and be as interoperable as possible - in detail this is not yet clear and requires further investigation into different manufacturer-dependent implementations.\n\n\n\nhttps://github.com/tschiemer/aes67\n\n## Rough feature/support roadmap\n\n- Clock / Synchronisation\n  - [ ] PTPv2 / IEEE1588-2008 (as per AES67-2018)\n  - [ ] PTPv1 / IEEE1588-2002 ?\n  - [ ] PTPv2.1 / IEEE1588-2019 ?\n  - [ ] IEEE802.1AS-2011 ?\n  \n\n- Discovery \u0026 | Management\n  - [x] SAP (required for broader interoperability)\n    - [x] ~~zlib (de-)compression support?~~ -\u003e interface for external implementation\n    - [x] ~~authentication support?~~ -\u003e interface for external implementation\n  - [x] SDP\n  - [ ] SIP ? (for unicast management according to standard, but most systems use multicast only..)\n  - [ ] RTSP ? (meaningful for system with Ravenna-based components if no RAV2SAP)\n    - [ ] make utility implementation embedded friendly\n  - [ ] [AES70/OCA](https://github.com/tschiemer/ocac) *work in progress*\n    - [x] [mDNS / DNS-SD](https://github.com/tschiemer/minimr)\n\n\n- Stream\n  - [ ] RTP\n  - [ ] RTCP\n\n  \n- Command line / developer utilities\n  - SAP\n    - [x] [sap-pack](#sap-pack): create SAP message(s)\n    - [x] [sap-unpack](#sap-unpack): parse SAP message(s) \n    - [ ] [sapd](#sapd): SAP daemon (with Ravenna support)\n      - [x] SAP server\n      - [x] RAV lookup + pass to SAP server\n      - [x] publish SDP files from config dir\n      - [x] RAV publish of locally managed sessions \n  - SDP\n    - [x] [sdp-parse](#sdp-parse): parse SDP(s)\n    - [x] [sdp-gen](#sdp-gen): generate SDP\n  - RTSP/HTTP\n    - [x] [rtsp-describe](#rtsp-describe): retrieve SDP from RTSP service\n    - [ ] ~~rtsp/http combo server?~~ -\u003e [rav-publish](#rav-publish)\n  - RAVENNA\n    - [ ] ~~RAV2SAP~~ -\u003e [sapd](#sapd)\n    - [x] [rav-lookup](#rav-lookup): browse for sessions/devices\n    - [x] [rav-publish](#rav-publish): publish sessions and optionally serve SDP files\n  - PTP\n    - [ ] ptp-monitor? -\u003e [ptptrackhound](https://www.ptptrackhound.com/) \u0026 [ptpmonkey](https://github.com/martim01/ptpmonkey)\n    - [ ] ptp-server?\n  - RTP/RTCP\n    - [ ] rtp-send: send RTP (from STDIN)\n    - [ ] rtp-recv: receive RTP (to STDOUT)\n  - Support\n    - [x] mDNS (abstraction for mdns service)\n      - [x] dns-sd\n      - [x] avahi (to be tested further)\n    - [x] RTSP describe client + server\n    \n  \n\n## In a Nutshell\n\nAspects of AES67 and the implementation considerations within this framework.\n\n*Disclaimer: my understanding as someone learning about AES67 still might not be error free, please drop me a line if you see something wrong.*\n\n### Clock / Synchronisation\n\nAES67 devices are ment to synchronize their local clocks through PTPv2 (IEEE 1588-2008) which foresees\na *best* (grand-)master clock telling all slaved devices the current time.  \nThis local clock will slightly drift with respect to the grandmaster clock and thus the local clock\nis to adapt its effective (network) clock rate to match the grandmaster clock as good as possible.\n\nThis local (network) clock then is ment to drive the stream's media clock and implicitly any\nother audo processing components, in particular also ADCs and DACs thus achieving a tight synchronisation\nvery much like a classical wordclock (WC).\n\nIf multiple clock synchronization sources are given, say a network clock and a wordclock, the wordclock will\nlikely be more precise as there should not be any variability due to network conditions - the device would be\na rather good candidate to act as grandmaster clock and generally the WC should be preferred if the clock source\nis identical (the principle of a strictly hierarchical clock distribution with but one overall clock master\nand transitive master-slave relationships only should be respected, obviously).\n\nIs a clock or synchronization required for any type of device? Pragmatically speaking, no.\nA passive device - such as a recorder-only device - doesn't necessarily have to be synchronised\nto a clock. Assuming all senders are properly synchronised then a recorder may just\nlisten to all stream packets and store them after (optimally) aligning them in time.\n\nOptimally (realtime) playout should occur after time alignment (if multiple sources are given).\nPragmatically speaking, time alignment isn't necessary and would allow for simpler implementations,\nbut in this case audio sent at the same time would be played back at (slightly) different times\nwhich might be unwanted behaviour and - strictly speaking - somewhat beats the purpose of tight\nsynchronisation.\n\nWhat's this with *time alignment*? Well, streams can be configured with different packet\n`ptime`s (realtime duration of stream data in a packet) which implies different sizes of receive\nbuffers which implies different playout times. So, allowing different combinations of incoming \nstream configurations (w.r.t. ptime) makes implementations more complicated, because the lower\nlatency streams (smaller `ptime`) will have to adapt to the highest latency stream (`maxptime`,\nso to speak). And technically speaking, receive buffer changes (due to combining of different\nptimes) can't happen without dropping or inserting samples - which leads to the decision of\neither not aligning received streams w.r.t. time or a priori fixing a common max delay setting.\n\nNon-dedicated devices - such as computers with virtual sound cards - would seem to be an\ninteresting case to be considered w.r.t. the clock/synchronisation.\n\n### Discovery \u0026 Management\n\nDiscovery and management approaches are generally not needed - but require other (ie manual) configuration. For ease of integration such methods are generally recommended and thus considered within this framework.\n\nJoining of multicast session_data essentially requires but the joining of respective multicast group.\nSetting up a unicast session_data requires cooperation of the partners, ie some form of control protocol.\nSeemingly unicast sessions are barely in use (see [wikipedia](https://en.wikipedia.org/wiki/AES67#Adoption)).\n\n\nAES67 generally leaves the choice of discovery and management mechanism open, but it names several possibilities to be aware of:\n\n - Bonjours / mDNS (DNS-SD) is proposed in conjunction with SIP, ie the device's SIP URI / service is announced (unicast sessions)\n - SAP is proposed for announcement of *multicast* sessions\n - Axia Discovery Protocol\n - Wheatstone WheatnetIP Discovery Protocol\n - [AMWA NMOS Discovery and Registration Specification (IS-04)]( https://github.com/AMWA-TV/nmos-discovery-registration)\n\nNot mentioned, but seemingly also used in distributed products (according to [wikipedia](https://en.wikipedia.org/wiki/AES67#Adoption)):\n\n- Real-Time Streaming Protocol\n\nAs discussed elsewhere AES70 - a rather young discovery and control standard of networked audio devices - is suggested as a promising solution.\n\n*Conclusion*\n\nFor broad integration SAP seems like a general requirement for any device.\n\nFurther it is (generally) proposed to use AES70 for discovery and management, in particular because the standard is a collaborative effort and provides several meaningful features out of the box (although it is somewhat complex) beyond discovery and stream management.\n\nSIP may be considered (in the future) for management of unicast streams but it is not only barely adopted, as an (somewhat elaborate) additional service it only provides connection management.\n\nRTSP may be considered (in the future) for management of unicast streams aswell as service discovery of Ravenna streams.\n\n### Audio\n\n#### Encoding\n\nAES67 Audio is to be streamed in L16 or L24 encoding; that is, each sample is a two-, three-byte respectively signed integer\nin two's complement representation in network byte order (bigendian),\n samples are interleaved.\nThe common I2S \u0026 TDM inter-chip audio protocols  use identical formats (roughly speaking) which shall be the primary encoding focused herein.\nAES3, AES10 (MADI), AES50 are frame-based and use or can use a least-significant-bit to most-significant-bit encoding.\n\n#### Routing\n\nGiven a fixed local audio sour multicast streaming is rather straightforward.\n\nFor potential optimization multiple instances might be considered supported.\n\nIn the most simple case incoming streams might be handled similarly, ie just one\nmulticast stream might be listened to and passed on to the local output.\n\nBut if audio is to come from different sources the situation gets more complicated: either\nthe device has the capability of listening to multiple streams and extracting the necessary\nchannels or the single channels are joined on another device into a single (multicast) stream.\nObviously this would introduce further latency and make configuration more complicated.\n\nInteresting to note, even basic AES70 connection management by default \nallows for internal routing of local channels to transmitted stream channels (of a multichannel \nstream), and analogously allows for custom assignment of incoming stream channels to\nlocal output channels. Thus a receiving device should support (at most) as many streams as it\nhas internal (receiving) channels - although practically speaking there typically will be less\nsenders than relevant received channels unless each sender transmits only one relevant channel,\nso this can be constrained (thereby constraining possible system configurations).\n\nIn the sense of AES70 transmission and reception buffers are designed to provide a single\ninterface for local in- and output of channels to be processed but allowing for merging of\nmultiple stream sources into one reception buffer (discarding any unwanted audio channels).\n\n\n\n\n## Corny details\n\n### SAP\n\n- Does not support encryption.\n- Provides interfaces for zlib de-/compression. For the moment being it is assumed that compression is not used by implementations.\n- Provides interfaces for authentication.\n- Can be used as an abstract service with basic session memory (only identifiers, ie no payloads, saved) and timeout detection but can also used to parse or generate SAP messages in a standalone fashion.\n- Note: global multicast scope (224.2.127.254) vs highest address in administered scope (AES67 devices typically use **239.255.255.255**). \n  \n### SDP\n\n- Parser to/generator from internal struct.\n- Narrowed down to options and attributes as required for AES67 streams.\n- Supports relevant session- and/or media-level options (connection, ref-clock, recvonly|sendonly|inactive|sendrecv).\n- Supports multiple ptp reference clocks on both session-/media level (1588-2002/08/19, 802.1AS-2011)\n- Support for audio media with dynamic payload types *only* and L8/L16/L24/L32/AM824 (AES3) encoding media encoding.\n- Intended to support encoding and ptime negotiation - capabilities are discarded (fallback to non-negotiated configuration) if capabilities other than ptime related are offered.\n- Provides implementable interface for unhandled media, options and attributes.\n  - Media sections if non-audio and unrecognized *predefined* payload types.\n  - Unknown dynamic payload type encodings.\n- Provides implementable interface for adding custom session- or media-level attributes.\n\n## Utilities\n\nPrimarily test/developer utilities that allow for convenient testing (or simple interactions) - socat is your friend. \n\n### `sap-pack`\n```\nUsage: ./sap-pack [-h|-?] | [-a|-d] [--hash \u003chash\u003e] [-o \u003corigin-ip\u003e] [-p \u003cpayloadtype\u003e | --v1] [\u003cfile\u003e ...]\nWrites SAP packet to STDOUT.\nIf a \u003cfile\u003e is given assumes it is a single payload file.\nIf no \u003cfile\u003e is given tries to read from STDIN (if SDP payload is assumed looks for SDP start, ie \"v=0\").\nOptions:\n\t -h,-?\t\t Prints this info.\n\t -a\t\t Announcement type message (default)\n\t -d\t\t Delete type message (note: expects but an originator line)\n\t --hash \u003chash\u003e\t Force this hash id (if not given tries to extract from SDP file, session id)\n\t -o \u003corigin-ip\u003e\t Force this originating IP (if not given tries to extract from SDP file, originating addr)\n\t -p \u003cpayloadtype\u003e\t Use this particular (MIME) payload type (if not given uses 'application/sdp')\n\t --v1\t\t Use a SAPv1 packet format (implies SDP payload, allows a zero-hash, requires IPv4 origin)\n\t --xf\t\t Attempt to parse SDP payload, on fail fallback to given hash and origin-ip\n\t -v\t\t Print some basic info to STDERR\nExamples:\n./sap-pack test.sdp | socat -u - UDP4-DATAGRAM:239.255.255.255:9875\nwatch -t 300 \"./sap-pack  test.sdp | socat -u -v - UDP4-DATAGRAM:224.2.127.254:9875\"\n```\nNote that you can improvise a SAP server that just broadcasts SDPs regularly :)\n\n### `sap-unpack`\n```\nUsage: ./sap-unpack [-h?ad]\nAttempts to parse SAP packets incoming on STDIN and prints to STDOUT in the following format:\n\t (announce|delete) \u003chash\u003e \u003cip\u003e \u003cpayload-type\u003e\n\t \u003cpayload-data\u003e\n\t \u003cnewline\u003e\nOptions:\n\t -a\t Print SAP headers\n\t -d\t Print basic dbg info to STDERR\n\t -h,-?\t Prints this help.\nExamples:\nsocat -u UDP4-RECVFROM:9875,ip-add-membership=239.255.255.255:192.168.1.122,reuseport,reuseaddr,fork - | ./sap-unpack -a\n```\n\n### `sapd`\n```\nUsage: ./sapd [-h|-?] | [-d] [-p \u003cport\u003e] [--l \u003cmcast-scope\u003e] [--s \u003cmcast-scope\u003e] [--ipv6-if \u003cifname\u003e] ..\nStarts an (SDP-only) SAP server that maintains incoming SDPs, informs about updates and keeps announcing\nspecified SDPs on network.\nCommunicates through local port (/var/run/sapd.sock)\nLogs to syslog (identity sapd.d)\n\nOptions:\n\t -h,-?\t\t Prints this info.\n\t -d,--daemonize\t Daemonize\n\t -v\t\t Also print syslog to STDERR\n\t -p,--port \u003cport\u003e\n\t\t\t Listen/send on this port (default 9875)\n\t --l\u003cmcast-scope\u003e, --s\u003cmcast-scope\u003e\n\t\t\t Listens, sends respectively on these IPv4/6 multicast scopes (multiple possible). Scopes:\n\t\t\t\t 4g\t IPv4 SAP global (224.2.127.254)\n\t\t\t\t 4a\t IPv4 SAP administered (239.255.255.255)\n\t\t\t\t 6ll\t IPv6 SAP link local (FF02::2:7FFE)\n\t\t\t\t 6ip4\t IPv6 SAP ip4 scope local (FF03::2:7FFE)\n\t\t\t\t 6al\t IPv6 SAP admin local (FF04::2:7FFE)\n\t\t\t\t 6sl\t IPv6 SAP site local (FF05::2:7FFE)\n\t\t\t Default listen: 4a\n\t\t\t Default send: 4a\n\t --ipv6-if\t IPv6 interface to listen on (default interface can fail)\n\t --sdp-dir \u003cpath\u003e\t Load all .sdp files from given directory on startup (equal to dynamically adding them)\n\t --rav\t\t Enable Ravenna session lookups\n\t --rav-no-autopub\n\t\t\t Disable automatic publishing of discovered ravenna sessions\n\t --rav-pub-delay \u003cdelay-sec\u003e\n\t\t\t Wait for this many seconds before publishing discovered ravenna sessions\n\t\t\t through SAP (0 .. 360, default 5)\n\t --rav-upd-interval \u003cinterval-sec\u003e\n\t\t\t Wait for this many seconds checking for SDP change of already published\n\t\t\t ravenna device (0 .. 360, default 0)\n\t --rav-no-handover\n\t\t\t Discovered ravenna session that are also found through SAP will NOT give\n\t\t\t up local management (ie will NOT continue to announce sessions).\t --rav-disable-server\n\t\t\t Generally disables Ravenna service announcements and RTSP server (default enabled).\n\t --rav-server-port \u003cport\u003e\n\t\t\t Port on which to start RTSP server to server SDP files (default 9191).\n\t --rav-no-autoannounce\n\t\t\t Local services will not be automatically announced as ravenna services and\n\t\t\t made available through the built in RTSP server (default enabled).\n\nCompile time options:\n\t AES67_SAP_MIN_INTERVAL_SEC \t 30 \t // +- announce time, depends on SAP traffic\n\t AES67_SAP_MIN_TIMEOUT_SEC \t 600\n\t AES67_SAPD_WITH_RAV \t\t 1 \t // Ravenna sessions supported?\n\nExamples:\nsudo ./sapd -v --ipv6-if en7\nsudo ./sapd -v --sdp-dir /usr/local/my-sdp-files\nsudo ./sapd -v --sdp-dir /usr/local/my-sdp-files --rav\nsudo ./sapd -v --rav --rav-no-autopub --rav-no-autoannounce # rav sessions managed through local sock\nsocat - UNIX-CONNECT:/var/run/sapd.sock,keepalive # to connect to local sock\n```\nA SAP daemon with a local client interface that supports local registration of sessions\naswell as lookup and injection of ravenna based sessions - somewhat like [RAV2SAP](https://www.ravenna-network.com/aes67/rav2sap/).\n\n*yet requires field testing (feel free)*\n\nEssentially any connection to the AF_LOCAL socket is considered a subscription and will receive updates but allows also\nfor registration and deletion of locally managed sessions (SDP files).\n\nFor documentation of protocol/interface used through AF_LOCAL sockets, see [src/include/aes67/utils/sapd.h](src/include/aes67/utils/sapd.h).\n\n(note: AES67-2018 is specified for IPv4 primarily, consider IPv6 a proof of concept and for other purposes..)\n\n---\n\nThe original [RAV2SAP](https://www.ravenna-network.com/aes67/rav2sap/) essentially is intended to translate RAVENNA-style mDNS-based\ndiscovery into SAP-based discovery (but also allowing for a managed point of manual SDP management).\n\nIt is somewhat straightforward as in:\n\n1. listen to mDNS services\n2. get SDP of discovered streams\n3. and pass to SAP\n\nTo improvise something to the same effect without the use of `sapd` you can also make use of utilities given herein:\n\n```bash \nrav-lookup -v | rtsp-describe -v | sap-pack -v | socat -u - UDP4-DATAGRAM:224.2.127.254:9875\n```\n\nNote: the `-v` option just helps to trace what's happening.\n\nAlso note multicast global scope (224.2.127.254) vs. administered scope which devices typically assume to be\n239.255.255.255.\n### `sdp-parse`\n\n```\nUsage: ./sdp-parse ([-h?] | [-t [-brc]])\nAttempts to parse SDP incoming on STDIN (primarily useful to validate SDP files quickly).\nOptions:\n\t -h\t Prints this info\n\t -d\t Prints some debug info to STDERR\n\t -t\t Test if the first (SDP) packet (and only the first) contains at least one valid stream; return 0 if valid, \u003e0 otherwise\n\t -b\t Filter by bitwidth/encoding (8/16/24/32/AM824, representing L8, L16, L24, L32, AM824 respectively)\n\t -r\t Filter by sampling rate (frequency); ex. 48000\n\t -c\t Filter by number of channels required\n```\n\n### `sdp-gen`\n```\nUsage:\n\t ./sdp-gen [-h?]\n\t ./sdp-gen [options...] \u003csrc-host\u003e \u003cdst-ip\u003e[:\u003crtp-port\u003e]\nGenerator for quick and dirty single-stream SDP generation.\nArguments:\n\t \u003csrc-host\u003e\t\t\t IPv4/v6 or hostname of SDP originator host (see --src-ipver to explicitly set ip version)\n\t \u003ctarget-ip-port\u003e\t\t IPv4/v6 of sending/receiving host\nOptions:\n\t -h, -?\t\t\t\t Prints this info\n\t --src-ipver \u003cipver\u003e\t\t Explicitly sets SDP originator IP version (4, default, or 6)\n\t --id \u003cid\u003e\t\t\t Session ID (U32, default 1)\n\t --version \u003cversion\u003e\t\t Session version (U32, default 1)\n\t -n, --name \u003cname\u003e\t\t Name of session (default none)\n\t -i, --info \u003cinfo\u003e\t\t Further session info (default none)\n\t --ptp-domain \u003cdomain\u003e\t\t (RAVENNA) PTP domain (u7, default none)\n\t -m, --mode \u003cmode\u003e\t\t Stream mode, most likely you will use \"recv\" (default, for recipient to be receiving only, ie you will be sending)\n\t -b \u003cbitrate\u003e\t\t\t 'Bitrate' of encoding, values 8/16/24/32/AM824 accepted only (default 24)\n\t -r \u003crate\u003e\t\t\t Samplerate (default 48000)\n\t -c \u003cnchannels\u003e\t\t\t Number of channels (default 2)\n\t --ttl \u003cttl\u003e\t\t\t IPv4 multicasting TTL override (default 32)\n\t --ptime \u003cptime\u003e\t\t ptime value as millisec float (default 1.0)\n\t --refclk-localmac \u003cmac\u003e\t Ethernet MAC (XX-XX-XX-XX-XX)\n\t --ptp-traceable\t\t Default reference clock!\n\t --ptp-clock \u003cptp-std\u003e:\u003cptp-eui64\u003e[:\u003cptp-domain\u003e]\n\t\t \u003cptp-std\u003e := 1588-2002|1588-2008|1588-2019|802.1AS-2011\n\t\t \u003cptp-eui64\u003e := XX-XX-XX-XX-XX-XX-XX-XX\n\t --mediaclk-offset \u003coffset\u003e\t Mediaclock offset (default 0)\n```\nWith default settings for command `./sdp-gen 10.0.0.2 224.0.0.12`:\n```\nv=0\no=- 1 1 IN IP4 10.0.0.2\ns=\nc=IN IP4 224.0.0.1/32\nt=0 0\na=tool:caes67\na=ts-refclk:ptp=traceable\na=recvonly\nm=audio 5004 RTP/AVP 96\na=rtpmap:96 L24/48000/2\na=ptime:1\na=mediaclk:direct=0\n```\n\n### `rtsp-describe`\n```\nUsage: ./rtsp-describe [-r] [\u003crtsp-url\u003e]\nAttempts to retrieve SDP header from given RTSP URL(s) (rtsp://\u003chost\u003e[:\u003cport\u003e][\u003cresource\u003e])\nand prints to STDOUT. If no \u003crtsp-url\u003e is given assumes there will be one rtsp-url per line\non STDIN.\nOptions:\n\t -h,-?\t Prints this info\n\t -r\t Prints RTSP header info to STDERR\nExample:\n./rtsp-describe -r rtsp://192.168.2.138:9090/by-name/here-be-kittens-ravenna_1\n```\nNote that there is also a quick and dirty script for this, although it is less reliable.\n\n### `rav-lookup`\n```\nUsage: rav-lookup [-h?] | [-v] [-s|--sessions] [-d|--devices] [--receivers] [--senders] [--filter (disco|term)] [-n]\nOutputs any found session, receivers or senders as found per mDNS requests to STDOUT.\nOne result per line:\n\tsession: rtsp://\u003chost\u003e:\u003cport\u003e/by-name/\u003csession-name\u003e\n\tsenders: rtsp://\u003chost\u003e:\u003cport\u003e\n\treceivers: http://\u003chost\u003e:\u003cport\u003e\nIf neither type is explicitly requested, looks for sessions only.\nOptions:\n\t -h,-?\t\t Outputs this info\n\t -v\t\t Some status output to STDERR\n\t -s,--sessions\t Browse for sessions\n\t --receivers\t Browse for receiving devices\n\t --senders\t Browse for sending devices\n\t -d,--devices\t Browse for senders and receivers (shortcut for --receivers --senders)\n\t -f,--filter (disco|term)\n\t\t\t Show discovered or terminated services only (default disco)\n\t -n, --no-enc\t Do not urlencode (session name, ie print as is)\n```\nJust a comfort utility, using `dns-sd` you could also discover services:\n\n```bash\n# sessions -\u003e rtsp://\u003chost\u003e:\u003cport\u003e/by-name/\u003cravenna-session-name\u003e\ndns-sd -Z _rtsp._tcp,_ravenna_session\n\n# general ravenna compatible devices\ndns-sd -Z _rtsp._tcp,_ravenna\ndns-sd -Z _http._tcp,_ravenna\n```\nOr similarly using `avahi-browse`\n```bash\navahi-browse -r _ravenna_session._sub._rtsp._tcp\navahi-browse -r _ravenna._sub._rtsp._tcp\navahi-browse -r _ravenna._sub._http._tcp\n```\n\n### `rav-publish`\n\n```\nUsage: ./rav-publish [-h?] | [-v] [-p \u003crtsp-port\u003e] [[--host \u003chost\u003e] [--ip \u003cip\u003e] | [--no-rtsp]] \u003csdp-file1\u003e ...\nSets up Ravenna style discovery mechanism for provided SDP files.\nBy default sets up a mini-RTSP server serving the given session descriptions.\nOptions:\n\t -h,-?\t\t Outputs this info\n\t -v\t\t Some status output to STDERR\n\t -p, --port \u003crtsp-port\u003e\t  Port of RTSP server.\n\t --host \u003chost\u003e\t Host of target device (by default will assume self; if given will try to use originator IPv4/6 from SDP file).\n\t --ip \u003cip\u003e\t (Override) IPv4/6 address of target device (create an record for host).\n\t --no-rtsp\t Do not start a RTSP server.\n\t --http \u003croot\u003e\t Start a http server with given root dir (implies RTSP server)\n\t --http-index \u003cindex-file\u003e Index file to serve from directories (default index.html)\nExamples\n./rav-publish -p 9191 --no-rtsp my-session.sdp another-session.sdp\nscripts/html-index.sh sdp.d \u003e\u003e sdp.d/index.html \u0026\u0026 ./rav-publish -p 9191 --http sdp.d sdp.d/*.sdp\n```\n\nTo quickly register a (test) ravenna session with name `Hello my pretty` on the localhost's port 9191:\n```bash\ndns-sd -R \"Hello my pretty\" _rtsp._tcp,_ravenna_session local 9191\navahi-publish -s \"Hello my pretty\" _rtsp._tcp 9191 --sub _ravenna_session._sub._rtsp._tcp\n```\n\nPlease note, that actual Ravenna devices expect to find an actual RTSP service on said host and port\nwith an SDP resource retrievable through an RTSP *DESCRIBE* request for URI `/by-name/Hello%20my%20pretty`\n(URL encoded session name).\n\n## References\n\n- [AES67-2018 Standard document](https://www.aes.org/publications/standards/search.cfm?docID=96)\n- [IEEE1558-2019 (PTPv2.1) Standard document](https://standards.ieee.org/content/ieee-standards/en/standard/1588-2019.html)\n- https://en.wikipedia.org/wiki/AES67\n- https://hartung.io/2020/07/aes67-resources/ (nice collection of resources)\n\n## License\n\nCopyright (C) 2021  Philip Tschiemer\n\nGNU Affero General Public License v3\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftschiemer%2Faes67","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftschiemer%2Faes67","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftschiemer%2Faes67/lists"}