/* API: find device */ PJ_DEF(pj_status_t) pjmedia_aud_dev_lookup( const char *drv_name, const char *dev_name, pjmedia_aud_dev_index *id) { pjmedia_aud_dev_factory *f = NULL; unsigned drv_idx, dev_idx; PJ_ASSERT_RETURN(drv_name && dev_name && id, PJ_EINVAL); //PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT); // DEAN don't assertion if (!aud_subsys.pf) return PJMEDIA_EAUD_INIT; for (drv_idx=0; drv_idx<aud_subsys.drv_cnt; ++drv_idx) { if (!pj_ansi_stricmp(drv_name, aud_subsys.drv[drv_idx].name)) { f = aud_subsys.drv[drv_idx].f; break; } } if (!f) { PJ_LOG(4, (THIS_FILE, "pjmedia_aud_dev_lookup() pjmedia_aud_dev_factory not found.")); return PJ_ENOTFOUND; } for (dev_idx=0; dev_idx<aud_subsys.drv[drv_idx].dev_cnt; ++dev_idx) { pjmedia_aud_dev_info info; pj_status_t status; status = f->op->get_dev_info(f, dev_idx, &info); if (status != PJ_SUCCESS) return status; if (!pj_ansi_stricmp(dev_name, info.name)) break; } if (dev_idx==aud_subsys.drv[drv_idx].dev_cnt) { PJ_LOG(4, (THIS_FILE, "pjmedia_aud_dev_lookup() aud_subsys.drv not found.")); return PJ_ENOTFOUND; } *id = dev_idx; make_global_index(drv_idx, id); return PJ_SUCCESS; }
/** * Get TAG reason code from pjsip_event */ int get_reason_code(pjsip_event *e, char* tag, int (*code_parser)(const char*)) { int code = 0; const pj_str_t HDR = { "Reason", 6 }; pj_bool_t has_tag = PJ_FALSE; if (e->body.tsx_state.type == PJSIP_EVENT_RX_MSG) { pjsip_generic_string_hdr *hdr = (pjsip_generic_string_hdr*) pjsip_msg_find_hdr_by_name( e->body.tsx_state.src.rdata->msg_info.msg, &HDR, NULL); // TODO : check if the header should not be parsed here? -- I don't see how it could work without parsing. if (hdr) { char *reason_header = strdup(hdr->hvalue.ptr); char *token = strtok(reason_header, ";"); while (token != NULL) { if (!has_tag && pj_ansi_stricmp(token, tag) == 0) { has_tag = PJ_TRUE; } else if (code == 0) { code = code_parser(token); } token = strtok(NULL, ";"); } free(reason_header); } } return (has_tag) ? code : 0; }
/** * Get Q.850 reason code from pjsip_event */ int get_q850_reason_code(pjsip_event *e) { int cause = 0; const pj_str_t HDR = { "Reason", 6 }; pj_bool_t is_q850 = PJ_FALSE; if (e->body.tsx_state.type == PJSIP_EVENT_RX_MSG) { pjsip_generic_string_hdr *hdr = (pjsip_generic_string_hdr*) pjsip_msg_find_hdr_by_name( e->body.tsx_state.src.rdata->msg_info.msg, &HDR, NULL); if (hdr) { char *token = strtok(hdr->hvalue.ptr, ";"); while (token != NULL) { if (!is_q850 && pj_ansi_stricmp(token, "Q.850") == 0) { is_q850 = PJ_TRUE; } else if (cause == 0) { cause = lookup_q850_cause(token); } token = strtok(NULL, ";"); } } } return (is_q850) ? cause : 0; }
/** * Utility to extract code from SIP cause */ int lookup_sip_cause(const char *cause) { if (pj_ansi_stricmp(cause, "cause=200") == 0) { return 200; // only useful reason code for now } else { return 0; } }
/* API: find device */ PJ_DEF(pj_status_t) pjmedia_vid_dev_lookup( const char *drv_name, const char *dev_name, pjmedia_vid_dev_index *id) { pjmedia_vid_dev_factory *f = NULL; unsigned drv_idx, dev_idx; PJ_ASSERT_RETURN(drv_name && dev_name && id, PJ_EINVAL); PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT); for (drv_idx=0; drv_idx<vid_subsys.drv_cnt; ++drv_idx) { if (!pj_ansi_stricmp(drv_name, vid_subsys.drv[drv_idx].name)) { f = vid_subsys.drv[drv_idx].f; break; } } if (!f) return PJ_ENOTFOUND; for (dev_idx=0; dev_idx<vid_subsys.drv[drv_idx].dev_cnt; ++dev_idx) { pjmedia_vid_dev_info info; pj_status_t status; status = f->op->get_dev_info(f, dev_idx, &info); if (status != PJ_SUCCESS) return status; if (!pj_ansi_stricmp(dev_name, info.name)) break; } if (dev_idx==vid_subsys.drv[drv_idx].dev_cnt) return PJ_ENOTFOUND; *id = dev_idx; make_global_index(drv_idx, id); return PJ_SUCCESS; }
static pj_bool_t parse_test_headers(char *line, test_param_t *param, test_cond_t *cond) { char *p = line; if (*p == '%') { /* Test params. */ char mode_st[16]; sscanf(p+1, "%s %u %u %u", mode_st, ¶m->init_prefetch, ¶m->min_prefetch, ¶m->max_prefetch); param->adaptive = (pj_ansi_stricmp(mode_st, "adaptive") == 0); } else if (*p == '!') { /* Success condition. */ char cond_st[16]; unsigned cond_val; sscanf(p+1, "%s %u", cond_st, &cond_val); if (pj_ansi_stricmp(cond_st, "burst") == 0) cond->burst = cond_val; else if (pj_ansi_stricmp(cond_st, "delay") == 0) cond->delay = cond_val; else if (pj_ansi_stricmp(cond_st, "delay_min") == 0) cond->delay_min = cond_val; else if (pj_ansi_stricmp(cond_st, "discard") == 0) cond->discard = cond_val; else if (pj_ansi_stricmp(cond_st, "empty") == 0) cond->empty = cond_val; else if (pj_ansi_stricmp(cond_st, "lost") == 0) cond->lost = cond_val; } else if (*p == '=') { /* Test title. */ ++p; while (*p && isspace(*p)) ++p; printf("%s", p); } else if (*p == '#') { /* Ignore comment line. */ } else { /* Unknown header, perhaps this is the test data */ /* Skip spaces */ while (*p && isspace(*p)) ++p; /* Test data started.*/ if (*p != 0) return PJ_FALSE; } return PJ_TRUE; }
/* Get cipher identifier */ PJ_DEF(pj_ssl_cipher) pj_ssl_cipher_id(const char *cipher_name) { unsigned i; if (ciphers_num_ == 0) { pj_ssl_cipher c[1]; i = 0; pj_ssl_cipher_get_availables(c, &i); } for (i = 0; i < ciphers_num_; ++i) { if (!pj_ansi_stricmp(ciphers_[i].name, cipher_name)) return ciphers_[i].id; } return PJ_TLS_UNKNOWN_CIPHER; }
/** * Utility from freeswitch to extract code from q.850 cause */ int lookup_q850_cause(const char *cause) { // Taken from http://wiki.freeswitch.org/wiki/Hangup_causes if (pj_ansi_stricmp(cause, "cause=1") == 0) { return 404; } else if (pj_ansi_stricmp(cause, "cause=2") == 0) { return 404; } else if (pj_ansi_stricmp(cause, "cause=3") == 0) { return 404; } else if (pj_ansi_stricmp(cause, "cause=17") == 0) { return 486; } else if (pj_ansi_stricmp(cause, "cause=18") == 0) { return 408; } else if (pj_ansi_stricmp(cause, "cause=19") == 0) { return 480; } else if (pj_ansi_stricmp(cause, "cause=20") == 0) { return 480; } else if (pj_ansi_stricmp(cause, "cause=21") == 0) { return 603; } else if (pj_ansi_stricmp(cause, "cause=22") == 0) { return 410; } else if (pj_ansi_stricmp(cause, "cause=23") == 0) { return 410; } else if (pj_ansi_stricmp(cause, "cause=25") == 0) { return 483; } else if (pj_ansi_stricmp(cause, "cause=27") == 0) { return 502; } else if (pj_ansi_stricmp(cause, "cause=28") == 0) { return 484; } else if (pj_ansi_stricmp(cause, "cause=29") == 0) { return 501; } else if (pj_ansi_stricmp(cause, "cause=31") == 0) { return 480; } else if (pj_ansi_stricmp(cause, "cause=34") == 0) { return 503; } else if (pj_ansi_stricmp(cause, "cause=38") == 0) { return 503; } else if (pj_ansi_stricmp(cause, "cause=41") == 0) { return 503; } else if (pj_ansi_stricmp(cause, "cause=42") == 0) { return 503; } else if (pj_ansi_stricmp(cause, "cause=44") == 0) { return 503; } else if (pj_ansi_stricmp(cause, "cause=52") == 0) { return 403; } else if (pj_ansi_stricmp(cause, "cause=54") == 0) { return 403; } else if (pj_ansi_stricmp(cause, "cause=57") == 0) { return 403; } else if (pj_ansi_stricmp(cause, "cause=58") == 0) { return 503; } else if (pj_ansi_stricmp(cause, "cause=65") == 0) { return 488; } else if (pj_ansi_stricmp(cause, "cause=69") == 0) { return 501; } else if (pj_ansi_stricmp(cause, "cause=79") == 0) { return 501; } else if (pj_ansi_stricmp(cause, "cause=88") == 0) { return 488; } else if (pj_ansi_stricmp(cause, "cause=102") == 0) { return 504; } else if (pj_ansi_stricmp(cause, "cause=487") == 0) { return 487; } else { return 0; } }
/* Parse crypto attribute line */ static pj_status_t parse_attr_crypto(pj_pool_t *pool, const pjmedia_sdp_attr *attr, pjmedia_srtp_crypto *crypto, int *tag) { pj_str_t input; char *token; int token_len; pj_str_t tmp; pj_status_t status; int itmp; pj_bzero(crypto, sizeof(*crypto)); pj_strdup_with_null(pool, &input, &attr->value); /* Tag */ token = strtok(input.ptr, " "); if (!token) { PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting tag")); return PJMEDIA_SDP_EINATTR; } token_len = pj_ansi_strlen(token); /* Tag must not use leading zeroes. */ if (token_len > 1 && *token == '0') return PJMEDIA_SDP_EINATTR; /* Tag must be decimal, i.e: contains only digit '0'-'9'. */ for (itmp = 0; itmp < token_len; ++itmp) if (!pj_isdigit(token[itmp])) return PJMEDIA_SDP_EINATTR; /* Get tag value. */ *tag = atoi(token); /* Crypto-suite */ token = strtok(NULL, " "); if (!token) { PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting crypto suite")); return PJMEDIA_SDP_EINATTR; } crypto->name = pj_str(token); /* Key method */ token = strtok(NULL, ":"); if (!token) { PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting key method")); return PJMEDIA_SDP_EINATTR; } if (pj_ansi_stricmp(token, "inline")) { PJ_LOG(4,(THIS_FILE, "Attribute crypto key method '%s' not supported!", token)); return PJMEDIA_SDP_EINATTR; } /* Key */ token = strtok(NULL, "| "); if (!token) { PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting key")); return PJMEDIA_SDP_EINATTR; } tmp = pj_str(token); crypto->key.ptr = (char*) pj_pool_zalloc(pool, MAX_KEY_LEN); /* Decode key */ itmp = MAX_KEY_LEN; status = pj_base64_decode(&tmp, (pj_uint8_t*)crypto->key.ptr, &itmp); if (status != PJ_SUCCESS) { PJ_LOG(4,(THIS_FILE, "Failed decoding crypto key from base64")); return status; } crypto->key.slen = itmp; return PJ_SUCCESS; }
static int encode_decode_test(pj_pool_t *pool, const char *codec_id, pjmedia_vid_packing packing) { const pj_str_t port_name = {"codec", 5}; pjmedia_vid_codec *codec=NULL; pjmedia_port codec_port; codec_port_data_t codec_port_data; pjmedia_vid_codec_param codec_param; const pjmedia_vid_codec_info *codec_info; const char *packing_name; pjmedia_vid_dev_index cap_idx, rdr_idx; pjmedia_vid_port *capture=NULL, *renderer=NULL; pjmedia_vid_port_param vport_param; pjmedia_video_format_detail *vfd; char codec_name[5]; pj_status_t status; int rc = 0; switch (packing) { case PJMEDIA_VID_PACKING_PACKETS: packing_name = "framed"; break; case PJMEDIA_VID_PACKING_WHOLE: packing_name = "whole"; break; default: packing_name = "unknown"; break; } PJ_LOG(3, (THIS_FILE, " encode decode test: codec=%s, packing=%s", codec_id, packing_name)); /* Lookup codec */ { pj_str_t codec_id_st; unsigned info_cnt = 1; /* Lookup codec */ pj_cstr(&codec_id_st, codec_id); status = pjmedia_vid_codec_mgr_find_codecs_by_id(NULL, &codec_id_st, &info_cnt, &codec_info, NULL); if (status != PJ_SUCCESS) { rc = 205; goto on_return; } } #if CAPTURE_DEV == -1 /* Lookup colorbar source */ status = pjmedia_vid_dev_lookup("Colorbar", "Colorbar generator", &cap_idx); if (status != PJ_SUCCESS) { rc = 206; goto on_return; } #elif CAPTURE_DEV == -2 /* Lookup any first non-colorbar source */ { unsigned i, cnt; pjmedia_vid_dev_info info; cap_idx = -1; cnt = pjmedia_vid_dev_count(); for (i = 0; i < cnt; ++i) { status = pjmedia_vid_dev_get_info(i, &info); if (status != PJ_SUCCESS) { rc = 206; goto on_return; } if (info.dir & PJMEDIA_DIR_CAPTURE && pj_ansi_stricmp(info.driver, "Colorbar")) { cap_idx = i; break; } } if (cap_idx == -1) { status = PJ_ENOTFOUND; rc = 206; goto on_return; } } #else cap_idx = CAPTURE_DEV; #endif /* Lookup SDL renderer */ status = pjmedia_vid_dev_lookup("SDL", "SDL renderer", &rdr_idx); if (status != PJ_SUCCESS) { rc = 207; goto on_return; } /* Prepare codec */ { pj_str_t codec_id_st; unsigned info_cnt = 1; const pjmedia_vid_codec_info *codec_info; /* Lookup codec */ pj_cstr(&codec_id_st, codec_id); status = pjmedia_vid_codec_mgr_find_codecs_by_id(NULL, &codec_id_st, &info_cnt, &codec_info, NULL); if (status != PJ_SUCCESS) { rc = 245; goto on_return; } status = pjmedia_vid_codec_mgr_get_default_param(NULL, codec_info, &codec_param); if (status != PJ_SUCCESS) { rc = 246; goto on_return; } codec_param.packing = packing; /* Open codec */ status = pjmedia_vid_codec_mgr_alloc_codec(NULL, codec_info, &codec); if (status != PJ_SUCCESS) { rc = 250; goto on_return; } status = pjmedia_vid_codec_init(codec, pool); if (status != PJ_SUCCESS) { rc = 251; goto on_return; } status = pjmedia_vid_codec_open(codec, &codec_param); if (status != PJ_SUCCESS) { rc = 252; goto on_return; } /* After opened, codec will update the param, let's sync encoder & * decoder format detail. */ codec_param.dec_fmt.det = codec_param.enc_fmt.det; /* Subscribe to codec events */ pjmedia_event_subscribe(NULL, &codec_on_event, &codec_port_data, codec); } pjmedia_vid_port_param_default(&vport_param); /* Create capture, set it to active (master) */ status = pjmedia_vid_dev_default_param(pool, cap_idx, &vport_param.vidparam); if (status != PJ_SUCCESS) { rc = 220; goto on_return; } pjmedia_format_copy(&vport_param.vidparam.fmt, &codec_param.dec_fmt); vport_param.vidparam.dir = PJMEDIA_DIR_CAPTURE; vport_param.active = PJ_TRUE; if (vport_param.vidparam.fmt.detail_type != PJMEDIA_FORMAT_DETAIL_VIDEO) { rc = 221; goto on_return; } vfd = pjmedia_format_get_video_format_detail(&vport_param.vidparam.fmt, PJ_TRUE); if (vfd == NULL) { rc = 225; goto on_return; } status = pjmedia_vid_port_create(pool, &vport_param, &capture); if (status != PJ_SUCCESS) { rc = 226; goto on_return; } /* Create renderer, set it to passive (slave) */ vport_param.active = PJ_FALSE; vport_param.vidparam.dir = PJMEDIA_DIR_RENDER; vport_param.vidparam.rend_id = rdr_idx; vport_param.vidparam.disp_size = vfd->size; status = pjmedia_vid_port_create(pool, &vport_param, &renderer); if (status != PJ_SUCCESS) { rc = 230; goto on_return; } /* Init codec port */ pj_bzero(&codec_port, sizeof(codec_port)); status = pjmedia_port_info_init2(&codec_port.info, &port_name, 0x1234, PJMEDIA_DIR_ENCODING, &codec_param.dec_fmt); if (status != PJ_SUCCESS) { rc = 260; goto on_return; } codec_port_data.codec = codec; codec_port_data.rdr_port = renderer; codec_port_data.enc_buf_size = codec_param.dec_fmt.det.vid.size.w * codec_param.dec_fmt.det.vid.size.h * 4; codec_port_data.enc_buf = pj_pool_alloc(pool, codec_port_data.enc_buf_size); codec_port_data.pack_buf_size = codec_port_data.enc_buf_size; codec_port_data.pack_buf = pj_pool_alloc(pool, codec_port_data.pack_buf_size); codec_port.put_frame = &codec_put_frame; codec_port.port_data.pdata = &codec_port_data; /* Connect capture to codec port */ status = pjmedia_vid_port_connect(capture, &codec_port, PJ_FALSE); if (status != PJ_SUCCESS) { rc = 270; goto on_return; } PJ_LOG(3, (THIS_FILE, " starting codec test: %s<->%.*s %dx%d", pjmedia_fourcc_name(codec_param.dec_fmt.id, codec_name), codec_info->encoding_name.slen, codec_info->encoding_name.ptr, codec_param.dec_fmt.det.vid.size.w, codec_param.dec_fmt.det.vid.size.h )); /* Start streaming.. */ status = pjmedia_vid_port_start(renderer); if (status != PJ_SUCCESS) { rc = 275; goto on_return; } status = pjmedia_vid_port_start(capture); if (status != PJ_SUCCESS) { rc = 280; goto on_return; } /* Sleep while the video is being displayed... */ pj_thread_sleep(10000); on_return: if (status != PJ_SUCCESS) { PJ_PERROR(3, (THIS_FILE, status, " error")); } if (capture) pjmedia_vid_port_stop(capture); if (renderer) pjmedia_vid_port_stop(renderer); if (capture) pjmedia_vid_port_destroy(capture); if (renderer) pjmedia_vid_port_destroy(renderer); if (codec) { pjmedia_event_unsubscribe(NULL, &codec_on_event, &codec_port_data, codec); pjmedia_vid_codec_close(codec); pjmedia_vid_codec_mgr_dealloc_codec(NULL, codec); } return rc; }
/* * Set default codec parameter. */ PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_set_default_param( pjmedia_vid_codec_mgr *mgr, const pjmedia_vid_codec_info *info, const pjmedia_vid_codec_param *param ) { unsigned i; pjmedia_codec_id codec_id; pjmedia_vid_codec_desc *codec_desc = NULL; pj_pool_t *pool, *old_pool = NULL; pjmedia_vid_codec_default_param *p; PJ_ASSERT_RETURN(info, PJ_EINVAL); if (!mgr) mgr = def_vid_codec_mgr; PJ_ASSERT_RETURN(mgr, PJ_EINVAL); if (!pjmedia_vid_codec_info_to_id(info, (char*)&codec_id, sizeof(codec_id))) return PJ_EINVAL; pj_mutex_lock(mgr->mutex); /* Lookup codec desc */ for (i=0; i < mgr->codec_cnt; ++i) { if (pj_ansi_stricmp(codec_id, mgr->codec_desc[i].id) == 0) { codec_desc = &mgr->codec_desc[i]; break; } } /* Codec not found */ if (!codec_desc) { pj_mutex_unlock(mgr->mutex); return PJMEDIA_CODEC_EUNSUP; } /* If codec param is previously set */ if (codec_desc->def_param) { pj_assert(codec_desc->def_param->pool); old_pool = codec_desc->def_param->pool; codec_desc->def_param = NULL; } /* When param is set to NULL, i.e: setting default codec param to library * default setting, just return PJ_SUCCESS. */ if (NULL == param) { pj_mutex_unlock(mgr->mutex); if (old_pool) pj_pool_release(old_pool); return PJ_SUCCESS; } /* Create new default codec param instance */ pool = pj_pool_create(mgr->pf, (char*)codec_id, 256, 256, NULL); codec_desc->def_param = PJ_POOL_ZALLOC_T(pool, pjmedia_vid_codec_default_param); p = codec_desc->def_param; p->pool = pool; /* Update codec default param */ p->param = pjmedia_vid_codec_param_clone(pool, param); if (!p) return PJ_EINVAL; codec_desc->def_param = p; pj_mutex_unlock(mgr->mutex); return PJ_SUCCESS; }
/* * Get default codec parameter. */ PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_get_default_param( pjmedia_vid_codec_mgr *mgr, const pjmedia_vid_codec_info *info, pjmedia_vid_codec_param *param ) { pjmedia_vid_codec_factory *factory; pj_status_t status; pjmedia_codec_id codec_id; pjmedia_vid_codec_desc *codec_desc = NULL; unsigned i; PJ_ASSERT_RETURN(info && param, PJ_EINVAL); if (!mgr) mgr = def_vid_codec_mgr; PJ_ASSERT_RETURN(mgr, PJ_EINVAL); if (!pjmedia_vid_codec_info_to_id(info, (char*)&codec_id, sizeof(codec_id))) return PJ_EINVAL; pj_mutex_lock(mgr->mutex); /* First, lookup default param in codec desc */ for (i=0; i < mgr->codec_cnt; ++i) { if (pj_ansi_stricmp(codec_id, mgr->codec_desc[i].id) == 0) { codec_desc = &mgr->codec_desc[i]; break; } } /* If we found the codec and its default param is set, return it */ if (codec_desc && codec_desc->def_param) { pj_memcpy(param, codec_desc->def_param->param, sizeof(pjmedia_vid_codec_param)); pj_mutex_unlock(mgr->mutex); return PJ_SUCCESS; } /* Otherwise query the default param from codec factory */ factory = mgr->factory_list.next; while (factory != &mgr->factory_list) { if ( (*factory->op->test_alloc)(factory, info) == PJ_SUCCESS ) { status = (*factory->op->default_attr)(factory, info, param); if (status == PJ_SUCCESS) { /* Check for invalid max_bps. */ //if (param->info.max_bps < param->info.avg_bps) // param->info.max_bps = param->info.avg_bps; pj_mutex_unlock(mgr->mutex); return PJ_SUCCESS; } } factory = factory->next; } pj_mutex_unlock(mgr->mutex); return PJMEDIA_CODEC_EUNSUP; }
/* * Decode test * * Decode the specified encoded file in "in_encoded_file" into temporary * PCM output file, and compare the temporary PCM output file with * the PCM reference file. * * Some reference file requires manipulation to the PCM output * before comparison, such manipulation can be done by supplying * this function with the "manip" function. */ static int codec_test_decode(pjmedia_codec_mgr *mgr, char *codec_name, unsigned bitrate, unsigned encoded_len, const char *in_encoded_file, const char *ref_pcm_file, void (*manip)(short *pcm, unsigned count)) { pj_str_t codec_id = pj_str(codec_name); pj_pool_t *pool = NULL; unsigned count, samples_per_frame, pos; pjmedia_codec *codec = NULL; const pjmedia_codec_info *ci[1]; pjmedia_codec_param codec_param; pjmedia_frame out_frame; void *pkt; FILE *input = NULL, *output = NULL, *fref = NULL; pj_bool_t is_itu_format = PJ_FALSE; int rc = 0; pj_status_t status; pool = pj_pool_create(mem, "codec-vectors", 512, 512, NULL); if (!pool) { rc = -20; goto on_return; } /* Find and open the codec */ count = 1; status = pjmedia_codec_mgr_find_codecs_by_id(mgr, &codec_id, &count, ci, NULL); if (status != PJ_SUCCESS) { rc = -30; goto on_return; } status = pjmedia_codec_mgr_alloc_codec(mgr, ci[0], &codec); if (status != PJ_SUCCESS) { rc = -40; goto on_return; } status = pjmedia_codec_mgr_get_default_param(mgr, ci[0], &codec_param); if (status != PJ_SUCCESS) { rc = -50; goto on_return; } codec_param.info.avg_bps = bitrate; codec_param.setting.vad = 0; /* For G7221, the bitrate is set via param.setting.dec_fmtp, if it has * no info about bitrate, the codec will check info.avg_bps. So, let's * just clear the SDP fmtp. */ if (pj_ansi_strstr(codec_name, "G7221/")) { codec_param.setting.dec_fmtp.cnt = 0; } status = pjmedia_codec_init(codec, pool); if (status != PJ_SUCCESS) { rc = -60; goto on_return; } status = pjmedia_codec_open(codec, &codec_param); if (status != PJ_SUCCESS) { rc = -70; goto on_return; } /* Open input file */ input = fopen(in_encoded_file, "rb"); if (!input) { rc = -80; goto on_return; } /* Is the file in ITU format? */ is_itu_format = pj_ansi_stricmp(in_encoded_file+strlen(in_encoded_file)-4, ".itu")==0; /* Open output file */ output = fopen(TMP_OUT, "wb"); if (!output) { rc = -90; goto on_return; } /* Allocate buffer for PCM and encoded frames */ samples_per_frame = codec_param.info.clock_rate * codec_param.info.frm_ptime / 1000; pkt = pj_pool_alloc(pool, samples_per_frame * 2); out_frame.buf = (pj_uint8_t*) pj_pool_alloc(pool, samples_per_frame * 2); /* Loop read WAV file and encode and write to output file */ for (;;) { pjmedia_frame in_frame[2]; pj_timestamp ts; unsigned count; pj_bool_t has_frame; if (is_itu_format) { int nsamp; short frame_err = 0; nsamp = read_ITU_format(input, (short*)pkt, &frame_err, encoded_len / 2, PJ_TRUE); if (nsamp != (int)encoded_len / 2) break; has_frame = !frame_err; } else { if (fread(pkt, encoded_len, 1, input) != 1) break; has_frame = PJ_TRUE; } if (has_frame) { count = 2; if (pjmedia_codec_parse(codec, pkt, encoded_len, &ts, &count, in_frame) != PJ_SUCCESS) { rc = -100; goto on_return; } if (count != 1) { rc = -110; goto on_return; } if (pjmedia_codec_decode(codec, &in_frame[0], samples_per_frame*2, &out_frame) != PJ_SUCCESS) { rc = -120; goto on_return; } } else { if (pjmedia_codec_recover(codec, samples_per_frame*2, &out_frame) != PJ_SUCCESS) { rc = -125; goto on_return; } } if (manip) manip((short*)out_frame.buf, samples_per_frame); if (fwrite(out_frame.buf, out_frame.size, 1, output) != 1) { rc = -130; goto on_return; } } fclose(input); input = NULL; fclose(output); output = NULL; /* Compare encoded files */ fref = fopen(ref_pcm_file, "rb"); if (!fref) { rc = -140; goto on_return; } output = fopen(TMP_OUT, "rb"); if (!output) { rc = -110; goto on_return; } pos = 0; for (;;) { pj_size_t count; count = fread(pkt, samples_per_frame*2, 1, fref); if (count != 1) break; count = fread(out_frame.buf, samples_per_frame*2, 1, output); if (count != 1) break; if (memcmp(pkt, out_frame.buf, samples_per_frame*2)) { unsigned i; pj_int16_t *in = (pj_int16_t*)pkt; pj_int16_t *out = (pj_int16_t*)out_frame.buf; for (i=0; i<samples_per_frame; ++i) { if (in[i] != out[i]) break; } PJ_LOG(1,(THIS_FILE," failed: mismatch at samples %d", pos+i)); rc = -200; break; } pos += samples_per_frame; } on_return: if (output) fclose(output); if (fref) fclose(fref); if (input) fclose(input); if (codec) { pjmedia_codec_close(codec); pjmedia_codec_mgr_dealloc_codec(mgr, codec); } if (pool) pj_pool_release(pool); return rc; }
/** * Utility from freeswitch to extract code from q.850 cause */ int lookup_q850_cause(const char *cause) { // VoX Mobile // // Re-purposed Q.850 codes that are necessary for prepaid services. if (pj_ansi_stricmp(cause, "cause=602") == 0) { // prepaid caller credit card was declined return 901; } else if (pj_ansi_stricmp(cause, "cause=603") == 0) { // prepaid caller out cash, called location requires cash return 902; } else if (pj_ansi_stricmp(cause, "cause=604") == 0) { // prepaid caller out of funds (minutes and cash) return 903; } // Taken from http://wiki.freeswitch.org/wiki/Hangup_causes if (pj_ansi_stricmp(cause, "cause=1") == 0) { return 404; } else if (pj_ansi_stricmp(cause, "cause=2") == 0) { return 404; } else if (pj_ansi_stricmp(cause, "cause=3") == 0) { return 404; } else if (pj_ansi_stricmp(cause, "cause=17") == 0) { return 486; } else if (pj_ansi_stricmp(cause, "cause=18") == 0) { return 408; } else if (pj_ansi_stricmp(cause, "cause=19") == 0) { return 480; } else if (pj_ansi_stricmp(cause, "cause=20") == 0) { return 480; } else if (pj_ansi_stricmp(cause, "cause=21") == 0) { return 603; } else if (pj_ansi_stricmp(cause, "cause=22") == 0) { return 410; } else if (pj_ansi_stricmp(cause, "cause=23") == 0) { return 410; } else if (pj_ansi_stricmp(cause, "cause=25") == 0) { return 483; } else if (pj_ansi_stricmp(cause, "cause=27") == 0) { return 502; } else if (pj_ansi_stricmp(cause, "cause=28") == 0) { return 484; } else if (pj_ansi_stricmp(cause, "cause=29") == 0) { return 501; } else if (pj_ansi_stricmp(cause, "cause=31") == 0) { return 480; } else if (pj_ansi_stricmp(cause, "cause=34") == 0) { return 503; } else if (pj_ansi_stricmp(cause, "cause=38") == 0) { return 503; } else if (pj_ansi_stricmp(cause, "cause=41") == 0) { return 503; } else if (pj_ansi_stricmp(cause, "cause=42") == 0) { return 503; } else if (pj_ansi_stricmp(cause, "cause=44") == 0) { return 503; } else if (pj_ansi_stricmp(cause, "cause=52") == 0) { return 403; } else if (pj_ansi_stricmp(cause, "cause=54") == 0) { return 403; } else if (pj_ansi_stricmp(cause, "cause=57") == 0) { return 403; } else if (pj_ansi_stricmp(cause, "cause=58") == 0) { return 503; } else if (pj_ansi_stricmp(cause, "cause=65") == 0) { return 488; } else if (pj_ansi_stricmp(cause, "cause=69") == 0) { return 501; } else if (pj_ansi_stricmp(cause, "cause=79") == 0) { return 501; } else if (pj_ansi_stricmp(cause, "cause=88") == 0) { return 488; } else if (pj_ansi_stricmp(cause, "cause=102") == 0) { return 504; } else if (pj_ansi_stricmp(cause, "cause=487") == 0) { return 487; } else { return 0; } }
/* Parse a=candidate line */ static pj_status_t parse_cand(const char *obj_name, pj_pool_t *pool, const pj_str_t *orig_input, pj_ice_sess_cand *cand) { pj_str_t input; char *token, *host; int af; pj_str_t s; pj_status_t status = PJNATH_EICEINCANDSDP; pj_bzero(cand, sizeof(*cand)); pj_strdup_with_null(pool, &input, orig_input); PJ_UNUSED_ARG(obj_name); /* Foundation */ token = strtok(input.ptr, " "); if (!token) { TRACE__((obj_name, "Expecting ICE foundation in candidate")); goto on_return; } pj_strdup2(pool, &cand->foundation, token); /* Component ID */ token = strtok(NULL, " "); if (!token) { TRACE__((obj_name, "Expecting ICE component ID in candidate")); goto on_return; } cand->comp_id = (pj_uint8_t) atoi(token); /* Transport */ token = strtok(NULL, " "); if (!token) { TRACE__((obj_name, "Expecting ICE transport in candidate")); goto on_return; } if (pj_ansi_stricmp(token, "UDP") != 0) { TRACE__((obj_name, "Expecting ICE UDP transport only in candidate")); goto on_return; } /* Priority */ token = strtok(NULL, " "); if (!token) { TRACE__((obj_name, "Expecting ICE priority in candidate")); goto on_return; } cand->prio = atoi(token); /* Host */ host = strtok(NULL, " "); if (!host) { TRACE__((obj_name, "Expecting ICE host in candidate")); goto on_return; } /* Detect address family */ if (pj_ansi_strchr(host, ':')) af = pj_AF_INET6(); else af = pj_AF_INET(); /* Assign address */ if (pj_sockaddr_init(af, &cand->addr, pj_cstr(&s, host), 0)) { TRACE__((obj_name, "Invalid ICE candidate address")); goto on_return; } /* Port */ token = strtok(NULL, " "); if (!token) { TRACE__((obj_name, "Expecting ICE port number in candidate")); goto on_return; } pj_sockaddr_set_port(&cand->addr, (pj_uint16_t)atoi(token)); /* typ */ token = strtok(NULL, " "); if (!token) { TRACE__((obj_name, "Expecting ICE \"typ\" in candidate")); goto on_return; } if (pj_ansi_stricmp(token, "typ") != 0) { TRACE__((obj_name, "Expecting ICE \"typ\" in candidate")); goto on_return; } /* candidate type */ token = strtok(NULL, " "); if (!token) { TRACE__((obj_name, "Expecting ICE candidate type in candidate")); goto on_return; } if (pj_ansi_stricmp(token, "host") == 0) { cand->type = PJ_ICE_CAND_TYPE_HOST; } else if (pj_ansi_stricmp(token, "srflx") == 0) { cand->type = PJ_ICE_CAND_TYPE_SRFLX; } else if (pj_ansi_stricmp(token, "relay") == 0) { cand->type = PJ_ICE_CAND_TYPE_RELAYED; } else if (pj_ansi_stricmp(token, "prflx") == 0) { cand->type = PJ_ICE_CAND_TYPE_PRFLX; } else { PJ_LOG(5,(obj_name, "Invalid ICE candidate type %s in candidate", token)); goto on_return; } status = PJ_SUCCESS; on_return: return status; }
/* Parse crypto attribute line */ static pj_status_t parse_attr_crypto(pj_pool_t *pool, const pjmedia_sdp_attr *attr, pjmedia_srtp_crypto *crypto, int *tag) { pj_str_t input; char *token; pj_str_t tmp; pj_status_t status; int itmp; pj_bzero(crypto, sizeof(*crypto)); pj_strdup_with_null(pool, &input, &attr->value); /* Tag */ token = strtok(input.ptr, " "); if (!token) { PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting tag")); return PJMEDIA_SDP_EINATTR; } *tag = atoi(token); if (*tag == 0) return PJMEDIA_SDP_EINATTR; /* Crypto-suite */ token = strtok(NULL, " "); if (!token) { PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting crypto suite")); return PJMEDIA_SDP_EINATTR; } crypto->name = pj_str(token); /* Key method */ token = strtok(NULL, ":"); if (!token) { PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting key method")); return PJMEDIA_SDP_EINATTR; } if (pj_ansi_stricmp(token, "inline")) { PJ_LOG(4,(THIS_FILE, "Attribute crypto key method '%s' not supported!", token)); return PJMEDIA_SDP_EINATTR; } /* Key */ token = strtok(NULL, "| "); if (!token) { PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting key")); return PJMEDIA_SDP_EINATTR; } tmp = pj_str(token); crypto->key.ptr = (char*) pj_pool_zalloc(pool, MAX_KEY_LEN); /* Decode key */ itmp = MAX_KEY_LEN; status = pj_base64_decode(&tmp, (pj_uint8_t*)crypto->key.ptr, &itmp); if (status != PJ_SUCCESS) { PJ_LOG(4,(THIS_FILE, "Failed decoding crypto key from base64")); return status; } crypto->key.slen = itmp; return PJ_SUCCESS; }
/* * Set default codec parameter. */ PJ_DEF(pj_status_t) pjmedia_codec_mgr_set_default_param( pjmedia_codec_mgr *mgr, const pjmedia_codec_info *info, const pjmedia_codec_param *param ) { unsigned i; pjmedia_codec_id codec_id; pj_pool_t *pool, *old_pool = NULL; struct pjmedia_codec_desc *codec_desc = NULL; pjmedia_codec_default_param *p; PJ_ASSERT_RETURN(mgr && info, PJ_EINVAL); if (!pjmedia_codec_info_to_id(info, (char*)&codec_id, sizeof(codec_id))) return PJ_EINVAL; pj_mutex_lock(mgr->mutex); /* Lookup codec desc */ for (i=0; i < mgr->codec_cnt; ++i) { if (pj_ansi_stricmp(codec_id, mgr->codec_desc[i].id) == 0) { codec_desc = &mgr->codec_desc[i]; break; } } /* Codec not found */ if (!codec_desc) { pj_mutex_unlock(mgr->mutex); return PJMEDIA_CODEC_EUNSUP; } /* If codec param is previously set, reset the codec param but release * the codec param pool later after the new param is set (ticket #1171). */ if (codec_desc->param) { pj_assert(codec_desc->param->pool); old_pool = codec_desc->param->pool; codec_desc->param = NULL; } /* When param is set to NULL, i.e: setting default codec param to library * default setting, just return PJ_SUCCESS. */ if (NULL == param) { pj_mutex_unlock(mgr->mutex); if (old_pool) pj_pool_release(old_pool); return PJ_SUCCESS; } /* Instantiate and initialize codec param */ pool = pj_pool_create(mgr->pf, (char*)codec_id, 256, 256, NULL); codec_desc->param = PJ_POOL_ZALLOC_T(pool, pjmedia_codec_default_param); p = codec_desc->param; p->pool = pool; p->param = PJ_POOL_ZALLOC_T(pool, pjmedia_codec_param); /* Update codec param */ pj_memcpy(p->param, param, sizeof(pjmedia_codec_param)); for (i = 0; i < param->setting.dec_fmtp.cnt; ++i) { pj_strdup(pool, &p->param->setting.dec_fmtp.param[i].name, ¶m->setting.dec_fmtp.param[i].name); pj_strdup(pool, &p->param->setting.dec_fmtp.param[i].val, ¶m->setting.dec_fmtp.param[i].val); } for (i = 0; i < param->setting.enc_fmtp.cnt; ++i) { pj_strdup(pool, &p->param->setting.enc_fmtp.param[i].name, ¶m->setting.enc_fmtp.param[i].name); pj_strdup(pool, &p->param->setting.enc_fmtp.param[i].val, ¶m->setting.enc_fmtp.param[i].val); } pj_mutex_unlock(mgr->mutex); if (old_pool) pj_pool_release(old_pool); return PJ_SUCCESS; }