コード例 #1
0
ファイル: mod_pocketsphinx.c プロジェクト: dgkae/unicallasr
/*! function to close the asr interface */
static switch_status_t pocketsphinx_asr_close(switch_asr_handle_t *ah, switch_asr_flag_t *flags)
{
	pocketsphinx_t *ps = (pocketsphinx_t *) ah->private_info;

    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, ">>>>>>>>pocketsphinx_asr_close<<<<<<<<<\n");

	switch_mutex_lock(ps->flag_mutex);
	if (switch_test_flag(ps, PSFLAG_ALLOCATED)) {
		if (switch_test_flag(ps, PSFLAG_READY)) {
			ps_end_utt(ps->ps);
		}
		ps_free(ps->ps);
		ps->ps = NULL;
	}
	switch_safe_free(ps->grammar);
	switch_mutex_unlock(ps->flag_mutex);
	switch_clear_flag(ps, PSFLAG_HAS_TEXT);
	switch_clear_flag(ps, PSFLAG_READY);
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Port Closed.\n");
	switch_set_flag(ah, SWITCH_ASR_FLAG_CLOSED);
    
    /* ifly  end session */
    
	QISRSessionEnd(ps->ifly_session_id, ps->ifly_hints);
    
	return SWITCH_STATUS_SUCCESS;
}
コード例 #2
0
SWITCH_DECLARE(uint32_t) switch_core_media_bug_set_flag(switch_media_bug_t *bug, uint32_t flag)
{
	if ((flag & SMBF_PRUNE)) {
		switch_clear_flag(bug, SMBF_LOCK);
	}
	return switch_set_flag(bug, flag);
}
コード例 #3
0
ファイル: mod_kazoo.c プロジェクト: odmanV2/freecenter
static switch_status_t handle_node_api_command(ei_node_t *ei_node, switch_stream_handle_t *stream, uint32_t command) {
	unsigned int year, day, hour, min, sec, delta;
	
	switch (command) {
	case API_COMMAND_DISCONNECT:
		stream->write_function(stream, "Disconnecting erlang node %s at managers request\n", ei_node->peer_nodename);
		switch_clear_flag(ei_node, LFLAG_RUNNING);
		break;
	case API_COMMAND_REMOTE_IP:
		delta = (switch_micro_time_now() - ei_node->created_time) / 1000000;
		sec = delta % 60;
		min = delta / 60 % 60;
		hour = delta / 3600 % 24;
		day = delta / 86400 % 7;
		year = delta / 31556926 % 12;
		
		stream->write_function(stream, "Uptime           %d years, %d days, %d hours, %d minutes, %d seconds\n", year, day, hour, min, sec);
		stream->write_function(stream, "Local Address    %s:%d\n", ei_node->local_ip, ei_node->local_port);
		stream->write_function(stream, "Remote Address   %s:%d\n", ei_node->remote_ip, ei_node->remote_port);
		break;
	case API_COMMAND_STREAMS:
		handle_node_api_event_streams(ei_node, stream);
		break;
	case API_COMMAND_BINDINGS:
		handle_api_command_streams(ei_node, stream);
		break;
	default:
		break;
	}
	
	return SWITCH_STATUS_SUCCESS;
}
コード例 #4
0
/*! function to read results from the ASR */
static switch_status_t pocketsphinx_asr_get_results(switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags)
{
	pocketsphinx_t *ps = (pocketsphinx_t *) ah->private_info;
	switch_status_t status = SWITCH_STATUS_SUCCESS;

	if (switch_test_flag(ps, PSFLAG_BARGE)) {
		switch_clear_flag_locked(ps, PSFLAG_BARGE);
		status = SWITCH_STATUS_BREAK;
	}

	if (switch_test_flag(ps, PSFLAG_HAS_TEXT)) {
		switch_mutex_lock(ps->flag_mutex);
		switch_clear_flag(ps, PSFLAG_HAS_TEXT);

		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Recognized: %s, Confidence: %d, Confidence-Threshold: %d\n", ps->hyp, ps->confidence, ps->confidence_threshold);
		switch_mutex_unlock(ps->flag_mutex);

		*xmlstr = switch_mprintf("<?xml version=\"1.0\"?>\n"
								 "<result grammar=\"%s\">\n"
								 "  <interpretation grammar=\"%s\" confidence=\"%d\">\n"
								 "    <input mode=\"speech\">%s</input>\n"
								 "  </interpretation>\n" "</result>\n", ps->grammar, ps->grammar, ps->confidence, ps->hyp);

		if (!switch_test_flag(ps, PSFLAG_INPUT_TIMERS) && switch_test_flag(ah, SWITCH_ASR_FLAG_AUTO_RESUME)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Auto Resuming\n");
			switch_set_flag(ps, PSFLAG_READY);

			ps_start_utt(ps->ps, NULL);
		}

		status = SWITCH_STATUS_SUCCESS;
	} else if (switch_test_flag(ps, PSFLAG_NOINPUT)) {
		switch_clear_flag_locked(ps, PSFLAG_NOINPUT);
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NO INPUT\n");

		*xmlstr = switch_mprintf("<?xml version=\"1.0\"?>\n"
								 "<result grammar=\"%s\">\n"
								 "  <interpretation>\n"
								 "    <input mode=\"speech\"><noinput/></input>\n"
								 "  </interpretation>\n"
								 "</result>\n", ps->grammar);

		status = SWITCH_STATUS_SUCCESS;
	} else if (switch_test_flag(ps, PSFLAG_NOMATCH)) {
		switch_clear_flag_locked(ps, PSFLAG_NOMATCH);
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NO MATCH\n");

		*xmlstr = switch_mprintf("<?xml version=\"1.0\"?>\n"
								 "<result grammar=\"%s\">\n"
								 "  <interpretation>\n"
								 "    <input mode=\"speech\"><nomatch/></input>\n"
								 "  </interpretation>\n"
								 "</result>\n", ps->grammar);

		status = SWITCH_STATUS_SUCCESS;
	}

	return status;
}
コード例 #5
0
ファイル: mod_reference.c プロジェクト: odmanV2/freecenter
static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
{
    switch_channel_t *channel = NULL;
    private_t *tech_pvt = NULL;
    //switch_time_t started = switch_time_now();
    //unsigned int elapsed;
    switch_byte_t *data;

    channel = switch_core_session_get_channel(session);
    assert(channel != NULL);

    tech_pvt = switch_core_session_get_private(session);
    assert(tech_pvt != NULL);
    tech_pvt->read_frame.flags = SFF_NONE;
    *frame = NULL;

    while (switch_test_flag(tech_pvt, TFLAG_IO)) {

        if (switch_test_flag(tech_pvt, TFLAG_BREAK)) {
            switch_clear_flag(tech_pvt, TFLAG_BREAK);
            goto cng;
        }

        if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
            return SWITCH_STATUS_FALSE;
        }

        if (switch_test_flag(tech_pvt, TFLAG_IO) && switch_test_flag(tech_pvt, TFLAG_VOICE)) {
            switch_clear_flag_locked(tech_pvt, TFLAG_VOICE);
            if (!tech_pvt->read_frame.datalen) {
                continue;
            }
            *frame = &tech_pvt->read_frame;
#if SWITCH_BYTE_ORDER == __BIG_ENDIAN
            if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) {
                switch_swap_linear((*frame)->data, (int) (*frame)->datalen / 2);
            }
#endif
            return SWITCH_STATUS_SUCCESS;
        }

        switch_cond_next();
    }


    return SWITCH_STATUS_FALSE;

cng:
    data = (switch_byte_t *) tech_pvt->read_frame.data;
    data[0] = 65;
    data[1] = 0;
    tech_pvt->read_frame.datalen = 2;
    tech_pvt->read_frame.flags = SFF_CNG;
    *frame = &tech_pvt->read_frame;
    return SWITCH_STATUS_SUCCESS;

}
コード例 #6
0
ファイル: mod_loopback.c プロジェクト: hsaid/FreeSWITCH
static switch_status_t channel_on_routing(switch_core_session_t *session)
{
	switch_channel_t *channel = NULL;
	private_t *tech_pvt = NULL;
	const char *app, *arg;

	channel = switch_core_session_get_channel(session);
	assert(channel != NULL);

	tech_pvt = switch_core_session_get_private(session);
	assert(tech_pvt != NULL);

	do_reset(tech_pvt);

	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel));
	
	if (switch_test_flag(tech_pvt, TFLAG_RUNNING_APP)) {
		switch_clear_flag(tech_pvt, TFLAG_RUNNING_APP);
	}

	if (switch_test_flag(tech_pvt, TFLAG_APP) && !switch_test_flag(tech_pvt, TFLAG_OUTBOUND) && 
		(app = switch_channel_get_variable(channel, "loopback_app"))) {
		switch_caller_extension_t *extension = NULL;

		switch_clear_flag(tech_pvt, TFLAG_APP);
		switch_set_flag(tech_pvt, TFLAG_RUNNING_APP);

		arg = switch_channel_get_variable(channel, "loopback_app_arg");
		extension = switch_caller_extension_new(session, app, app);
		switch_caller_extension_add_application(session, extension, "pre_answer", NULL);
		switch_caller_extension_add_application(session, extension, app, arg);

		switch_channel_set_caller_extension(channel, extension);
		switch_channel_set_state(channel, CS_EXECUTE);
		return SWITCH_STATUS_FALSE;
	}



	return SWITCH_STATUS_SUCCESS;
}
コード例 #7
0
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove(switch_core_session_t *session, switch_media_bug_t **bug)
{
	switch_media_bug_t *bp = NULL, *bp2 = NULL, *last = NULL;
	switch_status_t status = SWITCH_STATUS_FALSE;
	int tap_only = 0;

	if (switch_core_media_bug_test_flag(*bug, SMBF_LOCK)) {
		return status;
	}

	switch_thread_rwlock_wrlock(session->bug_rwlock);
	if (session->bugs) {
		for (bp = session->bugs; bp; bp = bp->next) {
			if ((!bp->thread_id || bp->thread_id == switch_thread_self()) && bp->ready && bp == *bug) {
				if (last) {
					last->next = bp->next;
				} else {
					session->bugs = bp->next;
				}
				break;
			}

			last = bp;
		}
	}

	if (!session->bugs && switch_core_codec_ready(&session->bug_codec)) {
		switch_core_codec_destroy(&session->bug_codec);
	}

	if (session->bugs) {
		for(bp2 = session->bugs; bp2; bp2 = bp2->next) {
			if (bp2->ready && !switch_test_flag(bp2, SMBF_TAP_NATIVE_READ) && !switch_test_flag(bp2, SMBF_TAP_NATIVE_WRITE)) {
				tap_only = 0;
			}	
		}
	}
	
	if (tap_only) {
		switch_set_flag(session, SSF_MEDIA_BUG_TAP_ONLY);
	} else {
		switch_clear_flag(session, SSF_MEDIA_BUG_TAP_ONLY);
	}

	switch_thread_rwlock_unlock(session->bug_rwlock);

	if (bp) {
		status = switch_core_media_bug_close(&bp);
	}
	
	return status;
}
コード例 #8
0
static switch_status_t switch_speex_encode(switch_codec_t *codec,
										   switch_codec_t *other_codec,
										   void *decoded_data,
										   uint32_t decoded_data_len,
										   uint32_t decoded_rate, void *encoded_data, uint32_t *encoded_data_len, uint32_t *encoded_rate,
										   unsigned int *flag)
{
	struct speex_context *context = codec->private_info;
	short *buf;
	int is_speech = 1;

	if (!context) {
		return SWITCH_STATUS_FALSE;
	}

	buf = decoded_data;

	if (context->pp) {
		is_speech = speex_preprocess(context->pp, buf, NULL);
	}

	if (is_speech) {
		is_speech = speex_encode_int(context->encoder_state, buf, &context->encoder_bits)
			|| !context->codec_settings.dtx;
	} else {
		speex_bits_pack(&context->encoder_bits, 0, 5);
	}


	if (is_speech) {
		switch_clear_flag(context, SWITCH_CODEC_FLAG_SILENCE);
		*flag |= SWITCH_CODEC_FLAG_SILENCE_STOP;
	} else {
		if (switch_test_flag(context, SWITCH_CODEC_FLAG_SILENCE)) {
			*encoded_data_len = 0;
			*flag |= SWITCH_CODEC_FLAG_SILENCE;
			return SWITCH_STATUS_SUCCESS;
		}

		switch_set_flag(context, SWITCH_CODEC_FLAG_SILENCE);
		*flag |= SWITCH_CODEC_FLAG_SILENCE_START;
	}


	speex_bits_pack(&context->encoder_bits, 15, 5);
	*encoded_data_len = speex_bits_write(&context->encoder_bits, (char *) encoded_data, context->encoder_frame_size);
	speex_bits_reset(&context->encoder_bits);
	(*encoded_data_len)--;

	return SWITCH_STATUS_SUCCESS;
}
コード例 #9
0
ファイル: switch_cpp.cpp プロジェクト: gujun/sscore
SWITCH_DECLARE(int) CoreSession::setAutoHangup(bool val) 
{
	this_check(-1);
	sanity_check(-1);

	if (!session) {
		return SWITCH_STATUS_FALSE;
	}	
	if (val) {
		switch_set_flag(this, S_HUP);
	} else {
		switch_clear_flag(this, S_HUP);
	}
	return SWITCH_STATUS_SUCCESS;
}
コード例 #10
0
ファイル: mod_pocketsphinx.c プロジェクト: hsaid/FreeSWITCH
/*! function to pause recognizer */
static switch_status_t pocketsphinx_asr_pause(switch_asr_handle_t *ah)
{
	pocketsphinx_t *ps = (pocketsphinx_t *) ah->private_info;
	switch_status_t status = SWITCH_STATUS_FALSE;

	switch_mutex_lock(ps->flag_mutex);
	if (switch_test_flag(ps, PSFLAG_READY)) {
		ps_end_utt(ps->ps);
		switch_clear_flag(ps, PSFLAG_READY);
		status = SWITCH_STATUS_SUCCESS;
	}
	switch_mutex_unlock(ps->flag_mutex);

	return status;
}
コード例 #11
0
ファイル: mod_pocketsphinx.c プロジェクト: dgkae/unicallasr
/*! function to read results from the ASR */
static switch_status_t pocketsphinx_asr_get_results(switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags)
{
	pocketsphinx_t *ps = (pocketsphinx_t *) ah->private_info;
	switch_status_t status = SWITCH_STATUS_SUCCESS;
    
    //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, ">>>>>>>>pocketsphinx_asr_get_results<<<<<<<<<\n");


	if (switch_test_flag(ps, PSFLAG_BARGE)) {
		switch_clear_flag_locked(ps, PSFLAG_BARGE);
		status = SWITCH_STATUS_BREAK;
	}

	if (switch_test_flag(ps, PSFLAG_HAS_TEXT)) {
		switch_mutex_lock(ps->flag_mutex);
		switch_clear_flag(ps, PSFLAG_HAS_TEXT);

		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Recognized: %s, Confidence: %d, Confidence-Threshold: %d\n", ps->hyp, ps->confidence, ps->confidence_threshold);
		switch_mutex_unlock(ps->flag_mutex);

		*xmlstr = switch_mprintf("%s", ps->hyp);

		if (!switch_test_flag(ps, PSFLAG_INPUT_TIMERS) && switch_test_flag(ah, SWITCH_ASR_FLAG_AUTO_RESUME)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Auto Resuming\n");
			switch_set_flag(ps, PSFLAG_READY);

			ps_start_utt(ps->ps, NULL);
		}

		status = SWITCH_STATUS_SUCCESS;
	} else if (switch_test_flag(ps, PSFLAG_NOINPUT)) {
		switch_clear_flag_locked(ps, PSFLAG_NOINPUT);
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NO INPUT\n");

		*xmlstr = switch_mprintf("");

		status = SWITCH_STATUS_SUCCESS;
	} else if (switch_test_flag(ps, PSFLAG_NOMATCH)) {
		switch_clear_flag_locked(ps, PSFLAG_NOMATCH);
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NO MATCH\n");

		*xmlstr = switch_mprintf("");

		status = SWITCH_STATUS_SUCCESS;
	}

	return status;
}
コード例 #12
0
ファイル: mod_pocketsphinx.c プロジェクト: hsaid/FreeSWITCH
/*! function to feed audio to the ASR */
static switch_status_t pocketsphinx_asr_feed(switch_asr_handle_t *ah, void *data, unsigned int len, switch_asr_flag_t *flags)
{
	pocketsphinx_t *ps = (pocketsphinx_t *) ah->private_info;
	int rv = 0;

	if (switch_test_flag(ah, SWITCH_ASR_FLAG_CLOSED))
		return SWITCH_STATUS_BREAK;

	if (!switch_test_flag(ps, PSFLAG_HAS_TEXT) && switch_test_flag(ps, PSFLAG_READY)) {
		if (stop_detect(ps, (int16_t *) data, len / 2)) {
			char const *hyp;

			switch_mutex_lock(ps->flag_mutex);
			if ((hyp = ps_get_hyp(ps->ps, &ps->score, &ps->uttid))) {
				if (!zstr(hyp)) {
					ps_end_utt(ps->ps);
					switch_clear_flag(ps, PSFLAG_READY);
					if ((hyp = ps_get_hyp(ps->ps, &ps->score, &ps->uttid))) {
						if (zstr(hyp)) {
							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Lost the text, never mind....\n");
							ps_start_utt(ps->ps, NULL);
							switch_set_flag(ps, PSFLAG_READY);
						} else {
							ps->hyp = switch_core_strdup(ah->memory_pool, hyp);
							switch_set_flag(ps, PSFLAG_HAS_TEXT);
						}
					}
				}
			}
			switch_mutex_unlock(ps->flag_mutex);
		}

		/* only feed ps_process_raw when we are listening */
		if (ps->listening) {
			switch_mutex_lock(ps->flag_mutex);
			rv = ps_process_raw(ps->ps, (int16 *) data, len / 2, FALSE, FALSE);
			switch_mutex_unlock(ps->flag_mutex);
		}

		if (rv < 0) {
			return SWITCH_STATUS_FALSE;
		}
	}

	return SWITCH_STATUS_SUCCESS;
}
コード例 #13
0
ファイル: mod_ssml.c プロジェクト: alleywind/FreeSWITCH
/**
 * open next file for reading
 * @param handle the file handle
 */
static switch_status_t next_file(switch_file_handle_t *handle)
{
	struct ssml_context *context = handle->private_info;
	const char *file;

  top:

	context->index++;

	if (switch_test_flag((&context->fh), SWITCH_FILE_OPEN)) {
		switch_core_file_close(&context->fh);
	}

	if (context->index >= context->num_files) {
		return SWITCH_STATUS_FALSE;
	}


	file = context->files[context->index].name;
	context->fh.prefix = context->files[context->index].prefix;

	if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
		/* unsupported */
		return SWITCH_STATUS_FALSE;
	}

	if (switch_core_file_open(&context->fh, file, handle->channels, handle->samplerate, handle->flags, NULL) != SWITCH_STATUS_SUCCESS) {
		goto top;
	}

	handle->samples = context->fh.samples;
	handle->format = context->fh.format;
	handle->sections = context->fh.sections;
	handle->seekable = context->fh.seekable;
	handle->speed = context->fh.speed;
	handle->interval = context->fh.interval;

	if (switch_test_flag((&context->fh), SWITCH_FILE_NATIVE)) {
		switch_set_flag(handle, SWITCH_FILE_NATIVE);
	} else {
		switch_clear_flag(handle, SWITCH_FILE_NATIVE);
	}

	return SWITCH_STATUS_SUCCESS;
}
コード例 #14
0
ファイル: mod_pocketsphinx.c プロジェクト: hsaid/FreeSWITCH
/*! function to read results from the ASR*/
static switch_status_t pocketsphinx_asr_get_results(switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags)
{
	pocketsphinx_t *ps = (pocketsphinx_t *) ah->private_info;
	switch_status_t status = SWITCH_STATUS_SUCCESS;
	int32_t conf;

	if (switch_test_flag(ps, PSFLAG_BARGE)) {
		switch_clear_flag_locked(ps, PSFLAG_BARGE);
		status = SWITCH_STATUS_BREAK;
	}

	if (switch_test_flag(ps, PSFLAG_HAS_TEXT)) {
		switch_mutex_lock(ps->flag_mutex);
		switch_clear_flag(ps, PSFLAG_HAS_TEXT);
		conf = ps_get_prob(ps->ps, &ps->uttid);

		ps->confidence = (conf + 20000) / 200;

		if (ps->confidence < 0) {
			ps->confidence = 0;
		}

		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Recognized: %s, Confidence: %d\n", ps->hyp, ps->confidence);
		switch_mutex_unlock(ps->flag_mutex);

		*xmlstr = switch_mprintf("<?xml version=\"1.0\"?>\n"
								 "<result grammar=\"%s\">\n"
								 "  <interpretation grammar=\"%s\" confidence=\"%d\">\n"
								 "    <input mode=\"speech\">%s</input>\n"
								 "  </interpretation>\n" "</result>\n", ps->grammar, ps->grammar, ps->confidence, ps->hyp);

		if (switch_test_flag(ps, SWITCH_ASR_FLAG_AUTO_RESUME)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Auto Resuming\n");
			switch_set_flag(ps, PSFLAG_READY);

			ps_start_utt(ps->ps, NULL);
		}

		status = SWITCH_STATUS_SUCCESS;
	}

	return status;
}
コード例 #15
0
ファイル: mod_pocketsphinx.c プロジェクト: hsaid/FreeSWITCH
/*! function to resume recognizer */
static switch_status_t pocketsphinx_asr_resume(switch_asr_handle_t *ah)
{
	pocketsphinx_t *ps = (pocketsphinx_t *) ah->private_info;
	switch_status_t status = SWITCH_STATUS_FALSE;

	switch_mutex_lock(ps->flag_mutex);
	switch_clear_flag(ps, PSFLAG_HAS_TEXT);
	if (!switch_test_flag(ps, PSFLAG_READY)) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Manually Resuming\n");

		if (ps_start_utt(ps->ps, NULL)) {
			status = SWITCH_STATUS_GENERR;
		} else {
			switch_set_flag(ps, PSFLAG_READY);
		}
	}
	switch_mutex_unlock(ps->flag_mutex);

	return status;
}
コード例 #16
0
SWITCH_DECLARE(uint32_t) switch_core_media_bug_prune(switch_core_session_t *session)
{
	switch_media_bug_t *bp = NULL, *last = NULL;
	int ttl = 0;


  top:

	switch_thread_rwlock_wrlock(session->bug_rwlock);
	if (session->bugs) {
		for (bp = session->bugs; bp; bp = bp->next) {
			if (switch_core_media_bug_test_flag(bp, SMBF_PRUNE)) {
				if (last) {
					last->next = bp->next;
				} else {
					session->bugs = bp->next;
				}
				break;
			}

			last = bp;
		}
	}

	if (!session->bugs && switch_core_codec_ready(&session->bug_codec)) {
		switch_core_codec_destroy(&session->bug_codec);
	}

	switch_thread_rwlock_unlock(session->bug_rwlock);

	if (bp) {
		switch_clear_flag(bp, SMBF_LOCK);
		bp->thread_id = 0;
		switch_core_media_bug_close(&bp);
		ttl++;
		goto top;
	}
	
	return ttl;
}
コード例 #17
0
SWITCH_DECLARE(switch_status_t) switch_core_codec_destroy(switch_codec_t *codec)
{
	switch_mutex_t *mutex;
	switch_memory_pool_t *pool;
	int free_pool = 0;

	switch_assert(codec != NULL);

	if (!codec->implementation || !switch_core_codec_ready(codec)) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Codec is not initialized!\n");
		return SWITCH_STATUS_NOT_INITALIZED;
	}

	if (switch_test_flag(codec, SWITCH_CODEC_FLAG_FREE_POOL)) {
		free_pool = 1;
	}

	pool = codec->memory_pool;
	mutex = codec->mutex;

	if (mutex)
		switch_mutex_lock(mutex);

	codec->implementation->destroy(codec);
	switch_clear_flag(codec, SWITCH_CODEC_FLAG_READY);

	UNPROTECT_INTERFACE(codec->codec_interface);

	if (mutex)
		switch_mutex_unlock(mutex);

	if (free_pool) {
		switch_core_destroy_memory_pool(&pool);
	}

	return SWITCH_STATUS_SUCCESS;
}
コード例 #18
0
ファイル: switch_core_speech.c プロジェクト: bodji/freeswitch
SWITCH_DECLARE(switch_status_t) switch_core_speech_close(switch_speech_handle_t *sh, switch_speech_flag_t *flags)
{
    switch_status_t status = sh->speech_interface->speech_close(sh, flags);

    if (!switch_test_flag(sh, SWITCH_SPEECH_FLAG_OPEN)) {
        return SWITCH_STATUS_FALSE;
    }

    if (sh->buffer) {
        switch_buffer_destroy(&sh->buffer);
    }

    switch_resample_destroy(&sh->resampler);

    UNPROTECT_INTERFACE(sh->speech_interface);

    if (switch_test_flag(sh, SWITCH_SPEECH_FLAG_FREE_POOL)) {
        switch_core_destroy_memory_pool(&sh->memory_pool);
    }

    switch_clear_flag(sh, SWITCH_SPEECH_FLAG_OPEN);

    return status;
}
コード例 #19
0
/**
 * Read from file
 * @param handle
 * @param data
 * @param len
 * @return
 */
static switch_status_t fileman_file_read(switch_file_handle_t *handle, void *data, size_t *len)
{
	struct fileman_file_context *context = (struct fileman_file_context *)handle->private_info;
	switch_file_handle_t *fh = &context->fh;
	switch_status_t status = SWITCH_STATUS_SUCCESS;
	switch_size_t o_len = 0;

	/* anything called "_len" is measured in 2-byte samples */

	if (switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
		return switch_core_file_read(fh, data, len);
	}

	//switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "len = %"SWITCH_SIZE_T_FMT"\n", *len);
	if (*len > context->max_frame_len) {
		*len = context->max_frame_len;
	}

	for (;;) {
		int do_speed = 1;
		size_t read_bytes = 0;

		if (switch_test_flag(handle, SWITCH_FILE_PAUSE)) {
			//switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Read pause frame\n");
			memset(context->abuf, 255, *len * 2);
			do_speed = 0;
			o_len = *len;
		} else if (fh->sp_audio_buffer && (context->eof || (switch_buffer_inuse(fh->sp_audio_buffer) > (switch_size_t) (*len * 2)))) {
			//switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Read speed frame\n");
			/* get next speed frame */
			if (!(read_bytes = switch_buffer_read(fh->sp_audio_buffer, context->abuf, *len * 2))) {
				/* This is the reverse of what happens in switch_ivr_play_file... i think that implementation is wrong */
				if (context->eof) {
					/* done with file */
					status = SWITCH_STATUS_FALSE;
					goto done;
				} else {
					/* try again to fetch frame */
					continue;
				}
			}

			/* pad short frame with silence */
			if (read_bytes < *len * 2) {
				//switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Padding speed frame %"SWITCH_SIZE_T_FMT" bytes\n", (context->frame_len * 2) - read_bytes);
				memset(context->abuf + read_bytes, 255, (*len * 2) - read_bytes);
			}
			o_len = *len;
			do_speed = 0;
		} else if (fh->audio_buffer && (context->eof || (switch_buffer_inuse(fh->audio_buffer) > (switch_size_t) (*len * 2)))) {
			//switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "(2) Read audio frame\n");
			/* get next file frame */
			if (!(read_bytes = switch_buffer_read(fh->audio_buffer, context->abuf, *len * 2))) {
				if (context->eof) {
					/* done with file */
					status = SWITCH_STATUS_FALSE;
					goto done;
				} else {
					/* try again to fetch frame */
					continue;
				}
			}
			//switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "(2) Read audio frame %"SWITCH_SIZE_T_FMT" bytes\n", read_bytes);
			fh->offset_pos += read_bytes / 2;
			//switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "(2) file pos = %i\n", fh->offset_pos);

			/* pad short frame with silence */
			if (read_bytes < (*len * 2)) {
				//switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Padding audio frame %"SWITCH_SIZE_T_FMT" bytes\n", (context->frame_len * 2) - read_bytes);
				memset(context->abuf + read_bytes, 255, (*len * 2) - read_bytes);
			}

			o_len = *len;
		} else {
			if (context->eof) {
				/* done with file */
				status = SWITCH_STATUS_FALSE;
				goto done;
			}
			o_len = FILE_STARTBYTES / 2;
			if (switch_core_file_read(fh, context->abuf, &o_len) != SWITCH_STATUS_SUCCESS) {
				context->eof++;
				/* at end of file... need to clear buffers before giving up */
				continue;
			}
			//switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Read file %"SWITCH_SIZE_T_FMT" bytes\n", o_len * 2);

			/* add file data to audio bufer */
			read_bytes = switch_buffer_write(fh->audio_buffer, context->abuf, o_len * 2);
			//switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Write audio frame %"SWITCH_SIZE_T_FMT" bytes\n", read_bytes);

			read_bytes = switch_buffer_read(fh->audio_buffer, context->abuf, *len * 2);
			o_len = read_bytes / 2;
			fh->offset_pos += o_len;
			//switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Read audio frame %"SWITCH_SIZE_T_FMT" bytes\n", read_bytes);
			//switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "file pos = %i\n", fh->offset_pos);
		}

		if (o_len <= 0) {
			//switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "o_len <= 0 (%"SWITCH_SIZE_T_FMT")\n", o_len);
			status = SWITCH_STATUS_FALSE;
			goto done;
		}

		/* limit speed... there is a .25 factor change in packet size relative to original packet size for each increment.
		   Too many increments and we cause badness when (factor * speed * o_len) > o_len */
		if (handle->speed > 2) {
			handle->speed = 2;
		} else if (handle->speed < -2) {
			handle->speed = -2;
		}

		if (switch_test_flag(fh, SWITCH_FILE_SEEK)) {
			/* file position has changed flush the buffer */
			switch_buffer_zero(fh->audio_buffer);
			switch_clear_flag(fh, SWITCH_FILE_SEEK);
		}

		/* generate speed frames */
		if (handle->speed && do_speed) {
			float factor = 0.25f * abs(handle->speed);
			switch_size_t new_len, supplement_len, step_len;
			short *bp = context->abuf;
			switch_size_t wrote_len = 0;
			//switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Generate speed frame (%i)\n", handle->speed);

			supplement_len = (int) (factor * o_len);
			if (!supplement_len) {
				supplement_len = 1;
			}
			new_len = (handle->speed > 0) ? o_len - supplement_len : o_len + supplement_len;

			step_len = (handle->speed > 0) ? (new_len / supplement_len) : (o_len / supplement_len);

			if (!fh->sp_audio_buffer) {
				switch_buffer_create_dynamic(&fh->sp_audio_buffer, 1024, 1024, 0);
			}

			while ((wrote_len + step_len) < new_len) {
				switch_buffer_write(fh->sp_audio_buffer, bp, step_len * 2);
				wrote_len += step_len;
				bp += step_len;
				if (handle->speed > 0) {
					bp++;
				} else {
					float f;
					short s;
					f = (float) (*bp + *(bp + 1) + *(bp - 1));
					f /= 3;
					s = (short) f;
					switch_buffer_write(fh->sp_audio_buffer, &s, 2);
					wrote_len++;
				}
			}
			if (wrote_len < new_len) {
				switch_size_t r_len = new_len - wrote_len;
				switch_buffer_write(fh->sp_audio_buffer, bp, r_len * 2);
				wrote_len += r_len;
			}
			continue;
		}

		/* adjust volume on frame */
		if (handle->vol) {
			//switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Adjust volume to = %i\n", handle->vol);
			switch_change_sln_volume(context->abuf, *len, handle->vol);
		}
		break;
	}

done:

	/* copy frame over to return to caller */
	memcpy(data, context->abuf, *len * 2);
	handle->offset_pos = context->fh.offset_pos;

	return status;
}
コード例 #20
0
/**
 * Wraps file with interface that can be controlled by fileman flags
 * @param handle
 * @param path the file to play
 * @return SWITCH_STATUS_SUCCESS if opened
 */
static switch_status_t fileman_file_open(switch_file_handle_t *handle, const char *path)
{
	int start_offset_ms = 0;
	switch_status_t status = SWITCH_STATUS_FALSE;
	struct fileman_file_context *context = switch_core_alloc(handle->memory_pool, sizeof(*context));
	handle->private_info = context;

	if (handle->params) {
		const char *id = switch_event_get_header(handle->params, "id");
		const char *uuid = switch_event_get_header(handle->params, "session");
		const char *start_offset_ms_str = switch_event_get_header(handle->params, "start_offset_ms");
		if (!zstr(id)) {
			context->id = switch_core_strdup(handle->memory_pool, id);
		}
		if (!zstr(uuid)) {
			context->uuid = switch_core_strdup(handle->memory_pool, uuid);
		}
		if (!zstr(start_offset_ms_str) && switch_is_number(start_offset_ms_str)) {
			start_offset_ms = atoi(start_offset_ms_str);
			if (start_offset_ms < 0) {
				start_offset_ms = 0;
			}
		}
	}

	switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Got path %s\n", path);

	if ((status = switch_core_file_open(&context->fh, path, handle->channels, handle->samplerate, handle->flags, NULL)) != SWITCH_STATUS_SUCCESS) {
		return status;
	}

	/* set up handle for external control */
	if (!context->id) {
		/* use filename as ID */
		context->id = switch_core_strdup(handle->memory_pool, path);
	}
	switch_mutex_lock(fileman_globals.mutex);
	if (!switch_core_hash_find(fileman_globals.hash, context->id)) {
		switch_core_hash_insert(fileman_globals.hash, context->id, handle);
	} else {
		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_WARNING, "Duplicate fileman ID: %s\n", context->id);
		return SWITCH_STATUS_FALSE;
	}
	switch_mutex_unlock(fileman_globals.mutex);

	context->max_frame_len = (handle->samplerate / 1000 * SWITCH_MAX_INTERVAL);
	switch_zmalloc(context->abuf, FILE_STARTBYTES * sizeof(*context->abuf));

	if (!context->fh.audio_buffer) {
		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Create audio buffer\n");
		switch_buffer_create_dynamic(&context->fh.audio_buffer, FILE_BLOCKSIZE, FILE_BUFSIZE, 0);
		switch_assert(context->fh.audio_buffer);
	}

	handle->samples = context->fh.samples;
	handle->format = context->fh.format;
	handle->sections = context->fh.sections;
	handle->seekable = context->fh.seekable;
	handle->speed = context->fh.speed;
	handle->vol = context->fh.vol;
	handle->offset_pos = context->fh.offset_pos;
	handle->interval = context->fh.interval;

	if (switch_test_flag((&context->fh), SWITCH_FILE_NATIVE)) {
		switch_set_flag(handle, SWITCH_FILE_NATIVE);
	} else {
		switch_clear_flag(handle, SWITCH_FILE_NATIVE);
	}

	if (handle->params && switch_true(switch_event_get_header(handle->params, "pause"))) {
		switch_set_flag(handle, SWITCH_FILE_PAUSE);
	}

	if (handle->seekable && start_offset_ms) {
		unsigned int pos = 0;
		int32_t target = start_offset_ms * (handle->samplerate / 1000);
		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "seek to position %d\n", target);
		switch_core_file_seek(&context->fh, &pos, target, SEEK_SET);
	}

	return status;
}
コード例 #21
0
/**
 * open next file for reading
 * @param handle the file handle
 */
static switch_status_t next_file(switch_file_handle_t *handle)
{
	int loops = 0;
	struct rayo_file_context *context = handle->private_info;
	struct output_component *output = context->component ? OUTPUT_COMPONENT(context->component) : NULL;

  top:

	if (switch_test_flag((&context->fh), SWITCH_FILE_OPEN)) {
		switch_core_file_close(&context->fh);
	}

	if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
		/* unsupported */
		return SWITCH_STATUS_FALSE;
	}

	if (!context->cur_doc) {
		context->cur_doc = iks_find(output->document, "document");
		if (!context->cur_doc) {
			iks_delete(output->document);
			output->document = NULL;
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing <document>\n");
			return SWITCH_STATUS_FALSE;
		}
	} else {
		context->cur_doc = iks_next_tag(context->cur_doc);
	}

	/* done? */
	if (!context->cur_doc) {
		if (context->could_open && ++loops < 2 && (output->repeat_times == 0 || ++context->play_count < output->repeat_times)) {
			/* repeat all document(s) */
			if (!output->repeat_interval_ms) {
				goto top;
			}
		} else {
			/* no more files to play */
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Done playing\n");
			return SWITCH_STATUS_FALSE;
		}
	}

	if (!context->cur_doc) {
		/* play silence between repeats */
		switch_safe_free(context->ssml);
		context->ssml = switch_mprintf("silence_stream://%i", output->repeat_interval_ms);
	} else {
		/* play next document */
		iks *speak = NULL;

		switch_safe_free(context->ssml);
		context->ssml = NULL;
 		speak = iks_find(context->cur_doc, "speak");
		if (speak) {
			/* <speak> is child node */
			char *ssml_str = iks_string(NULL, speak);
			if (zstr(output->renderer)) {
				/* FS must parse the SSML */
				context->ssml = switch_mprintf("ssml://%s", ssml_str);
			} else {
				/* renderer will parse the SSML */
				if (!zstr(output->headers) && !strncmp("unimrcp", output->renderer, 7)) {
					/* pass MRCP headers */
					context->ssml = switch_mprintf("tts://%s||%s%s", output->renderer, output->headers, ssml_str);
				} else {
					context->ssml = switch_mprintf("tts://%s||%s", output->renderer, ssml_str);
				}
			}
			iks_free(ssml_str);
		} else if (iks_has_children(context->cur_doc)) {
			/* check if <speak> is in CDATA */
			const char *ssml_str = NULL;
			iks *ssml = iks_child(context->cur_doc);
			if (ssml && iks_type(ssml) == IKS_CDATA) {
				ssml_str = iks_cdata(ssml);
			}
			if (zstr(ssml_str)) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing <document> CDATA\n");
				return SWITCH_STATUS_FALSE;
			}
			if (zstr(output->renderer)) {
				/* FS must parse the SSML */
				context->ssml = switch_mprintf("ssml://%s", ssml_str);
			} else {
				/* renderer will parse the SSML */
				if (!zstr(output->headers) && !strncmp("unimrcp", output->renderer, 7)) {
					/* pass MRCP headers */
					context->ssml = switch_mprintf("tts://%s||%s%s", output->renderer, output->headers, ssml_str);
				} else {
					context->ssml = switch_mprintf("tts://%s||%s", output->renderer, ssml_str);
				}
			}
		} else {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing <speak>\n");
			return SWITCH_STATUS_FALSE;
		}
	}
	if (switch_core_file_open(&context->fh, context->ssml, handle->channels, handle->samplerate, handle->flags, NULL) != SWITCH_STATUS_SUCCESS) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Failed to open %s\n", context->ssml);
		goto top;
	} else {
		context->could_open = 1;
	}

	handle->samples = context->fh.samples;
	handle->format = context->fh.format;
	handle->sections = context->fh.sections;
	handle->seekable = context->fh.seekable;
	handle->speed = context->fh.speed;
	handle->vol = context->fh.vol;
	handle->offset_pos = context->fh.offset_pos;
	handle->interval = context->fh.interval;

	if (switch_test_flag((&context->fh), SWITCH_FILE_NATIVE)) {
		switch_set_flag(handle, SWITCH_FILE_NATIVE);
	} else {
		switch_clear_flag(handle, SWITCH_FILE_NATIVE);
	}

	return SWITCH_STATUS_SUCCESS;
}
コード例 #22
0
/**
 * Process fileman command
 */
static switch_status_t fileman_process_cmd(const char *cmd, switch_file_handle_t *fhp)
{
	if (zstr(cmd)) {
		return SWITCH_STATUS_SUCCESS;
	}

	if (fhp) {
		struct fileman_file_context *context = (struct fileman_file_context *)fhp->private_info;
		if (!switch_test_flag(fhp, SWITCH_FILE_OPEN)) {
			return SWITCH_STATUS_FALSE;
		}

		if (!strncasecmp(cmd, "speed", 5)) {
			char *p;

			if ((p = strchr(cmd, ':'))) {
				p++;
				if (*p == '+' || *p == '-') {
					int step;
					if (!(step = atoi(p))) {
						if (*p == '+') {
							step = 1;
						} else {
							step = -1;
						}
					}
					fhp->speed += step;
				} else {
					int speed = atoi(p);
					fhp->speed = speed;
				}
				return SWITCH_STATUS_SUCCESS;
			}

			return SWITCH_STATUS_FALSE;

		} else if (!strncasecmp(cmd, "volume", 6)) {
			char *p;

			if ((p = strchr(cmd, ':'))) {
				p++;
				if (*p == '+' || *p == '-') {
					int step;
					if (!(step = atoi(p))) {
						if (*p == '+') {
							step = 1;
						} else {
							step = -1;
						}
					}
					fhp->vol += step;
				} else {
					int vol = atoi(p);
					fhp->vol = vol;
				}
				return SWITCH_STATUS_SUCCESS;
			}

			if (fhp->vol) {
				switch_normalize_volume(fhp->vol);
			}

			return SWITCH_STATUS_FALSE;
		} else if (!strcasecmp(cmd, "pause")) {
			switch_set_flag(fhp, SWITCH_FILE_PAUSE);
			return SWITCH_STATUS_SUCCESS;
		} else if (!strcasecmp(cmd, "resume")) {
			switch_clear_flag(fhp, SWITCH_FILE_PAUSE);
			return SWITCH_STATUS_SUCCESS;
		} else if (!strcasecmp(cmd, "stop")) {
			switch_set_flag(fhp, SWITCH_FILE_DONE);
			return SWITCH_STATUS_FALSE;
		} else if (!strcasecmp(cmd, "truncate")) {
			switch_core_file_truncate(fhp, 0);
		} else if (!strcasecmp(cmd, "restart")) {
			unsigned int pos = 0;
			fhp->speed = 0;
			switch_core_file_seek(fhp, &pos, 0, SEEK_SET);
			return SWITCH_STATUS_SUCCESS;
		} else if (!strncasecmp(cmd, "seek", 4)) {
			unsigned int samps = 0;
			unsigned int pos = 0;
			char *p;

			if ((p = strchr(cmd, ':'))) {
				p++;
				if (*p == '+' || *p == '-') {
					int step;
					int32_t target;
					if (!(step = atoi(p))) {
						if (*p == '+') {
							step = 1000;
						} else {
							step = -1000;
						}
					}

					samps = step * (fhp->samplerate / 1000);
					target = (int32_t)fhp->pos + samps;

					if (target < 0) {
						target = 0;
					}

					switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "seek to position %d\n", target);
					switch_core_file_seek(fhp, &pos, target, SEEK_SET);

				} else {
					samps = switch_atoui(p) * (fhp->samplerate / 1000);
					switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "seek to position %d\n", samps);
					switch_core_file_seek(fhp, &pos, samps, SEEK_SET);
				}
			}

			return SWITCH_STATUS_SUCCESS;
		}
	}

	if (!strcmp(cmd, "true") || !strcmp(cmd, "undefined")) {
		return SWITCH_STATUS_SUCCESS;
	}

	return SWITCH_STATUS_FALSE;
}
コード例 #23
0
ファイル: mod_loopback.c プロジェクト: hsaid/FreeSWITCH
static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
{
	switch_channel_t *channel = NULL;
	private_t *tech_pvt = NULL;
	switch_status_t status = SWITCH_STATUS_FALSE;
	switch_mutex_t *mutex = NULL;
	void *pop = NULL;

	channel = switch_core_session_get_channel(session);
	switch_assert(channel != NULL);

	tech_pvt = switch_core_session_get_private(session);
	switch_assert(tech_pvt != NULL);

	if (!switch_test_flag(tech_pvt, TFLAG_LINKED)) {
		goto end;
	}

	*frame = NULL;

	if (!switch_channel_ready(channel)) {
		goto end;
	}

	switch_core_timer_next(&tech_pvt->timer);

	mutex = tech_pvt->mutex;
	switch_mutex_lock(mutex);


	if (switch_test_flag(tech_pvt, TFLAG_CLEAR)) {
		clear_queue(tech_pvt);
		switch_clear_flag(tech_pvt, TFLAG_CLEAR);
	}

	if (switch_queue_trypop(tech_pvt->frame_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) {
		if (tech_pvt->write_frame) {
			switch_frame_free(&tech_pvt->write_frame);
		}
		
		tech_pvt->write_frame = (switch_frame_t *) pop;
		tech_pvt->write_frame->codec = &tech_pvt->read_codec;
		*frame = tech_pvt->write_frame;
		tech_pvt->packet_count++;
		switch_clear_flag(tech_pvt->write_frame, SFF_CNG);
		tech_pvt->first_cng = 0;
	} else {
		*frame = &tech_pvt->cng_frame;
		tech_pvt->cng_frame.codec = &tech_pvt->read_codec;
		tech_pvt->cng_frame.datalen = tech_pvt->read_codec.implementation->decoded_bytes_per_packet;
		switch_set_flag((&tech_pvt->cng_frame), SFF_CNG);
		if (!tech_pvt->first_cng) {
			switch_yield(tech_pvt->read_codec.implementation->samples_per_packet);
			tech_pvt->first_cng = 1;
		}
	}


	if (*frame) {
		status = SWITCH_STATUS_SUCCESS;
	} else {
		status = SWITCH_STATUS_FALSE;
	}

  end:

	if (mutex) {
		switch_mutex_unlock(mutex);
	}

	return status;
}
コード例 #24
0
ファイル: switch_cpp.cpp プロジェクト: gujun/sscore
SWITCH_DECLARE(switch_status_t) CoreSession::process_callback_result(char *result)
{
	
	this_check(SWITCH_STATUS_FALSE);
	sanity_check(SWITCH_STATUS_FALSE);
	
    if (zstr(result)) {
		return SWITCH_STATUS_SUCCESS;	
    }

	if (fhp) {
		if (!switch_test_flag(fhp, SWITCH_FILE_OPEN)) {
			return SWITCH_STATUS_FALSE;
		}

		if (!strncasecmp(result, "speed", 5)) {
			char *p;
		
			if ((p = strchr(result, ':'))) {
				p++;
				if (*p == '+' || *p == '-') {
					int step;
					if (!(step = atoi(p))) {
						step = 1;
					}
					fhp->speed += step;
				} else {
					int speed = atoi(p);
					fhp->speed = speed;
				}
				return SWITCH_STATUS_SUCCESS;
			}

			return SWITCH_STATUS_FALSE;

		} else if (!strncasecmp(result, "volume", 6)) {
			char *p;
			
			if ((p = strchr(result, ':'))) {
				p++;
				if (*p == '+' || *p == '-') {
					int step;
					if (!(step = atoi(p))) {
						step = 1;
					}
					fhp->vol += step;
				} else {
					int vol = atoi(p);
					fhp->vol = vol;
				}
				return SWITCH_STATUS_SUCCESS;
			}
			
			if (fhp->vol) {
				switch_normalize_volume(fhp->vol);
			}
			
			return SWITCH_STATUS_FALSE;
		} else if (!strcasecmp(result, "pause")) {
			if (switch_test_flag(fhp, SWITCH_FILE_PAUSE)) {
				switch_clear_flag(fhp, SWITCH_FILE_PAUSE);
			} else {
				switch_set_flag(fhp, SWITCH_FILE_PAUSE);
			}
			return SWITCH_STATUS_SUCCESS;
		} else if (!strcasecmp(result, "stop")) {
			return SWITCH_STATUS_FALSE;
		} else if (!strcasecmp(result, "truncate")) {
			switch_core_file_truncate(fhp, 0);
		} else if (!strcasecmp(result, "restart")) {
			unsigned int pos = 0;
			fhp->speed = 0;
			switch_core_file_seek(fhp, &pos, 0, SEEK_SET);
			return SWITCH_STATUS_SUCCESS;
		} else if (!strncasecmp(result, "seek", 4)) {
			switch_codec_t *codec;
			unsigned int samps = 0;
			unsigned int pos = 0;
			char *p;
			codec = switch_core_session_get_read_codec(session);
			
			if ((p = strchr(result, ':'))) {
				p++;
				if (*p == '+' || *p == '-') {
					int step;
					int32_t target;
					if (!(step = atoi(p))) {
						step = 1000;
					}

					samps = step * (codec->implementation->samples_per_second / 1000);
					target = (int32_t)fhp->pos + samps;

					if (target < 0) {
						target = 0;
					}

					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", target);
					switch_core_file_seek(fhp, &pos, target, SEEK_SET);

				} else {
					samps = atoi(p) * (codec->implementation->samples_per_second / 1000);
					if (samps < 0) {
						samps = 0;
					}
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", samps);
					switch_core_file_seek(fhp, &pos, samps, SEEK_SET);
				}
			}

			return SWITCH_STATUS_SUCCESS;
		}
	}

    if (!strcmp(result, "true") || !strcmp(result, "undefined")) {
		return SWITCH_STATUS_SUCCESS;
    }


    return SWITCH_STATUS_FALSE;
}
コード例 #25
0
SWITCH_DECLARE(uint32_t) switch_core_media_bug_clear_flag(switch_media_bug_t *bug, uint32_t flag)
{
	return switch_clear_flag(bug, flag);
}
コード例 #26
0
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_add(switch_core_session_t *session,
														  const char *function,
														  const char *target,
														  switch_media_bug_callback_t callback,
														  void *user_data, time_t stop_time, 
														  switch_media_bug_flag_t flags, 
														  switch_media_bug_t **new_bug)
{
	switch_media_bug_t *bug, *bp;
	switch_size_t bytes;
	switch_event_t *event;
	int tap_only = 1, punt = 0;

	const char *p;

	if (!zstr(function)) {
		if ((flags & SMBF_ONE_ONLY)) {
			switch_thread_rwlock_wrlock(session->bug_rwlock);
			for (bp = session->bugs; bp; bp = bp->next) {
				if (!zstr(bp->function) && !strcasecmp(function, bp->function)) {
					punt = 1;
					break;
				} 
			}
			switch_thread_rwlock_unlock(session->bug_rwlock);
		}
	}
	
	if (punt) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n");
	}


	if (!switch_channel_media_ready(session->channel)) {
		if (switch_channel_pre_answer(session->channel) != SWITCH_STATUS_SUCCESS) {
			return SWITCH_STATUS_FALSE;
		}
	}



	*new_bug = NULL;


	if ((p = switch_channel_get_variable(session->channel, "media_bug_answer_req")) && switch_true(p)) {
		flags |= SMBF_ANSWER_REQ;
	}
#if 0
	if (flags & SMBF_WRITE_REPLACE) {
		switch_thread_rwlock_wrlock(session->bug_rwlock);
		for (bp = session->bugs; bp; bp = bp->next) {
			if (switch_test_flag(bp, SMBF_WRITE_REPLACE)) {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n");
				switch_thread_rwlock_unlock(session->bug_rwlock);
				return SWITCH_STATUS_GENERR;
			}
		}
		switch_thread_rwlock_unlock(session->bug_rwlock);
	}

	if (flags & SMBF_READ_REPLACE) {
		switch_thread_rwlock_wrlock(session->bug_rwlock);
		for (bp = session->bugs; bp; bp = bp->next) {
			if (switch_test_flag(bp, SMBF_READ_REPLACE)) {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n");
				switch_thread_rwlock_unlock(session->bug_rwlock);
				return SWITCH_STATUS_GENERR;
			}
		}
		switch_thread_rwlock_unlock(session->bug_rwlock);
	}
#endif

	if (!(bug = switch_core_session_alloc(session, sizeof(*bug)))) {
		return SWITCH_STATUS_MEMERR;
	}

	bug->callback = callback;
	bug->user_data = user_data;
	bug->session = session;
	bug->flags = flags;
	bug->function = "N/A";
	bug->target = "N/A";

	switch_core_session_get_read_impl(session, &bug->read_impl);
	switch_core_session_get_write_impl(session, &bug->write_impl);

	if (function) {
		bug->function = switch_core_session_strdup(session, function);
	}

	if (target) {
		bug->target = switch_core_session_strdup(session, target);
	}
	
	bug->stop_time = stop_time;
	bytes = bug->read_impl.decoded_bytes_per_packet;

	if (!bug->flags) {
		bug->flags = (SMBF_READ_STREAM | SMBF_WRITE_STREAM);
	}

	if (switch_test_flag(bug, SMBF_READ_STREAM) || switch_test_flag(bug, SMBF_READ_PING)) {
		switch_buffer_create_dynamic(&bug->raw_read_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER);
		switch_mutex_init(&bug->read_mutex, SWITCH_MUTEX_NESTED, session->pool);
	}

	bytes = bug->write_impl.decoded_bytes_per_packet;

	if (switch_test_flag(bug, SMBF_WRITE_STREAM)) {
		switch_buffer_create_dynamic(&bug->raw_write_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER);
		switch_mutex_init(&bug->write_mutex, SWITCH_MUTEX_NESTED, session->pool);
	}

	if ((bug->flags & SMBF_THREAD_LOCK)) {
		bug->thread_id = switch_thread_self();
	}

	if (bug->callback) {
		switch_bool_t result = bug->callback(bug, bug->user_data, SWITCH_ABC_TYPE_INIT);
		if (result == SWITCH_FALSE) {
			switch_core_media_bug_destroy(bug);
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error attaching BUG to %s\n",
							  switch_channel_get_name(session->channel));
			return SWITCH_STATUS_GENERR;
		}
	}

	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Attaching BUG to %s\n", switch_channel_get_name(session->channel));
	bug->ready = 1;
	switch_thread_rwlock_wrlock(session->bug_rwlock);
	bug->next = session->bugs;
	session->bugs = bug;

	for(bp = session->bugs; bp; bp = bp->next) {
		if (bp->ready && !switch_test_flag(bp, SMBF_TAP_NATIVE_READ) && !switch_test_flag(bp, SMBF_TAP_NATIVE_WRITE)) {
			tap_only = 0;
		}	
	}

	switch_thread_rwlock_unlock(session->bug_rwlock);
	*new_bug = bug;


	if (tap_only) {
		switch_set_flag(session, SSF_MEDIA_BUG_TAP_ONLY);
	} else {
		switch_clear_flag(session, SSF_MEDIA_BUG_TAP_ONLY);
	}

	if (switch_event_create(&event, SWITCH_EVENT_MEDIA_BUG_START) == SWITCH_STATUS_SUCCESS) {
		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Function", "%s", bug->function);
		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Target", "%s", bug->target);
		switch_channel_event_set_data(session->channel, event);
		switch_event_fire(&event);
	}

	return SWITCH_STATUS_SUCCESS;
}
コード例 #27
0
SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags,
																int stream_id)
{

	switch_status_t status = SWITCH_STATUS_FALSE;
	switch_frame_t *enc_frame = NULL, *write_frame = frame;
	unsigned int flag = 0, need_codec = 0, perfect = 0, do_bugs = 0, do_write = 0, do_resample = 0, ptime_mismatch = 0, pass_cng = 0, resample = 0;
	int did_write_resample = 0;

	switch_assert(session != NULL);
	switch_assert(frame != NULL);

	if (!switch_channel_ready(session->channel)) {
		return SWITCH_STATUS_FALSE;
	}

	if (switch_mutex_trylock(session->codec_write_mutex) == SWITCH_STATUS_SUCCESS) {
		switch_mutex_unlock(session->codec_write_mutex);
	} else {
		return SWITCH_STATUS_SUCCESS;
	}

	if (switch_test_flag(frame, SFF_CNG)) {
		if (switch_channel_test_flag(session->channel, CF_ACCEPT_CNG)) {
			pass_cng = 1;
		} else {
			return SWITCH_STATUS_SUCCESS;
		}
	}

	if (!(session->write_codec && switch_core_codec_ready(session->write_codec)) && !pass_cng) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no write codec.\n", switch_channel_get_name(session->channel));
		switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
		return SWITCH_STATUS_FALSE;
	}

	if (switch_channel_test_flag(session->channel, CF_HOLD)) {
		return SWITCH_STATUS_SUCCESS;
	}

	if (switch_test_flag(frame, SFF_PROXY_PACKET) || pass_cng) {
		/* Fast PASS! */
		switch_mutex_lock(session->codec_write_mutex);
		status = perform_write(session, frame, flag, stream_id);
		switch_mutex_unlock(session->codec_write_mutex);
		return status;
	}

	switch_mutex_lock(session->codec_write_mutex);

	if (!(frame->codec && frame->codec->implementation)) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has received a bad frame with no codec!\n", 
						  switch_channel_get_name(session->channel));
		switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
		switch_mutex_unlock(session->codec_write_mutex);
		return SWITCH_STATUS_FALSE;
	}

	switch_assert(frame->codec != NULL);
	switch_assert(frame->codec->implementation != NULL);

	if (!(switch_core_codec_ready(session->write_codec) && frame->codec) ||
		!switch_channel_ready(session->channel) || !switch_channel_media_ready(session->channel)) {
		switch_mutex_unlock(session->codec_write_mutex);
		return SWITCH_STATUS_FALSE;
	}

	switch_mutex_lock(session->write_codec->mutex);
	switch_mutex_lock(frame->codec->mutex);

	if (!(switch_core_codec_ready(session->write_codec) && switch_core_codec_ready(frame->codec))) goto error;
	
	if ((session->write_codec && frame->codec && session->write_codec->implementation != frame->codec->implementation)) {
		if (session->write_impl.codec_id == frame->codec->implementation->codec_id ||
			session->write_impl.microseconds_per_packet != frame->codec->implementation->microseconds_per_packet) {
			ptime_mismatch = TRUE;
			if ((switch_test_flag(frame->codec, SWITCH_CODEC_FLAG_PASSTHROUGH) || switch_test_flag(session->read_codec, SWITCH_CODEC_FLAG_PASSTHROUGH)) ||
				switch_channel_test_flag(session->channel, CF_PASSTHRU_PTIME_MISMATCH)) {
				status = perform_write(session, frame, flags, stream_id);
				goto error;
			}
		}
		need_codec = TRUE;
	}

	if (session->write_codec && !frame->codec) {
		need_codec = TRUE;
	}

	if (session->bugs && !need_codec) {
		do_bugs = TRUE;
		need_codec = TRUE;
	}

	if (frame->codec->implementation->actual_samples_per_second != session->write_impl.actual_samples_per_second) {
		need_codec = TRUE;
		do_resample = TRUE;
	}

	if (switch_test_flag(session, SSF_WRITE_TRANSCODE) && !need_codec && switch_core_codec_ready(session->write_codec)) {
		switch_core_session_t *other_session;
		const char *uuid = switch_channel_get_variable(switch_core_session_get_channel(session), SWITCH_SIGNAL_BOND_VARIABLE);

		if (uuid && (other_session = switch_core_session_locate(uuid))) {
			switch_set_flag(other_session, SSF_READ_CODEC_RESET);
			switch_set_flag(other_session, SSF_READ_CODEC_RESET);
			switch_set_flag(other_session, SSF_WRITE_CODEC_RESET);
			switch_core_session_rwunlock(other_session);
		}
		
		switch_clear_flag(session, SSF_WRITE_TRANSCODE);
	}


	if (switch_test_flag(session, SSF_WRITE_CODEC_RESET)) {
		switch_core_codec_reset(session->write_codec);
		switch_clear_flag(session, SSF_WRITE_CODEC_RESET);
	}

	if (!need_codec) {
		do_write = TRUE;
		write_frame = frame;
		goto done;
	}

	if (!switch_test_flag(session, SSF_WARN_TRANSCODE)) {
		switch_core_session_message_t msg = { 0 };

		msg.message_id = SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY;
		switch_core_session_receive_message(session, &msg);
		switch_set_flag(session, SSF_WARN_TRANSCODE);
	}

	if (frame->codec) {
		session->raw_write_frame.datalen = session->raw_write_frame.buflen;
		status = switch_core_codec_decode(frame->codec,
										  session->write_codec,
										  frame->data,
										  frame->datalen,
										  session->write_impl.actual_samples_per_second,
										  session->raw_write_frame.data, &session->raw_write_frame.datalen, &session->raw_write_frame.rate, &frame->flags);




		if (do_resample && status == SWITCH_STATUS_SUCCESS) {
			status = SWITCH_STATUS_RESAMPLE;
		}

		switch (status) {
		case SWITCH_STATUS_RESAMPLE:
			resample++;
			write_frame = &session->raw_write_frame;
			write_frame->rate = frame->codec->implementation->actual_samples_per_second;
			if (!session->write_resampler) {
				switch_mutex_lock(session->resample_mutex);
				status = switch_resample_create(&session->write_resampler,
												frame->codec->implementation->actual_samples_per_second,
												session->write_impl.actual_samples_per_second,
												session->write_impl.decoded_bytes_per_packet, SWITCH_RESAMPLE_QUALITY, 1);


				switch_mutex_unlock(session->resample_mutex);
				if (status != SWITCH_STATUS_SUCCESS) {
					goto done;
				}
			}
			break;
		case SWITCH_STATUS_SUCCESS:
			session->raw_write_frame.samples = session->raw_write_frame.datalen / sizeof(int16_t);
			session->raw_write_frame.timestamp = frame->timestamp;
			session->raw_write_frame.rate = frame->rate;
			session->raw_write_frame.m = frame->m;
			session->raw_write_frame.ssrc = frame->ssrc;
			session->raw_write_frame.seq = frame->seq;
			session->raw_write_frame.payload = frame->payload;
			session->raw_write_frame.flags = 0;
			if (switch_test_flag(frame, SFF_PLC)) {
				session->raw_write_frame.flags |= SFF_PLC;
			}

			write_frame = &session->raw_write_frame;
			break;
		case SWITCH_STATUS_BREAK:
			status = SWITCH_STATUS_SUCCESS;
			goto error;
		case SWITCH_STATUS_NOOP:
			if (session->write_resampler) {
				switch_mutex_lock(session->resample_mutex);
				switch_resample_destroy(&session->write_resampler);
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Deactivating write resampler\n");
				switch_mutex_unlock(session->resample_mutex);
			}
			write_frame = frame;
			status = SWITCH_STATUS_SUCCESS;
			break;
		default:
			if (status == SWITCH_STATUS_NOT_INITALIZED) {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n");
				goto error;
			}
			if (ptime_mismatch) {
				status = perform_write(session, frame, flags, stream_id);
				status = SWITCH_STATUS_SUCCESS;
				goto error;
			}

			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s decoder error!\n",
							  frame->codec->codec_interface->interface_name);
			goto error;
		}
	}



	if (session->write_resampler) {
		short *data = write_frame->data;

		switch_mutex_lock(session->resample_mutex);
		if (session->write_resampler) {

			switch_resample_process(session->write_resampler, data, write_frame->datalen / 2);

			memcpy(data, session->write_resampler->to, session->write_resampler->to_len * 2);

			write_frame->samples = session->write_resampler->to_len;

			write_frame->datalen = write_frame->samples * 2;

			write_frame->rate = session->write_resampler->to_rate;

			did_write_resample = 1;
		}
		switch_mutex_unlock(session->resample_mutex);
	}



	if (session->bugs) {
		switch_media_bug_t *bp;
		int prune = 0;

		switch_thread_rwlock_rdlock(session->bug_rwlock);
		for (bp = session->bugs; bp; bp = bp->next) {
			switch_bool_t ok = SWITCH_TRUE;
			if (!bp->ready) {
				continue;
			}

			if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) {
				continue;
			}

			if (!switch_channel_test_flag(session->channel, CF_ANSWERED) && switch_core_media_bug_test_flag(bp, SMBF_ANSWER_REQ)) {
				continue;
			}

			if (switch_test_flag(bp, SMBF_PRUNE)) {
				prune++;
				continue;
			}

			if (switch_test_flag(bp, SMBF_WRITE_STREAM)) {

				switch_mutex_lock(bp->write_mutex);
				switch_buffer_write(bp->raw_write_buffer, write_frame->data, write_frame->datalen);
				switch_mutex_unlock(bp->write_mutex);
				if (bp->callback) {
					ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_WRITE);
				}
			}

			if (switch_test_flag(bp, SMBF_WRITE_REPLACE)) {
				do_bugs = 0;
				if (bp->callback) {
					bp->write_replace_frame_in = write_frame;
					bp->write_replace_frame_out = write_frame;
					if ((ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_WRITE_REPLACE)) == SWITCH_TRUE) {
						write_frame = bp->write_replace_frame_out;
					}
				}
			}

			if (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL)) {
				ok = SWITCH_FALSE;
			}


			if (ok == SWITCH_FALSE) {
				switch_set_flag(bp, SMBF_PRUNE);
				prune++;
			}
		}
		switch_thread_rwlock_unlock(session->bug_rwlock);
		if (prune) {
			switch_core_media_bug_prune(session);
		}
	}

	if (do_bugs) {
		do_write = TRUE;
		write_frame = frame;
		goto done;
	}

	if (session->write_codec) {
		if (!ptime_mismatch && write_frame->codec && write_frame->codec->implementation &&
			write_frame->codec->implementation->decoded_bytes_per_packet == session->write_impl.decoded_bytes_per_packet) {
			perfect = TRUE;
		}



		if (perfect) {

			if (write_frame->datalen < session->write_impl.decoded_bytes_per_packet) {
				memset(write_frame->data, 255, session->write_impl.decoded_bytes_per_packet - write_frame->datalen);
				write_frame->datalen = session->write_impl.decoded_bytes_per_packet;
			}

			enc_frame = write_frame;
			session->enc_write_frame.datalen = session->enc_write_frame.buflen;

			status = switch_core_codec_encode(session->write_codec,
											  frame->codec,
											  enc_frame->data,
											  enc_frame->datalen,
											  session->write_impl.actual_samples_per_second,
											  session->enc_write_frame.data, &session->enc_write_frame.datalen, &session->enc_write_frame.rate, &flag);




			switch (status) {
			case SWITCH_STATUS_RESAMPLE:
				resample++;
				/* switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Fixme 2\n"); */
			case SWITCH_STATUS_SUCCESS:
				session->enc_write_frame.codec = session->write_codec;
				session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t);
				if (frame->codec->implementation->samples_per_packet != session->write_impl.samples_per_packet) {
					session->enc_write_frame.timestamp = 0;
				} else {
					session->enc_write_frame.timestamp = frame->timestamp;
				}
				session->enc_write_frame.payload = session->write_impl.ianacode;
				session->enc_write_frame.m = frame->m;
				session->enc_write_frame.ssrc = frame->ssrc;
				session->enc_write_frame.seq = frame->seq;
				write_frame = &session->enc_write_frame;
				break;
			case SWITCH_STATUS_NOOP:
				enc_frame->codec = session->write_codec;
				enc_frame->samples = enc_frame->datalen / sizeof(int16_t);
				enc_frame->timestamp = frame->timestamp;
				enc_frame->m = frame->m;
				enc_frame->seq = frame->seq;
				enc_frame->ssrc = frame->ssrc;
				enc_frame->payload = enc_frame->codec->implementation->ianacode;
				write_frame = enc_frame;
				status = SWITCH_STATUS_SUCCESS;
				break;
			case SWITCH_STATUS_NOT_INITALIZED:
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n");
				write_frame = NULL;
				goto error;
			default:
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s encoder error!\n",
								  session->read_codec->codec_interface->interface_name);
				write_frame = NULL;
				goto error;
			}
			if (flag & SFF_CNG) {
				switch_set_flag(write_frame, SFF_CNG);
			}

			status = perform_write(session, write_frame, flags, stream_id);
			goto error;
		} else {
			if (!session->raw_write_buffer) {
				switch_size_t bytes_per_packet = session->write_impl.decoded_bytes_per_packet;
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
								  "Engaging Write Buffer at %u bytes to accommodate %u->%u\n",
								  (uint32_t) bytes_per_packet, write_frame->datalen, session->write_impl.decoded_bytes_per_packet);
				if ((status = switch_buffer_create_dynamic(&session->raw_write_buffer,
														   bytes_per_packet * SWITCH_BUFFER_BLOCK_FRAMES,
														   bytes_per_packet * SWITCH_BUFFER_START_FRAMES, 0)) != SWITCH_STATUS_SUCCESS) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Write Buffer Failed!\n");
					goto error;
				}
			}

			if (!(switch_buffer_write(session->raw_write_buffer, write_frame->data, write_frame->datalen))) {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Write Buffer %u bytes Failed!\n", write_frame->datalen);
				status = SWITCH_STATUS_MEMERR;
				goto error;
			}

			status = SWITCH_STATUS_SUCCESS;

			while (switch_buffer_inuse(session->raw_write_buffer) >= session->write_impl.decoded_bytes_per_packet) {
				int rate;

				if (switch_channel_down(session->channel) || !session->raw_write_buffer) {
					goto error;
				}
				if ((session->raw_write_frame.datalen = (uint32_t)
					 switch_buffer_read(session->raw_write_buffer, session->raw_write_frame.data, session->write_impl.decoded_bytes_per_packet)) == 0) {
					goto error;
				}

				enc_frame = &session->raw_write_frame;
				session->raw_write_frame.rate = session->write_impl.actual_samples_per_second;
				session->enc_write_frame.datalen = session->enc_write_frame.buflen;
				session->enc_write_frame.timestamp = 0;


				if (frame->codec && frame->codec->implementation && switch_core_codec_ready(frame->codec)) {
					rate = frame->codec->implementation->actual_samples_per_second;
				} else {
					rate = session->write_impl.actual_samples_per_second;
				}

				status = switch_core_codec_encode(session->write_codec,
												  frame->codec,
												  enc_frame->data,
												  enc_frame->datalen,
												  rate,
												  session->enc_write_frame.data, &session->enc_write_frame.datalen, &session->enc_write_frame.rate, &flag);


				switch (status) {
				case SWITCH_STATUS_RESAMPLE:
					resample++;
					session->enc_write_frame.codec = session->write_codec;
					session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t);
					session->enc_write_frame.m = frame->m;
					session->enc_write_frame.ssrc = frame->ssrc;
					session->enc_write_frame.payload = session->write_impl.ianacode;
					write_frame = &session->enc_write_frame;
					if (!session->write_resampler) {
						switch_mutex_lock(session->resample_mutex);
						if (!session->write_resampler) {
							status = switch_resample_create(&session->write_resampler,
															frame->codec->implementation->actual_samples_per_second,
															session->write_impl.actual_samples_per_second,
															session->write_impl.decoded_bytes_per_packet, SWITCH_RESAMPLE_QUALITY, 1);
						}
						switch_mutex_unlock(session->resample_mutex);



						if (status != SWITCH_STATUS_SUCCESS) {
							goto done;
						}
					}
					break;
				case SWITCH_STATUS_SUCCESS:
					session->enc_write_frame.codec = session->write_codec;
					session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t);
					session->enc_write_frame.m = frame->m;
					session->enc_write_frame.ssrc = frame->ssrc;
					session->enc_write_frame.payload = session->write_impl.ianacode;
					write_frame = &session->enc_write_frame;
					break;
				case SWITCH_STATUS_NOOP:
					if (session->write_resampler) {
						switch_mutex_lock(session->resample_mutex);
						if (session->write_resampler) {
							switch_resample_destroy(&session->write_resampler);
							switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Deactivating write resampler\n");
						}
						switch_mutex_unlock(session->resample_mutex);
					}
					enc_frame->codec = session->write_codec;
					enc_frame->samples = enc_frame->datalen / sizeof(int16_t);
					enc_frame->m = frame->m;
					enc_frame->ssrc = frame->ssrc;
					enc_frame->payload = enc_frame->codec->implementation->ianacode;
					write_frame = enc_frame;
					status = SWITCH_STATUS_SUCCESS;
					break;
				case SWITCH_STATUS_NOT_INITALIZED:
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n");
					write_frame = NULL;
					goto error;
				default:
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s encoder error %d!\n",
									  session->read_codec->codec_interface->interface_name, status);
					write_frame = NULL;
					goto error;
				}

				if (!did_write_resample && session->read_resampler) {
					short *data = write_frame->data;
					switch_mutex_lock(session->resample_mutex);
					if (session->read_resampler) {
						switch_resample_process(session->read_resampler, data, write_frame->datalen / 2);
						memcpy(data, session->read_resampler->to, session->read_resampler->to_len * 2);
						write_frame->samples = session->read_resampler->to_len;
						write_frame->datalen = session->read_resampler->to_len * 2;
						write_frame->rate = session->read_resampler->to_rate;
					}
					switch_mutex_unlock(session->resample_mutex);

				}

				if (flag & SFF_CNG) {
					switch_set_flag(write_frame, SFF_CNG);
				}

				if (ptime_mismatch || resample) {
					write_frame->timestamp = 0;
				}

				if ((status = perform_write(session, write_frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
					break;
				}

			}

			goto error;
		}
	}





  done:

	if (ptime_mismatch || resample) {
		write_frame->timestamp = 0;
	}

	if (do_write) {
		status = perform_write(session, write_frame, flags, stream_id);
	}

  error:

	switch_mutex_unlock(session->write_codec->mutex);
	switch_mutex_unlock(frame->codec->mutex);
	switch_mutex_unlock(session->codec_write_mutex);

	return status;
}
コード例 #28
0
SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags,
															   int stream_id)
{
	switch_io_event_hook_read_frame_t *ptr;
	switch_status_t status = SWITCH_STATUS_FALSE;
	int need_codec, perfect, do_bugs = 0, do_resample = 0, is_cng = 0;
	switch_codec_implementation_t codec_impl;
	unsigned int flag = 0;

	switch_assert(session != NULL);


	if (switch_mutex_trylock(session->codec_read_mutex) == SWITCH_STATUS_SUCCESS) {
		switch_mutex_unlock(session->codec_read_mutex);
	} else {
		switch_cond_next();
		*frame = &runtime.dummy_cng_frame;
		return SWITCH_STATUS_SUCCESS;
	}

	if (!(session->read_codec && session->read_codec->implementation && switch_core_codec_ready(session->read_codec))) {
		if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) || switch_channel_get_state(session->channel) == CS_HIBERNATE) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "%s reading on a session with no media!\n",
							  switch_channel_get_name(session->channel));
			switch_cond_next();
			*frame = &runtime.dummy_cng_frame;
			return SWITCH_STATUS_SUCCESS;
		}
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no read codec.\n", switch_channel_get_name(session->channel));
		switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
		return SWITCH_STATUS_FALSE;
	}

	switch_mutex_lock(session->codec_read_mutex);

	if (!switch_core_codec_ready(session->read_codec)) {
		switch_mutex_unlock(session->codec_read_mutex);
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no read codec.\n", switch_channel_get_name(session->channel));
		switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
		*frame = &runtime.dummy_cng_frame;
        return SWITCH_STATUS_FALSE;
	}

	switch_mutex_lock(session->read_codec->mutex);

  top:
	
	if (session->dmachine && !switch_channel_test_flag(session->channel, CF_BROADCAST)) {
		switch_ivr_dmachine_ping(session->dmachine, NULL);
	}
	
	if (switch_channel_down(session->channel) || !switch_core_codec_ready(session->read_codec)) {
		*frame = NULL;
		status = SWITCH_STATUS_FALSE;
		goto even_more_done;
	}


	status = SWITCH_STATUS_FALSE;
	need_codec = perfect = 0;

	*frame = NULL;

	if (session->read_codec && !session->track_id && session->track_duration) {
		if (session->read_frame_count == 0) {
			switch_event_t *event;
			session->read_frame_count = (session->read_impl.actual_samples_per_second / session->read_impl.samples_per_packet) * session->track_duration;

			switch_event_create(&event, SWITCH_EVENT_SESSION_HEARTBEAT);
			switch_channel_event_set_data(session->channel, event);
			switch_event_fire(&event);
		} else {
			session->read_frame_count--;
		}
	}


	if (switch_channel_test_flag(session->channel, CF_HOLD)) {
		switch_yield(session->read_impl.microseconds_per_packet);
		status = SWITCH_STATUS_BREAK;
		goto even_more_done;
	}

	if (session->endpoint_interface->io_routines->read_frame) {
		switch_mutex_unlock(session->read_codec->mutex);
		switch_mutex_unlock(session->codec_read_mutex);
		if ((status = session->endpoint_interface->io_routines->read_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) {
			for (ptr = session->event_hooks.read_frame; ptr; ptr = ptr->next) {
				if ((status = ptr->read_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
					break;
				}
			}
		}

		if (!SWITCH_READ_ACCEPTABLE(status) || !session->read_codec || !switch_core_codec_ready(session->read_codec)) {
			*frame = NULL;
			return SWITCH_STATUS_FALSE;
		}

		switch_mutex_lock(session->codec_read_mutex);

		if (!switch_core_codec_ready(session->read_codec)) {
			switch_mutex_unlock(session->codec_read_mutex);
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no read codec.\n", switch_channel_get_name(session->channel));
			switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
			*frame = &runtime.dummy_cng_frame;
			return SWITCH_STATUS_FALSE;
		}

		switch_mutex_lock(session->read_codec->mutex);
		if (!switch_core_codec_ready(session->read_codec)) {
			*frame = NULL;
			status = SWITCH_STATUS_FALSE;
			goto even_more_done;			
		}

	}

	if (status != SWITCH_STATUS_SUCCESS) {
		goto done;
	}

	if (!(*frame)) {
		goto done;
	}

	switch_assert(*frame != NULL);

	if (switch_test_flag(*frame, SFF_PROXY_PACKET)) {
		/* Fast PASS! */
		status = SWITCH_STATUS_SUCCESS;
		goto done;
	}

	if (switch_test_flag(*frame, SFF_CNG)) {
		status = SWITCH_STATUS_SUCCESS;
		if (!session->bugs && !session->plc) {
			goto done;
		}
		is_cng = 1;
	}

	switch_assert((*frame)->codec != NULL);

	if (!(session->read_codec && (*frame)->codec && (*frame)->codec->implementation) && switch_core_codec_ready((*frame)->codec)) {
		status = SWITCH_STATUS_FALSE;
		goto done;
	}

	codec_impl = *(*frame)->codec->implementation;

	if (session->read_codec->implementation->impl_id != codec_impl.impl_id) {
		need_codec = TRUE;
	} 
	
	if (codec_impl.actual_samples_per_second != session->read_impl.actual_samples_per_second) {
		do_resample = 1;
	}

	if (session->bugs && !need_codec) {
		do_bugs = 1;
		need_codec = 1;
	}

	if (switch_test_flag(session, SSF_READ_TRANSCODE) && !need_codec && switch_core_codec_ready(session->read_codec)) {
		switch_core_session_t *other_session;
		const char *uuid = switch_channel_get_variable(switch_core_session_get_channel(session), SWITCH_SIGNAL_BOND_VARIABLE);
		switch_clear_flag(session, SSF_READ_TRANSCODE);
		
		if (uuid && (other_session = switch_core_session_locate(uuid))) {
			switch_set_flag(other_session, SSF_READ_CODEC_RESET);
			switch_set_flag(other_session, SSF_READ_CODEC_RESET);
			switch_set_flag(other_session, SSF_WRITE_CODEC_RESET);
			switch_core_session_rwunlock(other_session);
		}
	}

	if (switch_test_flag(session, SSF_READ_CODEC_RESET)) {
		switch_core_codec_reset(session->read_codec);
		switch_clear_flag(session, SSF_READ_CODEC_RESET);
	}

	




	if (status == SWITCH_STATUS_SUCCESS && need_codec) {
		switch_frame_t *enc_frame, *read_frame = *frame;

		switch_set_flag(session, SSF_READ_TRANSCODE);

		if (!switch_test_flag(session, SSF_WARN_TRANSCODE)) {
			switch_core_session_message_t msg = { 0 };

			msg.message_id = SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY;
			switch_core_session_receive_message(session, &msg);
			switch_set_flag(session, SSF_WARN_TRANSCODE);
		}

		if (read_frame->codec || is_cng) {
			session->raw_read_frame.datalen = session->raw_read_frame.buflen;

			if (is_cng) {
				if (session->plc) {
					plc_fillin(session->plc, session->raw_read_frame.data, read_frame->codec->implementation->decoded_bytes_per_packet / 2);
					is_cng = 0;
					flag &= !SFF_CNG;
				} else {
					memset(session->raw_read_frame.data, 255, read_frame->codec->implementation->decoded_bytes_per_packet);
				}

				session->raw_read_frame.timestamp = 0;
				session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet;
				session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t);
				read_frame = &session->raw_read_frame;
				status = SWITCH_STATUS_SUCCESS;
			} else {
				switch_codec_t *use_codec = read_frame->codec;
				if (do_bugs) {
					switch_thread_rwlock_wrlock(session->bug_rwlock);
					if (!session->bugs) {
						do_bugs = 0;
						switch_thread_rwlock_unlock(session->bug_rwlock);
						goto done;
					}

					if (!switch_core_codec_ready(&session->bug_codec)) {
						switch_core_codec_copy(read_frame->codec, &session->bug_codec, NULL);
					}
					use_codec = &session->bug_codec;
					switch_thread_rwlock_unlock(session->bug_rwlock);

					switch_thread_rwlock_wrlock(session->bug_rwlock);
					if (!session->bugs) {
						do_bugs = 0;
					}
					switch_thread_rwlock_unlock(session->bug_rwlock);
					if (!do_bugs) goto done;
				}

				if (switch_test_flag(read_frame, SFF_PLC)) {
					session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet;
					session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t);
					memset(session->raw_read_frame.data, 255, session->raw_read_frame.datalen);
					status = SWITCH_STATUS_SUCCESS;
				} else {
					status = switch_core_codec_decode(use_codec,
													  session->read_codec,
													  read_frame->data,
													  read_frame->datalen,
													  session->read_impl.actual_samples_per_second,
													  session->raw_read_frame.data, &session->raw_read_frame.datalen, &session->raw_read_frame.rate, 
													  &read_frame->flags);
				}
				
				if (status == SWITCH_STATUS_SUCCESS) {
					if ((switch_channel_test_flag(session->channel, CF_JITTERBUFFER) || switch_channel_test_flag(session->channel, CF_CNG_PLC)) 
						&& !session->plc) {
						session->plc = plc_init(NULL);
					}
				
					if (session->plc) {
						if (switch_test_flag(read_frame, SFF_PLC)) {
							plc_fillin(session->plc, session->raw_read_frame.data, session->raw_read_frame.datalen / 2);
							switch_clear_flag(read_frame, SFF_PLC);
						} else {
							plc_rx(session->plc, session->raw_read_frame.data, session->raw_read_frame.datalen / 2);
						}
					}
				}


			}

			if (do_resample && ((status == SWITCH_STATUS_SUCCESS) || is_cng)) {
				status = SWITCH_STATUS_RESAMPLE;
			}

			switch (status) {
			case SWITCH_STATUS_RESAMPLE:
				if (!session->read_resampler) {
					switch_mutex_lock(session->resample_mutex);
					status = switch_resample_create(&session->read_resampler,
													read_frame->codec->implementation->actual_samples_per_second,
													session->read_impl.actual_samples_per_second,
													session->read_impl.decoded_bytes_per_packet, SWITCH_RESAMPLE_QUALITY, 1);

					switch_mutex_unlock(session->resample_mutex);

					if (status != SWITCH_STATUS_SUCCESS) {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unable to allocate resampler\n");
						status = SWITCH_STATUS_FALSE;
						goto done;
					}
				}
			case SWITCH_STATUS_SUCCESS:
				session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t);
				session->raw_read_frame.rate = read_frame->rate;
				if (read_frame->codec->implementation->samples_per_packet != session->read_impl.samples_per_packet) {
					session->raw_read_frame.timestamp = 0;
				} else {
					session->raw_read_frame.timestamp = read_frame->timestamp;
				}
				session->raw_read_frame.ssrc = read_frame->ssrc;
				session->raw_read_frame.seq = read_frame->seq;
				session->raw_read_frame.m = read_frame->m;
				session->raw_read_frame.payload = read_frame->payload;
				session->raw_read_frame.flags = 0;
				if (switch_test_flag(read_frame, SFF_PLC)) {
					session->raw_read_frame.flags |= SFF_PLC;
				}
				read_frame = &session->raw_read_frame;
				break;
			case SWITCH_STATUS_NOOP:
				if (session->read_resampler) {
					switch_mutex_lock(session->resample_mutex);
					switch_resample_destroy(&session->read_resampler);
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Deactivating read resampler\n");
					switch_mutex_unlock(session->resample_mutex);
				}

				status = SWITCH_STATUS_SUCCESS;
				break;
			case SWITCH_STATUS_BREAK:
				memset(session->raw_read_frame.data, 255, read_frame->codec->implementation->decoded_bytes_per_packet);
				session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet;
				session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t);
				session->raw_read_frame.timestamp = read_frame->timestamp;
				session->raw_read_frame.rate = read_frame->rate;
				session->raw_read_frame.ssrc = read_frame->ssrc;
				session->raw_read_frame.seq = read_frame->seq;
				session->raw_read_frame.m = read_frame->m;
				session->raw_read_frame.payload = read_frame->payload;
				session->raw_read_frame.flags = 0;
				if (switch_test_flag(read_frame, SFF_PLC)) {
					session->raw_read_frame.flags |= SFF_PLC;
				}

				read_frame = &session->raw_read_frame;
				status = SWITCH_STATUS_SUCCESS;
				break;
			case SWITCH_STATUS_NOT_INITALIZED:
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n");
				goto done;
			default:
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s decoder error!\n",
								  session->read_codec->codec_interface->interface_name);
				goto done;
			}
		}

		if (session->bugs) {
			switch_media_bug_t *bp;
			switch_bool_t ok = SWITCH_TRUE;
			int prune = 0;
			switch_thread_rwlock_rdlock(session->bug_rwlock);

			for (bp = session->bugs; bp; bp = bp->next) {
				if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) {
					continue;
				}

				if (!switch_channel_test_flag(session->channel, CF_ANSWERED) && switch_core_media_bug_test_flag(bp, SMBF_ANSWER_REQ)) {
					continue;
				}
				if (switch_test_flag(bp, SMBF_PRUNE)) {
					prune++;
					continue;
				}

				if (bp->ready && switch_test_flag(bp, SMBF_READ_STREAM)) {
					switch_mutex_lock(bp->read_mutex);
					switch_buffer_write(bp->raw_read_buffer, read_frame->data, read_frame->datalen);
					if (bp->callback) {
						ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ);
					}
					switch_mutex_unlock(bp->read_mutex);
				}

				if (ok && switch_test_flag(bp, SMBF_READ_REPLACE)) {
					do_bugs = 0;
					if (bp->callback) {
						bp->read_replace_frame_in = read_frame;
						bp->read_replace_frame_out = read_frame;
						if ((ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ_REPLACE)) == SWITCH_TRUE) {
							read_frame = bp->read_replace_frame_out;
						}
					}
				}

				if ((bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL)) || ok == SWITCH_FALSE) {
					switch_set_flag(bp, SMBF_PRUNE);
					prune++;
				}


			}
			switch_thread_rwlock_unlock(session->bug_rwlock);
			if (prune) {
				switch_core_media_bug_prune(session);
			}
		}

		if (do_bugs) {
			goto done;
		}

		if (session->read_codec) {
			if (session->read_resampler) {
				short *data = read_frame->data;
				switch_mutex_lock(session->resample_mutex);
				switch_resample_process(session->read_resampler, data, (int) read_frame->datalen / 2);
				memcpy(data, session->read_resampler->to, session->read_resampler->to_len * 2);
				read_frame->samples = session->read_resampler->to_len;
				read_frame->datalen = session->read_resampler->to_len * 2;
				read_frame->rate = session->read_resampler->to_rate;
				switch_mutex_unlock(session->resample_mutex);
			}

			if (read_frame->datalen == session->read_impl.decoded_bytes_per_packet) {
				perfect = TRUE;
			} else {
				if (!session->raw_read_buffer) {
					switch_size_t bytes = session->read_impl.decoded_bytes_per_packet;
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Engaging Read Buffer at %u bytes vs %u\n",
									  (uint32_t) bytes, (uint32_t) (*frame)->datalen);
					switch_buffer_create_dynamic(&session->raw_read_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, 0);
				}

				if (!switch_buffer_write(session->raw_read_buffer, read_frame->data, read_frame->datalen)) {
					status = SWITCH_STATUS_MEMERR;
					goto done;
				}
			}

			if (perfect || switch_buffer_inuse(session->raw_read_buffer) >= session->read_impl.decoded_bytes_per_packet) {
				if (perfect) {
					enc_frame = read_frame;
					session->raw_read_frame.rate = read_frame->rate;
				} else {
					session->raw_read_frame.datalen = (uint32_t) switch_buffer_read(session->raw_read_buffer,
																					session->raw_read_frame.data,
																					session->read_impl.decoded_bytes_per_packet);

					session->raw_read_frame.rate = session->read_impl.actual_samples_per_second;
					enc_frame = &session->raw_read_frame;
				}
				session->enc_read_frame.datalen = session->enc_read_frame.buflen;

				switch_assert(session->read_codec != NULL);
				switch_assert(enc_frame != NULL);
				switch_assert(enc_frame->data != NULL);

				status = switch_core_codec_encode(session->read_codec,
												  enc_frame->codec,
												  enc_frame->data,
												  enc_frame->datalen,
												  session->read_impl.actual_samples_per_second,
												  session->enc_read_frame.data, &session->enc_read_frame.datalen, &session->enc_read_frame.rate, &flag);

				switch (status) {
				case SWITCH_STATUS_RESAMPLE:
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Fixme 1\n");
				case SWITCH_STATUS_SUCCESS:
					session->enc_read_frame.samples = session->read_impl.decoded_bytes_per_packet / sizeof(int16_t);
					if (perfect) {
						if (enc_frame->codec->implementation->samples_per_packet != session->read_impl.samples_per_packet) {
							session->enc_read_frame.timestamp = 0;
						} else {
							session->enc_read_frame.timestamp = read_frame->timestamp;
						}
						session->enc_read_frame.rate = read_frame->rate;
						session->enc_read_frame.ssrc = read_frame->ssrc;
						session->enc_read_frame.seq = read_frame->seq;
						session->enc_read_frame.m = read_frame->m;
						session->enc_read_frame.payload = session->read_impl.ianacode;
					}
					*frame = &session->enc_read_frame;
					break;
				case SWITCH_STATUS_NOOP:
					session->raw_read_frame.samples = enc_frame->codec->implementation->samples_per_packet;
					session->raw_read_frame.timestamp = read_frame->timestamp;
					session->raw_read_frame.payload = enc_frame->codec->implementation->ianacode;
					session->raw_read_frame.m = read_frame->m;
					session->raw_read_frame.ssrc = read_frame->ssrc;
					session->raw_read_frame.seq = read_frame->seq;
					*frame = enc_frame;
					status = SWITCH_STATUS_SUCCESS;
					break;
				case SWITCH_STATUS_NOT_INITALIZED:
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n");
					*frame = NULL;
					status = SWITCH_STATUS_GENERR;
					break;
				default:
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s encoder error!\n",
									  session->read_codec->codec_interface->interface_name);
					*frame = NULL;
					status = SWITCH_STATUS_GENERR;
					break;
				}
			} else {
				goto top;
			}
		}
	}

  done:
	if (!(*frame)) {
		status = SWITCH_STATUS_FALSE;
	} else {
		if (flag & SFF_CNG) {
			switch_set_flag((*frame), SFF_CNG);
		}
		if (session->bugs) {
			switch_media_bug_t *bp;
			switch_bool_t ok = SWITCH_TRUE;
			int prune = 0;
			switch_thread_rwlock_rdlock(session->bug_rwlock);
			for (bp = session->bugs; bp; bp = bp->next) {
				if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) {
					continue;
				}

				if (!switch_channel_test_flag(session->channel, CF_ANSWERED) && switch_core_media_bug_test_flag(bp, SMBF_ANSWER_REQ)) {
					continue;
				}

				if (switch_test_flag(bp, SMBF_PRUNE)) {
					prune++;
					continue;
				}

				if (bp->ready && switch_test_flag(bp, SMBF_READ_PING)) {
					switch_mutex_lock(bp->read_mutex);
					if (bp->callback) {
						if (bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ_PING) == SWITCH_FALSE
							|| (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL))) {
							ok = SWITCH_FALSE;
						}
					}
					switch_mutex_unlock(bp->read_mutex);
				}

				if (ok == SWITCH_FALSE) {
					switch_set_flag(bp, SMBF_PRUNE);
					prune++;
				}
			}
			switch_thread_rwlock_unlock(session->bug_rwlock);
			if (prune) {
				switch_core_media_bug_prune(session);
			}
		}
	}

  even_more_done:

	if (!*frame || !(*frame)->codec || !(*frame)->codec->implementation || !switch_core_codec_ready((*frame)->codec)) {
		*frame = &runtime.dummy_cng_frame;
	}

	switch_mutex_unlock(session->read_codec->mutex);
	switch_mutex_unlock(session->codec_read_mutex);

	return status;
}
コード例 #29
0
SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session)
{
	switch_channel_state_t state = CS_NEW, midstate = CS_DESTROY, endstate;
	const switch_endpoint_interface_t *endpoint_interface;
	const switch_state_handler_table_t *driver_state_handler = NULL;
	const switch_state_handler_table_t *application_state_handler = NULL;
	int silly = 0;
	uint32_t new_loops = 500;

	/*
	   Life of the channel. you have channel and pool in your session
	   everywhere you go you use the session to malloc with
	   switch_core_session_alloc(session, <size>)

	   The endpoint module gets the first crack at implementing the state
	   if it wants to, it can cancel the default behavior by returning SWITCH_STATUS_FALSE

	   Next comes the channel's event handler table that can be set by an application
	   which also can veto the next behavior in line by returning SWITCH_STATUS_FALSE

	   Finally the default state behavior is called.


	 */
	switch_assert(session != NULL);

	switch_set_flag(session, SSF_THREAD_RUNNING);
	endpoint_interface = session->endpoint_interface;
	switch_assert(endpoint_interface != NULL);

	driver_state_handler = endpoint_interface->state_handler;
	switch_assert(driver_state_handler != NULL);

	switch_mutex_lock(session->mutex);

	while ((state = switch_channel_get_state(session->channel)) != CS_DESTROY) {

		if (switch_channel_test_flag(session->channel, CF_BLOCK_STATE)) {
			switch_channel_wait_for_flag(session->channel, CF_BLOCK_STATE, SWITCH_FALSE, 0, NULL);
			if ((state = switch_channel_get_state(session->channel)) == CS_DESTROY) {
				break;
			}
		}

		midstate = state;
		if (state != switch_channel_get_running_state(session->channel) || state >= CS_HANGUP) {
			int index = 0;
			int proceed = 1;
			int global_proceed = 1;
			int do_extra_handlers = 1;
			switch_io_event_hook_state_run_t *ptr;
			switch_status_t rstatus = SWITCH_STATUS_SUCCESS;

			switch_channel_set_running_state(session->channel, state);
			switch_channel_clear_flag(session->channel, CF_TRANSFER);
			switch_channel_clear_flag(session->channel, CF_REDIRECT);
			
			if (session->endpoint_interface->io_routines->state_run) {
				rstatus = session->endpoint_interface->io_routines->state_run(session);
			}
			
			if (rstatus == SWITCH_STATUS_SUCCESS) {
				for (ptr = session->event_hooks.state_run; ptr; ptr = ptr->next) {
					if ((rstatus = ptr->state_run(session)) != SWITCH_STATUS_SUCCESS) {
						break;
					}
				}
			}
			
			switch (state) {
			case CS_NEW:		/* Just created, Waiting for first instructions */
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "(%s) State NEW\n", switch_channel_get_name(session->channel));
				break;
			case CS_DESTROY:
				goto done;
			case CS_REPORTING:	/* Call Detail */
				{
					switch_core_session_reporting_state(session);
					switch_channel_set_state(session->channel, CS_DESTROY);
				}
				goto done;
			case CS_HANGUP:	/* Deactivate and end the thread */
				{
					switch_core_session_hangup_state(session, SWITCH_TRUE);
					switch_channel_set_state(session->channel, CS_REPORTING);
				}

				break;
			case CS_INIT:		/* Basic setup tasks */
				{
					switch_event_t *event;

					STATE_MACRO(init, "INIT");
					
					if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_CREATE) == SWITCH_STATUS_SUCCESS) {
						switch_channel_event_set_data(session->channel, event);
						switch_event_fire(&event);
					}

					if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
						if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_ORIGINATE) == SWITCH_STATUS_SUCCESS) {
							switch_channel_event_set_data(session->channel, event);
							switch_event_fire(&event);
						}
					}
				}
				break;
			case CS_ROUTING:	/* Look for a dialplan and find something to do */
				STATE_MACRO(routing, "ROUTING");
				break;
			case CS_RESET:		/* Reset */
				STATE_MACRO(reset, "RESET");
				break;
				/* These other states are intended for prolonged durations so we do not signal lock for them */
			case CS_EXECUTE:	/* Execute an Operation */
				STATE_MACRO(execute, "EXECUTE");
				break;
			case CS_EXCHANGE_MEDIA:	/* loop all data back to source */
				STATE_MACRO(exchange_media, "EXCHANGE_MEDIA");
				break;
			case CS_SOFT_EXECUTE:	/* send/recieve data to/from another channel */
				STATE_MACRO(soft_execute, "SOFT_EXECUTE");
				break;
			case CS_PARK:		/* wait in limbo */
				STATE_MACRO(park, "PARK");
				break;
			case CS_CONSUME_MEDIA:	/* wait in limbo */
				STATE_MACRO(consume_media, "CONSUME_MEDIA");
				break;
			case CS_HIBERNATE:	/* sleep */
				STATE_MACRO(hibernate, "HIBERNATE");
				break;
			case CS_NONE:
				abort();
				break;
			}

			check_presence(session);

			if (midstate == CS_DESTROY) {
				break;
			}

		}

		endstate = switch_channel_get_state(session->channel);

		if (endstate == switch_channel_get_running_state(session->channel)) {
			if (endstate == CS_NEW) {
				switch_yield(20000);
				switch_ivr_parse_all_events(session);
				if (!--new_loops) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s %s Abandoned\n",
									  session->uuid_str, switch_core_session_get_name(session));
					switch_channel_set_flag(session->channel, CF_NO_CDR);
					switch_channel_hangup(session->channel, SWITCH_CAUSE_WRONG_CALL_STATE);
				}
			} else {
				switch_ivr_parse_all_events(session);
				switch_ivr_parse_all_events(session);

				if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) {
					switch_channel_state_thread_lock(session->channel);
					switch_channel_set_flag(session->channel, CF_THREAD_SLEEPING);
					if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) {
						switch_ivr_parse_all_events(session);
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s session thread sleep state: %s!\n", 
										  switch_channel_get_name(session->channel),
										  switch_channel_state_name(switch_channel_get_running_state(session->channel)));
						switch_thread_cond_wait(session->cond, session->mutex);
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s session thread wake state: %s!\n", 
										  switch_channel_get_name(session->channel),
										  switch_channel_state_name(switch_channel_get_running_state(session->channel)));


					}
					switch_channel_clear_flag(session->channel, CF_THREAD_SLEEPING);
					switch_channel_state_thread_unlock(session->channel);
				}

				switch_ivr_parse_all_events(session);
				switch_ivr_parse_all_events(session);
			}
		}
	}
  done:
	switch_mutex_unlock(session->mutex);

	switch_clear_flag(session, SSF_THREAD_RUNNING);
}
コード例 #30
0
ファイル: switch_ivr_menu.c プロジェクト: hsaid/FreeSWITCH
SWITCH_DECLARE(switch_status_t) switch_ivr_menu_execute(switch_core_session_t *session, switch_ivr_menu_t *stack, char *name, void *obj)
{
	int reps = 0, errs = 0, timeouts = 0, match = 0, running = 1;
	char *greeting_sound = NULL, *aptr = NULL;
	char arg[512];
	switch_ivr_action_t todo = SWITCH_IVR_ACTION_DIE;
	switch_ivr_menu_action_t *ap;
	switch_ivr_menu_t *menu;
	switch_channel_t *channel;
	switch_status_t status = SWITCH_STATUS_SUCCESS;

	if (++stack->stack_count > 12) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Too many levels of recursion.\n");
		switch_goto_status(SWITCH_STATUS_FALSE, end);
	}

	if (!session || !stack || zstr(name)) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid menu context\n");
		switch_goto_status(SWITCH_STATUS_FALSE, end);
	}

	channel = switch_core_session_get_channel(session);

	if (!(menu = switch_ivr_menu_find(stack, name))) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Menu!\n");
		switch_goto_status(SWITCH_STATUS_FALSE, end);
	}

	if (!zstr(menu->tts_engine) && !zstr(menu->tts_voice)) {
		switch_channel_set_variable(channel, "tts_engine", menu->tts_engine);
		switch_channel_set_variable(channel, "tts_voice", menu->tts_voice);
	}

	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Executing IVR menu %s\n", menu->name);
	switch_channel_set_variable(channel, "ivr_menu_status", "success");

	for (reps = 0; running && status == SWITCH_STATUS_SUCCESS; reps++) {
		if (!switch_channel_ready(channel)) {
			break;
		}
		if (errs == menu->max_failures) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Maximum failures\n");
			switch_channel_set_variable(channel, "ivr_menu_status", "failure");
			break;
		}
		if (timeouts == menu->max_timeouts) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Maximum timeouts\n");
			switch_channel_set_variable(channel, "ivr_menu_status", "timeout");
			break;
		}

		if (reps > 0 && menu->short_greeting_sound) {
			greeting_sound = menu->short_greeting_sound;
		} else {
			greeting_sound = menu->greeting_sound;
		}

		match = 0;
		aptr = NULL;

		memset(arg, 0, sizeof(arg));

		memset(menu->buf, 0, menu->inlen + 1);

		if (play_and_collect(session, menu, greeting_sound, menu->inlen) == SWITCH_STATUS_TIMEOUT && *menu->buf == '\0') {
			timeouts++;
			continue;
		}

		if (*menu->buf != '\0') {

			for (ap = menu->actions; ap; ap = ap->next) {
				int ok = 0;
				char substituted[1024];
				char *use_arg = ap->arg;

				if (!zstr(menu->tts_engine) && !zstr(menu->tts_voice)) {
					switch_channel_set_variable(channel, "tts_engine", menu->tts_engine);
					switch_channel_set_variable(channel, "tts_voice", menu->tts_voice);
				}

				if (ap->re) {
					switch_regex_t *re = NULL;
					int ovector[30];

					if ((ok = switch_regex_perform(menu->buf, ap->bind, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
						switch_perform_substitution(re, ok, ap->arg, menu->buf, substituted, sizeof(substituted), ovector);
						use_arg = substituted;
					}
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "action regex [%s] [%s] [%d]\n", menu->buf, ap->bind, ok);

					switch_regex_safe_free(re);
				} else {
					ok = !strcmp(menu->buf, ap->bind);
				}

				if (ok) {
					match++;
					errs = 0;
					if (ap->function) {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
										  "IVR function on menu '%s' matched '%s' param '%s'\n", menu->name, menu->buf, use_arg);
						todo = ap->function(menu, use_arg, arg, sizeof(arg), obj);
						aptr = arg;
					} else {
						todo = ap->ivr_action;
						aptr = use_arg;
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
										  "IVR action on menu '%s' matched '%s' param '%s'\n", menu->name, menu->buf, aptr);
					}

					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "switch_ivr_menu_execute todo=[%d]\n", todo);

					switch (todo) {
					case SWITCH_IVR_ACTION_DIE:
						status = SWITCH_STATUS_FALSE;
						break;
					case SWITCH_IVR_ACTION_PLAYSOUND:
						status = switch_ivr_play_file(session, NULL, aptr, NULL);
						break;
					case SWITCH_IVR_ACTION_EXECMENU:
						if (!strcmp(aptr, menu->name)) {
							status = SWITCH_STATUS_SUCCESS;
						} else {
							reps = -1;
							status = switch_ivr_menu_execute(session, stack, aptr, obj);
						}
						break;
					case SWITCH_IVR_ACTION_EXECAPP:
						{
							switch_application_interface_t *application_interface;
							char *app_name;
							char *app_arg = NULL;

							status = SWITCH_STATUS_FALSE;

							if (!zstr(aptr)) {
								app_name = switch_core_session_strdup(session, aptr);
								if ((app_arg = strchr(app_name, ' '))) {
									*app_arg++ = '\0';
								}

								if ((application_interface = switch_loadable_module_get_application_interface(app_name))) {
									switch_core_session_exec(session, application_interface, app_arg);
									UNPROTECT_INTERFACE(application_interface);
									status = SWITCH_STATUS_SUCCESS;
								}
							}
						}
						break;
					case SWITCH_IVR_ACTION_BACK:
						running = 0;
						status = SWITCH_STATUS_SUCCESS;
						break;
					case SWITCH_IVR_ACTION_TOMAIN:
						switch_set_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN);
						status = SWITCH_STATUS_BREAK;
						break;
					case SWITCH_IVR_ACTION_NOOP:
						status = SWITCH_STATUS_SUCCESS;
						break;
					default:
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Invalid TODO!\n");
						break;
					}
				}
			}

			if (switch_test_flag(menu, SWITCH_IVR_MENU_FLAG_STACK)) {	/* top level */
				if (switch_test_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN)) {	/* catch the fallback and recover */
					switch_clear_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN);
					status = SWITCH_STATUS_SUCCESS;
					running = 1;
					continue;
				}
			}
		}
		if (!match) {
			if (*menu->buf) {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR menu '%s' caught invalid input '%s'\n", menu->name,
								  menu->buf);
				if (menu->invalid_sound) {
					play_and_collect(session, menu, menu->invalid_sound, 0);
				}
			} else {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR menu '%s' no input detected\n", menu->name);
			}
			errs++;

			/* breaks are ok too */
			if (SWITCH_STATUS_IS_BREAK(status)) {
				status = SWITCH_STATUS_SUCCESS;
			}
		}
	}

	if (stack->stack_count == 1) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "exit-sound '%s'\n", menu->exit_sound);
		if (!zstr(menu->exit_sound)) {
			status = play_and_collect(session, menu, menu->exit_sound, 0);
		}
	}

  end:

	stack->stack_count--;

	return status;
}