char *sdp_AddMedia (char **sdp, const char *type, const char *protocol, int dport, unsigned pt, bool bw_indep, unsigned bw, const char *ptname, unsigned clock, unsigned chans, const char *fmtp) { char *newsdp, *ptr; size_t inlen = strlen (*sdp), outlen = inlen; /* Some default values */ if (type == NULL) type = "video"; if (protocol == NULL) protocol = "RTP/AVP"; assert (pt < 128u); 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); newsdp = realloc (*sdp, outlen + 1); if (newsdp == NULL) return 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) { 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); } /* Format parameters */ if (fmtp != NULL) sdp_AddAttribute (sdp, "fmtp", "%u %s", pt, fmtp); return newsdp; }
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); 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; strcpy (subvar, "cat"); char *cat = var_GetNonEmptyString (obj, varname); if (cat != NULL) { sdp_AddAttribute (&sdp, "cat", "%s", cat); /* Totally non-standard */ sdp_AddAttribute (&sdp, "x-plgroup", "%s", cat); free (cat); } return sdp; }
/***************************************************************************** * SDPGenerateVoD * FIXME: needs to be merged more? *****************************************************************************/ char *SDPGenerateVoD( const vod_media_t *p_media, const char *rtsp_url ) { char *psz_sdp; assert(rtsp_url != NULL); /* Check against URL format rtsp://[<ipv6>]:<port>/<path> */ bool ipv6 = strlen( rtsp_url ) > 7 && rtsp_url[7] == '['; /* Dummy destination address for RTSP */ struct sockaddr_storage dst; socklen_t dstlen = ipv6 ? sizeof( struct sockaddr_in6 ) : sizeof( struct sockaddr_in ); memset (&dst, 0, dstlen); dst.ss_family = ipv6 ? AF_INET6 : AF_INET; #ifdef HAVE_SA_LEN dst.ss_len = dstlen; #endif psz_sdp = vlc_sdp_Start( VLC_OBJECT( p_media->p_vod ), "sout-rtp-", NULL, 0, (struct sockaddr *)&dst, dstlen ); if( psz_sdp == NULL ) return NULL; if( p_media->i_length > 0 ) { lldiv_t d = lldiv( p_media->i_length / 1000, 1000 ); sdp_AddAttribute( &psz_sdp, "range"," npt=0-%lld.%03u", d.quot, (unsigned)d.rem ); } sdp_AddAttribute ( &psz_sdp, "control", "%s", rtsp_url ); /* No locking needed, the ES table can't be modified now */ for( int i = 0; i < p_media->i_es; i++ ) { media_es_t *p_es = p_media->es[i]; rtp_format_t *rtp_fmt = &p_es->rtp_fmt; const char *mime_major; /* major MIME type */ switch( rtp_fmt->cat ) { case VIDEO_ES: mime_major = "video"; break; case AUDIO_ES: mime_major = "audio"; break; case SPU_ES: mime_major = "text"; break; default: continue; } sdp_AddMedia( &psz_sdp, mime_major, "RTP/AVP", 0, rtp_fmt->payload_type, false, 0, rtp_fmt->ptname, rtp_fmt->clock_rate, rtp_fmt->channels, rtp_fmt->fmtp ); char *track_url = RtspAppendTrackPath( p_es->rtsp_id, rtsp_url ); if( track_url != NULL ) { sdp_AddAttribute ( &psz_sdp, "control", "%s", track_url ); free( track_url ); } } return psz_sdp; }