1
0
mirror of https://github.com/signalwire/freeswitch.git synced 2025-03-30 02:10:39 +00:00
Brian West 915fa372d8 commit dbea6143d6b63765f2d0eba26728c3903d3d2606
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Wed Jul 8 17:37:24 2009 +0000

    Added yet another buffer of media frames mpf_frame_buffer.
    There are a number of similar buffers (mpf_jitter_buffer, mpf_buffer, mpf_frame_buffer). All of them produce mpf_frames as output, but input is somewhat dif
ferent. Input is RTP payload in case of mpf_jitter_buffer, synthesized chunks of voice in case of mpf_buffer, and mpf_frame in case of mpf_frame_buffer
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1043 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 1bf7a66012180649bd1f01fd72e483a9e5de3495
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Wed Jul 8 16:33:36 2009 +0000

    Fixed termination of client and server stacks (Issue-28)
    Network client/server stacks generated double TERMINATE_COMPLETE event, while mpf engine generated no TERMINATE_COMPLETE event.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1042 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 0327cf17779430b51290d22cc7d51130f997f2f2
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Sun Jul 5 19:22:31 2009 +0000

    Enhanced flite plugin to
    - support more than one SPEAK requests in a session (SPEAK -> STOP -> SPEAK or SPEAK-> SPEAK-COMPLETE->SPEAK), task is created upon channel creation and is 
waiting for consecutive SPEAK requests to process
    - properly handle race between STOP request and SPEAK-COMPLETE event
    - respond with IN-PROGRESS, when all the required parameters are checked to be valid and synthesizing is due to start
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1037 f001bc3a-424a-0410-80a0-a715b8f413a8

commit e2f73f9279e54ef3a40cb637a38ab1ff485ea5d3
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Sun Jul 5 03:46:13 2009 +0000

    Separated flite voices (unified voice register/unregister routine, select voice by name)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1036 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 694783a527cb795ca45982c2388895da06dd6009
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Sat Jul 4 05:06:17 2009 +0000

    Checked content-type to be "text/plain" as flite doesn't support SSML yet.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1035 f001bc3a-424a-0410-80a0-a715b8f413a8

commit aafdc6e30e77c40e5470cce844f48ec28a254786
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Fri Jul 3 14:55:10 2009 +0000

    Enhanced float value generation to use the precision (digits after decimal sign) user provides by removing optional trailing 0s (if any)
    Issue-35
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1034 f001bc3a-424a-0410-80a0-a715b8f413a8

commit bcc2f137956f5c532c0256b064c8a3d1015a46d0
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Fri Jul 3 07:04:07 2009 +0000

    Enhanced RTP port management (Issue-34, Thanks cpsoares)

    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1033 f001bc3a-424a-0410-80a0-a715b8f413a8



git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@14166 d0543943-73ff-0310-b7d9-9358b9ac24b2
2009-07-09 15:19:27 +00:00

312 lines
9.3 KiB
C

/*
* Copyright 2008 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mpf_engine.h"
#include "mpf_user.h"
#include "mpf_context.h"
#include "mpf_termination.h"
#include "mpf_stream.h"
#include "mpf_timer.h"
#include "mpf_codec_descriptor.h"
#include "mpf_codec_manager.h"
#include "apt_obj_list.h"
#include "apt_cyclic_queue.h"
#include "apt_log.h"
#define MPF_TASK_NAME "Media Processing Engine"
struct mpf_engine_t {
apr_pool_t *pool;
apt_task_t *task;
apt_task_msg_type_e task_msg_type;
apr_thread_mutex_t *request_queue_guard;
apt_cyclic_queue_t *request_queue;
apt_obj_list_t *contexts;
mpf_timer_t *timer;
const mpf_codec_manager_t *codec_manager;
};
static void mpf_engine_main(mpf_timer_t *timer, void *data);
static apt_bool_t mpf_engine_destroy(apt_task_t *task);
static apt_bool_t mpf_engine_start(apt_task_t *task);
static apt_bool_t mpf_engine_terminate(apt_task_t *task);
static apt_bool_t mpf_engine_msg_signal(apt_task_t *task, apt_task_msg_t *msg);
static apt_bool_t mpf_engine_msg_process(apt_task_t *task, apt_task_msg_t *msg);
static apt_bool_t mpf_engine_contexts_destroy(mpf_engine_t *engine);
mpf_codec_t* mpf_codec_lpcm_create(apr_pool_t *pool);
mpf_codec_t* mpf_codec_l16_create(apr_pool_t *pool);
mpf_codec_t* mpf_codec_g711u_create(apr_pool_t *pool);
mpf_codec_t* mpf_codec_g711a_create(apr_pool_t *pool);
MPF_DECLARE(mpf_engine_t*) mpf_engine_create(apr_pool_t *pool)
{
apt_task_vtable_t *vtable;
apt_task_msg_pool_t *msg_pool;
mpf_engine_t *engine = apr_palloc(pool,sizeof(mpf_engine_t));
engine->pool = pool;
engine->request_queue = NULL;
engine->contexts = NULL;
engine->codec_manager = NULL;
msg_pool = apt_task_msg_pool_create_dynamic(sizeof(mpf_message_t),pool);
apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create "MPF_TASK_NAME);
engine->task = apt_task_create(engine,msg_pool,pool);
if(!engine->task) {
return NULL;
}
apt_task_name_set(engine->task,MPF_TASK_NAME);
vtable = apt_task_vtable_get(engine->task);
if(vtable) {
vtable->destroy = mpf_engine_destroy;
vtable->start = mpf_engine_start;
vtable->terminate = mpf_engine_terminate;
vtable->signal_msg = mpf_engine_msg_signal;
vtable->process_msg = mpf_engine_msg_process;
}
engine->task_msg_type = TASK_MSG_USER;
engine->request_queue = apt_cyclic_queue_create(CYCLIC_QUEUE_DEFAULT_SIZE);
apr_thread_mutex_create(&engine->request_queue_guard,APR_THREAD_MUTEX_UNNESTED,engine->pool);
engine->contexts = apt_list_create(engine->pool);
return engine;
}
MPF_DECLARE(apt_task_t*) mpf_task_get(mpf_engine_t *engine)
{
return engine->task;
}
MPF_DECLARE(void) mpf_engine_task_msg_type_set(mpf_engine_t *engine, apt_task_msg_type_e type)
{
engine->task_msg_type = type;
}
static apt_bool_t mpf_engine_destroy(apt_task_t *task)
{
mpf_engine_t *engine = apt_task_object_get(task);
apt_list_destroy(engine->contexts);
apt_cyclic_queue_destroy(engine->request_queue);
apr_thread_mutex_destroy(engine->request_queue_guard);
return TRUE;
}
static apt_bool_t mpf_engine_start(apt_task_t *task)
{
mpf_engine_t *engine = apt_task_object_get(task);
engine->timer = mpf_timer_start(CODEC_FRAME_TIME_BASE,mpf_engine_main,engine,engine->pool);
apt_task_child_start(task);
return TRUE;
}
static apt_bool_t mpf_engine_terminate(apt_task_t *task)
{
mpf_engine_t *engine = apt_task_object_get(task);
mpf_timer_stop(engine->timer);
mpf_engine_contexts_destroy(engine);
apt_task_child_terminate(task);
return TRUE;
}
static apt_bool_t mpf_engine_contexts_destroy(mpf_engine_t *engine)
{
mpf_context_t *context;
context = apt_list_pop_front(engine->contexts);
while(context) {
mpf_context_destroy(context);
context = apt_list_pop_front(engine->contexts);
}
return TRUE;
}
static apt_bool_t mpf_engine_event_raise(mpf_termination_t *termination, int event_id, void *descriptor)
{
apt_task_msg_t *task_msg;
mpf_message_t *event_msg;
mpf_engine_t *engine;
engine = termination->event_handler_obj;
if(!engine) {
return FALSE;
}
task_msg = apt_task_msg_get(engine->task);
task_msg->type = engine->task_msg_type;
event_msg = (mpf_message_t*) task_msg->data;
event_msg->command_id = event_id;
event_msg->message_type = MPF_MESSAGE_TYPE_EVENT;
event_msg->status_code = MPF_STATUS_CODE_SUCCESS;
event_msg->context = NULL;
event_msg->termination = termination;
event_msg->descriptor = descriptor;
return apt_task_msg_parent_signal(engine->task,task_msg);
}
static apt_bool_t mpf_engine_msg_signal(apt_task_t *task, apt_task_msg_t *msg)
{
mpf_engine_t *engine = apt_task_object_get(task);
apr_thread_mutex_lock(engine->request_queue_guard);
if(apt_cyclic_queue_push(engine->request_queue,msg) == FALSE) {
apt_log(APT_LOG_MARK,APT_PRIO_ERROR,"MPF Request Queue is Full");
}
apr_thread_mutex_unlock(engine->request_queue_guard);
return TRUE;
}
static apt_bool_t mpf_engine_msg_process(apt_task_t *task, apt_task_msg_t *msg)
{
mpf_engine_t *engine = apt_task_object_get(task);
apt_task_msg_t *response_msg;
mpf_message_t *response;
mpf_context_t *context;
mpf_termination_t *termination;
const mpf_message_t *request = (const mpf_message_t*) msg->data;
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Process MPF Message");
if(request->message_type != MPF_MESSAGE_TYPE_REQUEST) {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Invalid MPF Message Type [%d]",request->message_type);
return FALSE;
}
response_msg = apt_task_msg_get(engine->task);
response_msg->type = engine->task_msg_type;
response = (mpf_message_t*) response_msg->data;
*response = *request;
response->message_type = MPF_MESSAGE_TYPE_RESPONSE;
response->status_code = MPF_STATUS_CODE_SUCCESS;
context = request->context;
termination = request->termination;
switch(request->command_id) {
case MPF_COMMAND_ADD:
{
termination->event_handler_obj = engine;
termination->event_handler = mpf_engine_event_raise;
termination->codec_manager = engine->codec_manager;
if(request->descriptor) {
mpf_termination_modify(termination,request->descriptor);
}
mpf_termination_validate(termination);
if(mpf_context_termination_add(context,termination) == FALSE) {
response->status_code = MPF_STATUS_CODE_FAILURE;
break;
}
mpf_context_topology_apply(context,termination);
if(context->termination_count == 1) {
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Add Context");
context->elem = apt_list_push_back(engine->contexts,context,context->pool);
}
break;
}
case MPF_COMMAND_SUBTRACT:
{
mpf_context_topology_destroy(context,termination);
if(mpf_context_termination_subtract(context,termination) == FALSE) {
response->status_code = MPF_STATUS_CODE_FAILURE;
break;
}
if(context->termination_count == 0) {
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Remove Context");
apt_list_elem_remove(engine->contexts,context->elem);
context->elem = NULL;
}
break;
}
case MPF_COMMAND_MODIFY:
{
if(request->descriptor) {
mpf_context_topology_destroy(context,termination);
mpf_termination_modify(termination,request->descriptor);
mpf_termination_validate(termination);
mpf_context_topology_apply(context,termination);
}
break;
}
default:
{
response->status_code = MPF_STATUS_CODE_FAILURE;
}
}
return apt_task_msg_parent_signal(engine->task,response_msg);
}
static void mpf_engine_main(mpf_timer_t *timer, void *data)
{
mpf_engine_t *engine = data;
apt_task_msg_t *msg;
apt_list_elem_t *elem;
mpf_context_t *context;
/* process request queue */
apr_thread_mutex_lock(engine->request_queue_guard);
msg = apt_cyclic_queue_pop(engine->request_queue);
while(msg) {
apr_thread_mutex_unlock(engine->request_queue_guard);
apt_task_msg_process(engine->task,msg);
apr_thread_mutex_lock(engine->request_queue_guard);
msg = apt_cyclic_queue_pop(engine->request_queue);
}
apr_thread_mutex_unlock(engine->request_queue_guard);
/* process contexts */
elem = apt_list_first_elem_get(engine->contexts);
while(elem) {
context = apt_list_elem_object_get(elem);
if(context) {
mpf_context_process(context);
}
elem = apt_list_next_elem_get(engine->contexts,elem);
}
}
MPF_DECLARE(mpf_codec_manager_t*) mpf_engine_codec_manager_create(apr_pool_t *pool)
{
mpf_codec_manager_t *codec_manager = mpf_codec_manager_create(3,pool);
if(codec_manager) {
mpf_codec_t *codec;
codec = mpf_codec_lpcm_create(pool);
mpf_codec_manager_codec_register(codec_manager,codec);
codec = mpf_codec_g711u_create(pool);
mpf_codec_manager_codec_register(codec_manager,codec);
codec = mpf_codec_g711a_create(pool);
mpf_codec_manager_codec_register(codec_manager,codec);
codec = mpf_codec_l16_create(pool);
mpf_codec_manager_codec_register(codec_manager,codec);
}
return codec_manager;
}
MPF_DECLARE(apt_bool_t) mpf_engine_codec_manager_register(mpf_engine_t *engine, const mpf_codec_manager_t *codec_manager)
{
engine->codec_manager = codec_manager;
return TRUE;
}