mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-11-13 21:17:06 +00:00
Update to latest UniMRCP version. MRCP requests can no timeout if there is no server response.
This commit is contained in:
1 parent
0555b702db
commit
17099473a3
441 files changed
+17430
-17071
No files matched your search
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
*
|
||||
* $Id: verifiersession.cpp 1778 2010-08-27 17:34:52Z achaloyan $
|
||||
*/
|
||||
|
||||
#include "verifiersession.h"
|
||||
#include "verifierscenario.h"
|
||||
#include "mrcp_message.h"
|
||||
#include "mrcp_generic_header.h"
|
||||
#include "mrcp_verifier_header.h"
|
||||
#include "mrcp_verifier_resource.h"
|
||||
#include "apt_nlsml_doc.h"
|
||||
#include "apt_log.h"
|
||||
|
||||
struct VerifierChannel
|
||||
{
|
||||
/** MRCP control channel */
|
||||
mrcp_channel_t* m_pMrcpChannel;
|
||||
/** IN-PROGRESS VERIFY request */
|
||||
mrcp_message_t* m_pVerificationRequest;
|
||||
/** Streaming is in-progress */
|
||||
bool m_Streaming;
|
||||
/** File to read audio stream from */
|
||||
FILE* m_pAudioIn;
|
||||
/** Estimated time to complete (used if no audio_in available) */
|
||||
apr_size_t m_TimeToComplete;
|
||||
|
||||
VerifierChannel() :
|
||||
m_pMrcpChannel(NULL),
|
||||
m_pVerificationRequest(NULL),
|
||||
m_Streaming(false),
|
||||
m_pAudioIn(NULL),
|
||||
m_TimeToComplete(0) {}
|
||||
};
|
||||
|
||||
VerifierSession::VerifierSession(const VerifierScenario* pScenario) :
|
||||
UmcSession(pScenario),
|
||||
m_pVerifierChannel(NULL),
|
||||
m_ContentId("request1@form-level")
|
||||
{
|
||||
}
|
||||
|
||||
VerifierSession::~VerifierSession()
|
||||
{
|
||||
}
|
||||
|
||||
bool VerifierSession::Start()
|
||||
{
|
||||
/* create channel and associate all the required data */
|
||||
m_pVerifierChannel = CreateVerifierChannel();
|
||||
if(!m_pVerifierChannel)
|
||||
return false;
|
||||
|
||||
/* add channel to session (send asynchronous request) */
|
||||
if(!AddMrcpChannel(m_pVerifierChannel->m_pMrcpChannel))
|
||||
{
|
||||
delete m_pVerifierChannel;
|
||||
m_pVerifierChannel = NULL;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VerifierSession::Stop()
|
||||
{
|
||||
if(!UmcSession::Stop())
|
||||
return false;
|
||||
|
||||
if(!m_pVerifierChannel)
|
||||
return false;
|
||||
|
||||
mrcp_message_t* pStopMessage = CreateMrcpMessage(m_pVerifierChannel->m_pMrcpChannel,VERIFIER_STOP);
|
||||
if(!pStopMessage)
|
||||
return false;
|
||||
|
||||
return SendMrcpRequest(m_pVerifierChannel->m_pMrcpChannel,pStopMessage);
|
||||
}
|
||||
|
||||
bool VerifierSession::OnSessionTerminate(mrcp_sig_status_code_e status)
|
||||
{
|
||||
if(m_pVerifierChannel)
|
||||
{
|
||||
FILE* pAudioIn = m_pVerifierChannel->m_pAudioIn;
|
||||
if(pAudioIn)
|
||||
{
|
||||
m_pVerifierChannel->m_pAudioIn = NULL;
|
||||
fclose(pAudioIn);
|
||||
}
|
||||
|
||||
delete m_pVerifierChannel;
|
||||
m_pVerifierChannel = NULL;
|
||||
}
|
||||
return UmcSession::OnSessionTerminate(status);
|
||||
}
|
||||
|
||||
static apt_bool_t ReadStream(mpf_audio_stream_t* pStream, mpf_frame_t* pFrame)
|
||||
{
|
||||
VerifierChannel* pVerifierChannel = (VerifierChannel*) pStream->obj;
|
||||
if(pVerifierChannel && pVerifierChannel->m_Streaming)
|
||||
{
|
||||
if(pVerifierChannel->m_pAudioIn)
|
||||
{
|
||||
if(fread(pFrame->codec_frame.buffer,1,pFrame->codec_frame.size,pVerifierChannel->m_pAudioIn) == pFrame->codec_frame.size)
|
||||
{
|
||||
/* normal read */
|
||||
pFrame->type |= MEDIA_FRAME_TYPE_AUDIO;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* file is over */
|
||||
pVerifierChannel->m_Streaming = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* fill with silence in case no file available */
|
||||
if(pVerifierChannel->m_TimeToComplete >= CODEC_FRAME_TIME_BASE)
|
||||
{
|
||||
pFrame->type |= MEDIA_FRAME_TYPE_AUDIO;
|
||||
memset(pFrame->codec_frame.buffer,0,pFrame->codec_frame.size);
|
||||
pVerifierChannel->m_TimeToComplete -= CODEC_FRAME_TIME_BASE;
|
||||
}
|
||||
else
|
||||
{
|
||||
pVerifierChannel->m_Streaming = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VerifierChannel* VerifierSession::CreateVerifierChannel()
|
||||
{
|
||||
mrcp_channel_t* pChannel;
|
||||
mpf_termination_t* pTermination;
|
||||
mpf_stream_capabilities_t* pCapabilities;
|
||||
apr_pool_t* pool = GetSessionPool();
|
||||
|
||||
/* create channel */
|
||||
VerifierChannel* pVerifierChannel = new VerifierChannel;
|
||||
|
||||
/* create source stream capabilities */
|
||||
pCapabilities = mpf_source_stream_capabilities_create(pool);
|
||||
GetScenario()->InitCapabilities(pCapabilities);
|
||||
|
||||
static const mpf_audio_stream_vtable_t audio_stream_vtable =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
ReadStream,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
pTermination = CreateAudioTermination(
|
||||
&audio_stream_vtable, /* virtual methods table of audio stream */
|
||||
pCapabilities, /* capabilities of audio stream */
|
||||
pVerifierChannel); /* object to associate */
|
||||
|
||||
pChannel = CreateMrcpChannel(
|
||||
MRCP_VERIFIER_RESOURCE, /* MRCP resource identifier */
|
||||
pTermination, /* media termination, used to terminate audio stream */
|
||||
NULL, /* RTP descriptor, used to create RTP termination (NULL by default) */
|
||||
pVerifierChannel); /* object to associate */
|
||||
if(!pChannel)
|
||||
{
|
||||
delete pVerifierChannel;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pVerifierChannel->m_pMrcpChannel = pChannel;
|
||||
return pVerifierChannel;
|
||||
}
|
||||
|
||||
bool VerifierSession::OnChannelAdd(mrcp_channel_t* pMrcpChannel, mrcp_sig_status_code_e status)
|
||||
{
|
||||
if(!UmcSession::OnChannelAdd(pMrcpChannel,status))
|
||||
return false;
|
||||
|
||||
if(status != MRCP_SIG_STATUS_CODE_SUCCESS)
|
||||
{
|
||||
/* error case, just terminate the demo */
|
||||
return Terminate();
|
||||
}
|
||||
|
||||
return StartVerification(pMrcpChannel);
|
||||
}
|
||||
|
||||
bool VerifierSession::OnMessageReceive(mrcp_channel_t* pMrcpChannel, mrcp_message_t* pMrcpMessage)
|
||||
{
|
||||
if(!UmcSession::OnMessageReceive(pMrcpChannel,pMrcpMessage))
|
||||
return false;
|
||||
|
||||
VerifierChannel* pVerifierChannel = (VerifierChannel*) mrcp_application_channel_object_get(pMrcpChannel);
|
||||
if(pMrcpMessage->start_line.message_type == MRCP_MESSAGE_TYPE_RESPONSE)
|
||||
{
|
||||
/* received MRCP response */
|
||||
if(pMrcpMessage->start_line.method_id == VERIFIER_START_SESSION)
|
||||
{
|
||||
/* received the response to START-SESSION request */
|
||||
/* create and send VERIFY request */
|
||||
mrcp_message_t* pMrcpMessage = CreateVerificationRequest(pMrcpChannel);
|
||||
if(pMrcpMessage)
|
||||
{
|
||||
SendMrcpRequest(pVerifierChannel->m_pMrcpChannel,pMrcpMessage);
|
||||
}
|
||||
}
|
||||
else if(pMrcpMessage->start_line.method_id == VERIFIER_END_SESSION)
|
||||
{
|
||||
/* received the response to END-SESSION request */
|
||||
Terminate();
|
||||
}
|
||||
else if(pMrcpMessage->start_line.method_id == VERIFIER_VERIFY)
|
||||
{
|
||||
/* received the response to VERIFY request */
|
||||
if(pMrcpMessage->start_line.request_state == MRCP_REQUEST_STATE_INPROGRESS)
|
||||
{
|
||||
VerifierChannel* pVerifierChannel = (VerifierChannel*) mrcp_application_channel_object_get(pMrcpChannel);
|
||||
if(pVerifierChannel)
|
||||
pVerifierChannel->m_pVerificationRequest = GetMrcpMessage();
|
||||
|
||||
/* start to stream the speech to Verify */
|
||||
if(pVerifierChannel)
|
||||
pVerifierChannel->m_Streaming = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* create and send END-SESSION request */
|
||||
mrcp_message_t* pMrcpMessage = CreateEndSessionRequest(pMrcpChannel);
|
||||
if(pMrcpMessage)
|
||||
{
|
||||
SendMrcpRequest(pVerifierChannel->m_pMrcpChannel,pMrcpMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* received unexpected response */
|
||||
}
|
||||
}
|
||||
else if(pMrcpMessage->start_line.message_type == MRCP_MESSAGE_TYPE_EVENT)
|
||||
{
|
||||
if(pMrcpMessage->start_line.method_id == VERIFIER_VERIFICATION_COMPLETE)
|
||||
{
|
||||
if(pVerifierChannel)
|
||||
pVerifierChannel->m_Streaming = false;
|
||||
|
||||
VerifierChannel* pVerifierChannel = (VerifierChannel*) mrcp_application_channel_object_get(pMrcpChannel);
|
||||
if(pVerifierChannel)
|
||||
pVerifierChannel->m_pVerificationRequest = NULL;
|
||||
|
||||
/* create and send END-SESSION request */
|
||||
mrcp_message_t* pMrcpMessage = CreateEndSessionRequest(pMrcpChannel);
|
||||
if(pMrcpMessage)
|
||||
{
|
||||
SendMrcpRequest(pVerifierChannel->m_pMrcpChannel,pMrcpMessage);
|
||||
}
|
||||
}
|
||||
else if(pMrcpMessage->start_line.method_id == VERIFIER_START_OF_INPUT)
|
||||
{
|
||||
/* received start-of-input, do whatever you need here */
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VerifierSession::StartVerification(mrcp_channel_t* pMrcpChannel)
|
||||
{
|
||||
VerifierChannel* pVerifierChannel = (VerifierChannel*) mrcp_application_channel_object_get(pMrcpChannel);
|
||||
/* create and send Verification request */
|
||||
mrcp_message_t* pMrcpMessage = CreateStartSessionRequest(pMrcpChannel);
|
||||
if(pMrcpMessage)
|
||||
{
|
||||
SendMrcpRequest(pVerifierChannel->m_pMrcpChannel,pMrcpMessage);
|
||||
}
|
||||
|
||||
const mpf_codec_descriptor_t* pDescriptor = mrcp_application_source_descriptor_get(pMrcpChannel);
|
||||
pVerifierChannel->m_pAudioIn = GetAudioIn(pDescriptor,GetSessionPool());
|
||||
if(!pVerifierChannel->m_pAudioIn)
|
||||
{
|
||||
/* no audio input availble, set some estimated time to complete instead */
|
||||
pVerifierChannel->m_TimeToComplete = 5000; // 5 sec
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
mrcp_message_t* VerifierSession::CreateStartSessionRequest(mrcp_channel_t* pMrcpChannel)
|
||||
{
|
||||
mrcp_message_t* pMrcpMessage = CreateMrcpMessage(pMrcpChannel,VERIFIER_START_SESSION);
|
||||
if(!pMrcpMessage)
|
||||
return NULL;
|
||||
|
||||
mrcp_verifier_header_t* pVerifierHeader;
|
||||
|
||||
/* get/allocate verifier header */
|
||||
pVerifierHeader = (mrcp_verifier_header_t*) mrcp_resource_header_prepare(pMrcpMessage);
|
||||
if(pVerifierHeader)
|
||||
{
|
||||
const VerifierScenario* pScenario = GetScenario();
|
||||
const char* pRepositoryURI = pScenario->GetRepositoryURI();
|
||||
if(pRepositoryURI)
|
||||
{
|
||||
apt_string_set(&pVerifierHeader->repository_uri,pRepositoryURI);
|
||||
mrcp_resource_header_property_add(pMrcpMessage,VERIFIER_HEADER_REPOSITORY_URI);
|
||||
}
|
||||
const char* pVoiceprintIdentifier = pScenario->GetVoiceprintIdentifier();
|
||||
if(pVoiceprintIdentifier)
|
||||
{
|
||||
apt_string_set(&pVerifierHeader->voiceprint_identifier,pVoiceprintIdentifier);
|
||||
mrcp_resource_header_property_add(pMrcpMessage,VERIFIER_HEADER_VOICEPRINT_IDENTIFIER);
|
||||
}
|
||||
const char* pVerificationMode = pScenario->GetVerificationMode();
|
||||
if(pVerificationMode)
|
||||
{
|
||||
apt_string_set(&pVerifierHeader->verification_mode,pVerificationMode);
|
||||
mrcp_resource_header_property_add(pMrcpMessage,VERIFIER_HEADER_VERIFICATION_MODE);
|
||||
}
|
||||
}
|
||||
return pMrcpMessage;
|
||||
}
|
||||
|
||||
mrcp_message_t* VerifierSession::CreateEndSessionRequest(mrcp_channel_t* pMrcpChannel)
|
||||
{
|
||||
return CreateMrcpMessage(pMrcpChannel,VERIFIER_END_SESSION);
|
||||
}
|
||||
|
||||
mrcp_message_t* VerifierSession::CreateVerificationRequest(mrcp_channel_t* pMrcpChannel)
|
||||
{
|
||||
mrcp_message_t* pMrcpMessage = CreateMrcpMessage(pMrcpChannel,VERIFIER_VERIFY);
|
||||
if(!pMrcpMessage)
|
||||
return NULL;
|
||||
|
||||
mrcp_verifier_header_t* pVerifierHeader;
|
||||
|
||||
/* get/allocate verifier header */
|
||||
pVerifierHeader = (mrcp_verifier_header_t*) mrcp_resource_header_prepare(pMrcpMessage);
|
||||
if(pVerifierHeader)
|
||||
{
|
||||
pVerifierHeader->no_input_timeout = 5000;
|
||||
mrcp_resource_header_property_add(pMrcpMessage,VERIFIER_HEADER_NO_INPUT_TIMEOUT);
|
||||
pVerifierHeader->start_input_timers = TRUE;
|
||||
mrcp_resource_header_property_add(pMrcpMessage,VERIFIER_HEADER_START_INPUT_TIMERS);
|
||||
}
|
||||
return pMrcpMessage;
|
||||
}
|
||||
|
||||
FILE* VerifierSession::GetAudioIn(const mpf_codec_descriptor_t* pDescriptor, apr_pool_t* pool) const
|
||||
{
|
||||
const VerifierScenario* pScenario = GetScenario();
|
||||
const char* pVoiceprintIdentifier = pScenario->GetVoiceprintIdentifier();
|
||||
if(!pVoiceprintIdentifier)
|
||||
{
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No Voiceprint Specified");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* pFileName = apr_psprintf(pool,"%s-%dkHz.pcm",
|
||||
pVoiceprintIdentifier,
|
||||
pDescriptor ? pDescriptor->sampling_rate/1000 : 8);
|
||||
apt_dir_layout_t* pDirLayout = pScenario->GetDirLayout();
|
||||
const char* pFilePath = apt_datadir_filepath_get(pDirLayout,pFileName,pool);
|
||||
if(!pFilePath)
|
||||
return NULL;
|
||||
|
||||
FILE* pFile = fopen(pFilePath,"rb");
|
||||
if(!pFile)
|
||||
{
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Cannot Find [%s]",pFilePath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Set [%s] as Speech Source",pFilePath);
|
||||
return pFile;
|
||||
}
|
||||
Reference in new issue
Block a user