#include "aes67_sdp_sap.h" #include #include #include "aes67_cfg.h" #include "aes67_net.h" #include "aes67_ptp.h" #include "aes67_web.h" #include "esp_netif.h" #define SDP_MAX 1024 // Same lines, in the same order, as the SDP preview in web/index.html. size_t aes67_sdp_build(char *buf, size_t size) { cJSON *a = cfg_get("aes67"); cJSON *p = cfg_get("ptp"); if (!a || !p) { cJSON_Delete(a); cJSON_Delete(p); return 0; } #define NUM(o, k) cJSON_GetObjectItemCaseSensitive(o, k)->valuedouble #define STR(o, k) cJSON_GetObjectItemCaseSensitive(o, k)->valuestring char ip[16] = "0.0.0.0"; esp_netif_ip_info_t info; esp_netif_t *netif = aes67_net_netif(); if (netif && esp_netif_get_ip_info(netif, &info) == ESP_OK && info.ip.addr) { snprintf(ip, sizeof(ip), IPSTR, IP2STR(&info.ip)); } char gm[24]; if (!aes67_ptp_gm_id(gm)) { strcpy(gm, "00-00-00-00-00-00-00-00"); } int ch = (int)NUM(a, "channels"); char info_ch[16]; snprintf(info_ch, sizeof(info_ch), ch == 1 ? "mono" : ch == 2 ? "stereo" : "%d ch", ch); int dom = (int)NUM(p, "domain"); int pt = (int)NUM(a, "pt"); int n = snprintf(buf, size, "v=0\r\n" "o=- %.0f %.0f IN IP4 %s\r\n" "s=%s\r\n" "c=IN IP4 %s/%d\r\n" "t=0 0\r\n" "a=clock-domain:PTPv2 %d\r\n" "m=audio %d RTP/AVP %d\r\n" "i=%s\r\n" "a=rtpmap:%d %s/%d/%d\r\n" "a=recvonly\r\n" "a=ptime:%g\r\n" "a=ts-refclk:ptp=IEEE1588-2008:%s:%d\r\n" "a=mediaclk:direct=%.0f\r\n", NUM(a, "session_id"), NUM(a, "session_ver"), ip, STR(a, "name"), STR(a, "mcast"), (int)NUM(a, "ttl"), dom, (int)NUM(a, "port"), pt, info_ch, pt, STR(a, "encoding"), (int)NUM(a, "rate"), ch, NUM(a, "ptime"), gm, dom, NUM(a, "clk_offset")); #undef NUM #undef STR cJSON_Delete(a); cJSON_Delete(p); return n > 0 && (size_t)n < size ? (size_t)n : 0; } static esp_err_t sdp_get(httpd_req_t *req) { char buf[SDP_MAX]; size_t len = aes67_sdp_build(buf, sizeof(buf)); if (!len) { return httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "SDP build failed"); } httpd_resp_set_type(req, "application/sdp"); httpd_resp_set_hdr(req, "Cache-Control", "no-store"); return httpd_resp_send(req, buf, len); } esp_err_t aes67_sdp_sap_init(void) { static const httpd_uri_t uri = { .uri = "/stream.sdp", .method = HTTP_GET, .handler = sdp_get }; return web_register_uri(&uri); }