/** * Allocate a new video source state * * @param stp Pointer to allocated state * @param name Name of the video source * @param ctx Optional media context * @param prm Video source parameters * @param size Wanted video size of the source * @param fmt Format parameter * @param dev Video device * @param frameh Video frame handler * @param errorh Error handler (optional) * @param arg Handler argument * * @return 0 if success, otherwise errorcode */ int vidsrc_alloc(struct vidsrc_st **stp, const char *name, struct media_ctx **ctx, struct vidsrc_prm *prm, const struct vidsz *size, const char *fmt, const char *dev, vidsrc_frame_h *frameh, vidsrc_error_h *errorh, void *arg) { struct vidsrc *vs = (struct vidsrc *)vidsrc_find(name); if (!vs) return ENOENT; return vs->alloch(stp, vs, ctx, prm, size, fmt, dev, frameh, errorh, arg); }
/** * Allocate a new Call state object * * @param callp Pointer to allocated Call state object * @param cfg Global configuration * @param lst List of call objects * @param local_name Local display name (optional) * @param local_uri Local SIP uri * @param acc Account parameters * @param ua User-Agent * @param prm Call parameters * @param msg SIP message for incoming calls * @param xcall Optional call to inherit properties from * @param eh Call event handler * @param arg Handler argument * * @return 0 if success, otherwise errorcode */ int call_alloc(struct call **callp, const struct config *cfg, struct list *lst, const char *local_name, const char *local_uri, struct account *acc, struct ua *ua, const struct call_prm *prm, const struct sip_msg *msg, struct call *xcall, call_event_h *eh, void *arg) { struct call *call; enum vidmode vidmode = prm ? prm->vidmode : VIDMODE_OFF; bool use_video = true, got_offer = false; int label = 0; int err = 0; if (!cfg || !local_uri || !acc || !ua) return EINVAL; call = mem_zalloc(sizeof(*call), call_destructor); if (!call) return ENOMEM; MAGIC_INIT(call); call->config_avt = cfg->avt; tmr_init(&call->tmr_inv); call->acc = mem_ref(acc); call->ua = ua; call->state = STATE_IDLE; call->eh = eh; call->arg = arg; call->af = prm ? prm->af : AF_INET; err = str_dup(&call->local_uri, local_uri); if (local_name) err |= str_dup(&call->local_name, local_name); if (err) goto out; /* Init SDP info */ err = sdp_session_alloc(&call->sdp, net_laddr_af(call->af)); if (err) goto out; err = sdp_session_set_lattr(call->sdp, true, "tool", "baresip " BARESIP_VERSION); if (err) goto out; /* Check for incoming SDP Offer */ if (msg && mbuf_get_left(msg->mb)) got_offer = true; /* Initialise media NAT handling */ if (acc->mnat) { err = acc->mnat->sessh(&call->mnats, net_dnsc(), call->af, acc->stun_host, acc->stun_port, acc->stun_user, acc->stun_pass, call->sdp, !got_offer, mnat_handler, call); if (err) { warning("call: medianat session: %m\n", err); goto out; } } call->mnat_wait = true; /* Media encryption */ if (acc->menc) { if (acc->menc->sessh) { err = acc->menc->sessh(&call->mencs, call->sdp, !got_offer, menc_error_handler, call); if (err) { warning("call: mediaenc session: %m\n", err); goto out; } } } /* Audio stream */ err = audio_alloc(&call->audio, cfg, call, call->sdp, ++label, acc->mnat, call->mnats, acc->menc, call->mencs, acc->ptime, account_aucodecl(call->acc), audio_event_handler, audio_error_handler, call); if (err) goto out; #ifdef USE_VIDEO /* We require at least one video codec, and at least one video source or video display */ use_video = (vidmode != VIDMODE_OFF) && (list_head(account_vidcodecl(call->acc)) != NULL) && (NULL != vidsrc_find(NULL) || NULL != vidisp_find(NULL)); /* Video stream */ if (use_video) { err = video_alloc(&call->video, cfg, call, call->sdp, ++label, acc->mnat, call->mnats, acc->menc, call->mencs, "main", account_vidcodecl(call->acc), video_error_handler, call); if (err) goto out; } if (str_isset(cfg->bfcp.proto)) { err = bfcp_alloc(&call->bfcp, call->sdp, cfg->bfcp.proto, !got_offer, acc->mnat, call->mnats); if (err) goto out; } #else (void)use_video; (void)vidmode; #endif /* inherit certain properties from original call */ if (xcall) { call->not = mem_ref(xcall->not); } list_append(lst, &call->le, call); out: if (err) mem_deref(call); else if (callp) *callp = call; return err; }