mirror of https://github.com/sipwise/sems.git
git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@820 8eb893ce-cfd4-0310-b710-fb5ebe64c474sayer/1.4-spce2.6
parent
ec59caa0f6
commit
9152aad8ff
@ -0,0 +1,7 @@
|
||||
plug_in_name = precoded_announce
|
||||
|
||||
module_ldflags =
|
||||
module_cflags = -DMOD_NAME=\"$(plug_in_name)\"
|
||||
|
||||
COREPATH ?=../../core
|
||||
include $(COREPATH)/plug-in/Makefile.app_module
|
||||
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* $Id: AmUtils.h 744 2008-02-21 18:40:01Z sayer $
|
||||
*
|
||||
* Copyright (C) 2008 iptego GmbH
|
||||
*
|
||||
* This file is part of sems, a free SIP media server.
|
||||
*
|
||||
* sems is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version
|
||||
*
|
||||
* For a license to use the ser software under conditions
|
||||
* other than those described here, or to purchase support for this
|
||||
* software, please contact iptel.org by e-mail at the following addresses:
|
||||
* info@iptel.org
|
||||
*
|
||||
* sems is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "PrecodedAnnounce.h"
|
||||
|
||||
#include "log.h"
|
||||
#include "AmConfigReader.h"
|
||||
#include "AmUtils.h"
|
||||
|
||||
EXPORT_SESSION_FACTORY(PrecodedFactory,MOD_NAME);
|
||||
|
||||
PrecodedFactory::PrecodedFactory(const string& _app_name)
|
||||
: AmSessionFactory(_app_name)
|
||||
{
|
||||
}
|
||||
|
||||
int PrecodedFactory::onLoad()
|
||||
{
|
||||
AmConfigReader cfg;
|
||||
if(cfg.loadFile(AmConfig::ModConfigPath + string(MOD_NAME ".conf")))
|
||||
return -1;
|
||||
|
||||
if (precoded_file.open(cfg.getParameter("announcement_file")) < 0) {
|
||||
ERROR("loading precoded file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
AmPrecodedFile::initPrecodedCodec();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
AmSession* PrecodedFactory::onInvite(const AmSipRequest& req)
|
||||
{
|
||||
return new PrecodedDialog(&precoded_file);
|
||||
}
|
||||
|
||||
PrecodedDialog::PrecodedDialog(AmPrecodedFile* file_def)
|
||||
: file_def(file_def)
|
||||
{
|
||||
}
|
||||
|
||||
PrecodedDialog::~PrecodedDialog()
|
||||
{
|
||||
}
|
||||
|
||||
AmPayloadProviderInterface* PrecodedDialog::getPayloadProvider() {
|
||||
return file_def;
|
||||
}
|
||||
|
||||
void PrecodedDialog::onSessionStart(const AmSipRequest& req)
|
||||
{
|
||||
|
||||
AmPrecodedFileInstance* file = file_def->getFileInstance(rtp_str.getCurrentPayload(),
|
||||
m_payloads);
|
||||
if (!file || file->open())
|
||||
throw string("PrecodedDialog::onSessionStart: Cannot open file\n");
|
||||
|
||||
rtp_str.setFormat(file->getRtpFormat());
|
||||
|
||||
setOutput(file);
|
||||
setReceiving(false);
|
||||
}
|
||||
|
||||
void PrecodedDialog::onBye(const AmSipRequest& req)
|
||||
{
|
||||
DBG("onBye: stopSession\n");
|
||||
setStopped();
|
||||
}
|
||||
|
||||
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* $Id: AmUtils.h 744 2008-02-21 18:40:01Z sayer $
|
||||
*
|
||||
* Copyright (C) 2008 iptego GmbH
|
||||
*
|
||||
* This file is part of sems, a free SIP media server.
|
||||
*
|
||||
* sems is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version
|
||||
*
|
||||
* For a license to use the ser software under conditions
|
||||
* other than those described here, or to purchase support for this
|
||||
* software, please contact iptel.org by e-mail at the following addresses:
|
||||
* info@iptel.org
|
||||
*
|
||||
* sems is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _PRECODEDANNOUNCEAPP_H_
|
||||
#define _PRECODEDANNOUNCEAPP_H_
|
||||
|
||||
#include "AmSession.h"
|
||||
#include "AmPrecodedFile.h"
|
||||
|
||||
#include <string>
|
||||
using std::string;
|
||||
|
||||
class PrecodedFactory: public AmSessionFactory
|
||||
{
|
||||
public:
|
||||
AmPrecodedFile precoded_file;
|
||||
|
||||
PrecodedFactory(const string& _app_name);
|
||||
|
||||
int onLoad();
|
||||
AmSession* onInvite(const AmSipRequest& req);
|
||||
};
|
||||
|
||||
class PrecodedDialog : public AmSession
|
||||
{
|
||||
|
||||
AmPrecodedFile* file_def;
|
||||
|
||||
public:
|
||||
PrecodedDialog(AmPrecodedFile* file_def);
|
||||
~PrecodedDialog();
|
||||
|
||||
void onSessionStart(const AmSipRequest& req);
|
||||
void onBye(const AmSipRequest& req);
|
||||
|
||||
AmPayloadProviderInterface* getPayloadProvider();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
# file played (predef definition file only, which references
|
||||
# the actual audio files for the payloads)
|
||||
#
|
||||
announcement_file=/usr/local/lib/sems/audio/precoded_announce/test.predef
|
||||
@ -0,0 +1,11 @@
|
||||
# format:
|
||||
# codec id;payload name;samplerate;channels;format parameters;frame milliseconds;frame bytes;filename (full path)
|
||||
#
|
||||
#
|
||||
0;PCMU;8000;1;<none>;20;160;test8k.pcmu;
|
||||
8;PCMA;8000;1;<none>;20;160;test8k.pcma;
|
||||
96;iLBC;8000;1;<none>;30;50;test8k.ilbc30;
|
||||
97;iLBC;8000;1;mode=30;30;50;test8k.ilbc30;
|
||||
98;iLBC;8000;1;mode=20;20;33;test8k.ilbc20;
|
||||
|
||||
|
||||
@ -0,0 +1,229 @@
|
||||
/*
|
||||
* $Id: AmUtils.h 744 2008-02-21 18:40:01Z sayer $
|
||||
*
|
||||
* Copyright (C) 2008 iptego GmbH
|
||||
*
|
||||
* This file is part of sems, a free SIP media server.
|
||||
*
|
||||
* sems is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version
|
||||
*
|
||||
* For a license to use the ser software under conditions
|
||||
* other than those described here, or to purchase support for this
|
||||
* software, please contact iptel.org by e-mail at the following addresses:
|
||||
* info@iptel.org
|
||||
*
|
||||
* sems is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "AmPrecodedFile.h"
|
||||
#include "AmUtils.h"
|
||||
#include "log.h"
|
||||
#include <fstream>
|
||||
|
||||
unsigned int precoded_bytes2samples(long h_codec, unsigned int num_bytes) {
|
||||
return num_bytes;
|
||||
}
|
||||
|
||||
unsigned int precoded_samples2bytes(long h_codec, unsigned int num_samples) {
|
||||
return num_samples;
|
||||
}
|
||||
|
||||
amci_codec_t _codec_precoded = {
|
||||
PRECODED_CODEC_ID,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
precoded_bytes2samples,
|
||||
precoded_samples2bytes
|
||||
};
|
||||
|
||||
|
||||
void AmPrecodedFile::initPrecodedCodec() {
|
||||
AmPlugIn::instance()->addCodec(&_codec_precoded);
|
||||
}
|
||||
|
||||
AmPrecodedRtpFormat::AmPrecodedRtpFormat(precoded_payload_t& precoded_payload,
|
||||
const vector<SdpPayload *>& payloads)
|
||||
: AmAudioRtpFormat(payloads), precoded_payload(precoded_payload)
|
||||
{
|
||||
channels = precoded_payload.channels;
|
||||
rate = precoded_payload.sample_rate;
|
||||
// frame_size is in samples, precoded_payload.frame_size in millisec
|
||||
frame_size = precoded_payload.frame_ms * precoded_payload.sample_rate / 1000;
|
||||
// fill unused stuff
|
||||
frame_length = precoded_payload.frame_ms;
|
||||
frame_encoded_size = precoded_payload.frame_bytes;
|
||||
}
|
||||
|
||||
AmPrecodedRtpFormat::~AmPrecodedRtpFormat() {
|
||||
}
|
||||
|
||||
int AmPrecodedRtpFormat::getCodecId() {
|
||||
return PRECODED_CODEC_ID;
|
||||
}
|
||||
|
||||
|
||||
AmPrecodedFileFormat::AmPrecodedFileFormat(precoded_payload_t& precoded_payload)
|
||||
: AmAudioFileFormat(""), precoded_payload(precoded_payload) {
|
||||
subtype.type = 0;
|
||||
subtype.name = precoded_payload.name;
|
||||
subtype.sample_rate = precoded_payload.sample_rate;
|
||||
subtype.channels = precoded_payload.channels;
|
||||
subtype.codec_id = PRECODED_CODEC_ID;
|
||||
|
||||
channels = precoded_payload.channels;
|
||||
rate = precoded_payload.sample_rate;
|
||||
codec = getCodec();
|
||||
}
|
||||
|
||||
AmPrecodedFileFormat::~AmPrecodedFileFormat() {
|
||||
}
|
||||
|
||||
int AmPrecodedFileFormat::getCodecId() {
|
||||
return PRECODED_CODEC_ID;
|
||||
}
|
||||
|
||||
int precoded_file_open(FILE* fp, struct amci_file_desc_t* fmt_desc, int options, long h_codec)
|
||||
{
|
||||
fseek (fp, 0, SEEK_END);
|
||||
fmt_desc->data_size=ftell (fp);
|
||||
rewind(fp);
|
||||
DBG("file opened, size = %d\n", fmt_desc->data_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int precoded_file_close(FILE* fp, struct amci_file_desc_t* fmt_desc, int options,
|
||||
long h_codec, struct amci_codec_t *codec)
|
||||
{
|
||||
DBG("file closed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
AmPrecodedFileInstance::AmPrecodedFileInstance(precoded_payload_t& precoded_payload,
|
||||
const vector<SdpPayload*>& payloads)
|
||||
: precoded_payload(precoded_payload), payloads(payloads)
|
||||
{
|
||||
memset(&m_iofmt, 0, sizeof(amci_inoutfmt_t));
|
||||
m_iofmt.open = &precoded_file_open;
|
||||
m_iofmt.on_close = &precoded_file_close;
|
||||
iofmt = &m_iofmt;
|
||||
}
|
||||
|
||||
AmPrecodedFileInstance::~AmPrecodedFileInstance(){
|
||||
}
|
||||
|
||||
AmAudioFileFormat* AmPrecodedFileInstance::fileName2Fmt(const string& name) {
|
||||
return new AmPrecodedFileFormat(precoded_payload);
|
||||
}
|
||||
|
||||
int AmPrecodedFileInstance::open() {
|
||||
return AmAudioFile::open(precoded_payload.filename, AmAudioFile::Read);
|
||||
}
|
||||
|
||||
AmPrecodedRtpFormat* AmPrecodedFileInstance::getRtpFormat() {
|
||||
return new AmPrecodedRtpFormat(precoded_payload, payloads);
|
||||
}
|
||||
|
||||
AmPrecodedFile::AmPrecodedFile()
|
||||
{
|
||||
}
|
||||
|
||||
AmPrecodedFile::~AmPrecodedFile() {
|
||||
}
|
||||
|
||||
int AmPrecodedFile::open(std::string filename) {
|
||||
std::ifstream ifs(filename.c_str());
|
||||
if (!ifs.good()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (ifs.good() && !ifs.eof()) {
|
||||
string codec_line;
|
||||
getline(ifs, codec_line);
|
||||
if (!codec_line.length() || codec_line[0]=='#')
|
||||
continue;
|
||||
|
||||
vector<string> codec_def = explode(codec_line, ";");
|
||||
if (codec_def.size() != 8) {
|
||||
ERROR("unable to decipher codec line '%s'\n",
|
||||
codec_line.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
precoded_payload_t pl;
|
||||
|
||||
#define get_uint_item(name, index, description) \
|
||||
unsigned int name; \
|
||||
if (str2i(codec_def[index], name)) { \
|
||||
ERROR("decoding " description " in codec line '%s'\n", \
|
||||
codec_line.c_str()); \
|
||||
continue; \
|
||||
} \
|
||||
pl.name = name;
|
||||
|
||||
get_uint_item(payload_id, 0, "payload_id");
|
||||
pl.c_name = codec_def[1];
|
||||
pl.name = pl.c_name.c_str();
|
||||
get_uint_item(sample_rate, 2, "sample_rate");
|
||||
get_uint_item(channels, 3, "channels");
|
||||
pl.format_parameters = codec_def[4];
|
||||
get_uint_item(frame_ms, 5, "frame ms");
|
||||
get_uint_item(frame_bytes, 6, "frame bytes");
|
||||
pl.filename=codec_def[7];
|
||||
#undef get_uint_item
|
||||
|
||||
DBG("inserting codec '%s' file '%s' and id %d\n",
|
||||
pl.name, pl.filename.c_str(), pl.payload_id);
|
||||
payloads[pl.payload_id]=pl;
|
||||
}
|
||||
|
||||
return 0; // OK
|
||||
}
|
||||
|
||||
amci_payload_t* AmPrecodedFile::payload(int payload_id) {
|
||||
std::map<int,precoded_payload_t>::iterator it =
|
||||
payloads.find(payload_id);
|
||||
|
||||
if(it != payloads.end())
|
||||
return &it->second;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int AmPrecodedFile::getDynPayload(const string& name, int rate, int encoding_param) {
|
||||
// find a dynamic payload by name/rate and encoding_param (channels, if > 0)
|
||||
for(std::map<int, precoded_payload_t>::const_iterator pl_it = payloads.begin();
|
||||
pl_it != payloads.end(); ++pl_it)
|
||||
if( (name == pl_it->second.name)
|
||||
&& (rate == pl_it->second.sample_rate) ) {
|
||||
if ((encoding_param > 0) && (pl_it->second.channels > 0) &&
|
||||
(encoding_param != pl_it->second.channels))
|
||||
continue;
|
||||
|
||||
return pl_it->first;
|
||||
}
|
||||
|
||||
// not found
|
||||
return -1;
|
||||
}
|
||||
|
||||
AmPrecodedFileInstance* AmPrecodedFile::getFileInstance(int payload_id,
|
||||
const vector<SdpPayload*>& m_payloads) {
|
||||
std::map<int,precoded_payload_t>::iterator it=payloads.find(payload_id);
|
||||
if (it != payloads.end())
|
||||
return new AmPrecodedFileInstance(it->second, m_payloads);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* $Id: AmUtils.h 744 2008-02-21 18:40:01Z sayer $
|
||||
*
|
||||
* Copyright (C) 2008 iptego GmbH
|
||||
*
|
||||
* This file is part of sems, a free SIP media server.
|
||||
*
|
||||
* sems is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version
|
||||
*
|
||||
* For a license to use the ser software under conditions
|
||||
* other than those described here, or to purchase support for this
|
||||
* software, please contact iptel.org by e-mail at the following addresses:
|
||||
* info@iptel.org
|
||||
*
|
||||
* sems is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _AmPrecodedFile_H
|
||||
#define _AmPrecodedFile_H
|
||||
|
||||
#include "AmPlugIn.h"
|
||||
#include "AmSdp.h"
|
||||
#include "amci/amci.h"
|
||||
#include "AmAudioFile.h"
|
||||
#include "AmAudio.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#define PRECODED_CODEC_ID 100 // could go into amci/codecs.h
|
||||
|
||||
struct precoded_payload_t : public amci_payload_t {
|
||||
public:
|
||||
string c_name;
|
||||
string format_parameters;
|
||||
unsigned int frame_ms;
|
||||
unsigned int frame_bytes;
|
||||
string filename;
|
||||
};
|
||||
|
||||
class AmPrecodedFileFormat : public AmAudioFileFormat {
|
||||
|
||||
precoded_payload_t& precoded_payload;
|
||||
amci_subtype_t subtype;
|
||||
|
||||
public:
|
||||
AmPrecodedFileFormat(precoded_payload_t& precoded_payload);
|
||||
~AmPrecodedFileFormat();
|
||||
amci_subtype_t* getSubtype() { return &subtype; }
|
||||
|
||||
protected:
|
||||
virtual int getCodecId();
|
||||
};
|
||||
|
||||
class AmPrecodedRtpFormat : public AmAudioRtpFormat {
|
||||
precoded_payload_t& precoded_payload;
|
||||
|
||||
public:
|
||||
AmPrecodedRtpFormat(precoded_payload_t& precoded_payload,
|
||||
const vector<SdpPayload *>& payloads);
|
||||
~AmPrecodedRtpFormat();
|
||||
|
||||
protected:
|
||||
int getCodecId();
|
||||
};
|
||||
|
||||
class AmPrecodedFileInstance
|
||||
: public AmAudioFile {
|
||||
|
||||
precoded_payload_t& precoded_payload;
|
||||
const vector<SdpPayload*>& payloads;
|
||||
amci_inoutfmt_t m_iofmt;
|
||||
|
||||
public:
|
||||
AmPrecodedFileInstance(precoded_payload_t& precoded_payload,
|
||||
const vector<SdpPayload*>& payloads);
|
||||
~AmPrecodedFileInstance();
|
||||
|
||||
AmPrecodedRtpFormat* getRtpFormat();
|
||||
|
||||
int open();
|
||||
|
||||
protected:
|
||||
AmAudioFileFormat* fileName2Fmt(const string& name);
|
||||
};
|
||||
|
||||
class AmPrecodedFile
|
||||
: public AmPayloadProviderInterface {
|
||||
|
||||
std::map<int,precoded_payload_t> payloads;
|
||||
|
||||
public:
|
||||
AmPrecodedFile();
|
||||
~AmPrecodedFile();
|
||||
static void initPrecodedCodec();
|
||||
|
||||
int open(std::string filename);
|
||||
|
||||
amci_payload_t* payload(int payload_id);
|
||||
int getDynPayload(const string& name, int rate, int encoding_param);
|
||||
|
||||
AmPrecodedFileInstance* getFileInstance(int payload_id, const vector<SdpPayload*>& m_payloads);
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Reference in new issue