📄 pjsua_media.c
字号:
return PJ_SUCCESS;}/* * Create UDP media transports for all the calls. This function creates * one UDP media transport for each call. */PJ_DEF(pj_status_t) pjsua_media_transports_create(const pjsua_transport_config *app_cfg){ pjsua_transport_config cfg; unsigned i; pj_status_t status; /* Make sure pjsua_init() has been called */ PJ_ASSERT_RETURN(pjsua_var.ua_cfg.max_calls>0, PJ_EINVALIDOP); PJSUA_LOCK(); /* Delete existing media transports */ for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { if (pjsua_var.calls[i].med_tp != NULL) { pjsua_var.calls[i].med_tp->op->destroy(pjsua_var.calls[i].med_tp); pjsua_var.calls[i].med_tp = NULL; } } /* Copy config */ pj_memcpy(&cfg, app_cfg, sizeof(*app_cfg)); pjsua_normalize_stun_config(&cfg.stun_config); /* Create each media transport */ for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { status = create_rtp_rtcp_sock(&cfg, &pjsua_var.calls[i].skinfo); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to create RTP/RTCP socket", status); goto on_error; } status = pjmedia_transport_udp_attach(pjsua_var.med_endpt, NULL, &pjsua_var.calls[i].skinfo, 0, &pjsua_var.calls[i].med_tp); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to create media transport", status); goto on_error; } pjmedia_transport_udp_simulate_lost(pjsua_var.calls[i].med_tp, PJMEDIA_DIR_ENCODING, pjsua_var.media_cfg.tx_drop_pct); pjmedia_transport_udp_simulate_lost(pjsua_var.calls[i].med_tp, PJMEDIA_DIR_DECODING, pjsua_var.media_cfg.rx_drop_pct); } PJSUA_UNLOCK(); return PJ_SUCCESS;on_error: for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { if (pjsua_var.calls[i].med_tp != NULL) { pjsua_var.calls[i].med_tp->op->destroy(pjsua_var.calls[i].med_tp); pjsua_var.calls[i].med_tp = NULL; } } PJSUA_UNLOCK(); return status;}/* * Get maxinum number of conference ports. */PJ_DEF(unsigned) pjsua_conf_get_max_ports(void){ return pjsua_var.media_cfg.max_media_ports;}/* * Get current number of active ports in the bridge. */PJ_DEF(unsigned) pjsua_conf_get_active_ports(void){ unsigned ports[256]; unsigned count = PJ_ARRAY_SIZE(ports); pj_status_t status; status = pjmedia_conf_enum_ports(pjsua_var.mconf, ports, &count); if (status != PJ_SUCCESS) count = 0; return count;}/* * Enumerate all conference ports. */PJ_DEF(pj_status_t) pjsua_enum_conf_ports(pjsua_conf_port_id id[], unsigned *count){ return pjmedia_conf_enum_ports(pjsua_var.mconf, (unsigned*)id, count);}/* * Get information about the specified conference port */PJ_DEF(pj_status_t) pjsua_conf_get_port_info( pjsua_conf_port_id id, pjsua_conf_port_info *info){ pjmedia_conf_port_info cinfo; unsigned i; pj_status_t status; status = pjmedia_conf_get_port_info( pjsua_var.mconf, id, &cinfo); if (status != PJ_SUCCESS) return status; pj_bzero(info, sizeof(*info)); info->slot_id = id; info->name = cinfo.name; info->clock_rate = cinfo.clock_rate; info->channel_count = cinfo.channel_count; info->samples_per_frame = cinfo.samples_per_frame; info->bits_per_sample = cinfo.bits_per_sample; /* Build array of listeners */ info->listener_cnt = cinfo.listener_cnt; for (i=0; i<cinfo.listener_cnt; ++i) { info->listeners[i] = cinfo.listener_slots[i]; } return PJ_SUCCESS;}/* * Add arbitrary media port to PJSUA's conference bridge. */PJ_DEF(pj_status_t) pjsua_conf_add_port( pj_pool_t *pool, pjmedia_port *port, pjsua_conf_port_id *p_id){ pj_status_t status; status = pjmedia_conf_add_port(pjsua_var.mconf, pool, port, NULL, (unsigned*)p_id); if (status != PJ_SUCCESS) { if (p_id) *p_id = PJSUA_INVALID_ID; } return status;}/* * Remove arbitrary slot from the conference bridge. */PJ_DEF(pj_status_t) pjsua_conf_remove_port(pjsua_conf_port_id id){ return pjmedia_conf_remove_port(pjsua_var.mconf, (unsigned)id);}/* * Establish unidirectional media flow from souce to sink. */PJ_DEF(pj_status_t) pjsua_conf_connect( pjsua_conf_port_id source, pjsua_conf_port_id sink){ return pjmedia_conf_connect_port(pjsua_var.mconf, source, sink, 0);}/* * Disconnect media flow from the source to destination port. */PJ_DEF(pj_status_t) pjsua_conf_disconnect( pjsua_conf_port_id source, pjsua_conf_port_id sink){ return pjmedia_conf_disconnect_port(pjsua_var.mconf, source, sink);}/* * Adjust the signal level to be transmitted from the bridge to the * specified port by making it louder or quieter. */PJ_DEF(pj_status_t) pjsua_conf_adjust_tx_level(pjsua_conf_port_id slot, float level){ return pjmedia_conf_adjust_tx_level(pjsua_var.mconf, slot, (int)((level-1) * 128));}/* * Adjust the signal level to be received from the specified port (to * the bridge) by making it louder or quieter. */PJ_DEF(pj_status_t) pjsua_conf_adjust_rx_level(pjsua_conf_port_id slot, float level){ return pjmedia_conf_adjust_rx_level(pjsua_var.mconf, slot, (int)((level-1) * 128));}/* * Get last signal level transmitted to or received from the specified port. */PJ_DEF(pj_status_t) pjsua_conf_get_signal_level(pjsua_conf_port_id slot, unsigned *tx_level, unsigned *rx_level){ return pjmedia_conf_get_signal_level(pjsua_var.mconf, slot, tx_level, rx_level);}/***************************************************************************** * File player. *//* * Create a file player, and automatically connect this player to * the conference bridge. */PJ_DEF(pj_status_t) pjsua_player_create( const pj_str_t *filename, unsigned options, pjsua_player_id *p_id){ unsigned slot, file_id; char path[PJ_MAXPATH]; pjmedia_port *port; pj_status_t status; if (pjsua_var.player_cnt >= PJ_ARRAY_SIZE(pjsua_var.player)) return PJ_ETOOMANY; PJSUA_LOCK(); for (file_id=0; file_id<PJ_ARRAY_SIZE(pjsua_var.player); ++file_id) { if (pjsua_var.player[file_id].port == NULL) break; } if (file_id == PJ_ARRAY_SIZE(pjsua_var.player)) { /* This is unexpected */ PJSUA_UNLOCK(); pj_assert(0); return PJ_EBUG; } pj_memcpy(path, filename->ptr, filename->slen); path[filename->slen] = '\0'; status = pjmedia_wav_player_port_create(pjsua_var.pool, path, pjsua_var.mconf_cfg.samples_per_frame * 1000 / pjsua_var.media_cfg.clock_rate, options, 0, &port); if (status != PJ_SUCCESS) { PJSUA_UNLOCK(); pjsua_perror(THIS_FILE, "Unable to open file for playback", status); return status; } status = pjmedia_conf_add_port(pjsua_var.mconf, pjsua_var.pool, port, filename, &slot); if (status != PJ_SUCCESS) { pjmedia_port_destroy(port); PJSUA_UNLOCK(); pjsua_perror(THIS_FILE, "Unable to add file to conference bridge", status); return status; } pjsua_var.player[file_id].type = 0; pjsua_var.player[file_id].port = port; pjsua_var.player[file_id].slot = slot; if (p_id) *p_id = file_id; ++pjsua_var.player_cnt; PJSUA_UNLOCK(); return PJ_SUCCESS;}/* * Create a file playlist media port, and automatically add the port * to the conference bridge. */PJ_DEF(pj_status_t) pjsua_playlist_create( const pj_str_t file_names[], unsigned file_count, const pj_str_t *label, unsigned options, pjsua_player_id *p_id){ unsigned slot, file_id, ptime; pjmedia_port *port; pj_status_t status; if (pjsua_var.player_cnt >= PJ_ARRAY_SIZE(pjsua_var.player)) return PJ_ETOOMANY; PJSUA_LOCK(); for (file_id=0; file_id<PJ_ARRAY_SIZE(pjsua_var.player); ++file_id) { if (pjsua_var.player[file_id].port == NULL) break; } if (file_id == PJ_ARRAY_SIZE(pjsua_var.player)) { /* This is unexpected */ PJSUA_UNLOCK(); pj_assert(0); return PJ_EBUG; } ptime = pjsua_var.mconf_cfg.samples_per_frame * 1000 / pjsua_var.media_cfg.clock_rate; status = pjmedia_wav_playlist_create(pjsua_var.pool, label, file_names, file_count, ptime, options, 0, &port); if (status != PJ_SUCCESS) { PJSUA_UNLOCK(); pjsua_perror(THIS_FILE, "Unable to create playlist", status); return status; } status = pjmedia_conf_add_port(pjsua_var.mconf, pjsua_var.pool, port, &port->info.name, &slot); if (status != PJ_SUCCESS) { pjmedia_port_destroy(port); PJSUA_UNLOCK(); pjsua_perror(THIS_FILE, "Unable to add port", status); return status; } pjsua_var.player[file_id].type = 1; pjsua_var.player[file_id].port = port; pjsua_var.player[file_id].slot = slot; if (p_id) *p_id = file_id; ++pjsua_var.player_cnt; PJSUA_UNLOCK(); return PJ_SUCCESS;}/* * Get conference port ID associated with player. */PJ_DEF(pjsua_conf_port_id) pjsua_player_get_conf_port(pjsua_player_id id){ PJ_ASSERT_RETURN(id>=0 && id<PJ_ARRAY_SIZE(pjsua_var.player), PJ_EINVAL); PJ_ASSERT_RETURN(pjsua_var.player[id].port != NULL, PJ_EINVAL); return pjsua_var.player[id].slot;}/* * Get the media port for the player. */PJ_DEF(pj_status_t) pjsua_player_get_port( pjsua_recorder_id id, pjmedia_port **p_port){ PJ_ASSERT_RETURN(id>=0 && id<PJ_ARRAY_SIZE(pjsua_var.player), PJ_EINVAL); PJ_ASSERT_RETURN(pjsua_var.player[id].port != NULL, PJ_EINVAL); PJ_ASSERT_RETURN(p_port != NULL, PJ_EINVAL); *p_port = pjsua_var.player[id].port; return PJ_SUCCESS;}/* * Set playback position. */PJ_DEF(pj_status_t) pjsua_player_set_pos( pjsua_player_id id, pj_uint32_t samples){ PJ_ASSERT_RETURN(id>=0 && id<PJ_ARRAY_SIZE(pjsua_var.player), PJ_EINVAL); PJ_ASSERT_RETURN(pjsua_var.player[id].port != NULL, PJ_EINVAL); PJ_ASSERT_RETURN(pjsua_var.player[id].type == 0, PJ_EINVAL); return pjmedia_wav_player_port_set_pos(pjsua_var.player[id].port, samples);}/* * Close the file, remove the player from the bridge, and free * resources associated with the file player. */PJ_DEF(pj_status_t) pjsua_player_destroy(pjsua_player_id id){ PJ_ASSERT_RETURN(id>=0 && id<PJ_ARRAY_SIZE(pjsua_var.player), PJ_EINVAL); PJ_ASSERT_RETURN(pjsua_var.player[id].port != NULL, PJ_EINVAL); PJSUA_LOCK(); if (pjsua_var.player[id].port) { pjmedia_conf_remove_port(pjsua_var.mconf, pjsua_var.player[id].slot); pjmedia_port_destroy(pjsua_var.player[id].port); pjsua_var.player[id].port = NULL; pjsua_var.player[id].slot = 0xFFFF; pjsua_var.player_cnt--; } PJSUA_UNLOCK(); return PJ_SUCCESS;}/***************************************************************************** * File recorder. *//* * Create a file recorder, and automatically connect this recorder to * the conference bridge. */PJ_DEF(pj_status_t) pjsua_recorder_create( const pj_str_t *filename, unsigned enc_type, void *enc_param, pj_ssize_t max_size, unsigned options, pjsua_recorder_id *p_id){ enum Format { FMT_UNKNOWN, FMT_WAV, FMT_MP3, }; unsigned slot, file_id; char path[PJ_MAXPATH]; pj_str_t ext; int file_format; pjmedia_port *port; pj_status_t status; /* Filename must present */ PJ_ASSERT_RETURN(filename != NULL, PJ_EINVAL); /* Don't support max_size at present */ PJ_ASSERT_RETURN(max_size == 0 || max_size == -1, PJ_EINVAL); /* Don't support encoding type at present */ PJ_ASSERT_RETURN(enc_type == 0, PJ_EINVAL); if (pjsua_var.rec_cnt >= PJ_ARRAY_SIZE(pjsua_var.recorder)) return PJ_ETOOMANY; /* Determine the file format */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -