958 lines
17 KiB
C
958 lines
17 KiB
C
/**
|
|
* @file sdp/media.c SDP Media
|
|
*
|
|
* Copyright (C) 2010 Creytiv.com
|
|
*/
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <re_types.h>
|
|
#include <re_fmt.h>
|
|
#include <re_mem.h>
|
|
#include <re_mbuf.h>
|
|
#include <re_list.h>
|
|
#include <re_sa.h>
|
|
#include <re_sdp.h>
|
|
#include "sdp.h"
|
|
|
|
|
|
static void destructor(void *arg)
|
|
{
|
|
struct sdp_media *m = arg;
|
|
unsigned i;
|
|
|
|
list_flush(&m->lfmtl);
|
|
list_flush(&m->rfmtl);
|
|
list_flush(&m->rattrl);
|
|
list_flush(&m->lattrl);
|
|
|
|
if (m->le.list) {
|
|
m->disabled = true;
|
|
m->ench = NULL;
|
|
mem_ref(m);
|
|
return;
|
|
}
|
|
|
|
for (i=0; i<ARRAY_SIZE(m->protov); i++)
|
|
mem_deref(m->protov[i]);
|
|
|
|
list_unlink(&m->le);
|
|
mem_deref(m->name);
|
|
mem_deref(m->proto);
|
|
mem_deref(m->uproto);
|
|
}
|
|
|
|
|
|
static int media_alloc(struct sdp_media **mp, struct list *list)
|
|
{
|
|
struct sdp_media *m;
|
|
int i;
|
|
|
|
m = mem_zalloc(sizeof(*m), destructor);
|
|
if (!m)
|
|
return ENOMEM;
|
|
|
|
list_append(list, &m->le, m);
|
|
|
|
m->ldir = SDP_SENDRECV;
|
|
m->rdir = SDP_SENDRECV;
|
|
m->dynpt = RTP_DYNPT_START;
|
|
|
|
sa_init(&m->laddr, AF_INET);
|
|
sa_init(&m->raddr, AF_INET);
|
|
sa_init(&m->laddr_rtcp, AF_INET);
|
|
sa_init(&m->raddr_rtcp, AF_INET);
|
|
|
|
for (i=0; i<SDP_BANDWIDTH_MAX; i++) {
|
|
m->lbwv[i] = -1;
|
|
m->rbwv[i] = -1;
|
|
}
|
|
|
|
*mp = m;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* Add a media line to an SDP Session
|
|
*
|
|
* @param mp Pointer to allocated SDP Media line object
|
|
* @param sess SDP Session
|
|
* @param name Media name
|
|
* @param port Port number
|
|
* @param proto Transport protocol
|
|
*
|
|
* @return 0 if success, otherwise errorcode
|
|
*/
|
|
int sdp_media_add(struct sdp_media **mp, struct sdp_session *sess,
|
|
const char *name, uint16_t port, const char *proto)
|
|
{
|
|
struct sdp_media *m;
|
|
int err;
|
|
|
|
if (!sess || !name || !proto)
|
|
return EINVAL;
|
|
|
|
err = media_alloc(&m, &sess->lmedial);
|
|
if (err)
|
|
return err;
|
|
|
|
err = str_dup(&m->name, name);
|
|
err |= str_dup(&m->proto, proto);
|
|
if (err)
|
|
goto out;
|
|
|
|
sa_set_port(&m->laddr, port);
|
|
|
|
out:
|
|
if (err)
|
|
mem_deref(m);
|
|
else if (mp)
|
|
*mp = m;
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
/**
|
|
* Add a remote SDP media line to an SDP Session
|
|
*
|
|
* @param mp Pointer to allocated SDP Media line object
|
|
* @param sess SDP Session
|
|
* @param name Media name
|
|
* @param proto Transport protocol
|
|
*
|
|
* @return 0 if success, otherwise errorcode
|
|
*/
|
|
int sdp_media_radd(struct sdp_media **mp, struct sdp_session *sess,
|
|
const struct pl *name, const struct pl *proto)
|
|
{
|
|
struct sdp_media *m;
|
|
int err;
|
|
|
|
if (!mp || !sess || !name || !proto)
|
|
return EINVAL;
|
|
|
|
err = media_alloc(&m, &sess->medial);
|
|
if (err)
|
|
return err;
|
|
|
|
m->disabled = true;
|
|
|
|
err = pl_strdup(&m->name, name);
|
|
err |= pl_strdup(&m->proto, proto);
|
|
|
|
if (err)
|
|
mem_deref(m);
|
|
else
|
|
*mp = m;
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
/**
|
|
* Reset the remote part of an SDP Media line
|
|
*
|
|
* @param m SDP Media line
|
|
*/
|
|
void sdp_media_rreset(struct sdp_media *m)
|
|
{
|
|
int i;
|
|
|
|
if (!m)
|
|
return;
|
|
|
|
sa_init(&m->raddr, AF_INET);
|
|
sa_init(&m->raddr_rtcp, AF_INET);
|
|
|
|
list_flush(&m->rfmtl);
|
|
list_flush(&m->rattrl);
|
|
|
|
m->rdir = SDP_SENDRECV;
|
|
|
|
for (i=0; i<SDP_BANDWIDTH_MAX; i++)
|
|
m->rbwv[i] = -1;
|
|
}
|
|
|
|
|
|
/**
|
|
* Compare media line protocols
|
|
*
|
|
* @param m SDP Media line
|
|
* @param proto Transport protocol
|
|
* @param update Update media protocol if match is found in alternate set
|
|
*
|
|
* @return True if matching, False if not
|
|
*/
|
|
bool sdp_media_proto_cmp(struct sdp_media *m, const struct pl *proto,
|
|
bool update)
|
|
{
|
|
unsigned i;
|
|
|
|
if (!m || !proto)
|
|
return false;
|
|
|
|
if (!pl_strcmp(proto, m->proto))
|
|
return true;
|
|
|
|
for (i=0; i<ARRAY_SIZE(m->protov); i++) {
|
|
|
|
if (!m->protov[i] || pl_strcmp(proto, m->protov[i]))
|
|
continue;
|
|
|
|
if (update) {
|
|
mem_deref(m->proto);
|
|
m->proto = mem_ref(m->protov[i]);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
/**
|
|
* Find an SDP Media line from name and transport protocol
|
|
*
|
|
* @param sess SDP Session
|
|
* @param name Media name
|
|
* @param proto Transport protocol
|
|
* @param update_proto Update media transport protocol
|
|
*
|
|
* @return Matching media line if found, NULL if not found
|
|
*/
|
|
struct sdp_media *sdp_media_find(const struct sdp_session *sess,
|
|
const struct pl *name,
|
|
const struct pl *proto,
|
|
bool update_proto)
|
|
{
|
|
struct le *le;
|
|
|
|
if (!sess || !name || !proto)
|
|
return NULL;
|
|
|
|
for (le=sess->lmedial.head; le; le=le->next) {
|
|
|
|
struct sdp_media *m = le->data;
|
|
|
|
if (pl_strcmp(name, m->name))
|
|
continue;
|
|
|
|
if (!sdp_media_proto_cmp(m, proto, update_proto))
|
|
continue;
|
|
|
|
return m;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
* Align the locate/remote formats of an SDP Media line
|
|
*
|
|
* @param m SDP Media line
|
|
* @param offer True if SDP Offer, False if SDP Answer
|
|
*/
|
|
void sdp_media_align_formats(struct sdp_media *m, bool offer)
|
|
{
|
|
struct sdp_format *rfmt, *lfmt;
|
|
struct le *rle, *lle;
|
|
|
|
if (!m || m->disabled || !sa_port(&m->raddr) || m->fmt_ignore)
|
|
return;
|
|
|
|
for (lle=m->lfmtl.head; lle; lle=lle->next) {
|
|
|
|
lfmt = lle->data;
|
|
|
|
lfmt->rparams = mem_deref(lfmt->rparams);
|
|
lfmt->sup = false;
|
|
}
|
|
|
|
for (rle=m->rfmtl.head; rle; rle=rle->next) {
|
|
|
|
rfmt = rle->data;
|
|
|
|
for (lle=m->lfmtl.head; lle; lle=lle->next) {
|
|
|
|
lfmt = lle->data;
|
|
|
|
if (sdp_format_cmp(lfmt, rfmt))
|
|
break;
|
|
}
|
|
|
|
if (!lle) {
|
|
rfmt->sup = false;
|
|
continue;
|
|
}
|
|
|
|
mem_deref(lfmt->rparams);
|
|
lfmt->rparams = mem_ref(rfmt->params);
|
|
|
|
lfmt->sup = true;
|
|
rfmt->sup = true;
|
|
|
|
if (rfmt->ref)
|
|
rfmt->data = mem_deref(rfmt->data);
|
|
else
|
|
rfmt->data = NULL;
|
|
|
|
if (lfmt->ref)
|
|
rfmt->data = mem_ref(lfmt->data);
|
|
else
|
|
rfmt->data = lfmt->data;
|
|
|
|
rfmt->ref = lfmt->ref;
|
|
|
|
if (offer) {
|
|
mem_deref(lfmt->id);
|
|
lfmt->id = mem_ref(rfmt->id);
|
|
lfmt->pt = atoi(lfmt->id ? lfmt->id : "");
|
|
|
|
list_unlink(&lfmt->le);
|
|
list_append(&m->lfmtl, &lfmt->le, lfmt);
|
|
}
|
|
}
|
|
|
|
if (offer) {
|
|
|
|
for (lle=m->lfmtl.tail; lle; ) {
|
|
|
|
lfmt = lle->data;
|
|
|
|
lle = lle->prev;
|
|
|
|
if (!lfmt->sup) {
|
|
list_unlink(&lfmt->le);
|
|
list_append(&m->lfmtl, &lfmt->le, lfmt);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Set alternative protocols for an SDP Media line
|
|
*
|
|
* @param m SDP Media line
|
|
* @param protoc Number of alternative protocols
|
|
*
|
|
* @return 0 if success, otherwise errorcode
|
|
*/
|
|
int sdp_media_set_alt_protos(struct sdp_media *m, unsigned protoc, ...)
|
|
{
|
|
const char *proto;
|
|
int err = 0;
|
|
unsigned i;
|
|
va_list ap;
|
|
|
|
if (!m)
|
|
return EINVAL;
|
|
|
|
va_start(ap, protoc);
|
|
|
|
for (i=0; i<ARRAY_SIZE(m->protov); i++) {
|
|
|
|
m->protov[i] = mem_deref(m->protov[i]);
|
|
|
|
if (i >= protoc)
|
|
continue;
|
|
|
|
proto = va_arg(ap, const char *);
|
|
if (proto)
|
|
err |= str_dup(&m->protov[i], proto);
|
|
}
|
|
|
|
va_end(ap);
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
/**
|
|
* Set SDP Media line encode handler
|
|
*
|
|
* @param m SDP Media line
|
|
* @param ench Encode handler
|
|
* @param arg Encode handler argument
|
|
*/
|
|
void sdp_media_set_encode_handler(struct sdp_media *m, sdp_media_enc_h *ench,
|
|
void *arg)
|
|
{
|
|
if (!m)
|
|
return;
|
|
|
|
m->ench = ench;
|
|
m->arg = arg;
|
|
}
|
|
|
|
|
|
/**
|
|
* Set an SDP Media line to ignore formats
|
|
*
|
|
* @param m SDP Media line
|
|
* @param fmt_ignore True for ignore formats, otherwise false
|
|
*/
|
|
void sdp_media_set_fmt_ignore(struct sdp_media *m, bool fmt_ignore)
|
|
{
|
|
if (!m)
|
|
return;
|
|
|
|
m->fmt_ignore = fmt_ignore;
|
|
}
|
|
|
|
|
|
/**
|
|
* Set an SDP Media line to enabled/disabled
|
|
*
|
|
* @param m SDP Media line
|
|
* @param disabled True for disabled, False for enabled
|
|
*/
|
|
void sdp_media_set_disabled(struct sdp_media *m, bool disabled)
|
|
{
|
|
if (!m)
|
|
return;
|
|
|
|
m->disabled = disabled;
|
|
}
|
|
|
|
|
|
/**
|
|
* Set the local port number of an SDP Media line
|
|
*
|
|
* @param m SDP Media line
|
|
* @param port Port number
|
|
*/
|
|
void sdp_media_set_lport(struct sdp_media *m, uint16_t port)
|
|
{
|
|
if (!m)
|
|
return;
|
|
|
|
sa_set_port(&m->laddr, port);
|
|
}
|
|
|
|
|
|
/**
|
|
* Set the local network address of an SDP media line
|
|
*
|
|
* @param m SDP Media line
|
|
* @param laddr Local network address
|
|
*/
|
|
void sdp_media_set_laddr(struct sdp_media *m, const struct sa *laddr)
|
|
{
|
|
if (!m || !laddr)
|
|
return;
|
|
|
|
m->laddr = *laddr;
|
|
}
|
|
|
|
|
|
/**
|
|
* Set a local bandwidth of an SDP Media line
|
|
*
|
|
* @param m SDP Media line
|
|
* @param type Bandwidth type
|
|
* @param bw Bandwidth value
|
|
*/
|
|
void sdp_media_set_lbandwidth(struct sdp_media *m, enum sdp_bandwidth type,
|
|
int32_t bw)
|
|
{
|
|
if (!m || type >= SDP_BANDWIDTH_MAX)
|
|
return;
|
|
|
|
m->lbwv[type] = bw;
|
|
}
|
|
|
|
|
|
/**
|
|
* Set the local RTCP port number of an SDP Media line
|
|
*
|
|
* @param m SDP Media line
|
|
* @param port RTCP Port number
|
|
*/
|
|
void sdp_media_set_lport_rtcp(struct sdp_media *m, uint16_t port)
|
|
{
|
|
if (!m)
|
|
return;
|
|
|
|
sa_set_port(&m->laddr_rtcp, port);
|
|
}
|
|
|
|
|
|
/**
|
|
* Set the local RTCP network address of an SDP media line
|
|
*
|
|
* @param m SDP Media line
|
|
* @param laddr Local RTCP network address
|
|
*/
|
|
void sdp_media_set_laddr_rtcp(struct sdp_media *m, const struct sa *laddr)
|
|
{
|
|
if (!m || !laddr)
|
|
return;
|
|
|
|
m->laddr_rtcp = *laddr;
|
|
}
|
|
|
|
|
|
/**
|
|
* Set the local direction flag of an SDP Media line
|
|
*
|
|
* @param m SDP Media line
|
|
* @param dir Media direction flag
|
|
*/
|
|
void sdp_media_set_ldir(struct sdp_media *m, enum sdp_dir dir)
|
|
{
|
|
if (!m)
|
|
return;
|
|
|
|
m->ldir = dir;
|
|
}
|
|
|
|
|
|
/**
|
|
* Set a local attribute of an SDP Media line
|
|
*
|
|
* @param m SDP Media line
|
|
* @param replace True to replace attribute, False to append
|
|
* @param name Attribute name
|
|
* @param value Formatted attribute value
|
|
*
|
|
* @return 0 if success, otherwise errorcode
|
|
*/
|
|
int sdp_media_set_lattr(struct sdp_media *m, bool replace,
|
|
const char *name, const char *value, ...)
|
|
{
|
|
va_list ap;
|
|
int err;
|
|
|
|
if (!m || !name)
|
|
return EINVAL;
|
|
|
|
if (replace)
|
|
sdp_attr_del(&m->lattrl, name);
|
|
|
|
va_start(ap, value);
|
|
err = sdp_attr_addv(&m->lattrl, name, value, ap);
|
|
va_end(ap);
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
/**
|
|
* Delete a local attribute of an SDP Media line
|
|
*
|
|
* @param m SDP Media line
|
|
* @param name Attribute name
|
|
*/
|
|
void sdp_media_del_lattr(struct sdp_media *m, const char *name)
|
|
{
|
|
if (!m || !name)
|
|
return;
|
|
|
|
sdp_attr_del(&m->lattrl, name);
|
|
}
|
|
|
|
|
|
const char *sdp_media_proto(const struct sdp_media *m)
|
|
{
|
|
return m ? m->proto : NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get the remote port number of an SDP Media line
|
|
*
|
|
* @param m SDP Media line
|
|
*
|
|
* @return Remote port number
|
|
*/
|
|
uint16_t sdp_media_rport(const struct sdp_media *m)
|
|
{
|
|
return m ? sa_port(&m->raddr) : 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get the remote network address of an SDP Media line
|
|
*
|
|
* @param m SDP Media line
|
|
*
|
|
* @return Remote network address
|
|
*/
|
|
const struct sa *sdp_media_raddr(const struct sdp_media *m)
|
|
{
|
|
return m ? &m->raddr : NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get the local network address of an SDP Media line
|
|
*
|
|
* @param m SDP Media line
|
|
*
|
|
* @return Local network address
|
|
*/
|
|
const struct sa *sdp_media_laddr(const struct sdp_media *m)
|
|
{
|
|
return m ? &m->laddr : NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get the remote RTCP network address of an SDP Media line
|
|
*
|
|
* @param m SDP Media line
|
|
* @param raddr On return, contains remote RTCP network address
|
|
*/
|
|
void sdp_media_raddr_rtcp(const struct sdp_media *m, struct sa *raddr)
|
|
{
|
|
if (!m || !raddr)
|
|
return;
|
|
|
|
if (sa_isset(&m->raddr_rtcp, SA_ALL)) {
|
|
*raddr = m->raddr_rtcp;
|
|
}
|
|
else if (sa_isset(&m->raddr_rtcp, SA_PORT)) {
|
|
*raddr = m->raddr;
|
|
sa_set_port(raddr, sa_port(&m->raddr_rtcp));
|
|
}
|
|
else {
|
|
uint16_t port = sa_port(&m->raddr);
|
|
|
|
*raddr = m->raddr;
|
|
sa_set_port(raddr, port ? port + 1 : 0);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Get a remote bandwidth of an SDP Media line
|
|
*
|
|
* @param m SDP Media line
|
|
* @param type Bandwidth type
|
|
*
|
|
* @return Remote bandwidth value
|
|
*/
|
|
int32_t sdp_media_rbandwidth(const struct sdp_media *m,
|
|
enum sdp_bandwidth type)
|
|
{
|
|
if (!m || type >= SDP_BANDWIDTH_MAX)
|
|
return 0;
|
|
|
|
return m->rbwv[type];
|
|
}
|
|
|
|
|
|
/**
|
|
* Get the local media direction of an SDP Media line
|
|
*
|
|
* @param m SDP Media line
|
|
*
|
|
* @return Local media direction
|
|
*/
|
|
enum sdp_dir sdp_media_ldir(const struct sdp_media *m)
|
|
{
|
|
return m ? m->ldir : SDP_INACTIVE;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get the remote media direction of an SDP Media line
|
|
*
|
|
* @param m SDP Media line
|
|
*
|
|
* @return Remote media direction
|
|
*/
|
|
enum sdp_dir sdp_media_rdir(const struct sdp_media *m)
|
|
{
|
|
return m ? m->rdir : SDP_INACTIVE;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get the combined media direction of an SDP Media line
|
|
*
|
|
* @param m SDP Media line
|
|
*
|
|
* @return Combined media direction
|
|
*/
|
|
enum sdp_dir sdp_media_dir(const struct sdp_media *m)
|
|
{
|
|
return m ? (enum sdp_dir)(m->ldir & m->rdir) : SDP_INACTIVE;
|
|
}
|
|
|
|
|
|
/**
|
|
* Find a local SDP format from a payload type
|
|
*
|
|
* @param m SDP Media line
|
|
* @param pt Payload type
|
|
*
|
|
* @return Local SDP format if found, NULL if not found
|
|
*/
|
|
const struct sdp_format *sdp_media_lformat(const struct sdp_media *m, int pt)
|
|
{
|
|
struct le *le;
|
|
|
|
if (!m)
|
|
return NULL;
|
|
|
|
for (le=m->lfmtl.head; le; le=le->next) {
|
|
|
|
const struct sdp_format *fmt = le->data;
|
|
|
|
if (pt == fmt->pt)
|
|
return fmt;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
* Find a remote SDP format from a format name
|
|
*
|
|
* @param m SDP Media line
|
|
* @param name Format name
|
|
*
|
|
* @return Remote SDP format if found, NULL if not found
|
|
*/
|
|
const struct sdp_format *sdp_media_rformat(const struct sdp_media *m,
|
|
const char *name)
|
|
{
|
|
struct le *le;
|
|
|
|
if (!m || !sa_port(&m->raddr))
|
|
return NULL;
|
|
|
|
for (le=m->rfmtl.head; le; le=le->next) {
|
|
|
|
const struct sdp_format *fmt = le->data;
|
|
|
|
if (!fmt->sup)
|
|
continue;
|
|
|
|
if (name && str_casecmp(name, fmt->name))
|
|
continue;
|
|
|
|
return fmt;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
* Find an SDP Format of an SDP Media line
|
|
*
|
|
* @param m SDP Media line
|
|
* @param local True if local media, False if remote
|
|
* @param id SDP format id
|
|
* @param pt Payload type
|
|
* @param name Format name
|
|
* @param srate Sampling rate
|
|
* @param ch Number of channels
|
|
*
|
|
* @return SDP Format if found, NULL if not found
|
|
*/
|
|
struct sdp_format *sdp_media_format(const struct sdp_media *m,
|
|
bool local, const char *id,
|
|
int pt, const char *name,
|
|
int32_t srate, int8_t ch)
|
|
{
|
|
return sdp_media_format_apply(m, local, id, pt, name, srate, ch,
|
|
NULL, NULL);
|
|
}
|
|
|
|
|
|
/**
|
|
* Apply a function handler to all matching SDP formats
|
|
*
|
|
* @param m SDP Media line
|
|
* @param local True if local media, False if remote
|
|
* @param id SDP format id
|
|
* @param pt Payload type
|
|
* @param name Format name
|
|
* @param srate Sampling rate
|
|
* @param ch Number of channels
|
|
* @param fmth SDP Format handler
|
|
* @param arg Handler argument
|
|
*
|
|
* @return SDP Format if found, NULL if not found
|
|
*/
|
|
struct sdp_format *sdp_media_format_apply(const struct sdp_media *m,
|
|
bool local, const char *id,
|
|
int pt, const char *name,
|
|
int32_t srate, int8_t ch,
|
|
sdp_format_h *fmth, void *arg)
|
|
{
|
|
struct le *le;
|
|
|
|
if (!m)
|
|
return NULL;
|
|
|
|
le = local ? m->lfmtl.head : m->rfmtl.head;
|
|
|
|
while (le) {
|
|
|
|
struct sdp_format *fmt = le->data;
|
|
|
|
le = le->next;
|
|
|
|
if (id && (!fmt->id || strcmp(id, fmt->id)))
|
|
continue;
|
|
|
|
if (pt >= 0 && pt != fmt->pt)
|
|
continue;
|
|
|
|
if (name && str_casecmp(name, fmt->name))
|
|
continue;
|
|
|
|
if (srate >= 0 && (uint32_t)srate != fmt->srate)
|
|
continue;
|
|
|
|
if (ch >= 0 && (uint8_t)ch != fmt->ch)
|
|
continue;
|
|
|
|
if (!fmth || fmth(fmt, arg))
|
|
return fmt;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get the list of SDP Formats
|
|
*
|
|
* @param m SDP Media line
|
|
* @param local True if local, False if remote
|
|
*
|
|
* @return List of SDP Formats
|
|
*/
|
|
const struct list *sdp_media_format_lst(const struct sdp_media *m, bool local)
|
|
{
|
|
if (!m)
|
|
return NULL;
|
|
|
|
return local ? &m->lfmtl : &m->rfmtl;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get a remote attribute from an SDP Media line
|
|
*
|
|
* @param m SDP Media line
|
|
* @param name Attribute name
|
|
*
|
|
* @return Attribute value, NULL if not found
|
|
*/
|
|
const char *sdp_media_rattr(const struct sdp_media *m, const char *name)
|
|
{
|
|
if (!m || !name)
|
|
return NULL;
|
|
|
|
return sdp_attr_apply(&m->rattrl, name, NULL, NULL);
|
|
}
|
|
|
|
|
|
/**
|
|
* Get a remote attribute from an SDP Media line or the SDP session
|
|
*
|
|
* @param m SDP Media line
|
|
* @param sess SDP Session
|
|
* @param name Attribute name
|
|
*
|
|
* @return Attribute value, NULL if not found
|
|
*/
|
|
const char *sdp_media_session_rattr(const struct sdp_media *m,
|
|
const struct sdp_session *sess,
|
|
const char *name)
|
|
{
|
|
const char *val;
|
|
|
|
val = sdp_media_rattr(m, name);
|
|
if (!val)
|
|
val = sdp_session_rattr(sess, name);
|
|
|
|
return val;
|
|
}
|
|
|
|
|
|
/**
|
|
* Apply a function handler to all matching remote attributes
|
|
*
|
|
* @param m SDP Media line
|
|
* @param name Attribute name
|
|
* @param attrh Attribute handler
|
|
* @param arg Handler argument
|
|
*
|
|
* @return Attribute value if match
|
|
*/
|
|
const char *sdp_media_rattr_apply(const struct sdp_media *m, const char *name,
|
|
sdp_attr_h *attrh, void *arg)
|
|
{
|
|
if (!m)
|
|
return NULL;
|
|
|
|
return sdp_attr_apply(&m->rattrl, name, attrh, arg);
|
|
}
|
|
|
|
|
|
/**
|
|
* Get the name of an SDP Media line
|
|
*
|
|
* @param m SDP Media line
|
|
*
|
|
* @return SDP Media line name
|
|
*/
|
|
const char *sdp_media_name(const struct sdp_media *m)
|
|
{
|
|
return m ? m->name : NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
* Print SDP Media line debug information
|
|
*
|
|
* @param pf Print function for output
|
|
* @param m SDP Media line
|
|
*
|
|
* @return 0 if success, otherwise errorcode
|
|
*/
|
|
int sdp_media_debug(struct re_printf *pf, const struct sdp_media *m)
|
|
{
|
|
struct le *le;
|
|
int err;
|
|
|
|
if (!m)
|
|
return 0;
|
|
|
|
err = re_hprintf(pf, "%s %s\n", m->name, m->proto);
|
|
|
|
err |= re_hprintf(pf, " local formats:\n");
|
|
|
|
for (le=m->lfmtl.head; le; le=le->next)
|
|
err |= re_hprintf(pf, " %H\n", sdp_format_debug, le->data);
|
|
|
|
err |= re_hprintf(pf, " remote formats:\n");
|
|
|
|
for (le=m->rfmtl.head; le; le=le->next)
|
|
err |= re_hprintf(pf, " %H\n", sdp_format_debug, le->data);
|
|
|
|
err |= re_hprintf(pf, " local attributes:\n");
|
|
|
|
for (le=m->lattrl.head; le; le=le->next)
|
|
err |= re_hprintf(pf, " %H\n", sdp_attr_debug, le->data);
|
|
|
|
err |= re_hprintf(pf, " remote attributes:\n");
|
|
|
|
for (le=m->rattrl.head; le; le=le->next)
|
|
err |= re_hprintf(pf, " %H\n", sdp_attr_debug, le->data);
|
|
|
|
return err;
|
|
}
|