X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fstream_output%2Fsdp.c;h=82be7910c3083d275047bf8af245c0efcb61ec04;hb=4d17700cc4d49410acdb29ed3968d69408489526;hp=7cb4420ba500606b41b1cac575e958f3b9f5f4e1;hpb=3ce51320ea315d088049a672bc9fe8b308b3a4fa;p=vlc diff --git a/src/stream_output/sdp.c b/src/stream_output/sdp.c index 7cb4420ba5..82be7910c3 100644 --- a/src/stream_output/sdp.c +++ b/src/stream_output/sdp.c @@ -12,15 +12,20 @@ * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include +#include #include #include #include @@ -86,16 +91,20 @@ static vlc_bool_t IsSDPString (const char *str) } -char *StartSDP (const char *name, const char *description, const char *url, - const char *email, const char *phone, vlc_bool_t ssm, - const struct sockaddr *orig, socklen_t origlen, - const struct sockaddr *addr, socklen_t addrlen) +static +char *sdp_Start (const char *name, const char *description, const char *url, + const char *email, const char *phone, + const struct sockaddr *src, size_t srclen, + const struct sockaddr *addr, size_t addrlen) { - uint64_t t = NTPtime64 (); - char *sdp, machine[MAXSDPADDRESS], conn[MAXSDPADDRESS], + uint64_t now = NTPtime64 (); + char *sdp; + char connection[MAXSDPADDRESS], hostname[256], sfilter[MAXSDPADDRESS + sizeof ("\r\na=source-filter: incl * ")]; const char *preurl = "\r\nu=", *premail = "\r\ne=", *prephone = "\r\np="; + gethostname (hostname, sizeof (hostname)); + if (name == NULL) name = "Unnamed"; if (description == NULL) @@ -109,18 +118,21 @@ char *StartSDP (const char *name, const char *description, const char *url, if (!IsSDPString (name) || !IsSDPString (description) || !IsSDPString (url) || !IsSDPString (email) || !IsSDPString (phone) - || (AddressToSDP (orig, origlen, machine) == NULL) - || (AddressToSDP (addr, addrlen, conn) == NULL)) + || (AddressToSDP (addr, addrlen, connection) == NULL)) return NULL; - if (ssm) - sprintf (sfilter, "\r\na=source-filter: incl IN IP%c * %s", - machine[5], machine + 7); - else - *sfilter = '\0'; + strcpy (sfilter, ""); + if (srclen > 0) + { + char machine[MAXSDPADDRESS]; + + if (AddressToSDP (src, srclen, machine) != NULL) + sprintf (sfilter, "\r\na=source-filter: incl IN IP%c * %s", + machine[5], machine + 7); + } if (asprintf (&sdp, "v=0" - "\r\no=- "I64Fu" "I64Fu" %s" + "\r\no=- "I64Fu" "I64Fu" IN IP%c %s" "\r\ns=%s" "\r\ni=%s" "%s%s" // optional URL @@ -138,60 +150,160 @@ char *StartSDP (const char *name, const char *description, const char *url, "\r\na=charset:UTF-8" "%s" // optional source filter "\r\n", - /* o= */ t, t, machine, + /* o= */ now, now, connection[5], hostname, /* s= */ name, /* i= */ description, /* u= */ preurl, url, /* e= */ premail, email, /* p= */ prephone, phone, - /* c= */ conn, + /* c= */ connection, /* source-filter */ sfilter) == -1) return NULL; return sdp; } -char *vMakeSDPMedia (const char *type, int dport, const char *protocol, - unsigned pt, const char *rtpmap, - const char *fmtpfmt, va_list ap) +static char * +vsdp_AddAttribute (char **sdp, const char *name, const char *fmt, va_list ap) +{ + size_t oldlen = strlen (*sdp); + size_t addlen = sizeof ("a=\r\n") + strlen (name); + + if (fmt != NULL) + { + va_list aq; + + va_copy (aq, ap); + addlen += 1 + vsnprintf (NULL, 0, fmt, aq); + va_end (aq); + } + + char *ret = realloc (*sdp, oldlen + addlen); + if (ret == NULL) + return NULL; + + oldlen += sprintf (ret + oldlen, "a=%s", name); + if (fmt != NULL) + { + ret[oldlen++] = ':'; + oldlen += vsprintf (ret + oldlen, fmt, ap); + } + + strcpy (ret + oldlen, "\r\n"); + return *sdp = ret; +} + + +char *sdp_AddAttribute (char **sdp, const char *name, const char *fmt, ...) +{ + char *ret; + va_list ap; + + va_start (ap, fmt); + ret = vsdp_AddAttribute (sdp, name, fmt, ap); + va_end (ap); + + return ret; +} + + +char *sdp_AddMedia (char **sdp, + const char *type, const char *protocol, int dport, + unsigned pt, vlc_bool_t bw_indep, unsigned bw, + const char *ptname, unsigned clock, unsigned chans, + const char *fmtp) { - char *sdp_media = NULL; + char *newsdp, *ptr; + size_t inlen = strlen (*sdp), outlen = inlen; /* Some default values */ if (type == NULL) type = "video"; - if (dport == 0) - dport = 9; if (protocol == NULL) protocol = "RTP/AVP"; assert (pt < 128u); - /* RTP payload type map */ - char sdp_rtpmap[rtpmap ? (sizeof ("a=rtpmap:123 *\r\n") + strlen (rtpmap)) : 1]; - if (rtpmap != NULL) - sprintf (sdp_rtpmap, "a=rtpmap:%u %s\r\n", pt, rtpmap); - else - *sdp_rtpmap = '\0'; + outlen += snprintf (NULL, 0, + "m=%s %u %s %d\r\n" + "b=TIAS:%u\r\n" + "b=RR:0\r\n", + type, dport, protocol, pt, bw); - /* Format parameters */ - char *fmtp = NULL; - if ((fmtpfmt != NULL) - && (vasprintf (&fmtp, fmtpfmt, ap) == -1)) + newsdp = realloc (*sdp, outlen + 1); + if (newsdp == NULL) return NULL; - char sdp_fmtp[fmtp ? (sizeof ("a=fmtp:123 *\r\n") + strlen (fmtp)) : 1]; - if (fmtp != NULL) + *sdp = newsdp; + ptr = newsdp + inlen; + + ptr += sprintf (ptr, "m=%s %u %s %u\r\n", + type, dport, protocol, pt); + if (bw > 0) + ptr += sprintf (ptr, "b=%s:%u\r\n", bw_indep ? "TIAS" : "AS", bw); + ptr += sprintf (ptr, "b=RR:0\r\n"); + + /* RTP payload type map */ + if (ptname != NULL) { - sprintf (sdp_fmtp, "a=fmtp:%u %s\r\n", pt, fmtp); - free (fmtp); + if ((strcmp (type, "audio") == 0) && (chans != 1)) + sdp_AddAttribute (sdp, "rtpmap", "%u %s/%u/%u", pt, ptname, clock, + chans); + else + sdp_AddAttribute (sdp, "rtpmap", "%u %s/%u", pt, ptname, clock); } - else - *sdp_fmtp = '\0'; + /* Format parameters */ + if (fmtp != NULL) + sdp_AddAttribute (sdp, "fmtp", "%u %s", pt, fmtp); + + return newsdp; +} + - if (asprintf (&sdp_media, "m=%s %u %s %d\r\n" "%s" "%s", - type, dport, protocol, pt, - sdp_rtpmap, sdp_fmtp) == -1) +char *vlc_sdp_Start (vlc_object_t *obj, const char *cfgpref, + const struct sockaddr *src, size_t srclen, + const struct sockaddr *addr, size_t addrlen) +{ + size_t cfglen = strlen (cfgpref); + if (cfglen > 100) + return NULL; + + char varname[cfglen + sizeof ("description")], *subvar = varname + cfglen; + strcpy (varname, cfgpref); + + session_descriptor_t *p_session = calloc (1, sizeof (*p_session)); + if (p_session == NULL) + return NULL; + + strcpy (subvar, "name"); + char *name = var_GetNonEmptyString (obj, varname); + strcpy (subvar, "description"); + char *description = var_GetNonEmptyString (obj, varname); + strcpy (subvar, "url"); + char *url = var_GetNonEmptyString (obj, varname); + strcpy (subvar, "email"); + char *email = var_GetNonEmptyString (obj, varname); + strcpy (subvar, "phone"); + char *phone = var_GetNonEmptyString (obj, varname); + + char *sdp = sdp_Start (name, description, url, email, phone, + src, srclen, addr, addrlen); + free (name); + free (description); + free (url); + free (email); + free (phone); + + if (sdp == NULL) return NULL; - return sdp_media; + /* Totally non-standard */ + strcpy (subvar, "group"); + char *group = var_GetNonEmptyString (obj, varname); + if (group != NULL) + { + sdp_AddAttribute (&sdp, "x-plgroup", "%s", group); + free (group); + } + + return sdp; }