static struct ast_channel *rec_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause) { struct ast_channel *chan; struct ast_format format; const char *conf_name = data; chan = ast_channel_alloc(1, AST_STATE_UP, NULL, NULL, NULL, NULL, NULL, NULL, 0, "CBRec/conf-%s-uid-%d", conf_name, (int) ast_random()); if (!chan) { return NULL; } if (ast_channel_add_bridge_role(chan, "recorder")) { ast_channel_release(chan); return NULL; } ast_format_set(&format, AST_FORMAT_SLINEAR, 0); ast_channel_tech_set(chan, conf_record_get_tech()); ast_format_cap_add_all(ast_channel_nativeformats(chan)); ast_format_copy(ast_channel_writeformat(chan), &format); ast_format_copy(ast_channel_rawwriteformat(chan), &format); ast_format_copy(ast_channel_readformat(chan), &format); ast_format_copy(ast_channel_rawreadformat(chan), &format); return chan; }
/*! \brief Helper function which gets the format for a Snoop channel based on the channel being snooped on */ static void snoop_determine_format(struct ast_channel *chan, struct stasis_app_snoop *snoop) { SCOPED_CHANNELLOCK(lock, chan); unsigned int rate = MAX(ast_format_get_sample_rate(ast_channel_rawwriteformat(chan)), ast_format_get_sample_rate(ast_channel_rawreadformat(chan))); snoop->spy_format = ast_format_cache_get_slin_by_rate(rate); }
/*! \internal \brief Enable talk detection on the channel */ static int set_talk_detect(struct ast_channel *chan, int dsp_silence_threshold, int dsp_talking_threshold) { struct ast_datastore *datastore = NULL; struct talk_detect_params *td_params; SCOPED_CHANNELLOCK(chan_lock, chan); datastore = ast_channel_datastore_find(chan, &talk_detect_datastore, NULL); if (!datastore) { datastore = ast_datastore_alloc(&talk_detect_datastore, NULL); if (!datastore) { return -1; } td_params = ast_calloc(1, sizeof(*td_params)); if (!td_params) { ast_datastore_free(datastore); return -1; } ast_audiohook_init(&td_params->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "TALK_DETECT", AST_AUDIOHOOK_MANIPULATE_ALL_RATES); td_params->audiohook.manipulate_callback = talk_detect_audiohook_cb; ast_set_flag(&td_params->audiohook, AST_AUDIOHOOK_TRIGGER_READ); td_params->dsp = ast_dsp_new_with_rate(ast_format_get_sample_rate(ast_channel_rawreadformat(chan))); if (!td_params->dsp) { ast_datastore_free(datastore); ast_free(td_params); return -1; } datastore->data = td_params; ast_channel_datastore_add(chan, datastore); ast_audiohook_attach(chan, &td_params->audiohook); } else { /* Talk detection already enabled; update existing settings */ td_params = datastore->data; } td_params->dsp_talking_threshold = dsp_talking_threshold; td_params->dsp_silence_threshold = dsp_silence_threshold; ast_dsp_set_threshold(td_params->dsp, td_params->dsp_talking_threshold); return 0; }
static int serialize_showchan(struct ast_channel *c, char *buf, size_t size) { long elapsed_seconds = 0; int hour = 0, min = 0, sec = 0; struct ast_str *format_buf = ast_str_alloca(64); char cgrp[256]; char pgrp[256]; struct ast_str *write_transpath = ast_str_alloca(256); struct ast_str *read_transpath = ast_str_alloca(256); struct ast_bridge *bridge; memset(buf, 0, size); if (!c) return 0; elapsed_seconds = ast_channel_get_duration(c); hour = elapsed_seconds / 3600; min = (elapsed_seconds % 3600) / 60; sec = elapsed_seconds % 60; ast_channel_lock(c); bridge = ast_channel_get_bridge(c); ast_channel_unlock(c); snprintf(buf,size, "Name= %s\n" "Type= %s\n" "UniqueID= %s\n" "LinkedID= %s\n" "CallerIDNum= %s\n" "CallerIDName= %s\n" "ConnectedLineIDNum= %s\n" "ConnectedLineIDName=%s\n" "DNIDDigits= %s\n" "RDNIS= %s\n" "Parkinglot= %s\n" "Language= %s\n" "State= %s (%u)\n" "Rings= %d\n" "NativeFormat= %s\n" "WriteFormat= %s\n" "ReadFormat= %s\n" "RawWriteFormat= %s\n" "RawReadFormat= %s\n" "WriteTranscode= %s %s\n" "ReadTranscode= %s %s\n" "1stFileDescriptor= %d\n" "Framesin= %u %s\n" "Framesout= %u %s\n" "TimetoHangup= %ld\n" "ElapsedTime= %dh%dm%ds\n" "BridgeID= %s\n" "Context= %s\n" "Extension= %s\n" "Priority= %d\n" "CallGroup= %s\n" "PickupGroup= %s\n" "Application= %s\n" "Data= %s\n" "Blocking_in= %s\n", ast_channel_name(c), ast_channel_tech(c)->type, ast_channel_uniqueid(c), ast_channel_linkedid(c), S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, "(N/A)"), S_COR(ast_channel_caller(c)->id.name.valid, ast_channel_caller(c)->id.name.str, "(N/A)"), S_COR(ast_channel_connected(c)->id.number.valid, ast_channel_connected(c)->id.number.str, "(N/A)"), S_COR(ast_channel_connected(c)->id.name.valid, ast_channel_connected(c)->id.name.str, "(N/A)"), S_OR(ast_channel_dialed(c)->number.str, "(N/A)"), S_COR(ast_channel_redirecting(c)->from.number.valid, ast_channel_redirecting(c)->from.number.str, "(N/A)"), ast_channel_parkinglot(c), ast_channel_language(c), ast_state2str(ast_channel_state(c)), ast_channel_state(c), ast_channel_rings(c), ast_format_cap_get_names(ast_channel_nativeformats(c), &format_buf), ast_format_get_name(ast_channel_writeformat(c)), ast_format_get_name(ast_channel_readformat(c)), ast_format_get_name(ast_channel_rawwriteformat(c)), ast_format_get_name(ast_channel_rawreadformat(c)), ast_channel_writetrans(c) ? "Yes" : "No", ast_translate_path_to_str(ast_channel_writetrans(c), &write_transpath), ast_channel_readtrans(c) ? "Yes" : "No", ast_translate_path_to_str(ast_channel_readtrans(c), &read_transpath), ast_channel_fd(c, 0), ast_channel_fin(c) & ~DEBUGCHAN_FLAG, (ast_channel_fin(c) & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "", ast_channel_fout(c) & ~DEBUGCHAN_FLAG, (ast_channel_fout(c) & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "", (long)ast_channel_whentohangup(c)->tv_sec, hour, min, sec, bridge ? bridge->uniqueid : "(Not bridged)", ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c), ast_print_group(cgrp, sizeof(cgrp), ast_channel_callgroup(c)), ast_print_group(pgrp, sizeof(pgrp), ast_channel_pickupgroup(c)), ast_channel_appl(c) ? ast_channel_appl(c) : "(N/A)", ast_channel_data(c) ? S_OR(ast_channel_data(c), "(Empty)") : "(None)", (ast_test_flag(ast_channel_flags(c), AST_FLAG_BLOCKING) ? ast_channel_blockproc(c) : "(Not Blocking)")); ao2_cleanup(bridge); return 0; }
/*! \brief Function called when we should prepare to call the destination */ static struct ast_channel *multicast_rtp_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause) { char *tmp = ast_strdupa(data), *multicast_type = tmp, *destination, *control; struct ast_rtp_instance *instance; struct ast_sockaddr control_address; struct ast_sockaddr destination_address; struct ast_channel *chan; struct ast_format fmt; ast_best_codec(cap, &fmt); ast_sockaddr_setnull(&control_address); /* If no type was given we can't do anything */ if (ast_strlen_zero(multicast_type)) { goto failure; } if (!(destination = strchr(tmp, '/'))) { goto failure; } *destination++ = '\0'; if ((control = strchr(destination, '/'))) { *control++ = '\0'; if (!ast_sockaddr_parse(&control_address, control, PARSE_PORT_REQUIRE)) { goto failure; } } if (!ast_sockaddr_parse(&destination_address, destination, PARSE_PORT_REQUIRE)) { goto failure; } if (!(instance = ast_rtp_instance_new("multicast", NULL, &control_address, multicast_type))) { goto failure; } if (!(chan = ast_channel_alloc(1, AST_STATE_DOWN, "", "", "", "", "", requestor ? ast_channel_linkedid(requestor) : "", 0, "MulticastRTP/%p", instance))) { ast_rtp_instance_destroy(instance); goto failure; } ast_rtp_instance_set_channel_id(instance, ast_channel_uniqueid(chan)); ast_rtp_instance_set_remote_address(instance, &destination_address); ast_channel_tech_set(chan, &multicast_rtp_tech); ast_format_cap_add(ast_channel_nativeformats(chan), &fmt); ast_format_copy(ast_channel_writeformat(chan), &fmt); ast_format_copy(ast_channel_rawwriteformat(chan), &fmt); ast_format_copy(ast_channel_readformat(chan), &fmt); ast_format_copy(ast_channel_rawreadformat(chan), &fmt); ast_channel_tech_pvt_set(chan, instance); return chan; failure: *cause = AST_CAUSE_FAILURE; return NULL; }
int ast_channel_data_add_structure(struct ast_data *tree, struct ast_channel *chan, int add_bridged) { struct ast_data *data_bridged; struct ast_data *data_cdr; struct ast_data *data_flags; struct ast_data *data_zones; struct ast_data *enum_node; struct ast_data *data_softhangup; #if 0 /* XXX AstData: ast_callerid no longer exists. (Equivalent code not readily apparent.) */ struct ast_data *data_callerid; char value_str[100]; #endif if (!tree) { return -1; } ast_data_add_structure(ast_channel, tree, chan); if (add_bridged) { RAII_VAR(struct ast_channel *, bc, ast_channel_bridge_peer(chan), ast_channel_cleanup); if (bc) { data_bridged = ast_data_add_node(tree, "bridged"); if (!data_bridged) { return -1; } ast_channel_data_add_structure(data_bridged, bc, 0); } } ast_data_add_codec(tree, "oldwriteformat", ast_channel_oldwriteformat(chan)); ast_data_add_codec(tree, "readformat", ast_channel_readformat(chan)); ast_data_add_codec(tree, "writeformat", ast_channel_writeformat(chan)); ast_data_add_codec(tree, "rawreadformat", ast_channel_rawreadformat(chan)); ast_data_add_codec(tree, "rawwriteformat", ast_channel_rawwriteformat(chan)); ast_data_add_codecs(tree, "nativeformats", ast_channel_nativeformats(chan)); /* state */ enum_node = ast_data_add_node(tree, "state"); if (!enum_node) { return -1; } ast_data_add_str(enum_node, "text", ast_state2str(ast_channel_state(chan))); ast_data_add_int(enum_node, "value", ast_channel_state(chan)); /* hangupcause */ enum_node = ast_data_add_node(tree, "hangupcause"); if (!enum_node) { return -1; } ast_data_add_str(enum_node, "text", ast_cause2str(ast_channel_hangupcause(chan))); ast_data_add_int(enum_node, "value", ast_channel_hangupcause(chan)); /* amaflags */ enum_node = ast_data_add_node(tree, "amaflags"); if (!enum_node) { return -1; } ast_data_add_str(enum_node, "text", ast_channel_amaflags2string(ast_channel_amaflags(chan))); ast_data_add_int(enum_node, "value", ast_channel_amaflags(chan)); /* transfercapability */ enum_node = ast_data_add_node(tree, "transfercapability"); if (!enum_node) { return -1; } ast_data_add_str(enum_node, "text", ast_transfercapability2str(ast_channel_transfercapability(chan))); ast_data_add_int(enum_node, "value", ast_channel_transfercapability(chan)); /* _softphangup */ data_softhangup = ast_data_add_node(tree, "softhangup"); if (!data_softhangup) { return -1; } ast_data_add_bool(data_softhangup, "dev", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_DEV); ast_data_add_bool(data_softhangup, "asyncgoto", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_ASYNCGOTO); ast_data_add_bool(data_softhangup, "shutdown", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_SHUTDOWN); ast_data_add_bool(data_softhangup, "timeout", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_TIMEOUT); ast_data_add_bool(data_softhangup, "appunload", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_APPUNLOAD); ast_data_add_bool(data_softhangup, "explicit", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_EXPLICIT); ast_data_add_bool(data_softhangup, "unbridge", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_UNBRIDGE); /* channel flags */ data_flags = ast_data_add_node(tree, "flags"); if (!data_flags) { return -1; } channel_data_add_flags(data_flags, chan); ast_data_add_uint(tree, "timetohangup", ast_channel_whentohangup(chan)->tv_sec); #if 0 /* XXX AstData: ast_callerid no longer exists. (Equivalent code not readily apparent.) */ /* callerid */ data_callerid = ast_data_add_node(tree, "callerid"); if (!data_callerid) { return -1; } ast_data_add_structure(ast_callerid, data_callerid, &(chan->cid)); /* insert the callerid ton */ enum_node = ast_data_add_node(data_callerid, "cid_ton"); if (!enum_node) { return -1; } ast_data_add_int(enum_node, "value", chan->cid.cid_ton); snprintf(value_str, sizeof(value_str), "TON: %s/Plan: %s", party_number_ton2str(chan->cid.cid_ton), party_number_plan2str(chan->cid.cid_ton)); ast_data_add_str(enum_node, "text", value_str); #endif /* tone zone */ if (ast_channel_zone(chan)) { data_zones = ast_data_add_node(tree, "zone"); if (!data_zones) { return -1; } ast_tone_zone_data_add_structure(data_zones, ast_channel_zone(chan)); } /* insert cdr */ data_cdr = ast_data_add_node(tree, "cdr"); if (!data_cdr) { return -1; } return 0; }
static int cli_channelstats_print_body(void *obj, void *arg, int flags) { struct ast_sip_cli_context *context = arg; const struct ast_channel_snapshot *snapshot = obj; struct ast_channel *channel = ast_channel_get_by_name(snapshot->name); struct ast_sip_channel_pvt *cpvt = channel ? ast_channel_tech_pvt(channel) : NULL; struct ast_sip_session *session; struct ast_sip_session_media *media; struct ast_rtp_instance *rtp; struct ast_rtp_instance_stats stats; char *print_name = NULL; char *print_time = alloca(32); char codec_in_use[7]; ast_assert(context->output_buffer != NULL); if (!channel) { ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->name); return -1; } ast_channel_lock(channel); session = cpvt->session; if (!session) { ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->name); ast_channel_unlock(channel); ao2_cleanup(channel); return -1; } media = session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO]; if (!media || !media->rtp) { ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->name); ast_channel_unlock(channel); ao2_cleanup(channel); return -1; } rtp = ao2_bump(media->rtp); codec_in_use[0] = '\0'; if (ast_channel_rawreadformat(channel)) { ast_copy_string(codec_in_use, ast_format_get_name(ast_channel_rawreadformat(channel)), sizeof(codec_in_use)); } ast_channel_unlock(channel); print_name = ast_strdupa(snapshot->name); /* Skip the PJSIP/. We know what channel type it is and we need the space. */ print_name += 6; ast_format_duration_hh_mm_ss(ast_tvnow().tv_sec - snapshot->creationtime.tv_sec, print_time, 32); if (ast_rtp_instance_get_stats(rtp, &stats, AST_RTP_INSTANCE_STAT_ALL)) { ast_str_append(&context->output_buffer, 0, "%s direct media\n", snapshot->name); } else { ast_str_append(&context->output_buffer, 0, " %8.8s %-18.18s %-8.8s %-6.6s %6u%s %6u%s %3u %7.3f %6u%s %6u%s %3u %7.3f %7.3f\n", snapshot->bridgeid, print_name, print_time, codec_in_use, stats.rxcount > 100000 ? stats.rxcount / 1000 : stats.rxcount, stats.rxcount > 100000 ? "K": " ", stats.rxploss > 100000 ? stats.rxploss / 1000 : stats.rxploss, stats.rxploss > 100000 ? "K": " ", stats.rxcount ? (stats.rxploss * 100) / stats.rxcount : 0, MIN(stats.rxjitter, 999.999), stats.txcount > 100000 ? stats.txcount / 1000 : stats.txcount, stats.txcount > 100000 ? "K": " ", stats.txploss > 100000 ? stats.txploss / 1000 : stats.txploss, stats.txploss > 100000 ? "K": " ", stats.txcount ? (stats.txploss * 100) / stats.txcount : 0, MIN(stats.txjitter, 999.999), MIN(stats.normdevrtt, 999.999) ); } ao2_cleanup(rtp); ao2_cleanup(channel); return 0; }
struct ast_unreal_pvt *ast_unreal_alloc(size_t size, ao2_destructor_fn destructor, struct ast_format_cap *cap) { struct ast_unreal_pvt *unreal; static const struct ast_jb_conf jb_conf = { .flags = 0, .max_size = -1, .resync_threshold = -1, .impl = "", .target_extra = -1, }; unreal = ao2_alloc(size, destructor); if (!unreal) { return NULL; } unreal->reqcap = ast_format_cap_dup(cap); if (!unreal->reqcap) { ao2_ref(unreal, -1); return NULL; } memcpy(&unreal->jb_conf, &jb_conf, sizeof(unreal->jb_conf)); return unreal; } struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p, const struct ast_channel_tech *tech, int semi1_state, int semi2_state, const char *exten, const char *context, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, struct ast_callid *callid) { struct ast_channel *owner; struct ast_channel *chan; struct ast_format fmt; struct ast_assigned_ids id1 = {NULL, NULL}; struct ast_assigned_ids id2 = {NULL, NULL}; int generated_seqno = ast_atomic_fetchadd_int((int *) &name_sequence, +1); /* set unique ids for the two channels */ if (assignedids && !ast_strlen_zero(assignedids->uniqueid)) { id1.uniqueid = assignedids->uniqueid; id2.uniqueid = assignedids->uniqueid2; } /* if id1 given but not id2, use default of id1;2 */ if (id1.uniqueid && ast_strlen_zero(id2.uniqueid)) { char *uniqueid2; uniqueid2 = ast_alloca(strlen(id1.uniqueid) + 2); strcpy(uniqueid2, id1.uniqueid);/* Safe */ strcat(uniqueid2, ";2");/* Safe */ id2.uniqueid = uniqueid2; } /* * Allocate two new Asterisk channels * * Make sure that the ;2 channel gets the same linkedid as ;1. * You can't pass linkedid to both allocations since if linkedid * isn't set, then each channel will generate its own linkedid. */ if (!(owner = ast_channel_alloc(1, semi1_state, NULL, NULL, NULL, exten, context, &id1, requestor, 0, "%s/%s-%08x;1", tech->type, p->name, generated_seqno))) { ast_log(LOG_WARNING, "Unable to allocate owner channel structure\n"); return NULL; } if (callid) { ast_channel_callid_set(owner, callid); } ast_channel_tech_set(owner, tech); ao2_ref(p, +1); ast_channel_tech_pvt_set(owner, p); ast_format_cap_copy(ast_channel_nativeformats(owner), p->reqcap); /* Determine our read/write format and set it on each channel */ ast_best_codec(p->reqcap, &fmt); ast_format_copy(ast_channel_writeformat(owner), &fmt); ast_format_copy(ast_channel_rawwriteformat(owner), &fmt); ast_format_copy(ast_channel_readformat(owner), &fmt); ast_format_copy(ast_channel_rawreadformat(owner), &fmt); ast_set_flag(ast_channel_flags(owner), AST_FLAG_DISABLE_DEVSTATE_CACHE); ast_jb_configure(owner, &p->jb_conf); if (ast_channel_cc_params_init(owner, requestor ? ast_channel_get_cc_config_params((struct ast_channel *) requestor) : NULL)) { ao2_ref(p, -1); ast_channel_unlock(owner); ast_channel_release(owner); return NULL; } p->owner = owner; ast_channel_unlock(owner); if (!(chan = ast_channel_alloc(1, semi2_state, NULL, NULL, NULL, exten, context, &id2, owner, 0, "%s/%s-%08x;2", tech->type, p->name, generated_seqno))) { ast_log(LOG_WARNING, "Unable to allocate chan channel structure\n"); ao2_ref(p, -1); ast_channel_release(owner); return NULL; } if (callid) { ast_channel_callid_set(chan, callid); } ast_channel_tech_set(chan, tech); ao2_ref(p, +1); ast_channel_tech_pvt_set(chan, p); ast_format_cap_copy(ast_channel_nativeformats(chan), p->reqcap); /* Format was already determined when setting up owner */ ast_format_copy(ast_channel_writeformat(chan), &fmt); ast_format_copy(ast_channel_rawwriteformat(chan), &fmt); ast_format_copy(ast_channel_readformat(chan), &fmt); ast_format_copy(ast_channel_rawreadformat(chan), &fmt); ast_set_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_DEVSTATE_CACHE); p->chan = chan; ast_channel_unlock(chan); return owner; }
static int native_rtp_bridge_compatible_check(struct ast_bridge *bridge, struct ast_bridge_channel *bc0, struct ast_bridge_channel *bc1) { enum ast_rtp_glue_result native_type; struct ast_rtp_glue *glue0; struct ast_rtp_glue *glue1; RAII_VAR(struct ast_rtp_instance *, instance0, NULL, ao2_cleanup); RAII_VAR(struct ast_rtp_instance *, instance1, NULL, ao2_cleanup); RAII_VAR(struct ast_rtp_instance *, vinstance0, NULL, ao2_cleanup); RAII_VAR(struct ast_rtp_instance *, vinstance1, NULL, ao2_cleanup); RAII_VAR(struct ast_format_cap *, cap0, NULL, ao2_cleanup); RAII_VAR(struct ast_format_cap *, cap1, NULL, ao2_cleanup); int read_ptime0; int read_ptime1; int write_ptime0; int write_ptime1; if (!native_rtp_bridge_capable(bc0->chan)) { ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has features which prevent it\n", bridge->uniqueid, ast_channel_name(bc0->chan)); return 0; } if (!native_rtp_bridge_capable(bc1->chan)) { ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has features which prevent it\n", bridge->uniqueid, ast_channel_name(bc1->chan)); return 0; } native_type = native_rtp_bridge_get(bc0->chan, bc1->chan, &glue0, &glue1, &instance0, &instance1, &vinstance0, &vinstance1); if (native_type == AST_RTP_GLUE_RESULT_FORBID) { ast_debug(1, "Bridge '%s' can not use native RTP bridge as it was forbidden while getting details\n", bridge->uniqueid); return 0; } if (ao2_container_count(bc0->features->dtmf_hooks) && ast_rtp_instance_dtmf_mode_get(instance0)) { ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has DTMF hooks\n", bridge->uniqueid, ast_channel_name(bc0->chan)); return 0; } if (ao2_container_count(bc1->features->dtmf_hooks) && ast_rtp_instance_dtmf_mode_get(instance1)) { ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has DTMF hooks\n", bridge->uniqueid, ast_channel_name(bc1->chan)); return 0; } if (native_type == AST_RTP_GLUE_RESULT_LOCAL && (ast_rtp_instance_get_engine(instance0)->local_bridge != ast_rtp_instance_get_engine(instance1)->local_bridge || (ast_rtp_instance_get_engine(instance0)->dtmf_compatible && !ast_rtp_instance_get_engine(instance0)->dtmf_compatible(bc0->chan, instance0, bc1->chan, instance1)))) { ast_debug(1, "Bridge '%s' can not use local native RTP bridge as local bridge or DTMF is not compatible\n", bridge->uniqueid); return 0; } cap0 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); cap1 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); if (!cap0 || !cap1) { return 0; } /* Make sure that codecs match */ if (glue0->get_codec) { glue0->get_codec(bc0->chan, cap0); } if (glue1->get_codec) { glue1->get_codec(bc1->chan, cap1); } if (ast_format_cap_count(cap0) != 0 && ast_format_cap_count(cap1) != 0 && !ast_format_cap_iscompatible(cap0, cap1)) { struct ast_str *codec_buf0 = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN); struct ast_str *codec_buf1 = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN); ast_debug(1, "Bridge '%s': Channel codec0 = %s is not codec1 = %s, cannot native bridge in RTP.\n", bridge->uniqueid, ast_format_cap_get_names(cap0, &codec_buf0), ast_format_cap_get_names(cap1, &codec_buf1)); return 0; } read_ptime0 = ast_format_cap_get_format_framing(cap0, ast_channel_rawreadformat(bc0->chan)); read_ptime1 = ast_format_cap_get_format_framing(cap1, ast_channel_rawreadformat(bc1->chan)); write_ptime0 = ast_format_cap_get_format_framing(cap0, ast_channel_rawwriteformat(bc0->chan)); write_ptime1 = ast_format_cap_get_format_framing(cap1, ast_channel_rawwriteformat(bc1->chan)); if (read_ptime0 != write_ptime1 || read_ptime1 != write_ptime0) { ast_debug(1, "Bridge '%s': Packetization differs between RTP streams (%d != %d or %d != %d). Cannot native bridge in RTP\n", bridge->uniqueid, read_ptime0, write_ptime1, read_ptime1, write_ptime0); return 0; } return 1; }