コード例 #1
0
ファイル: tsk_uuid.c プロジェクト: NewComerBH/doubango
/**@ingroup tsk_uuid_group
*/
int tsk_uuidgenerate(tsk_uuidstring_t *result)
{
	/* From wikipedia
	*	Version 5 UUIDs use a scheme with SHA-1 hashing, otherwise it is the same idea as in version 3. 
	*	RFC 4122 states that version 5 is preferred over version 3 name based UUIDs. 
	*	Note that the 160 bit SHA-1 hash is truncated to 128 bits to make the length work out.
	*/
	tsk_sha1string_t sha1result;
	tsk_istr_t epoch;
	unsigned i, k;
	static char HEX[] = "0123456789abcdef";

	tsk_itoa(tsk_time_epoch(), &epoch);
	tsk_sha1compute(epoch, sizeof(epoch), &sha1result);

	/* XOR the SHA-1 result with random numbers. */
	for(i=0; i<(TSK_UUID_DIGEST_SIZE*2); i+=4){
#if 0
		*((uint32_t*)&sha1result[i]) ^= rand();
#else
		k = rand();
		sha1result[i] ^= k, sha1result[i + 1] ^= k,
		sha1result[i + 2] ^= k, sha1result[i + 3] ^= k;
#endif
		
		for(k=0; k<sizeof(uint32_t); k++){
			sha1result[i+k] = HEX[sha1result[i+k] & 0x0F]; /* To hexa. */
		}
	}

	/* f47ac10b-58cc-4372-a567-0e02b2c3d479 */
	memcpy(&(*result)[0], &sha1result[0], 8);
	(*result)[8] = '-';

	memcpy(&(*result)[9], &sha1result[8], 4);
	(*result)[13] = '-';

	memcpy(&(*result)[14], &sha1result[12], 4);
	(*result)[18] = '-';

	memcpy(&(*result)[19], &sha1result[16], 4);
	(*result)[23] = '-';

	memcpy(&(*result)[24], &sha1result[20], 12);
	(*result)[36] = '\0';

	return 0;
}
コード例 #2
0
//=================================================================================================
//	SOCKET object definition
//
static tsk_object_t* tnet_socket_ctor(tsk_object_t * self, va_list * app)
{
	tnet_socket_t *sock = self;
	if(sock){
		int status;
		tsk_bool_t nonblocking;
		tsk_bool_t bindsocket;
		tsk_istr_t port;
		struct addrinfo *result = 0;
		struct addrinfo *ptr = 0;
		struct addrinfo hints;
		tnet_host_t local_hostname;

		const char *host = va_arg(*app, const char*);
#if defined(__GNUC__)
		sock->port = (tnet_port_t)va_arg(*app, unsigned);
#else
		sock->port = va_arg(*app, tnet_port_t);
#endif
		tsk_itoa(sock->port, &port);
		sock->type = va_arg(*app, tnet_socket_type_t);
		nonblocking = va_arg(*app, tsk_bool_t);
		bindsocket = va_arg(*app, tsk_bool_t);

		memset(local_hostname, 0, sizeof(local_hostname));

		/* Get the local host name */
		if(host != TNET_SOCKET_HOST_ANY && !tsk_strempty(host)){
			memcpy(local_hostname, host, tsk_strlen(host)>sizeof(local_hostname)-1 ? sizeof(local_hostname)-1 : tsk_strlen(host));
		}
		else{
			if(TNET_SOCKET_TYPE_IS_IPV6(sock->type)){
				memcpy(local_hostname, "::", 2);
			}
			else{
				memcpy(local_hostname, "0.0.0.0", 7);
			}
			//if((status = tnet_gethostname(&local_hostname)))
			//{
			//	TNET_PRINT_LAST_ERROR("gethostname have failed.");
			//	goto bail;
			//}
		}

		/* hints address info structure */
		memset(&hints, 0, sizeof(hints));
		hints.ai_family = TNET_SOCKET_TYPE_IS_IPV46(sock->type) ? AF_UNSPEC : (TNET_SOCKET_TYPE_IS_IPV6(sock->type) ? AF_INET6 : AF_INET);
		hints.ai_socktype = TNET_SOCKET_TYPE_IS_STREAM(sock->type) ? SOCK_STREAM : SOCK_DGRAM;
		hints.ai_protocol = TNET_SOCKET_TYPE_IS_STREAM(sock->type) ? IPPROTO_TCP : IPPROTO_UDP;
		hints.ai_flags = AI_PASSIVE
#if !TNET_UNDER_WINDOWS || _WIN32_WINNT>=0x600
			| AI_ADDRCONFIG
#endif
			;

		/* Performs getaddrinfo */
		if((status = tnet_getaddrinfo(local_hostname, port, &hints, &result))){
			TNET_PRINT_LAST_ERROR("tnet_getaddrinfo(family=%d, hostname=%s and port=%s) failed: [%s]", 
				hints.ai_family, local_hostname, port, tnet_gai_strerror(status));
			goto bail;
		}
		
		/* Find our address. */
		for(ptr = result; ptr; ptr = ptr->ai_next){
			sock->fd = tnet_soccket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
			if(ptr->ai_family != AF_INET6 && ptr->ai_family != AF_INET){
				continue;
			}
			
			if(bindsocket){
				/* Bind the socket */
				if((status = bind(sock->fd, ptr->ai_addr, ptr->ai_addrlen))){
					TNET_PRINT_LAST_ERROR("bind have failed.");
					tnet_socket_close(sock);
					continue;
				}

				/* Get local IP string. */
				if(status = tnet_get_ip_n_port(sock->fd , &sock->ip, &sock->port)) /* % */
				//if((status = tnet_getnameinfo(ptr->ai_addr, ptr->ai_addrlen, sock->ip, sizeof(sock->ip), 0, 0, NI_NUMERICHOST)))
				{
					TNET_PRINT_LAST_ERROR("Failed to get local IP and port.");
					tnet_socket_close(sock);
					continue;
				}
//				else{
//#if TNET_UNDER_WINDOWS
//					int index;
//					if((index = tsk_strindexOf(sock->ip, tsk_strlen(sock->ip), "%")) > 0){
//						*(sock->ip + index) = '\0';
//					}
//#endif
//				}
			}

			/* sets the real socket type (if ipv46) */
			if(ptr->ai_family == AF_INET6) {
				TNET_SOCKET_TYPE_SET_IPV6Only(sock->type);
			}
			else{
				TNET_SOCKET_TYPE_SET_IPV4Only(sock->type);
			}
			break;
		}
		
		/* Check socket validity. */
		if(!TNET_SOCKET_IS_VALID(sock)) {
			TNET_PRINT_LAST_ERROR("Invalid socket.");
			goto bail;
		}		

		/* To avoid "Address already in use" error */
		{
#if defined(SOLARIS)
			char yes = '1';
#else
			int yes = 1;
#endif
			if(setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(int))){
				TNET_PRINT_LAST_ERROR("setsockopt(SO_REUSEADDR) have failed.");
			}
		}

		/* Sets the socket to nonblocking mode */
		if(nonblocking){
			if((status = tnet_sockfd_set_nonblocking(sock->fd))){
				goto bail;
			}
		}

bail:
		/* Free addrinfo */
		tnet_freeaddrinfo(result);

		/* Close socket if failed. */
		if(status && TNET_SOCKET_IS_VALID(sock)){
			tnet_socket_close(sock);
		}

	}
	return self;
}
コード例 #3
0
/**@ingroup tsk_string_group
 * Generates a random string.
 *
 * @param result	A pointer to the result. 
**/
void tsk_strrandom(tsk_istr_t *result)
{
	static uint64_t __counter = 1;
	tsk_itoa((tsk_time_now() ^ (rand())) ^ ++__counter, result);
}
コード例 #4
0
ファイル: main.c プロジェクト: Globik/doubango
int execute(const cmd_t* cmd)
{
	int ret = 0;
	tsip_ssession_id_t sid;
	tsk_istr_t istr;

	if(!cmd){
		TSK_DEBUG_ERROR("Invalid parameter");
		return -1;
	}

	tsk_safeobj_lock(ctx);

	switch(cmd->type){
		case cmd_audio:
		case cmd_audiovideo:
			{
				TSK_DEBUG_INFO("command=audio/video");
				if((sid = invite_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID){
					if(cmd->sidparam){
						tsk_itoa(sid, &istr);
						update_param(cmd->sidparam, istr);
					}
				}
				break;
			}
		case cmd_config_session:
			{
				TSK_DEBUG_INFO("command=config-session");
				break;
			}
		case cmd_config_stack:
			{
				TSK_DEBUG_INFO("command=config-satck");
				ret = stack_config(cmd->opts);
				break;
			}
		case cmd_dtmf:
			{
				const opt_t* opt;
				TSK_DEBUG_INFO("command=dtmf");
				if(!(opt = opt_get_by_type(cmd->opts, opt_sid)) || tsk_strnullORempty(opt->value)){ /* --sid option */
					TSK_DEBUG_ERROR("++dtmf command need --sid option");
					break;
				}
				if(!(opt = opt_get_by_type(cmd->opts, opt_event)) || tsk_strnullORempty(opt->value)){ /* --event option */
					TSK_DEBUG_ERROR("++dtmf command need --event option");
					break;
				}
				invite_handle_cmd(cmd->type, cmd->opts);
				break;
			}
		case cmd_dump:
			{
				TSK_DEBUG_INFO("command=dump");
				ret = stack_dump();
				break;
			}
		case cmd_ect:
		{
			const opt_t* opt;
			TSK_DEBUG_INFO("command=ect");
			if((opt = opt_get_by_type(cmd->opts, opt_sid)) && !tsk_strnullORempty(opt->value)){
				TSK_DEBUG_ERROR("++ect command need --sid option");
				ret = -1;
				break;
			}
			if((opt = opt_get_by_type(cmd->opts, opt_to)) && !tsk_strnullORempty(opt->value)){
				TSK_DEBUG_ERROR("++ect command need --to option");
				ret = -1;
				break;
			}
			invite_handle_cmd(cmd->type, cmd->opts);
			break;
		}
		case cmd_exit:
			{
				TSK_DEBUG_INFO("command=exit");
				goto bail;
				break;
			}
		case cmd_file:
			{
				const opt_t* opt;
				TSK_DEBUG_INFO("command=file");
				if(!(opt = opt_get_by_type(cmd->opts, opt_path)) || tsk_strnullORempty(opt->value)){
					TSK_DEBUG_ERROR("++file command need --path option");
					break;
				}
				if((sid = invite_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID){
					if(cmd->sidparam){
						tsk_itoa(sid, &istr);
						update_param(cmd->sidparam, istr);
					}
				}
				break;
			}
		case cmd_hangup:
			{
				const opt_t* opt;
				TSK_DEBUG_INFO("command=hangup");
				if((opt = opt_get_by_type(cmd->opts, opt_sid)) && !tsk_strnullORempty(opt->value)){ /* --sid option */
					ret = session_hangup(tsk_atoll(opt->value));
				}
				else{
					TSK_DEBUG_ERROR("++hangup command need --sid option");
					ret = -1;
				}
				break;
			}
		case cmd_help:
			{
				TSK_DEBUG_INFO("command=help");
				cmd_print_help();
				break;
			}
		case cmd_hold:
			{
				const opt_t* opt;
				TSK_DEBUG_INFO("command=hold");
				if((opt = opt_get_by_type(cmd->opts, opt_sid)) && !tsk_strnullORempty(opt->value)){ /* --sid option */
					invite_handle_cmd(cmd->type, cmd->opts);
				}
				else{
					TSK_DEBUG_ERROR("++hold command need --sid option");
					ret = -1;
				}
				break;
			}
		case cmd_message:
			{
				TSK_DEBUG_INFO("command=message");
				if((sid = message_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID){
					if(cmd->sidparam){
						tsk_itoa(sid, &istr);
						update_param(cmd->sidparam, istr);
					}
				}
				break;
			}

		case cmd_options:
			{
				TSK_DEBUG_INFO("command=options");
				if((sid = options_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID){
					if(cmd->sidparam){
						tsk_itoa(sid, &istr);
						update_param(cmd->sidparam, istr);
					}
				}
				break;
			}
		case cmd_publish:
			{
				TSK_DEBUG_INFO("command=publish");
				if((sid = publish_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID){
					if(cmd->sidparam){
						tsk_itoa(sid, &istr);
						update_param(cmd->sidparam, istr);
					}
				}
				break;
			}
		case cmd_register:
			{
				TSK_DEBUG_INFO("command=register");
				if((sid = register_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID){
					if(cmd->sidparam){
						tsk_itoa(sid, &istr);
						update_param(cmd->sidparam, istr);
					}
				}
				break;
			}
		case cmd_resume:
			{
				const opt_t* opt;
				TSK_DEBUG_INFO("command=resume");
				if((opt = opt_get_by_type(cmd->opts, opt_sid)) && !tsk_strnullORempty(opt->value)){ /* --sid option */
					invite_handle_cmd(cmd->type, cmd->opts);
				}
				else{
					TSK_DEBUG_ERROR("++resume command need --sid option");
					ret = -1;
				}
				break;
			}
		case cmd_run:
			{
				TSK_DEBUG_INFO("command=run");
				ret = stack_run(cmd->opts);
				break;
			}
		case cmd_scenario:
			{
				TSK_DEBUG_INFO("command=scenario");
				break;
			}
		case cmd_sleep:
			{
				const opt_t* opt;
				double seconds;

				tsk_safeobj_unlock(ctx); /* beacuse of callback function */

				if((opt = opt_get_by_type(cmd->opts, opt_sec)) && !tsk_strnullORempty(opt->value)){ /* --sec option */
					seconds = strtod(opt->value, tsk_null); /* strtod() is better than atof() */
					if(seconds<=0){
						printf("\n==== Press ENTER to continue...\n");
						getchar();
					}
					else{
						TSK_DEBUG_INFO("Sleeping %f seconds", seconds);
						tsk_thread_sleep((uint64_t)(seconds * 1000));
					}
				}
				else{
					TSK_DEBUG_WARN("++sleep need --sec option.");
				}
				return 0; /* bail: will unlock again */
			}
		case cmd_sms:
			{
				TSK_DEBUG_INFO("command=sms");
				if((sid = message_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID){
					if(cmd->sidparam){
						tsk_itoa(sid, &istr);
						update_param(cmd->sidparam, istr);
					}
				}
				break;
			}
		case cmd_stop:
			{
				TSK_DEBUG_INFO("command=stop");
				tsip_stack_stop(ctx->stack);
				break;
			}
		case cmd_subscribe:
			{
				TSK_DEBUG_INFO("command=subscribe");
				if((sid = subscribe_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID){
					if(cmd->sidparam){
						tsk_itoa(sid, &istr);
						update_param(cmd->sidparam, istr);
					}
				}
				break;
			}
		case cmd_video:
			{
				TSK_DEBUG_INFO("command=video");
				break;
			}
		default:
			{
				TSK_DEBUG_ERROR("%d not a valid command.", cmd);
				break;
			}
	}

bail:
	tsk_safeobj_unlock(ctx);

	return ret;
}
コード例 #5
0
ファイル: tnet_socket.c プロジェクト: amin3411/doubango
/**@ingroup tnet_socket_group
* Creates a new socket.
* To check that the returned socket is valid use @ref TNET_SOCKET_IS_VALID function.
* @param host FQDN (e.g. www.doubango.org) or IPv4/IPv6 IP string.
* @param port The local/remote port used to receive/send data. Set the port value to @ref TNET_SOCKET_PORT_ANY to bind to a random port.
* @param type The type of the socket. See @ref tnet_socket_type_t.
* @param nonblocking Indicates whether to create non-blocking socket.
* @param bindsocket Indicates whether to bind the newly created socket or not.
* @retval @ref tnet_socket_t object.
* @sa @ref tnet_socket_create.
*/
tnet_socket_t* tnet_socket_create_2(const char* host, tnet_port_t port_, tnet_socket_type_t type, tsk_bool_t nonblocking, tsk_bool_t bindsocket)
{
	tnet_socket_t *sock;
	if ((sock = tsk_object_new(tnet_socket_def_t))) {
		int status;
		tsk_istr_t port;
		struct addrinfo *result = tsk_null;
		struct addrinfo *ptr = tsk_null;
		struct addrinfo hints;
		tnet_host_t local_hostname;

		sock->port = port_;
		tsk_itoa(sock->port, &port);
		sock->type = type;

		memset(local_hostname, 0, sizeof(local_hostname));

		/* Get the local host name */
		if (host != TNET_SOCKET_HOST_ANY && !tsk_strempty(host)){
			memcpy(local_hostname, host, tsk_strlen(host) > sizeof(local_hostname) - 1 ? sizeof(local_hostname) - 1 : tsk_strlen(host));
		}
		else{
			if (TNET_SOCKET_TYPE_IS_IPV6(sock->type)){
				memcpy(local_hostname, "::", 2);
			}
			else {
				memcpy(local_hostname, "0.0.0.0", 7);
			}
		}

		/* hints address info structure */
		memset(&hints, 0, sizeof(hints));
		hints.ai_family = TNET_SOCKET_TYPE_IS_IPV46(sock->type) ? AF_UNSPEC : (TNET_SOCKET_TYPE_IS_IPV6(sock->type) ? AF_INET6 : AF_INET);
		hints.ai_socktype = TNET_SOCKET_TYPE_IS_STREAM(sock->type) ? SOCK_STREAM : SOCK_DGRAM;
		hints.ai_protocol = TNET_SOCKET_TYPE_IS_STREAM(sock->type) ? IPPROTO_TCP : IPPROTO_UDP;
		hints.ai_flags = AI_PASSIVE
#if !TNET_UNDER_WINDOWS || _WIN32_WINNT>=0x600
			| AI_ADDRCONFIG
#endif
			;

		/* Performs getaddrinfo */
		if ((status = tnet_getaddrinfo(local_hostname, port, &hints, &result))) {
			TNET_PRINT_LAST_ERROR("tnet_getaddrinfo(family=%d, hostname=%s and port=%s) failed: [%s]",
				hints.ai_family, local_hostname, port, tnet_gai_strerror(status));
			goto bail;
	}

		/* Find our address. */
		for (ptr = result; ptr; ptr = ptr->ai_next){
			sock->fd = (tnet_fd_t)tnet_soccket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
			if (ptr->ai_family != AF_INET6 && ptr->ai_family != AF_INET){
				continue;
			}
			/* To avoid "Address already in use" error
			* Check issue 368 (https://code.google.com/p/doubango/issues/detail?id=368) to understand why it's not used for UDP/DTLS.
			*/
			//
			if (TNET_SOCKET_TYPE_IS_STREAM(sock->type)) {
				if ((status = tnet_sockfd_reuseaddr(sock->fd, 1))) {
					// do not break...continue
				}
			}

			if (bindsocket){
				/* Bind the socket */
				if ((status = bind(sock->fd, ptr->ai_addr, (int)ptr->ai_addrlen))){
					TNET_PRINT_LAST_ERROR("bind to [%s:%s]have failed", local_hostname, port);
					tnet_socket_close(sock);
					continue;
				}

				/* Get local IP string. */
				if ((status = tnet_get_ip_n_port(sock->fd, tsk_true/*local*/, &sock->ip, &sock->port))) /* % */
					//if((status = tnet_getnameinfo(ptr->ai_addr, ptr->ai_addrlen, sock->ip, sizeof(sock->ip), 0, 0, NI_NUMERICHOST)))
				{
					TNET_PRINT_LAST_ERROR("Failed to get local IP and port.");
					tnet_socket_close(sock);
					continue;
				}
			}

			/* sets the real socket type (if ipv46) */
			if (ptr->ai_family == AF_INET6) {
				TNET_SOCKET_TYPE_SET_IPV6Only(sock->type);
			}
			else {
				TNET_SOCKET_TYPE_SET_IPV4Only(sock->type);
			}
			break;
		}

		/* Check socket validity. */
		if (!TNET_SOCKET_IS_VALID(sock)) {
			TNET_PRINT_LAST_ERROR("Invalid socket.");
			goto bail;
		}

#if TNET_UNDER_IPHONE || TNET_UNDER_IPHONE_SIMULATOR
		/* disable SIGPIPE signal */
		{
			int yes = 1;
			if (setsockopt(sock->fd, SOL_SOCKET, SO_NOSIGPIPE, (char*)&yes, sizeof(int))){
				TNET_PRINT_LAST_ERROR("setsockopt(SO_NOSIGPIPE) have failed.");
			}
		}
#endif /* TNET_UNDER_IPHONE */

		/* Sets the socket to nonblocking mode */
		if(nonblocking){
			if((status = tnet_sockfd_set_nonblocking(sock->fd))){
				goto bail;
			}
		}

	bail:
		/* Free addrinfo */
		tnet_freeaddrinfo(result);

		/* Close socket if failed. */
		if (status){
			if (TNET_SOCKET_IS_VALID(sock)){
				tnet_socket_close(sock);
			}
			return tsk_null;
		}
}

	return sock;
}
コード例 #6
0
// RTP/RTCP callback (From the network to the consumer)
static int tdav_session_audio_rtp_cb(const void* callback_data, const struct trtp_rtp_packet_s* packet)
{
	tdav_session_audio_t* audio = (tdav_session_audio_t*)callback_data;
	tdav_session_av_t* base = (tdav_session_av_t*)callback_data;

	if(!audio || !packet || !packet->header){
		TSK_DEBUG_ERROR("Invalid parameter");
		return -1;
	}

	if(audio->is_started && base->consumer && base->consumer->is_started){
		tsk_size_t out_size = 0;

		// Find the codec to use to decode the RTP payload
		if(!audio->decoder.codec || audio->decoder.payload_type != packet->header->payload_type){
			tsk_istr_t format;
			TSK_OBJECT_SAFE_FREE(audio->decoder.codec);
			tsk_itoa(packet->header->payload_type, &format);
			if(!(audio->decoder.codec = tmedia_codec_find_by_format(TMEDIA_SESSION(audio)->neg_codecs, format)) || !audio->decoder.codec->plugin || !audio->decoder.codec->plugin->decode){
				TSK_DEBUG_ERROR("%s is not a valid payload for this session", format);
				return -2;
			}
			audio->decoder.payload_type = packet->header->payload_type;
		}
		
		// Open codec if not already done
		if(!TMEDIA_CODEC(audio->decoder.codec)->opened){
			int ret;
			tsk_safeobj_lock(base);
			if((ret = tmedia_codec_open(audio->decoder.codec))){
				tsk_safeobj_unlock(base);
				TSK_DEBUG_ERROR("Failed to open [%s] codec", audio->decoder.codec->plugin->desc);
				TSK_OBJECT_SAFE_FREE(audio->decoder.codec);
				return ret;
			}
			tsk_safeobj_unlock(base);
		}
		// Decode data
		out_size = audio->decoder.codec->plugin->decode(audio->decoder.codec, packet->payload.data, packet->payload.size, &audio->decoder.buffer, &audio->decoder.buffer_size, packet->header);
		if(out_size){
			void* buffer = audio->decoder.buffer;
			tsk_size_t size = out_size;

			// resample if needed
			if((base->consumer->audio.out.rate && base->consumer->audio.out.rate != audio->decoder.codec->in.rate) || (base->consumer->audio.out.channels && base->consumer->audio.out.channels != TMEDIA_CODEC_AUDIO(audio->decoder.codec)->in.channels)){
				tsk_size_t resampler_result_size = 0;
				int bytesPerSample = (base->consumer->audio.bits_per_sample >> 3);

				if(!audio->decoder.resampler.instance){
					TSK_DEBUG_INFO("Create audio resampler(%s) for consumer: rate=%d->%d, channels=%d->%d, bytesPerSample=%d", 
						audio->decoder.codec->plugin->desc, 
						audio->decoder.codec->in.rate, base->consumer->audio.out.rate,
						TMEDIA_CODEC_AUDIO(audio->decoder.codec)->in.channels, base->consumer->audio.out.channels,
						bytesPerSample);
					audio->decoder.resampler.instance = _tdav_session_audio_resampler_create(
							bytesPerSample, 
							audio->decoder.codec->in.rate, base->consumer->audio.out.rate, 
							base->consumer->audio.ptime, 
							TMEDIA_CODEC_AUDIO(audio->decoder.codec)->in.channels, base->consumer->audio.out.channels, 
							TDAV_AUDIO_RESAMPLER_DEFAULT_QUALITY, 
							&audio->decoder.resampler.buffer, &audio->decoder.resampler.buffer_size
						);
				}
				if(!audio->decoder.resampler.instance){
					TSK_DEBUG_ERROR("No resampler to handle data");
					return -5;
				}
				if(!(resampler_result_size = tmedia_resampler_process(audio->decoder.resampler.instance, buffer, size/bytesPerSample, audio->decoder.resampler.buffer, audio->decoder.resampler.buffer_size/bytesPerSample))){
					TSK_DEBUG_ERROR("Failed to process audio resampler input buffer");
					return -6;
				}
				
				buffer = audio->decoder.resampler.buffer;
				size = audio->decoder.resampler.buffer_size;
			}

			// adjust the gain
			if(base->consumer->audio.gain){
				_tdav_session_audio_apply_gain(buffer, size, base->consumer->audio.bits_per_sample, base->consumer->audio.gain);
			}
			// consume the frame
			tmedia_consumer_consume(base->consumer, buffer, size, packet->header);
		}