precoded file support and sample announcement application

git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@820 8eb893ce-cfd4-0310-b710-fb5ebe64c474
sayer/1.4-spce2.6
Stefan Sayer 19 years ago
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…
Cancel
Save