?? ilbc.c
字號:
/* $Id: ilbc.c 974 2007-02-19 01:13:53Z bennylp $ */
/*
* Copyright (C)2003-2007 Benny Prijono <benny@prijono.org>
*
* This program 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.
*
* This program 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 <pjmedia-codec/ilbc.h>
#include <pjmedia-codec/types.h>
#include <pjmedia/codec.h>
#include <pjmedia/errno.h>
#include <pjmedia/endpoint.h>
#include <pjmedia/plc.h>
#include <pjmedia/port.h>
#include <pjmedia/silencedet.h>
#include <pj/assert.h>
#include <pj/log.h>
#include <pj/pool.h>
#include <pj/string.h>
#include <pj/os.h>
#include "ilbc/iLBC_encode.h"
#include "ilbc/iLBC_decode.h"
/*
* Only build this file if PJMEDIA_HAS_ILBC_CODEC != 0
*/
#if defined(PJMEDIA_HAS_ILBC_CODEC) && PJMEDIA_HAS_ILBC_CODEC != 0
#define THIS_FILE "ilbc.c"
#define CLOCK_RATE 8000
#define DEFAULT_MODE 30
/* Prototypes for iLBC factory */
static pj_status_t ilbc_test_alloc(pjmedia_codec_factory *factory,
const pjmedia_codec_info *id );
static pj_status_t ilbc_default_attr(pjmedia_codec_factory *factory,
const pjmedia_codec_info *id,
pjmedia_codec_param *attr );
static pj_status_t ilbc_enum_codecs(pjmedia_codec_factory *factory,
unsigned *count,
pjmedia_codec_info codecs[]);
static pj_status_t ilbc_alloc_codec(pjmedia_codec_factory *factory,
const pjmedia_codec_info *id,
pjmedia_codec **p_codec);
static pj_status_t ilbc_dealloc_codec(pjmedia_codec_factory *factory,
pjmedia_codec *codec );
/* Prototypes for iLBC implementation. */
static pj_status_t ilbc_codec_init(pjmedia_codec *codec,
pj_pool_t *pool );
static pj_status_t ilbc_codec_open(pjmedia_codec *codec,
pjmedia_codec_param *attr );
static pj_status_t ilbc_codec_close(pjmedia_codec *codec );
static pj_status_t ilbc_codec_modify(pjmedia_codec *codec,
const pjmedia_codec_param *attr );
static pj_status_t ilbc_codec_parse(pjmedia_codec *codec,
void *pkt,
pj_size_t pkt_size,
const pj_timestamp *ts,
unsigned *frame_cnt,
pjmedia_frame frames[]);
static pj_status_t ilbc_codec_encode(pjmedia_codec *codec,
const struct pjmedia_frame *input,
unsigned output_buf_len,
struct pjmedia_frame *output);
static pj_status_t ilbc_codec_decode(pjmedia_codec *codec,
const struct pjmedia_frame *input,
unsigned output_buf_len,
struct pjmedia_frame *output);
static pj_status_t ilbc_codec_recover(pjmedia_codec *codec,
unsigned output_buf_len,
struct pjmedia_frame *output);
/* Definition for iLBC codec operations. */
static pjmedia_codec_op ilbc_op =
{
&ilbc_codec_init,
&ilbc_codec_open,
&ilbc_codec_close,
&ilbc_codec_modify,
&ilbc_codec_parse,
&ilbc_codec_encode,
&ilbc_codec_decode,
&ilbc_codec_recover
};
/* Definition for iLBC codec factory operations. */
static pjmedia_codec_factory_op ilbc_factory_op =
{
&ilbc_test_alloc,
&ilbc_default_attr,
&ilbc_enum_codecs,
&ilbc_alloc_codec,
&ilbc_dealloc_codec
};
/* iLBC factory */
static struct ilbc_factory
{
pjmedia_codec_factory base;
pjmedia_endpt *endpt;
int mode;
int bps;
} ilbc_factory;
/* iLBC codec private data. */
struct ilbc_codec
{
pjmedia_codec base;
pj_pool_t *pool;
char obj_name[PJ_MAX_OBJ_NAME];
pjmedia_silence_det *vad;
pj_bool_t vad_enabled;
pj_bool_t plc_enabled;
pj_timestamp last_tx;
pj_bool_t enc_ready;
iLBC_Enc_Inst_t enc;
unsigned enc_frame_size;
unsigned enc_samples_per_frame;
float enc_block[BLOCKL_MAX];
pj_bool_t dec_ready;
iLBC_Dec_Inst_t dec;
unsigned dec_frame_size;
unsigned dec_samples_per_frame;
float dec_block[BLOCKL_MAX];
};
/*
* Initialize and register iLBC codec factory to pjmedia endpoint.
*/
PJ_DEF(pj_status_t) pjmedia_codec_ilbc_init( pjmedia_endpt *endpt,
int mode )
{
pjmedia_codec_mgr *codec_mgr;
pj_status_t status;
PJ_ASSERT_RETURN(endpt != NULL, PJ_EINVAL);
PJ_ASSERT_RETURN(mode==0 || mode==20 || mode==30, PJ_EINVAL);
/* Create iLBC codec factory. */
ilbc_factory.base.op = &ilbc_factory_op;
ilbc_factory.base.factory_data = NULL;
ilbc_factory.endpt = endpt;
if (mode == 0)
mode = DEFAULT_MODE;
ilbc_factory.mode = mode;
if (mode == 20) {
ilbc_factory.bps = 15200;
} else {
ilbc_factory.bps = 13333;
}
/* Get the codec manager. */
codec_mgr = pjmedia_endpt_get_codec_mgr(endpt);
if (!codec_mgr)
return PJ_EINVALIDOP;
/* Register codec factory to endpoint. */
status = pjmedia_codec_mgr_register_factory(codec_mgr,
&ilbc_factory.base);
if (status != PJ_SUCCESS)
return status;
/* Done. */
return PJ_SUCCESS;
}
/*
* Unregister iLBC codec factory from pjmedia endpoint and deinitialize
* the iLBC codec library.
*/
PJ_DEF(pj_status_t) pjmedia_codec_ilbc_deinit(void)
{
pjmedia_codec_mgr *codec_mgr;
pj_status_t status;
/* Get the codec manager. */
codec_mgr = pjmedia_endpt_get_codec_mgr(ilbc_factory.endpt);
if (!codec_mgr)
return PJ_EINVALIDOP;
/* Unregister iLBC codec factory. */
status = pjmedia_codec_mgr_unregister_factory(codec_mgr,
&ilbc_factory.base);
return status;
}
/*
* Check if factory can allocate the specified codec.
*/
static pj_status_t ilbc_test_alloc( pjmedia_codec_factory *factory,
const pjmedia_codec_info *info )
{
const pj_str_t ilbc_tag = { "iLBC", 4};
PJ_UNUSED_ARG(factory);
PJ_ASSERT_RETURN(factory==&ilbc_factory.base, PJ_EINVAL);
/* Type MUST be audio. */
if (info->type != PJMEDIA_TYPE_AUDIO)
return PJMEDIA_CODEC_EUNSUP;
/* Check encoding name. */
if (pj_stricmp(&info->encoding_name, &ilbc_tag) != 0)
return PJMEDIA_CODEC_EUNSUP;
/* Check clock-rate */
if (info->clock_rate != CLOCK_RATE)
return PJMEDIA_CODEC_EUNSUP;
/* Channel count must be one */
if (info->channel_cnt != 1)
return PJMEDIA_CODEC_EUNSUP;
/* Yes, this should be iLBC! */
return PJ_SUCCESS;
}
/*
* Generate default attribute.
*/
static pj_status_t ilbc_default_attr (pjmedia_codec_factory *factory,
const pjmedia_codec_info *id,
pjmedia_codec_param *attr )
{
PJ_UNUSED_ARG(factory);
PJ_ASSERT_RETURN(factory==&ilbc_factory.base, PJ_EINVAL);
PJ_UNUSED_ARG(id);
PJ_ASSERT_RETURN(pj_stricmp2(&id->encoding_name, "iLBC")==0, PJ_EINVAL);
pj_bzero(attr, sizeof(pjmedia_codec_param));
attr->info.clock_rate = CLOCK_RATE;
attr->info.channel_cnt = 1;
attr->info.avg_bps = ilbc_factory.bps;
attr->info.pcm_bits_per_sample = 16;
attr->info.frm_ptime = (short)ilbc_factory.mode;
attr->info.pt = PJMEDIA_RTP_PT_ILBC;
attr->setting.frm_per_pkt = 1;
attr->setting.vad = 1;
attr->setting.plc = 1;
attr->setting.penh = 1;
attr->setting.dec_fmtp_mode = (pj_uint8_t)ilbc_factory.mode;
return PJ_SUCCESS;
}
/*
* Enum codecs supported by this factory (i.e. only iLBC!).
*/
static pj_status_t ilbc_enum_codecs(pjmedia_codec_factory *factory,
unsigned *count,
pjmedia_codec_info codecs[])
{
PJ_UNUSED_ARG(factory);
PJ_ASSERT_RETURN(factory==&ilbc_factory.base, PJ_EINVAL);
PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);
pj_bzero(&codecs[0], sizeof(pjmedia_codec_info));
codecs[0].encoding_name = pj_str("iLBC");
codecs[0].pt = PJMEDIA_RTP_PT_ILBC;
codecs[0].type = PJMEDIA_TYPE_AUDIO;
codecs[0].clock_rate = 8000;
codecs[0].channel_cnt = 1;
*count = 1;
return PJ_SUCCESS;
}
/*
* Allocate a new iLBC codec instance.
*/
static pj_status_t ilbc_alloc_codec(pjmedia_codec_factory *factory,
const pjmedia_codec_info *id,
pjmedia_codec **p_codec)
{
pj_pool_t *pool;
struct ilbc_codec *codec;
PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
PJ_ASSERT_RETURN(factory == &ilbc_factory.base, PJ_EINVAL);
pool = pjmedia_endpt_create_pool(ilbc_factory.endpt, "iLBC%p",
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -