/** * Load a module by name or by filename * * @param name Module name incl/excl extension, excluding module path * * @return 0 if success, otherwise errorcode * * example: "foo" * example: "foo.so" */ int module_load(const char *name) { char filename[256]; struct pl path, pl_name; int err; if (!str_isset(name)) return EINVAL; append_extension(filename, sizeof(filename), name); pl_set_str(&pl_name, filename); if (conf_get(conf_cur(), "module_path", &path)) pl_set_str(&path, "."); err = load_module(NULL, &path, &pl_name); return err; }
static unsigned int find_dev(const char *name) { WAVEINCAPS wic; unsigned int i, nInDevices = waveInGetNumDevs(); if (!str_isset(name)) return WAVE_MAPPER; for (i=0; i<nInDevices; i++) { if (waveInGetDevCaps(i, &wic, sizeof(WAVEINCAPS))==MMSYSERR_NOERROR) { if (0 == str_casecmp(name, wic.szPname)) { return i; } } } return WAVE_MAPPER; }
static int verify_sas(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; (void)pf; if (str_isset(carg->prm)) { char *s2h; char rzid[ZRTP_STRING16] = ""; zrtp_status_t s; zrtp_string16_t remote_zid = ZSTR_INIT_EMPTY(remote_zid); if (str_len(carg->prm) != 24) { warning("zrtp: invalid remote ZID (%s)\n", carg->prm); return EINVAL; } s2h = str2hex(carg->prm, (int) str_len(carg->prm), rzid, sizeof(rzid)); if (str_len(rzid) != sizeof(zrtp_zid_t)) { warning("zrtp: str2hex failed (%s)\n", s2h); return EINVAL; } zrtp_zstrncpyc(ZSTR_GV(remote_zid), (const char*)rzid, sizeof(zrtp_zid_t)); s = zrtp_cache_set_verified(zrtp_global->cache, ZSTR_GV(remote_zid), true); if (s == zrtp_status_ok) info("zrtp: SAS for peer %s verified\n", carg->prm); else { warning("zrtp: zrtp_cache_set_verified" " failed (status = %d)\n", s); return EINVAL; } } return 0; }
int trice_lcands_debug(struct re_printf *pf, const struct list *lst) { struct le *le; int err; err = re_hprintf(pf, " (%u)\n", list_count(lst)); for (le = list_head(lst); le && !err; le = le->next) { const struct ice_lcand *cand = le->data; err |= re_hprintf(pf, " {%u} [tx=%3zu, rx=%3zu] " "fnd=%-8s prio=%08x ", cand->attr.compid, cand->stats.n_tx, cand->stats.n_rx, cand->attr.foundation, cand->attr.prio); if (str_isset(cand->ifname)) err |= re_hprintf(pf, "%s:", cand->ifname); err |= re_hprintf(pf, "%24H", trice_cand_print, cand); if (sa_isset(&cand->base_addr, SA_ADDR)) { err |= re_hprintf(pf, " (base-addr = %J)", &cand->base_addr); } if (sa_isset(&cand->attr.rel_addr, SA_ADDR)) { err |= re_hprintf(pf, " (rel-addr = %J)", &cand->attr.rel_addr); } err |= re_hprintf(pf, "\n"); } return err; }
static int src_alloc(struct vidsrc_st **stp, const struct vidsrc *vs, 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_st *st; int err = 0; (void)ctx; (void)prm; (void)fmt; (void)errorh; (void)arg; if (!stp || !size || !frameh) return EINVAL; st = mem_zalloc(sizeof(*st), src_destructor); if (!st) return ENOMEM; st->vs = vs; /* NOTE: copy instance data into global space */ if (str_isset(dev)) str_ncpy(v4l2.device, dev, sizeof(v4l2.device)); v4l2.width = size->w; v4l2.height = size->h; if (err) mem_deref(st); else *stp = st; return err; }
int ICACHE_FLASH_ATTR user_dns_param_alloc(struct user_dns_param **pp, const char *hostname, user_dns_h *h, void *arg) { struct user_dns_param *param; if(!pp || !h || !str_isset(hostname)) { DEBUG_WARNING("EINVAL\n"); return EINVAL; } *pp = NULL; DEBUG_PRINTF("mem_zalloc param\n"); param = mem_zalloc(sizeof(*param), param_de); DEBUG_INFO("%p\n", param); if(!param) { DEBUG_WARNING("ENOMEM\n"); return ENOMEM; } param->h = h; param->arg = arg; DEBUG_PRINTF("str_dup hostname\n"); str_dup(¶m->hostname, hostname); DEBUG_PRINTF("list_append param\n"); list_append(¶m_list, ¶m->le, param); *pp = param; return 0; }
static int get_device(struct vidsrc_st *st, const char *name) { ICreateDevEnum *dev_enum; IEnumMoniker *enum_mon; IMoniker *mon; ULONG fetched; HRESULT res; int id = 0; bool found = false; if (!st) return EINVAL; res = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&dev_enum); if (res != NOERROR) return ENOENT; res = dev_enum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &enum_mon, 0); if (res != NOERROR) return ENOENT; enum_mon->Reset(); while (enum_mon->Next(1, &mon, &fetched) == S_OK && !found) { IPropertyBag *bag; VARIANT var; char dev_name[256]; int len = 0; res = mon->BindToStorage(0, 0, IID_IPropertyBag, (void **)&bag); if (!SUCCEEDED(res)) continue; var.vt = VT_BSTR; res = bag->Read(L"FriendlyName", &var, NULL); if (NOERROR != res) continue; len = WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, dev_name, sizeof(dev_name), NULL, NULL); if (len > 0) { found = !str_isset(name) || !str_casecmp(dev_name, name); if (found) { info("dshow: got device '%s' id=%d\n", name, id); st->dev_moniker = mon; } } SysFreeString(var.bstrVal); bag->Release(); if (!found) { mon->Release(); ++id; } } return found ? 0 : ENOENT; }
int opus_encode_update(struct auenc_state **aesp, const struct aucodec *ac, struct auenc_param *param, const char *fmtp) { struct auenc_state *aes; struct opus_param prm, conf_prm; opus_int32 fch, vbr; const struct aucodec *auc = ac; (void)param; if (!aesp || !ac || !ac->ch) return EINVAL; debug("opus: encoder fmtp (%s)\n", fmtp); /* Save the incoming OPUS parameters from SDP offer */ if (str_isset(fmtp)) { opus_mirror_params(fmtp); } aes = *aesp; if (!aes) { const opus_int32 complex = 10; int opuserr; aes = mem_zalloc(sizeof(*aes), destructor); if (!aes) return ENOMEM; aes->ch = ac->ch; aes->enc = opus_encoder_create(ac->srate, ac->ch, /* this has big impact on cpu */ OPUS_APPLICATION_AUDIO, &opuserr); if (!aes->enc) { warning("opus: encoder create: %s\n", opus_strerror(opuserr)); mem_deref(aes); return ENOMEM; } (void)opus_encoder_ctl(aes->enc, OPUS_SET_COMPLEXITY(complex)); *aesp = aes; } prm.srate = 48000; prm.bitrate = OPUS_AUTO; prm.stereo = 1; prm.cbr = 0; prm.inband_fec = 0; prm.dtx = 0; opus_decode_fmtp(&prm, fmtp); conf_prm.bitrate = OPUS_AUTO; opus_decode_fmtp(&conf_prm, auc->fmtp); if ((prm.bitrate == OPUS_AUTO) || ((conf_prm.bitrate != OPUS_AUTO) && (conf_prm.bitrate < prm.bitrate))) prm.bitrate = conf_prm.bitrate; fch = prm.stereo ? OPUS_AUTO : 1; vbr = prm.cbr ? 0 : 1; (void)opus_encoder_ctl(aes->enc, OPUS_SET_MAX_BANDWIDTH(srate2bw(prm.srate))); (void)opus_encoder_ctl(aes->enc, OPUS_SET_BITRATE(prm.bitrate)); (void)opus_encoder_ctl(aes->enc, OPUS_SET_FORCE_CHANNELS(fch)); (void)opus_encoder_ctl(aes->enc, OPUS_SET_VBR(vbr)); (void)opus_encoder_ctl(aes->enc, OPUS_SET_INBAND_FEC(prm.inband_fec)); (void)opus_encoder_ctl(aes->enc, OPUS_SET_DTX(prm.dtx)); #if 0 { opus_int32 bw, complex; (void)opus_encoder_ctl(aes->enc, OPUS_GET_MAX_BANDWIDTH(&bw)); (void)opus_encoder_ctl(aes->enc, OPUS_GET_BITRATE(&prm.bitrate)); (void)opus_encoder_ctl(aes->enc, OPUS_GET_FORCE_CHANNELS(&fch)); (void)opus_encoder_ctl(aes->enc, OPUS_GET_VBR(&vbr)); (void)opus_encoder_ctl(aes->enc, OPUS_GET_INBAND_FEC(&prm.inband_fec)); (void)opus_encoder_ctl(aes->enc, OPUS_GET_DTX(&prm.dtx)); (void)opus_encoder_ctl(aes->enc, OPUS_GET_COMPLEXITY(&complex)); debug("opus: encode bw=%s bitrate=%i fch=%s " "vbr=%i fec=%i dtx=%i complex=%i\n", bwname(bw), prm.bitrate, chname(fch), vbr, prm.inband_fec, prm.dtx, complex); } #endif return 0; }
/** * 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; }
static int play_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg) { struct auplay_st *st; struct sio_par *par = NULL; int err; const char *name; if (!stp || !ap || !prm) return EINVAL; name = (str_isset(device)) ? device : SIO_DEVANY; if ((st = mem_zalloc(sizeof(*st), auplay_destructor)) == NULL) return ENOMEM; st->ap = ap; st->wh = wh; st->arg = arg; st->hdl = sio_open(name, SIO_PLAY, 0); if (!st->hdl) { warning("sndio: could not open auplay device '%s'\n", name); err = EINVAL; goto out; } par = sndio_initpar(prm->srate, prm->ch); if (!par) { err = ENOMEM; goto out; } if (!sio_setpar(st->hdl, par)) { err = EINVAL; goto out; } if (!sio_getpar(st->hdl, par)) { err = EINVAL; goto out; } st->sampc = prm->srate * prm->ch * prm->ptime / 1000; st->sampv = mem_alloc(2 * st->sampc, NULL); if (!st->sampv) { err = ENOMEM; goto out; } st->run = true; err = pthread_create(&st->thread, NULL, write_thread, st); if (err) st->run = false; out: mem_deref(par); if (err) mem_deref(st); else *stp = st; return err; }
static int alloc(struct vidsrc_st **stp, struct vidsrc *vs, 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_st *st; int err; (void)ctx; (void)prm; (void)fmt; (void)errorh; if (!stp || !size || !frameh) return EINVAL; if (!str_isset(dev)) dev = "/dev/video0"; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->vs = mem_ref(vs); st->fd = -1; st->size = *size; st->frameh = frameh; st->arg = arg; DEBUG_NOTICE("open: %s %ix%i\n", dev, size->w, size->h); err = vd_open(st, dev); if (err) goto out; v4l_get_caps(st); err = v4l_check_palette(st); if (err) goto out; err = v4l_get_win(st->fd, st->size.w, st->size.h); if (err) goto out; /* note: assumes RGB24 */ st->mb = mbuf_alloc(rgb24_size(&st->size)); if (!st->mb) { err = ENOMEM; goto out; } st->run = true; err = pthread_create(&st->thread, NULL, read_thread, st); if (err) { st->run = false; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; }
static int auloop_reset(struct audio_loop *al) { struct auplay_prm auplay_prm; struct ausrc_prm ausrc_prm; const struct config *cfg = conf_config(); int err; if (!cfg) return ENOENT; /* Optional audio codec */ if (str_isset(aucodec)) start_codec(al, aucodec); /* audio player/source must be stopped first */ al->auplay = mem_deref(al->auplay); al->ausrc = mem_deref(al->ausrc); al->sampv = mem_deref(al->sampv); al->ab = mem_deref(al->ab); al->srate = configv[al->index].srate; al->ch = configv[al->index].ch; if (str_isset(aucodec)) { al->sampc = al->srate * al->ch * PTIME / 1000; al->sampv = mem_alloc(al->sampc * 2, NULL); if (!al->sampv) return ENOMEM; } info("Audio-loop: %uHz, %dch\n", al->srate, al->ch); err = aubuf_alloc(&al->ab, 320, 0); if (err) return err; auplay_prm.srate = al->srate; auplay_prm.ch = al->ch; auplay_prm.ptime = PTIME; err = auplay_alloc(&al->auplay, cfg->audio.play_mod, &auplay_prm, cfg->audio.play_dev, write_handler, al); if (err) { warning("auloop: auplay %s,%s failed: %m\n", cfg->audio.play_mod, cfg->audio.play_dev, err); return err; } ausrc_prm.srate = al->srate; ausrc_prm.ch = al->ch; ausrc_prm.ptime = PTIME; err = ausrc_alloc(&al->ausrc, NULL, cfg->audio.src_mod, &ausrc_prm, cfg->audio.src_dev, read_handler, error_handler, al); if (err) { warning("auloop: ausrc %s,%s failed: %m\n", cfg->audio.src_mod, cfg->audio.src_dev, err); return err; } return err; }
static int add_transp_af(const struct sa *laddr) { struct sa local; int err = 0; if (str_isset(uag.cfg->local)) { err = sa_decode(&local, uag.cfg->local, str_len(uag.cfg->local)); if (err) { err = sa_set_str(&local, uag.cfg->local, 0); if (err) { warning("ua: decode failed: '%s'\n", uag.cfg->local); return err; } } if (!sa_isset(&local, SA_ADDR)) { uint16_t port = sa_port(&local); (void)sa_set_sa(&local, &laddr->u.sa); sa_set_port(&local, port); } if (sa_af(laddr) != sa_af(&local)) return 0; } else { sa_cpy(&local, laddr); sa_set_port(&local, 0); } if (uag.use_udp) err |= sip_transp_add(uag.sip, SIP_TRANSP_UDP, &local); if (uag.use_tcp) err |= sip_transp_add(uag.sip, SIP_TRANSP_TCP, &local); if (err) { warning("ua: SIP Transport failed: %m\n", err); return err; } #ifdef USE_TLS if (uag.use_tls) { /* Build our SSL context*/ if (!uag.tls) { const char *cert = NULL; if (str_isset(uag.cfg->cert)) { cert = uag.cfg->cert; info("SIP Certificate: %s\n", cert); } err = tls_alloc(&uag.tls, TLS_METHOD_SSLV23, cert, NULL); if (err) { warning("ua: tls_alloc() failed: %m\n", err); return err; } } if (sa_isset(&local, SA_PORT)) sa_set_port(&local, sa_port(&local) + 1); err = sip_transp_add(uag.sip, SIP_TRANSP_TLS, &local, uag.tls); if (err) { warning("ua: SIP/TLS transport failed: %m\n", err); return err; } } #endif return err; }
/** * Allocate a SIP User-Agent * * @param uap Pointer to allocated User-Agent object * @param aor SIP Address-of-Record (AOR) * * @return 0 if success, otherwise errorcode */ int ua_alloc(struct ua **uap, const char *aor) { struct ua *ua; int err; if (!aor) return EINVAL; ua = mem_zalloc(sizeof(*ua), ua_destructor); if (!ua) return ENOMEM; MAGIC_INIT(ua); list_init(&ua->calls); #if HAVE_INET6 ua->af = uag.prefer_ipv6 ? AF_INET6 : AF_INET; #else ua->af = AF_INET; #endif /* Decode SIP address */ err = account_alloc(&ua->acc, aor); if (err) goto out; /* generate a unique contact-user, this is needed to route incoming requests when using multiple useragents */ err = re_sdprintf(&ua->cuser, "%r-%p", &ua->acc->luri.user, ua); if (err) goto out; if (ua->acc->sipnat) { ua_printf(ua, "Using sipnat: `%s'\n", ua->acc->sipnat); } if (ua->acc->mnat) { ua_printf(ua, "Using medianat `%s'\n", ua->acc->mnat->id); if (0 == str_casecmp(ua->acc->mnat->id, "ice")) add_extension(ua, "ice"); } if (ua->acc->menc) { ua_printf(ua, "Using media encryption `%s'\n", ua->acc->menc->id); } /* Register clients */ if (str_isset(uag.cfg->uuid)) add_extension(ua, "gruu"); if (0 == str_casecmp(ua->acc->sipnat, "outbound")) { size_t i; add_extension(ua, "path"); add_extension(ua, "outbound"); if (!str_isset(uag.cfg->uuid)) { warning("ua: outbound requires valid UUID!\n"); err = ENOSYS; goto out; } for (i=0; i<ARRAY_SIZE(ua->acc->outbound); i++) { if (ua->acc->outbound[i] && ua->acc->regint) { err = reg_add(&ua->regl, ua, (int)i+1); if (err) break; } } } else if (ua->acc->regint) { err = reg_add(&ua->regl, ua, 0); } if (err) goto out; list_append(&uag.ual, &ua->le, ua); if (ua->acc->regint) { err = ua_register(ua); } if (!uag_current()) uag_current_set(ua); out: if (err) mem_deref(ua); else if (uap) { *uap = ua; ua->uap = uap; } return err; }
static int cmd_print_all(struct re_printf *pf, const struct commands *commands, bool print_long, bool print_short, const char *match, size_t match_len) { struct list sortedl = LIST_INIT; struct le *le; size_t width_long = 1; size_t width_short = 5; char fmt[64]; char buf[16]; int err = 0; if (!commands) return EINVAL; for (le = commands->cmdl.head; le; le = le->next) { struct cmds *cmds = le->data; size_t i; for (i=0; i<cmds->cmdc; i++) { const struct cmd *cmd = &cmds->cmdv[i]; struct cmd_sort *cs; if (match && match_len) { if (str_len(cmd->name) >= match_len && 0 == memcmp(cmd->name, match, match_len)) { /* Match */ } else { continue; } } if (!str_isset(cmd->desc)) continue; if (print_short && !print_long) { if (cmd->key == KEYCODE_NONE) continue; } cs = mem_zalloc(sizeof(*cs), NULL); if (!cs) { err = ENOMEM; goto out; } cs->cmd = cmd; list_append(&sortedl, &cs->le, cs); width_long = max(width_long, 1+str_len(cmd->name)+3); } } list_sort(&sortedl, sort_handler, &print_long); if (re_snprintf(fmt, sizeof(fmt), " %%-%zus %%-%zus %%s\n", width_long, width_short) < 0) { err = ENOMEM; goto out; } for (le = sortedl.head; le; le = le->next) { struct cmd_sort *cs = le->data; const struct cmd *cmd = cs->cmd; char namep[64] = ""; if (print_long && str_isset(cmd->name)) { re_snprintf(namep, sizeof(namep), "%c%s%s", LONG_PREFIX, cmd->name, (cmd->flags & CMD_PRM) ? " .." : ""); } err |= re_hprintf(pf, fmt, namep, (print_short && cmd->key) ? cmd_name(buf, sizeof(buf), cmd) : "", cmd->desc); } err |= re_hprintf(pf, "\n"); out: list_flush(&sortedl); return err; }
int alsa_play_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg) { struct auplay_st *st; snd_pcm_format_t pcmfmt; int num_frames; int err; if (!stp || !ap || !prm || !wh) return EINVAL; if (!str_isset(device)) device = alsa_dev; st = mem_zalloc(sizeof(*st), auplay_destructor); if (!st) return ENOMEM; err = str_dup(&st->device, device); if (err) goto out; st->prm = *prm; st->ap = ap; st->wh = wh; st->arg = arg; st->aufmt = alsa_sample_format; st->sampc = prm->srate * prm->ch * prm->ptime / 1000; num_frames = st->prm.srate * st->prm.ptime / 1000; st->sampv = mem_alloc(2 * st->sampc, NULL); if (!st->sampv) { err = ENOMEM; goto out; } if (st->aufmt != AUFMT_S16LE) { size_t sz = aufmt_sample_size(st->aufmt) * st->sampc; st->xsampv = mem_alloc(sz, NULL); if (!st->xsampv) { err = ENOMEM; goto out; } } err = snd_pcm_open(&st->write, st->device, SND_PCM_STREAM_PLAYBACK, 0); if (err < 0) { warning("alsa: could not open auplay device '%s' (%s)\n", st->device, snd_strerror(err)); goto out; } pcmfmt = aufmt_to_alsaformat(st->aufmt); if (pcmfmt == SND_PCM_FORMAT_UNKNOWN) { warning("alsa: unknown sample format '%s'\n", aufmt_name(st->aufmt)); err = EINVAL; goto out; } err = alsa_reset(st->write, st->prm.srate, st->prm.ch, num_frames, pcmfmt); if (err) { warning("alsa: could not reset player '%s' (%s)\n", st->device, snd_strerror(err)); goto out; } st->run = true; err = pthread_create(&st->thread, NULL, write_thread, st); if (err) { st->run = false; goto out; } debug("alsa: playback started (%s)\n", st->device); out: if (err) mem_deref(st); else *stp = st; return err; }
static int src_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; struct sio_par *par = NULL; int err; const char *name; (void)ctx; (void)errh; if (!stp || !as || !prm) return EINVAL; name = (str_isset(device)) ? device : SIO_DEVANY; if ((st = mem_zalloc(sizeof(*st), ausrc_destructor)) == NULL) return ENOMEM; st->as = as; st->rh = rh; st->arg = arg; st->hdl = sio_open(name, SIO_REC, 0); if (!st->hdl) { warning("sndio: could not open ausrc device '%s'\n", name); err = EINVAL; goto out; } par = sndio_initpar(prm->srate, prm->ch); if (!par) { err = ENOMEM; goto out; } if (!sio_setpar(st->hdl, par)) { err = EINVAL; goto out; } if (!sio_getpar(st->hdl, par)) { err = EINVAL; goto out; } st->sampc = par->bufsz / 2; st->sampv = mem_alloc(2 * st->sampc, NULL); if (!st->sampv) { err = ENOMEM; goto out; } st->run = true; err = pthread_create(&st->thread, NULL, read_thread, st); if (err) st->run = false; out: mem_deref(par); if (err) mem_deref(st); else *stp = st; return err; }
static int alloc(struct vidcodec_st **stp, struct vidcodec *vc, const char *name, struct vidcodec_prm *encp, const char *fmtp, vidcodec_enq_h *enqh, vidcodec_send_h *sendh, void *arg) { struct vidcodec_st *st; int err = 0; if (!encp) return EINVAL; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->vc = mem_ref(vc); st->encprm = *encp; if (0 == str_casecmp(name, "H263")) st->codec_id = CODEC_ID_H263; else if (0 == str_casecmp(name, "H264")) st->codec_id = CODEC_ID_H264; else if (0 == str_casecmp(name, "MP4V-ES")) st->codec_id = CODEC_ID_MPEG4; else { err = EINVAL; goto out; } st->enc.mb = mbuf_alloc(FF_MIN_BUFFER_SIZE * 20); st->dec.mb = mbuf_alloc(1024); st->mb_frag = mbuf_alloc(1024); if (!st->enc.mb || !st->dec.mb || !st->mb_frag) { err = ENOMEM; goto out; } st->enc.sz_max = st->enc.mb->size; st->dec.sz_max = st->dec.mb->size; if (st->codec_id == CODEC_ID_H264) { #ifndef USE_X264 err = init_encoder(st); #endif } else err = init_encoder(st); if (err) { DEBUG_WARNING("%s: could not init encoder\n", name); goto out; } err = init_decoder(st); if (err) { DEBUG_WARNING("%s: could not init decoder\n", name); goto out; } if (str_isset(fmtp)) { struct pl sdp_fmtp; pl_set_str(&sdp_fmtp, fmtp); fmt_param_apply(&sdp_fmtp, param_handler, st); } st->enqh = enqh; st->sendh = sendh; st->arg = arg; re_printf("video codec %s: %d fps, %d bit/s\n", name, encp->fps, encp->bitrate); out: if (err) mem_deref(st); else *stp = st; return err; }
int alsa_src_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; snd_pcm_format_t pcmfmt; int num_frames; int err; (void)ctx; (void)errh; if (!stp || !as || !prm || !rh) return EINVAL; if (!str_isset(device)) device = alsa_dev; st = mem_zalloc(sizeof(*st), ausrc_destructor); if (!st) return ENOMEM; err = str_dup(&st->device, device); if (err) goto out; st->prm = *prm; st->as = as; st->rh = rh; st->arg = arg; st->aufmt = alsa_sample_format; st->sampc = prm->srate * prm->ch * prm->ptime / 1000; num_frames = st->prm.srate * st->prm.ptime / 1000; st->sampv = mem_alloc(2 * st->sampc, NULL); if (!st->sampv) { err = ENOMEM; goto out; } if (st->aufmt != AUFMT_S16LE) { size_t sz = aufmt_sample_size(st->aufmt) * st->sampc; st->xsampv = mem_alloc(sz, NULL); if (!st->xsampv) { err = ENOMEM; goto out; } } err = snd_pcm_open(&st->read, st->device, SND_PCM_STREAM_CAPTURE, 0); if (err < 0) { warning("alsa: could not open ausrc device '%s' (%s)\n", st->device, snd_strerror(err)); goto out; } pcmfmt = aufmt_to_alsaformat(st->aufmt); if (pcmfmt == SND_PCM_FORMAT_UNKNOWN) { warning("alsa: unknown sample format '%s'\n", aufmt_name(st->aufmt)); err = EINVAL; goto out; } err = alsa_reset(st->read, st->prm.srate, st->prm.ch, num_frames, pcmfmt); if (err) { warning("alsa: could not reset source '%s' (%s)\n", st->device, snd_strerror(err)); goto out; } st->run = true; err = pthread_create(&st->thread, NULL, read_thread, st); if (err) { st->run = false; goto out; } debug("alsa: recording started (%s)\n", st->device); out: if (err) mem_deref(st); else *stp = st; return err; }
int encode_update(struct videnc_state **vesp, const struct vidcodec *vc, struct videnc_param *prm, const char *fmtp, videnc_packet_h *pkth, void *arg) { struct videnc_state *st; int err = 0; if (!vesp || !vc || !prm || !pkth) return EINVAL; if (*vesp) return 0; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->encprm = *prm; st->pkth = pkth; st->arg = arg; st->codec_id = avcodec_resolve_codecid(vc->name); if (st->codec_id == AV_CODEC_ID_NONE) { err = EINVAL; goto out; } st->mb = mbuf_alloc(FF_MIN_BUFFER_SIZE * 20); st->mb_frag = mbuf_alloc(1024); if (!st->mb || !st->mb_frag) { err = ENOMEM; goto out; } st->sz_max = st->mb->size; if (st->codec_id == AV_CODEC_ID_H264) { #ifndef USE_X264 err = init_encoder(st); #endif } else err = init_encoder(st); if (err) { warning("avcodec: %s: could not init encoder\n", vc->name); goto out; } if (str_isset(fmtp)) { struct pl sdp_fmtp; pl_set_str(&sdp_fmtp, fmtp); fmt_param_apply(&sdp_fmtp, param_handler, st); } debug("avcodec: video encoder %s: %d fps, %d bit/s, pktsize=%u\n", vc->name, prm->fps, prm->bitrate, prm->pktsize); out: if (err) mem_deref(st); else *vesp = st; return err; }
int alsa_src_alloc(struct ausrc_st **stp, struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; int err; (void)ctx; (void)errh; if (!str_isset(device)) device = alsa_dev; st = mem_zalloc(sizeof(*st), ausrc_destructor); if (!st) return ENOMEM; st->as = mem_ref(as); st->rh = rh; st->arg = arg; st->sample_size = prm->ch * (prm->fmt == AUFMT_S16LE ? 2 : 1); st->frame_size = prm->frame_size; err = snd_pcm_open(&st->read, device, SND_PCM_STREAM_CAPTURE, 0); if (err < 0) { DEBUG_WARNING("read open: %s %s\n", device, snd_strerror(err)); goto out; } st->mbr = mbuf_alloc(st->sample_size * st->frame_size); if (!st->mbr) { err = ENOMEM; goto out; } err = alsa_reset(st->read, prm->srate, prm->ch, prm->fmt, prm->frame_size); if (err) goto out; /* Start */ err = snd_pcm_start(st->read); if (err) { DEBUG_WARNING("snd_pcm_start on read: %s\n", snd_strerror(err)); goto out; } st->run = true; err = pthread_create(&st->thread, NULL, read_thread, st); if (err) { st->run = false; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; }
static int alloc(struct aucodec_st **stp, struct aucodec *ac, struct aucodec_prm *encp, struct aucodec_prm *decp, const char *fmtp) { struct aucodec_st *st; const uint32_t srate = aucodec_srate(ac); const uint8_t ch = aucodec_ch(ac); int err = 0; (void)decp; st = mem_zalloc(sizeof(*st), celt_destructor); if (!st) return ENOMEM; st->ac = mem_ref(ac); st->bitrate = DEFAULT_BITRATE; st->low_overhead = celt_low_overhead; if (encp && encp->ptime) { st->frame_size = srate * ch * encp->ptime / 1000; DEBUG_NOTICE("calc ptime=%u ---> frame_size=%u\n", encp->ptime, st->frame_size); } else { st->frame_size = DEFAULT_FRAME_SIZE; } if (str_isset(fmtp)) decode_params(st, fmtp); /* Common mode */ st->mode = celt_mode_create(srate, st->frame_size, NULL); if (!st->mode) { DEBUG_WARNING("alloc: could not create CELT mode\n"); err = EPROTO; goto out; } #ifdef CELT_GET_FRAME_SIZE celt_mode_info(st->mode, CELT_GET_FRAME_SIZE, &st->frame_size); #endif st->fsize = 2 * st->frame_size * ch; st->bytes_per_packet = (st->bitrate * st->frame_size / srate + 4)/8; DEBUG_NOTICE("alloc: frame_size=%u bitrate=%ubit/s fsize=%u" " bytes_per_packet=%u\n", st->frame_size, st->bitrate, st->fsize, st->bytes_per_packet); /* Encoder */ #ifdef CELT_OLD_API st->enc = celt_encoder_create(st->mode, ch, NULL); #else st->enc = celt_encoder_create(srate, ch, NULL); #endif if (!st->enc) { DEBUG_WARNING("alloc: could not create CELT encoder\n"); err = EPROTO; goto out; } /* Decoder */ #ifdef CELT_OLD_API st->dec = celt_decoder_create(st->mode, ch, NULL); #else st->dec = celt_decoder_create(srate, ch, NULL); #endif if (!st->dec) { DEBUG_WARNING("alloc: could not create CELT decoder\n"); err = EPROTO; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; }
int icem_stund_recv(struct icem_comp *comp, const struct sa *src, struct stun_msg *req, size_t presz) { struct icem *icem = comp->icem; struct ice *ice = icem->ice; struct stun_attr *attr; struct pl lu, ru; enum role rrole = ROLE_UNKNOWN; uint64_t tiebrk = 0; uint32_t prio_prflx; bool use_cand = false; int err; /* RFC 5389: Fingerprint errors are silently discarded */ err = stun_msg_chk_fingerprint(req); if (err) return err; err = stun_msg_chk_mi(req, (uint8_t *)ice->lpwd, strlen(ice->lpwd)); if (err) { if (err == EBADMSG) goto unauth; else goto badmsg; } attr = stun_msg_attr(req, STUN_ATTR_USERNAME); if (!attr) goto badmsg; err = re_regex(attr->v.username, strlen(attr->v.username), "[^:]+:[^]+", &lu, &ru); if (err) { DEBUG_WARNING("could not parse USERNAME attribute (%s)\n", attr->v.username); goto unauth; } if (pl_strcmp(&lu, ice->lufrag)) goto unauth; if (str_isset(icem->rufrag) && pl_strcmp(&ru, icem->rufrag)) goto unauth; attr = stun_msg_attr(req, STUN_ATTR_CONTROLLED); if (attr) { rrole = ROLE_CONTROLLED; tiebrk = attr->v.uint64; } attr = stun_msg_attr(req, STUN_ATTR_CONTROLLING); if (attr) { rrole = ROLE_CONTROLLING; tiebrk = attr->v.uint64; } if (rrole == ice->lrole) { if (ice->tiebrk >= tiebrk) ice_switch_local_role(ice); else goto conflict; } attr = stun_msg_attr(req, STUN_ATTR_PRIORITY); if (attr) prio_prflx = attr->v.uint32; else goto badmsg; attr = stun_msg_attr(req, STUN_ATTR_USE_CAND); if (attr) use_cand = true; err = handle_stun(ice, icem, comp, src, prio_prflx, use_cand, presz > 0); if (err) goto badmsg; return stun_reply(icem->proto, comp->sock, src, presz, req, (uint8_t *)ice->lpwd, strlen(ice->lpwd), true, 2, STUN_ATTR_XOR_MAPPED_ADDR, src, STUN_ATTR_SOFTWARE, sw); badmsg: return stunsrv_ereply(comp, src, presz, req, 400, "Bad Request"); unauth: return stunsrv_ereply(comp, src, presz, req, 401, "Unauthorized"); conflict: return stunsrv_ereply(comp, src, presz, req, 487, "Role Conflict"); }
int trice_stund_recv(struct trice *icem, struct ice_lcand *lcand, void *sock, const struct sa *src, struct stun_msg *req, size_t presz) { struct stun_attr *attr; struct pl lu, ru; bool remote_controlling; uint64_t tiebrk = 0; uint32_t prio_prflx; bool use_cand = false; int err; /* RFC 5389: Fingerprint errors are silently discarded */ err = stun_msg_chk_fingerprint(req); if (err) return err; err = stun_msg_chk_mi(req, (uint8_t *)icem->lpwd, strlen(icem->lpwd)); if (err) { DEBUG_WARNING("message-integrity failed (src=%J)\n", src); if (err == EBADMSG) goto unauth; else goto badmsg; } attr = stun_msg_attr(req, STUN_ATTR_USERNAME); if (!attr) goto badmsg; err = re_regex(attr->v.username, strlen(attr->v.username), "[^:]+:[^]+", &lu, &ru); if (err) { DEBUG_WARNING("could not parse USERNAME attribute (%s)\n", attr->v.username); goto unauth; } if (pl_strcmp(&lu, icem->lufrag)) { DEBUG_WARNING("local ufrag err (expected %s, actual %r)\n", icem->lufrag, &lu); goto unauth; } if (str_isset(icem->rufrag) && pl_strcmp(&ru, icem->rufrag)) { DEBUG_WARNING("remote ufrag err (expected %s, actual %r)\n", icem->rufrag, &ru); goto unauth; } attr = stun_msg_attr(req, STUN_ATTR_CONTROLLED); if (attr) { remote_controlling = false; tiebrk = attr->v.uint64; } attr = stun_msg_attr(req, STUN_ATTR_CONTROLLING); if (attr) { remote_controlling = true; tiebrk = attr->v.uint64; } if (remote_controlling == icem->controlling) { if (icem->tiebrk >= tiebrk) trice_switch_local_role(icem); else goto conflict; } attr = stun_msg_attr(req, STUN_ATTR_PRIORITY); if (attr) prio_prflx = attr->v.uint32; else goto badmsg; attr = stun_msg_attr(req, STUN_ATTR_USE_CAND); if (attr) use_cand = true; err = handle_stun_full(icem, lcand, sock, src, prio_prflx, use_cand); if (err) goto badmsg; trice_tracef(icem, 32, "[%u] STUNSRV: Tx success respons [%H ---> %J]\n", lcand->attr.compid, trice_cand_print, lcand, src); return stun_reply(lcand->attr.proto, sock, src, presz, req, (uint8_t *)icem->lpwd, strlen(icem->lpwd), true, 2, STUN_ATTR_XOR_MAPPED_ADDR, src, STUN_ATTR_SOFTWARE, icem->sw ? icem->sw : sw); badmsg: return stunsrv_ereply(icem, lcand, sock, src, presz, req, 400, "Bad Request"); unauth: return stunsrv_ereply(icem, lcand, sock, src, presz, req, 401, "Unauthorized"); conflict: return stunsrv_ereply(icem, lcand, sock, src, presz, req, 487, "Role Conflict"); }