/* ============ Media Producer Interface ================= */
static int _tdav_producer_video_v4l2_set(tmedia_producer_t *p_self, const tmedia_param_t* pc_param)
{
    int ret = 0;
    tdav_producer_video_v4l2_t* p_v4l2 = (tdav_producer_video_v4l2_t*)p_self;

    if (!p_v4l2 || !pc_param) {
        V4L2_DEBUG_ERROR("Invalid parameter");
        return -1;
    }

    if (pc_param->value_type == tmedia_pvt_pchar) {
        if (tsk_striequals(pc_param->key, "local-hwnd") || tsk_striequals(pc_param->key, "preview-hwnd")) {
            V4L2_DEBUG_ERROR("Not implemented yet");
        }
        else if (tsk_striequals(pc_param->key, "src-hwnd")) {
            V4L2_DEBUG_ERROR("Not implemented yet");
        }
    }
    else if (pc_param->value_type == tmedia_pvt_int32) {
        if (tsk_striequals(pc_param->key, "mute")) {
            p_v4l2->b_muted = (TSK_TO_INT32((uint8_t*)pc_param->value) != 0);
        }
    }

    return ret;
}
int tdav_consumer_audio_set(tdav_consumer_audio_t* self, const tmedia_param_t* param)
{
	if(!self){
		TSK_DEBUG_ERROR("Invalid parameter");
		return -1;
	}

	if(param->plugin_type == tmedia_ppt_consumer){
		if(param->value_type == tmedia_pvt_int32){
			if(tsk_striequals(param->key, "gain")){
				int32_t gain = *((int32_t*)param->value);
				if(gain<TDAV_AUDIO_GAIN_MAX && gain>=0){
					TMEDIA_CONSUMER(self)->audio.gain = (uint8_t)gain;
					TSK_DEBUG_INFO("audio consumer gain=%u", gain);
				}
				else{
					TSK_DEBUG_ERROR("%u is invalid as gain value", gain);
					return -2;
				}
			}
			else if(tsk_striequals(param->key, "volume")){
				TMEDIA_CONSUMER(self)->audio.volume = TSK_TO_INT32((uint8_t*)param->value);
				TMEDIA_CONSUMER(self)->audio.volume = TSK_CLAMP(0, TMEDIA_CONSUMER(self)->audio.volume, 100);
			}
		}
	}

	return 0;
}
Exemple #3
0
/**@ingroup tsk_xml_group
* Find an XML node by name
* @param curr The XML node from which to start
* @param name The name of the XML node to find
* @param ftype The find type
* @retval Returns the node which match our criteria. If none match, this method returns NULL.
*/
xmlNodePtr tsk_xml_find_node(const xmlNodePtr curr, const char* name, tsk_xml_node_find_type_t ftype)
{
	xmlNodePtr node = curr;
	
	while(node)
	{
		switch(ftype)
		{
		case nft_none:		return (tsk_striequals(node->name, name))? node : 0;
		case nft_children: node = node->children; break;
		case nft_parent:	node = node->parent; break;
		case nft_next:		node = node->next; break;
		case nft_prev:		node = node->prev; break;
		default: return 0;
		} /* switch */

		/* check and return value if match */
		if( node && (!name || tsk_striequals(node->name, name)) ) 
		//if( node && (name == 0 || !tsk_stricmp((const char*)node->name, name)) ) 
		{
			return node;
		}
	}

	return 0;
}
Exemple #4
0
char* tdav_codec_mp4ves_sdp_att_get(const tmedia_codec_t* _self, const char* att_name)
{
	tdav_codec_mp4ves_t *self = (tdav_codec_mp4ves_t *)_self;

	if(tsk_striequals(att_name, "fmtp")){
		char* fmtp = tsk_null;
		switch(_self->bl){//FIXME: deprecated
			case tmedia_bl_low:
			default:
				self->profile = Simple_Profile_Level_1;
				break;
			case tmedia_bl_medium:
				self->profile = Simple_Profile_Level_2;
				break;
			case tmedia_bl_hight:
			case tmedia_bl_unrestricted:
				self->profile = Simple_Profile_Level_3;
				break;
		}
		tsk_sprintf(&fmtp, "profile-level-id=%d", self->profile);
		return fmtp;
	}
	else if(tsk_striequals(att_name, "imageattr")){
		return tmedia_get_video_imageattr(TMEDIA_CODEC_VIDEO(self)->pref_size, 
			TMEDIA_CODEC_VIDEO(self)->in.width, TMEDIA_CODEC_VIDEO(self)->in.height, TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height);
	}
	return tsk_null;
}
static tsk_bool_t _fsm_cond_notify_terminated(tsip_dialog_subscribe_t* dialog, tsip_message_t* message)
{
	const tsip_header_Subscription_State_t *hdr_state;
	if((hdr_state = (const tsip_header_Subscription_State_t*)tsip_message_get_header(message, tsip_htype_Subscription_State)))
	{
		return tsk_striequals(hdr_state->state, "terminated") &&
			(hdr_state->expires < 0 || tsk_striequals(hdr_state->reason, "rejected") || tsk_striequals(hdr_state->reason, "noresource"));
	}
	return tsk_false;
}
Exemple #6
0
int trtp_srtp_match_line(const char* crypto_line, int32_t* tag, int32_t* crypto_type, char* key, tsk_size_t key_size)
{
	char* v = strtok((char*)crypto_line, " :|;");
	int32_t k = 0;
	while(v){
		switch(k){
			case 0:
				{
					if(tag){
						*tag = atoi(v);
					}
					break;
				}
			case 1:
				{
					if(tsk_striequals(v, TRTP_SRTP_AES_CM_128_HMAC_SHA1_80)){
						if(crypto_type){
							*crypto_type = HMAC_SHA1_80;
						}
					}
					else if(tsk_striequals(v, TRTP_SRTP_AES_CM_128_HMAC_SHA1_32)){
						if(crypto_type){
							*crypto_type = HMAC_SHA1_32;
						}
					}
					else {
						return -0xFF; 
					}
					break;
				}
			case 2:
				{
					if(!tsk_striequals(v, "inline")){
						return -0xFF;
					}
					break;
				}
			case 3:
				{
					if(key && key_size){
						memset(key, 0, key_size);
						memcpy(key, v, TSK_MIN(key_size, tsk_strlen(v)));
					}
					return 0;
				}
		}
		++k;
		v = strtok(tsk_null, " :|;");
	}

	return -0xF0;
}
Exemple #7
0
static int tdav_codec_mp4ves_set(tmedia_codec_t* self, const tmedia_param_t* param)
{
	tdav_codec_mp4ves_t* mp4ves = (tdav_codec_mp4ves_t*)self;
	if(!self->opened){
		TSK_DEBUG_ERROR("Codec not opened");
		return -1;
	}
	if(param->value_type == tmedia_pvt_int32){
		if(tsk_striequals(param->key, "action")){
			tmedia_codec_action_t action = (tmedia_codec_action_t)TSK_TO_INT32((uint8_t*)param->value);
			switch(action){
				case tmedia_codec_action_encode_idr:
					{
						mp4ves->encoder.force_idr = tsk_true;
						break;
					}
				case tmedia_codec_action_bw_down:
					{
						mp4ves->encoder.quality = TSK_CLAMP(1, (mp4ves->encoder.quality + 1), 31);
						mp4ves->encoder.context->global_quality = FF_QP2LAMBDA * mp4ves->encoder.quality;
						break;
					}
				case tmedia_codec_action_bw_up:
					{
						mp4ves->encoder.quality = TSK_CLAMP(1, (mp4ves->encoder.quality - 1), 31);
						mp4ves->encoder.context->global_quality = FF_QP2LAMBDA * mp4ves->encoder.quality;
						break;
					}
			}
		}
		else if(tsk_striequals(param->key, "rotation")){
			int rotation = *((int32_t*)param->value);
			if(mp4ves->encoder.rotation != rotation){
				if(self->opened){
					int ret;
					mp4ves->encoder.rotation = rotation;
					if((ret = tdav_codec_mp4ves_close_encoder(mp4ves))){
						return ret;
					}
					if((ret = tdav_codec_mp4ves_open_encoder(mp4ves))){
						return ret;
					}
				}
			}
			return 0;
		}
	}
	return -1;
}
static int init_neg_types(tdav_session_msrp_t* msrp, const tsdp_header_M_t* m)
{
	const tsdp_header_A_t* A;

	if((A = tsdp_header_M_findA(m, "accept-types"))){
		char* atype = strtok((char*)A->value, " ");
		const char* default_atype = atype;
		while(atype){
			if(tsk_striequals(atype, "message/CPIM")){
				tsk_strupdate(&msrp->neg_accept_type, atype);
				if((A = tsdp_header_M_findA(m, "accept-wrapped-types"))){
					char* awtype = strtok((char*)A->value, " ");
					tsk_strupdate(&msrp->neg_accept_w_type, awtype); // first
				}
				break;
			}
			atype = strtok(tsk_null, " ");
		}
		
		if(!msrp->neg_accept_type){
			tsk_strupdate(&msrp->neg_accept_type, default_atype);
		}

		return 0;
	}
	return -1;
}
Exemple #9
0
char* tdav_codec_dtmf_sdp_att_get(const tmedia_codec_t* self, const char* att_name)
{
	if(tsk_striequals(att_name, "fmtp")){
		return tsk_strdup("0-16");
	}
	return tsk_null;
}
/* ============ Media Consumer Interface ================= */
int tdav_consumer_audiounit_set(tmedia_consumer_t* self, const tmedia_param_t* param)
{
    tdav_consumer_audiounit_t* consumer = (tdav_consumer_audiounit_t*)self;
    if (param->plugin_type == tmedia_ppt_consumer) {
        if (param->value_type == tmedia_pvt_int32) {
            if (tsk_striequals(param->key, "interrupt")) {
                int32_t interrupt = *((uint8_t*)param->value) ? 1 : 0;
                return tdav_audiounit_handle_interrupt(consumer->audioUnitHandle, interrupt);
            }
            else if (tsk_striequals(param->key, "pause") || tsk_striequals(param->key, "hold")) {
                int32_t pause = *((uint8_t*)param->value) ? 1 : 0;
                return pause ? tdav_consumer_audiounit_pause(self) : tdav_consumer_audiounit_resume(self);
            }
        }
    }
    return tdav_consumer_audio_set(TDAV_CONSUMER_AUDIO(self), param);
}
/* ============ Media Producer Interface ================= */
int tdav_producer_audiounit_set(tmedia_producer_t* self, const tmedia_param_t* param)
{	
    tdav_producer_audiounit_t* producer = (tdav_producer_audiounit_t*)self;
	if(param->plugin_type == tmedia_ppt_producer){
		if(param->value_type == tmedia_pvt_int32){
			if (tsk_striequals(param->key, "mute")) {
				producer->muted = TSK_TO_INT32((uint8_t*)param->value);
				return tdav_audiounit_handle_mute(((tdav_producer_audiounit_t*)self)->audioUnitHandle, producer->muted);
			}
            else if (tsk_striequals(param->key, "interrupt")) {
				int32_t interrupt = *((uint8_t*)param->value) ? 1 : 0;
                return tdav_audiounit_handle_interrupt(producer->audioUnitHandle, interrupt);
            }
		}
	}
	return tdav_producer_audio_set(TDAV_PRODUCER_AUDIO(self), param);
}
Exemple #12
0
tsk_bool_t tdav_codec_mp4ves_sdp_att_match(const tmedia_codec_t* _self, const char* att_name, const char* att_value)
{
	tdav_codec_mp4ves_t *self = (tdav_codec_mp4ves_t *)_self;

	if(!self){
		TSK_DEBUG_ERROR("Invalid parameter");
		return tsk_false;
	}

	if(tsk_striequals(att_name, "fmtp")){
		tsk_params_L_t* params ;
		/* e.g. profile-level-id=1; xx=yy */
		if((params = tsk_params_fromstring(att_value, ";", tsk_true))){
			int val_int;
			if((val_int = tsk_params_get_param_value_as_int(params, "profile-level-id")) != -1){
				TSK_DEBUG_INFO("Proposed profile-level-id=%d", val_int);
				self->profile = val_int; // FIXME: Take the remote profile-level-id even if the bandwidth level doesn't match
			}
			TSK_OBJECT_SAFE_FREE(params);
		}
		
		switch (self->profile ) {
			case Simple_Profile_Level_1:
				TMEDIA_CODEC_VIDEO(self)->out.width = TMEDIA_CODEC_VIDEO(self)->in.width = 176; TMEDIA_CODEC_VIDEO(self)->in.height = TMEDIA_CODEC_VIDEO(self)->out.height = 144;
				break;
			case Simple_Profile_Level_2:
			case Simple_Profile_Level_3:
			default:
				TMEDIA_CODEC_VIDEO(self)->out.width = TMEDIA_CODEC_VIDEO(self)->in.width = 352; TMEDIA_CODEC_VIDEO(self)->in.height = TMEDIA_CODEC_VIDEO(self)->out.height = 288;
				break;
		}
	}
	else if(tsk_striequals(att_name, "imageattr")){
		unsigned in_width, in_height, out_width, out_height;
		if(tmedia_parse_video_imageattr(att_value, TMEDIA_CODEC_VIDEO(self)->pref_size, &in_width, &in_height, &out_width, &out_height) != 0){
			return tsk_false;
		}
		TMEDIA_CODEC_VIDEO(self)->in.width = in_width;
		TMEDIA_CODEC_VIDEO(self)->in.height = in_height;
		TMEDIA_CODEC_VIDEO(self)->out.width = out_width;
		TMEDIA_CODEC_VIDEO(self)->out.height = out_height;
	}

	return tsk_true;
}
Exemple #13
0
static char* tdav_codec_ilbc_sdp_att_get(const tmedia_codec_t* codec, const char* att_name)
{
	if(tsk_striequals(att_name, "fmtp")){
		char* fmtp = tsk_null;
		tsk_sprintf(&fmtp, "mode=%d", TDAV_ILBC_MODE);
		return fmtp;
	}
	return tsk_null;
}
Exemple #14
0
/**@ingroup tsk_xml_group
* Get an XML namespace from an XML document
* @param docPtr A pointer to the XML document
* @param node The XML node from which to extract the namespace
* @param href The namespace href
* @retval The Namespace value matching our criteria (href)
*/
xmlNsPtr tsk_xml_get_namespace(xmlDocPtr docPtr, xmlNodePtr node, const char *href)
{
	xmlNs *ns = *xmlGetNsList(docPtr, node);
	while (ns)
	{
		if (tsk_striequals(ns->href, href)) return ns;
		else ns = ns->next;
	}

	return 0;
}
int tdav_session_msrp_send_message(tmedia_session_msrp_t* self, const void* data, tsk_size_t size, const tmedia_params_L_t *params)
{
	const tdav_session_msrp_t* msrp;
	const tmedia_param_t* param;
	int ret;
	const tsk_list_item_t* item;
	const char* content_type = tsk_null;
	const char* w_content_type = tsk_null;

	if(!data || !size || !(msrp = (tdav_session_msrp_t*)self) || !msrp->sender){
		TSK_DEBUG_ERROR("Invalid parameter");
		return -1;
	}

	tsk_list_foreach(item, params){
		if((param = TMEDIA_PARAM(item->data))){
			if((param->media_type & tmedia_msrp) == param->media_type 
				&& param->plugin_type == tmedia_ppt_session
				&& param->value_type == tmedia_pvt_pchar){

					if(tsk_striequals(param->key, "content-type")){
						content_type = (const char*)param->value;
					}
					else if(tsk_striequals(param->key, "w-content-type")){
						w_content_type = (const char*)param->value;
					}
			}
		}
	}

	if(content_type || w_content_type){ // user-defined content-types
		ret = tsmrp_sender_send_data(msrp->sender, data, size, content_type, w_content_type);
	}
	else{ // neg. content-types
		ret = tsmrp_sender_send_data(msrp->sender, data, size, 
			msrp->neg_accept_type, msrp->neg_accept_w_type
			);
	}

	return ret;
}
/* ============ Media Producer Interface ================= */
int tdav_producer_audiounit_set(tmedia_producer_t* self, const tmedia_param_t* param)
{	
	if(param->plugin_type == tmedia_ppt_producer){
		if(param->value_type == tmedia_pvt_int32){
			if(tsk_striequals(param->key, "mute")){
				int32_t mute = TSK_TO_INT32((uint8_t*)param->value);
				return tdav_audiounit_handle_mute(((tdav_producer_audiounit_t*)self)->audioUnitHandle, mute ? tsk_true : tsk_false);
			}
		}
	}
	return tdav_producer_audio_set(TDAV_PRODUCER_AUDIO(self), param);
}
Exemple #17
0
tnet_dtls_setup_t tnet_dtls_get_setup_from_string(const char* setup)
{
	if (setup){
		int32_t i;
		for (i = 0; i < TNET_DTLS_SETUP_MAX; ++i){
			if (tsk_striequals(TNET_DTLS_SETUP_NAMES[i], setup)){
				return (tnet_dtls_setup_t)i;
			}
		}
	}
	return tnet_dtls_setup_none;
}
Exemple #18
0
tnet_dtls_hash_type_t tnet_dtls_get_hash_from_string(const char* hash)
{
	if (hash){
		int32_t i;
		for (i = 0; i < TNET_DTLS_HASH_TYPE_MAX; ++i){
			if (tsk_striequals(TNET_DTLS_HASH_NAMES[i], hash)){
				return (tnet_dtls_hash_type_t)i;
			}
		}
	}
	return tnet_dtls_hash_type_none;
}
//#define tdav_producer_audioqueue_set tsk_null
int tdav_producer_audioqueue_set(tmedia_producer_t* self, const tmedia_param_t* param)
{
    tdav_producer_audioqueue_t* producer = (tdav_producer_audioqueue_t*)self;
	if(param->plugin_type == tmedia_ppt_producer){
		if(param->value_type == tmedia_pvt_int32){
			if(tsk_striequals(param->key, "mute")){
				producer->muted = TSK_TO_INT32((uint8_t*)param->value);
	            return 1;
			}
		}
	}
	return tdav_producer_audio_set(TDAV_PRODUCER_AUDIO(self), param);
}
Exemple #20
0
/**@ingroup thttp_auth_group
 *
 * Generates HTTP digest response as per RFC 2617 subclause 3.2.2.1.
 *
 * @param [in,out]	ha1			HA1 string generated using  @ref thttp_auth_digest_HA1 or @ref thttp_auth_digest_HA1sess.
 * @param [in,out]	nonce		The nonce value.
 * @param [in,out]	noncecount	The nonce count.
 * @param [in,out]	cnonce		The client nounce (unquoted).
 * @param [in,out]	qop			The Quality Of Protection (unquoted).
 * @param [in,out]	ha2			HA2 string generated using @ref thttp_auth_digest_HA2.
 * @param [in,out]	response	A pointer to the response.
 *
 * @return	Zero if succeed and non-zero error code otherwise.
 **/
int thttp_auth_digest_response(const tsk_md5string_t *ha1, const char* nonce, const nonce_count_t noncecount, const char* cnonce,
	const char* qop, const tsk_md5string_t* ha2, tsk_md5string_t* response)
{
	int ret;

	/* RFC 2617 3.2.2.1 Request-Digest

	============ CASE 1 ============
	If the "qop" value is "auth" or "auth-int":
	request-digest  = <"> < KD ( H(A1),     unq(nonce-value)
	":" nc-value
	":" unq(cnonce-value)
	":" unq(qop-value)
	":" H(A2)
	) <">
	============ CASE 2 ============
	If the "qop" directive is not present (this construction is for
	compatibility with RFC 2069):
	request-digest  =
	<"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) >
	<">
	*/

	char *res = tsk_null;

	if (tsk_striequals(qop, "auth") || tsk_striequals(qop, "auth-int")){
		/* CASE 1 */
		tsk_sprintf(&res, "%s:%s:%s:%s:%s:%s", *ha1, nonce, noncecount, cnonce, qop, *ha2);
	}
	else{
		/* CASE 2 */
		tsk_sprintf(&res, "%s:%s:%s", *ha1, nonce, *ha2);
	}

	ret = tsk_md5compute(res, tsk_strlen(res), response);
	TSK_FREE(res);

	return ret;
}
Exemple #21
0
/**@ingroup thttp_auth_group
 * Generates digest HA2 value as per RFC 2617 subclause 3.2.2.3.
 *
 *
 * @param [in,out]	method		The HTTP/SIP method name.
 * @param [in,out]	url			The HTTP URL or SIP URI of the request.
 * @param [in,out]	entity_body	The entity body.
 * @param [in,out]	qop			The Quality Of Protection.
 * @param [in,out]	ha2			A pointer to the response.
 *
 * @return	Zero if succeed and non-zero error code otherwise.
 **/
int thttp_auth_digest_HA2(const char* method, const char* url, const tsk_buffer_t* entity_body, const char* qop, tsk_md5string_t* ha2)
{
	int ret;
	/* RFC 2617 - 3.2.2.3 A2

	If the "qop" directive's value is "auth" or is unspecified, then A2
	is:
	A2       = Method ":" digest-url-value

	If the "qop" value is "auth-int", then A2 is:
	A2       = Method ":" digest-url-value ":" H(entity-body)
	*/

	char *a2 = tsk_null;

	if (!qop || tsk_strempty(qop) || tsk_striequals(qop, "auth")){
		tsk_sprintf(&a2, "%s:%s", method, url);
	}
	else if (tsk_striequals(qop, "auth-int"))
	{
		if (entity_body && entity_body->data){
			tsk_md5string_t hEntity;
			if ((ret = tsk_md5compute(entity_body->data, entity_body->size, &hEntity))){
				goto bail;
			}
			tsk_sprintf(&a2, "%s:%s:%s", method, url, hEntity);
		}
		else{
			tsk_sprintf(&a2, "%s:%s:%s", method, url, TSK_MD5_EMPTY);
		}
	}

	ret = tsk_md5compute(a2, tsk_strlen(a2), ha2);

bail:
	TSK_FREE(a2);

	return ret;
}
Exemple #22
0
static char* tdav_codec_g729ab_sdp_att_get(const tmedia_codec_t* codec, const char* att_name)
{
	tdav_codec_g729ab_t* g729a = (tdav_codec_g729ab_t*)codec;

	if(tsk_striequals(att_name, "fmtp")){
		if(g729a->encoder.vad_enable){
			return tsk_strdup("annexb=yes");
		}
		else{
			return tsk_strdup("annexb=no");
		}
	}
	return tsk_null;
}
/* ======================== conds ======================== */
static tsk_bool_t _fsm_cond_get_local_candidates(tsip_dialog_invite_t* self, tsip_message_t* message)
{
	if(self->supported.ice){
		tsk_bool_t use_ice = tsk_false;
		// "action->media.type" will be defined for locally initiated media update
		tmedia_type_t new_media = TSIP_DIALOG(self)->curr_action ? TSIP_DIALOG(self)->curr_action->media.type : tmedia_none;

		if(message && TSIP_MESSAGE_HAS_CONTENT(message) && tsk_striequals("application/sdp", TSIP_MESSAGE_CONTENT_TYPE(message))){
			// If this code is called this means that we are the "answerer"
			// only gets the candidates if ICE is enabled and the remote peer supports ICE
			tsdp_message_t* sdp_ro;
			const tsdp_header_M_t* M;
			int index;
			if(!(sdp_ro = tsdp_message_parse(TSIP_MESSAGE_CONTENT_DATA(message), TSIP_MESSAGE_CONTENT_DATA_LENGTH(message)))){
				TSK_DEBUG_ERROR("Failed to parse remote sdp message");
				return tsk_false;
			}
			
			index = 0;
			while((M = (const tsdp_header_M_t*)tsdp_message_get_headerAt(sdp_ro, tsdp_htype_M, index++))){
				if(!tsdp_header_M_findA(M, "candidate")){
					use_ice = tsk_false; // do not use ICE if at least on media is ICE-less (e.g. MSRP)
					break;
				}
				use_ice = tsk_true; // only use ICE if there is a least one media line
			}
			
			new_media = tmedia_type_from_sdp(sdp_ro);

			TSK_OBJECT_SAFE_FREE(sdp_ro);
		}
		else if(!message){
			// we are the "offerer" -> use ICE only for audio or video medias (ignore ice for MSRP)
			use_ice = (new_media & tmedia_audio) || (new_media & tmedia_video);
		}

		if(use_ice){
			if(!self->ice.ctx_audio && !self->ice.ctx_video){ // First time
				return tsk_true;
			}
			else{
				if(self->ice.media_type != new_media){
					return tsk_true;
				}
				return !tsip_dialog_invite_ice_got_local_candidates(self);
			}
		}
	}
	return tsk_false;
}
Exemple #24
0
static char* tdav_codec_h264_sdp_att_get(const tmedia_codec_t* self, const char* att_name)
{
	char* att = tdav_codec_h264_common_sdp_att_get((const tdav_codec_h264_common_t*)self, att_name);
	if(att && tsk_striequals(att_name, "fmtp")) {
		tsk_strcat_2(&att, "; impl=%s",
#if HAVE_FFMPEG
			"FFMPEG"
#elif HAVE_H264_PASSTHROUGH
			"PASSTHROUGH"
#endif
			);
	}
	return att;
}
Exemple #25
0
static tsk_bool_t tdav_codec_g729ab_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
{	
	tdav_codec_g729ab_t* g729a = (tdav_codec_g729ab_t*)codec;

	if(tsk_striequals(att_name, "fmtp")){
		tsk_params_L_t* params = tsk_null;
		const char* val_str;
		if((params = tsk_params_fromstring(att_value, ";", tsk_true))){
			if((val_str = tsk_params_get_param_value(params, "annexb"))){
                g729a->encoder.vad_enable &= tsk_strequals(val_str, "yes") ? 1 : 0;
			}
			TSK_OBJECT_SAFE_FREE(params);
		}
	}
	return tsk_true;
}
// Current -> (iINVITE) -> Current
static int x0500_Current_2_Current_X_iINVITE(va_list *app)
{
	int ret;
	tsip_dialog_invite_t *self;
	const tsip_action_t* action;
	const tsip_message_t *message;

	self = va_arg(*app, tsip_dialog_invite_t *);
	message = va_arg(*app, const tsip_message_t *);
	action = va_arg(*app, const tsip_action_t *);

	self->is_client = tsk_false;
	ret = tsip_dialog_invite_ice_save_action(self, _fsm_action_iINVITE, action, message);
	
	// Cancel without notifying ("silent mode") and perform the operation right now ("sync mode")
	tsip_dialog_invite_ice_cancel_silent_and_sync_ctx(self);

	// set remote candidates
	if(TSIP_MESSAGE_HAS_CONTENT(message)){
		if(tsk_striequals("application/sdp", TSIP_MESSAGE_CONTENT_TYPE(message))){
			tsdp_message_t* sdp_ro;
			if(!(sdp_ro = tsdp_message_parse(TSIP_MESSAGE_CONTENT_DATA(message), TSIP_MESSAGE_CONTENT_DATA_LENGTH(message)))){
				TSK_DEBUG_ERROR("Failed to parse remote sdp message");
				return -2;
			}
			// create ICE context
			if((ret = tsip_dialog_invite_ice_create_ctx(self, tmedia_type_from_sdp(sdp_ro)))){
				TSK_DEBUG_ERROR("tsip_dialog_invite_ice_create_ctx() failed");
				return ret;
			}
			ret = tsip_dialog_invite_ice_process_ro(self, sdp_ro, tsk_true);
			TSK_OBJECT_SAFE_FREE(sdp_ro);
		}
		else{
			TSK_DEBUG_ERROR("[%s] content-type is not supportted", TSIP_MESSAGE_CONTENT_TYPE(message));
			return -3;
		}
	}

	// For now disable ICE timers until we send the 2xx and receive the ACK
	ret = tsip_dialog_invite_ice_timers_set(self, -1);

	// Start ICE
	ret = tsip_dialog_invite_ice_start_ctx(self);

	return ret;
}
Exemple #27
0
static int tdav_speex_denoise_set(tmedia_denoise_t* _self, const tmedia_param_t* param)
{
	tdav_speex_denoise_t *self = (tdav_speex_denoise_t *)_self;
	if(!self || !param){
		TSK_DEBUG_ERROR("Invalid parameter");
		return -1;
	}
	
	if(param->value_type == tmedia_pvt_int32){
		if(tsk_striequals(param->key, "echo-tail")){
			int32_t echo_tail = *((int32_t*)param->value);
			TSK_DEBUG_INFO("speex_set_echo_tail(%d) ignore", echo_tail); // because Speex AEC just do not work (use WebRTC)
			return 0;
		}
	}
	return -1;
}
Exemple #28
0
/**@ingroup txc_document_group
* Create a custom XCAP document selector URI as per <a href="http://tools.ietf.org/html/rfc4825#section-6.2">RFC 4825 subclause 6.2</a>
* @param xcaproot The XCAP Root URI. A context that contains all the documents across all
* application usages and users that are managed by the server. For more information see <a href="http://tools.ietf.org/html/rfc4825#section-4">RFC 4825 subclause 4</a>
* @param auid The Application Unique ID.  unique identifier within the namespace of application unique IDs created by this specification
* that differentiates XCAP resources accessed by one application from XCAP resources accessed by another.
* For more information see <a href="http://tools.ietf.org/html/rfc4825#section-4">RFC 4825 subclause 4</a>
* @param xui The XCAP User Identifier. The XUI is a string, valid as a path element in an HTTP URI, that is associated with each user served
*  by the XCAP server. For more information see <a href="http://tools.ietf.org/html/rfc4825#section-4">RFC 4825 subclause 4</a>.
* For global document, this parameter must be NULL or equal to "global"
* @param name The document name.
* @retval The HTTP URI containing the XCAP root and document selector, resulting in the selection of a specific document.  As a
  result, performing a GET against the document URI would retrieve the document.
* If supplied parameters are not valide this method will return NULL.
* You must free the returned string using TSK_FREE or TSK_SAFE_FREE.
* @sa @ref TXC_DOC_GET_SEL and @ref TXC_DOC_GET_SEL2
*/
char* txc_doc_get_cust_sel(const char *xcaproot, const char *auid, const char *xui, const char *name)
{
	char *selector = 0;

	if(!xcaproot || !auid || !name) return 0;

	if(!xui || tsk_striequals("global", xui))
	{	/* xdm-root/auid-name/global/doc-name */
		tsk_sprintf(&selector, "%s/%s/global/%s", xcaproot, auid, name);
	}
	else
	{	/* xdm-root/auid-name/users/xui/doc-name */
		tsk_sprintf(&selector, "%s/%s/users/%s/%s", xcaproot, auid, xui, name);
	}

	return selector;
}
Exemple #29
0
/**@ingroup tmedia_codec_group
* Creates a new codec using an already registered plugin.
* @param format The format of the codec to create (e.g. "0" for PCMU or "8" for PCMA or "*" for MSRP)
* @sa @ref tmedia_codec_plugin_register()
*/
tmedia_codec_t* tmedia_codec_create(const char* format)
{
    tmedia_codec_t* codec = tsk_null;
    const tmedia_codec_plugin_def_t* plugin;
    tsk_size_t i = 0;

    while((i < TMED_CODEC_MAX_PLUGINS) && (plugin = __tmedia_codec_plugins[i++])) {
        if(plugin->objdef && tsk_striequals(plugin->format, format)) {
            if((codec = tsk_object_new(plugin->objdef))) {
                /* initialize the newly created codec */
                codec->id = plugin->codec_id;
                codec->dyn = plugin->dyn;
                codec->plugin = plugin;
                codec->bl = tmedia_bl_medium;
                switch(plugin->type) {
                case tmedia_audio: {
                    /* Audio codec */
                    tmedia_codec_audio_t* audio = TMEDIA_CODEC_AUDIO(codec);
                    tmedia_codec_audio_init(TMEDIA_CODEC(audio), plugin->name, plugin->desc, plugin->format);
                    break;
                }
                case tmedia_video: {
                    /* Video codec */
                    tmedia_codec_video_t* video = TMEDIA_CODEC_VIDEO(codec);
                    tmedia_codec_video_init(TMEDIA_CODEC(video), plugin->name, plugin->desc, plugin->format);
                    break;
                }
                case tmedia_msrp: {
                    /* Msrp codec */
                    tmedia_codec_msrp_init(codec, plugin->name, plugin->desc);
                    break;
                }
                default: {
                    /* Any other codec */
                    tmedia_codec_init(codec, plugin->type, plugin->name, plugin->desc, plugin->format);
                    break;
                }
                }
                break;
            }
        }
    }

    return codec;
}
static int tdav_webrtc_denoise_set(tmedia_denoise_t* _self, const tmedia_param_t* param)
{
	tdav_webrtc_denoise_t *self = (tdav_webrtc_denoise_t *)_self;
	if(!self || !param){
		TSK_DEBUG_ERROR("Invalid parameter");
		return -1;
	}
	
	if(param->value_type == tmedia_pvt_int32){
		if(tsk_striequals(param->key, "echo-tail")){
			int32_t echo_tail = *((int32_t*)param->value);
			self->echo_tail = TSK_CLAMP(WEBRTC_MIN_ECHO_TAIL, echo_tail, WEBRTC_MAX_ECHO_TAIL);
			TSK_DEBUG_INFO("set_echo_tail (%d->%d)", echo_tail, self->echo_tail);
			return 0;
		}
	}
	return -1;
}