//
|
// Created by lilin on 2019-12-10.
|
//
|
|
#include "BaresipObj.h"
|
|
BaresipObj::BaresipObj(JavaListener *javaListener) {
|
this->javaListener = javaListener;
|
|
}
|
|
BaresipObj::~BaresipObj() {
|
|
}
|
static void dtmf_handler(struct call *call, char key, void *arg){
|
LOGE("收到key=%c",key);
|
}
|
static void ua_exit_handler(void *arg)
|
{
|
(void)arg;
|
LOGD("ua exited -- stopping main runloop\n");
|
re_cancel();
|
}
|
static void ua_event_handler( ua *ua, enum ua_event ev,
|
struct call *call, const char *prm, void *arg)
|
{
|
|
player *player = baresip_player();
|
BaresipObj *baresip = (BaresipObj *)(arg);
|
|
const char * str= uag_event_str(ev);
|
LOGE( "event_str==%s" ,str);
|
baresip->javaListener->onBaresipState( str);
|
switch (ev) {
|
case UA_EVENT_REGISTERING:
|
case UA_EVENT_UNREGISTERING:
|
case UA_EVENT_REGISTER_OK:
|
if(ev==UA_EVENT_REGISTER_OK){
|
char codec[100]="";
|
list * a= baresip_aucodecl(); struct le *le;int num=0;
|
for (le = list_head(a); num<list_count(a) ; le = le->next){
|
aucodec *ac =(aucodec *) le->data;
|
strcat(codec,ac->name);strcat(codec,",");num++;
|
}
|
strcat(codec,"=");
|
list * c = baresip_vidcodecl();num=0;
|
for (le = list_head(c); num<list_count(c) ; le = le->next) {
|
vidcodec *ac = (vidcodec *)le->data;
|
strcat(codec,ac->name);strcat(codec,",");num++;
|
}
|
baresip->javaListener->onBaresipCodec( codec);
|
}
|
|
break;
|
case UA_EVENT_REGISTER_FAIL:
|
|
break;
|
case UA_EVENT_CALL_INCOMING:
|
baresip->barecall=call;
|
(void)play_file(&baresip->bareplay, player, "ring.wav", 5);
|
|
break;
|
case UA_EVENT_CALL_RINGING:
|
|
break;
|
case UA_EVENT_CALL_PROGRESS:
|
|
break;
|
case UA_EVENT_CALL_ESTABLISHED:
|
mem_deref(baresip->bareplay); baresip->bareplay =NULL;
|
LOGE("收到set key=");
|
//call_set_handlers( call, NULL, dtmf_handler, NULL);
|
break;
|
case UA_EVENT_CALL_MENC:
|
|
break;
|
case UA_EVENT_CALL_TRANSFER:
|
|
break;
|
case UA_EVENT_CALL_TRANSFER_FAILED:
|
|
break;
|
case UA_EVENT_CALL_CLOSED:
|
mem_deref(baresip->bareplay); baresip->bareplay =NULL;
|
baresip->javaListener->onBaresipVstop();
|
baresip->barecall= NULL;
|
break;
|
case UA_EVENT_AUDIO_ERROR:
|
mem_deref(call); baresip->barecall= NULL;
|
goto out;
|
default:
|
goto out;
|
}
|
|
out:
|
return;
|
}
|
static void net_debug_log() {
|
char debug_buf[2048];
|
int l;
|
l = re_snprintf(&(debug_buf[0]), 2047, "%H", net_debug, baresip_network());
|
if (l != -1) {
|
debug_buf[l] = '\0';
|
LOGD("1.%s\n", debug_buf);
|
}
|
}
|
|
static void ua_print_sip_status_log() {
|
char debug_buf[2048];
|
int l;
|
l = re_snprintf(&(debug_buf[0]), 2047, "%H", ua_print_sip_status);
|
if (l != -1) {
|
debug_buf[l] = '\0';
|
LOGD("2.%s\n", debug_buf);
|
}
|
}
|
////////////////////////
|
|
struct vidsrc_st {
|
const struct vidsrc *vs; /* inheritance */
|
pthread_t thread;
|
bool run;
|
struct vidsz sz;
|
vidsrc_frame_h *frameh;
|
void *arg;
|
FrameQueue *frameQueue=NULL;
|
};
|
BaresipObj *xbaresipObj=NULL;
|
|
static struct vidsrc *mod_avf;
|
|
static void destructorsrc(void *arg)
|
{
|
vidsrc_st *st = (vidsrc_st *)arg;
|
st->frameQueue->notifyQueue();
|
st->frameQueue->clearQueue();
|
st->frameQueue=NULL;
|
if (st->run) {
|
st->run = false;
|
pthread_join(st->thread, NULL);
|
}
|
}
|
|
static void *read_thread(void *data)
|
{
|
struct vidsrc_st *st =(struct vidsrc_st *) data;
|
int64_t pts;
|
uint64_t timestamp; unsigned i;
|
while (st->run) {
|
if( st->frameQueue==NULL ){ break;}
|
AVFrame *frame=st->frameQueue->getAvFrame();
|
if( frame==NULL ){ continue;}
|
struct vidframe vf;
|
vf.fmt =VID_FMT_YUV420P;
|
st->sz.w=frame->width ;st->sz.h=frame->height;
|
vf.size =st->sz;
|
for (i=0; i<4; i++) {
|
vf.data[i] = frame->data[i];
|
vf.linesize[i] = frame->linesize[i];
|
}
|
pts = frame->pts;
|
timestamp = pts * VIDEO_TIMEBASE * 1 / 25;
|
// LOGE("当前pts==%lld",pts);
|
st->frameh(&vf, timestamp, st->arg);
|
|
if (frame) {
|
av_frame_free(&frame);
|
}
|
}
|
LOGE("停止");
|
return NULL;
|
}
|
|
static int allocsrc(struct vidsrc_st **stp, const struct vidsrc *vs,
|
struct media_ctx **mctx, struct vidsrc_prm *prm,
|
const struct vidsz *size, const char *fmt,
|
const char *dev, vidsrc_frame_h *frameh,
|
vidsrc_error_h *errorh, void *arg)
|
{
|
vidsrc_st *st;
|
uint32_t i;
|
int ret, err = 0;
|
double input_fps = 0;
|
|
(void)mctx;
|
(void)fmt;
|
(void)errorh;
|
|
if (!stp || !vs || !prm || !size || !frameh)
|
return EINVAL;
|
|
st = static_cast<vidsrc_st *>(mem_zalloc(sizeof(*st), destructorsrc));
|
if (!st)
|
return ENOMEM;
|
if(xbaresipObj->frameQueue==NULL){xbaresipObj->frameQueue = new FrameQueue();}
|
|
//需要发送开始send
|
st->frameQueue= xbaresipObj->frameQueue;
|
st->vs = vs;
|
st->sz = *size;
|
st->frameh = frameh;
|
st->arg = arg;
|
|
st->sz.w =640;
|
st->sz.h =480;
|
|
st->run = true;
|
err = pthread_create(&st->thread, NULL, read_thread, st);
|
if (err) {
|
st->run = false;
|
goto out;
|
}
|
//set
|
//g_ctx.st=st;
|
out:
|
if (err)
|
mem_deref(st);
|
else
|
*stp = st;
|
|
return err;
|
}
|
struct vidisp_st {
|
const struct vidisp *vd; /**< Inheritance (1st) */
|
struct vidsz size;
|
};
|
static struct vidisp *vid;
|
static int display(struct vidisp_st *st, const char *title, const struct vidframe *frame, uint64_t timestamp)
|
{
|
AVFrame *avFrame = av_frame_alloc();
|
for (int i=0; i<4; i++) {
|
avFrame->data[i]=frame->data[i] ;
|
avFrame->linesize[i]=frame->linesize[i] ;
|
}
|
int width=frame->size.w,height=frame->size.h;
|
|
uint8_t *t= avFrame->data[0];
|
|
xbaresipObj->javaListener->onBaresipVyuv( width,height,avFrame->data[0],avFrame->data[1],avFrame->data[2]);
|
|
av_frame_free(&avFrame);
|
av_free(avFrame);
|
avFrame=NULL;
|
|
return 0;
|
}
|
static void hide(struct vidisp_st *st) {
|
if (!st)
|
return;
|
}
|
static void destructordispl(void *arg)
|
{
|
}
|
static int allocdispl(struct vidisp_st **stp, const struct vidisp *vd,
|
struct vidisp_prm *prm, const char *dev,
|
vidisp_resize_h *resizeh, void *arg)
|
{
|
struct vidisp_st *st;
|
st = static_cast<vidisp_st *>(mem_zalloc(sizeof(*st), destructordispl));
|
if (!st)
|
return ENOMEM;
|
st->vd = vd;
|
*stp = st;
|
return 0;
|
}
|
|
////////////729////////////////
|
|
struct g729_aucodec {
|
struct aucodec ac;
|
uint32_t bitrate;
|
};
|
int g729_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt,
|
bool offer, void *arg)
|
{
|
const struct g729_aucodec *g729 = static_cast<const g729_aucodec *>(arg);
|
(void)offer;
|
|
if (!mb || !fmt || !g729)
|
return 0;
|
return mbuf_printf(mb, "a=fmtp:%s bitrate=%u\r\n", fmt->id, g729->bitrate);
|
}
|
|
static uint32_t g729_bitrate(const char *fmtp)
|
{
|
struct pl pl, bitrate;
|
|
if (!fmtp)
|
return 0;
|
|
pl_set_str(&pl, fmtp);
|
|
if (fmt_param_get(&pl, "bitrate", &bitrate))
|
return pl_u32(&bitrate);
|
return 0;
|
}
|
|
bool g729_fmtp_cmp(const char *lfmtp, const char *rfmtp, void *arg)
|
{
|
const struct g729_aucodec *g729 = static_cast<const g729_aucodec *>(arg);
|
(void)lfmtp;
|
if (!g729)
|
return false;
|
if (g729->bitrate != g729_bitrate(rfmtp))
|
return false;
|
|
return true;
|
}
|
|
|
struct auenc_state {
|
bcg729EncoderChannelContextStruct *encoder;
|
|
};
|
|
static void g729_encode_updatedestructor(void *arg)
|
{
|
struct auenc_state *aes = static_cast<auenc_state *>(arg);
|
closeBcg729EncoderChannel(aes->encoder);
|
}
|
int g729_encode_update(struct auenc_state **aesp, const struct aucodec *ac,
|
struct auenc_param *prm, const char *fmtp)
|
{
|
struct auenc_state *aes;
|
(void)prm;
|
(void)fmtp;
|
|
if (!aesp || !ac)
|
return EINVAL;
|
|
aes = *aesp;
|
|
if (aes)
|
return 0;
|
|
aes = static_cast<auenc_state *>(mem_alloc(sizeof(*aes), g729_encode_updatedestructor));
|
if (!aes)
|
return ENOMEM;
|
aes->encoder = initBcg729EncoderChannel(0);
|
|
*aesp = aes;
|
LOGE("729编码init1");
|
return 0;
|
}
|
|
|
int g729_encode1(struct auenc_state *aes, uint8_t *buf, size_t *len,
|
int fmt, const void *sampv, size_t sampc)
|
{
|
|
if (!aes || !buf || !len || !sampv)
|
return EINVAL;
|
int16_t *ddp = (int16_t *) sampv;
|
uint8_t *edp = buf;
|
int total_len = 0;
|
while (sampc >= 80) {
|
uint8_t frameSize;
|
bcg729Encoder(aes->encoder, ddp, edp, &frameSize);
|
ddp += 80;
|
sampc -= 80;
|
edp += frameSize;
|
total_len += frameSize;
|
}
|
*len = total_len;
|
|
return 0;
|
}
|
|
struct audec_state {
|
bcg729DecoderChannelContextStruct *decoder;
|
};
|
static void g729_decode_updatedestructor(void *arg)
|
{
|
struct audec_state *ads = static_cast<audec_state *>(arg);
|
closeBcg729DecoderChannel(ads->decoder);
|
}
|
int g729_decode_update(struct audec_state **adsp, const struct aucodec *ac,
|
const char *fmtp)
|
{
|
//const struct g729_aucodec *g729 = (struct g729_aucodec *)ac;
|
struct audec_state *ads;
|
(void)fmtp;
|
|
if (!adsp || !ac)
|
return EINVAL;
|
|
ads = *adsp;
|
|
if (ads)
|
return 0;
|
|
ads = static_cast<audec_state *>(mem_alloc(sizeof(*ads), g729_decode_updatedestructor));
|
if (!ads)
|
return ENOMEM;
|
|
ads->decoder = initBcg729DecoderChannel( );
|
|
*adsp = ads;
|
|
return 0;
|
}
|
|
|
int g729_decode1(struct audec_state *ads,
|
int fmt, void *sampv, size_t *sampc,
|
const uint8_t *buf, size_t len)
|
{
|
//size_t framec;
|
|
if (!ads || !sampv || !sampc || !buf)
|
return EINVAL;
|
|
|
int total_sampc = 0;
|
int16_t *ddp = (int16_t *) sampv;
|
LOGE("====%d",len);
|
while (len >= 10) {
|
bcg729Decoder(ads->decoder, const_cast<uint8_t *>(buf), 10, 0, 0, 0, ddp ) ;
|
buf += 10;
|
len -= 10;
|
ddp += 80;
|
total_sampc += 80;
|
}
|
*sampc = total_sampc;
|
|
return 0;
|
}
|
|
static struct g729_aucodec g729 = {
|
.ac = {
|
.le=LE_INIT,
|
.pt="18",
|
.name = "G729",
|
.srate = 8000,
|
.crate = 8000,
|
.ch = 1,
|
.pch = 1,
|
.encupdh = g729_encode_update,
|
.ench = g729_encode1,
|
.decupdh = g729_decode_update,
|
.dech = g729_decode1,
|
.fmtp_ench = g729_fmtp_enc,
|
.fmtp_cmph = g729_fmtp_cmp,
|
},
|
.bitrate = 8000
|
};
|
/////snd/////
|
////////////////////////////
|
|
struct sndfile_enc {
|
struct aufilt_enc_st af; /* base class */
|
enum aufmt fmt;
|
FILE *file = NULL;
|
};
|
|
struct sndfile_dec {
|
struct aufilt_dec_st af; /* base class */
|
enum aufmt fmt;
|
FILE *file = NULL;
|
};
|
static void enc_destructor(void *arg)
|
{
|
struct sndfile_enc *st = static_cast<sndfile_enc *>(arg);
|
fclose(st->file);LOGE("关闭文件");
|
list_unlink(&st->af.le);
|
}
|
|
|
static void dec_destructor(void *arg)
|
{
|
struct sndfile_dec *st = static_cast<sndfile_dec *>(arg);
|
// fclose(st->file);LOGE("关闭文件");
|
list_unlink(&st->af.le);
|
}
|
|
static int encodeaudio_update(struct aufilt_enc_st **stp, void **ctx,
|
const struct aufilt *af, struct aufilt_prm *prm,
|
const struct audio *au)
|
{
|
struct sndfile_enc *st;
|
int err = 0;
|
(void)ctx;
|
(void)af;
|
(void)au;
|
|
if (!stp || !prm)
|
return EINVAL;
|
|
st = static_cast<sndfile_enc *>(mem_zalloc(sizeof(*st), enc_destructor));
|
if (!st)
|
return EINVAL;
|
st->file=fopen("/data/data/lilin.com/files/2.pcm","wb");
|
st->fmt = static_cast<aufmt>(prm->fmt);
|
if(st->fmt==AUFMT_S16LE ){
|
LOGE( "====ok lalal =%d=%d",prm->srate , prm->ch);
|
}
|
|
*stp = (struct aufilt_enc_st *)st;
|
|
return err;
|
}
|
static int encodeaudio(struct aufilt_enc_st *st, void *sampv, size_t *sampc)
|
{
|
struct sndfile_enc *sf = (struct sndfile_enc *)st;
|
size_t num_bytes;
|
|
if (!st || !sampv || !sampc)
|
return EINVAL;
|
|
// num_bytes = *sampc * aufmt_sample_size(sf->fmt);
|
LOGE("编码写");
|
fwrite(sampv, *sampc, aufmt_sample_size(sf->fmt) ,sf->file);
|
// LOGE("encodeaudio=%d", num_bytes);
|
|
return 0;
|
}
|
|
static int decodeaudio_update(struct aufilt_dec_st **stp, void **ctx,
|
const struct aufilt *af, struct aufilt_prm *prm,
|
const struct audio *au)
|
{
|
struct sndfile_dec *st;
|
int err = 0;
|
(void)ctx;
|
(void)af;
|
(void)au;
|
|
if (!stp || !prm)
|
return EINVAL;
|
|
st = static_cast<sndfile_dec *>(mem_zalloc(sizeof(*st), dec_destructor));
|
if (!st)
|
return EINVAL;
|
|
//st->file=fopen("/data/data/lilin.com/files/1.pcm","wb");
|
|
st->fmt = static_cast<aufmt>(prm->fmt);
|
if(st->fmt==AUFMT_S16LE ){
|
LOGE( "====ok lalal =%d=%d",prm->srate , prm->ch);
|
}
|
|
*stp = (struct aufilt_dec_st *)st;
|
|
return err;
|
}
|
static int decodeaudio(struct aufilt_dec_st *st, void *sampv, size_t *sampc)
|
{
|
struct sndfile_dec *sf = (struct sndfile_dec *)st;
|
size_t num_bytes;
|
|
if (!st || !sampv || !sampc)
|
return EINVAL;
|
|
//num_bytes = *sampc * aufmt_sample_size(sf->fmt);
|
//LOGE("解码写");
|
//fwrite(sampv, *sampc, aufmt_sample_size(sf->fmt) ,sf->file);
|
//LOGE("decodeaudio=%d", num_bytes);
|
|
return 0;
|
}
|
|
|
static struct aufilt sndfile = { LE_INIT, "sndfile", encodeaudio_update, encodeaudio, decodeaudio_update, decodeaudio };
|
|
/////
|
|
static void signal_handler(int sig)
|
{
|
static bool term = false;
|
if (term) {
|
mod_close();
|
exit(0);
|
}
|
term = true;
|
LOGD("liili terminated by signal (%d)\n", sig);
|
ua_stop_all(false);
|
}
|
void *baresipthreadrun(void *arg){
|
|
BaresipObj *baresipobj = (BaresipObj *)(arg);
|
|
avdevice_register_all();
|
avformat_network_init();
|
|
int err;
|
const char *path = "/data/data/lilin.com/files";
|
|
//runLoggingThread();
|
|
err = libre_init();
|
if (err)
|
goto out;
|
conf_path_set(path);
|
log_enable_debug(true);
|
err = conf_configure();
|
if (err) {
|
LOGD("conf_configure() failed: (%d)\n", err);
|
goto out;
|
}
|
|
err = baresip_init(conf_config());
|
if (err) {
|
LOGD("baresip_init() failed (%d)\n", err);
|
goto out;
|
}
|
|
play_set_path(baresip_player(), path);
|
|
err = ua_init("baresip v", true, true, false);
|
if (err) {
|
LOGD("ua_init() failed (%d)\n", err);
|
goto out;
|
}
|
|
uag_set_exit_handler(ua_exit_handler, NULL);
|
uag_event_register(ua_event_handler, arg);
|
|
err = conf_modules();
|
if (err) {
|
LOGE("conf_modules() failed (%d)\n", err);
|
goto out;
|
}
|
struct le *le;
|
for (le = list_head(uag_list()); le != NULL; le = le->next) {
|
baresipobj->bareua = (struct ua *)le->data;
|
}
|
|
net_debug_log();
|
ua_print_sip_status_log();
|
|
|
//reg
|
xbaresipObj=baresipobj;
|
aucodec_register(baresip_aucodecl(), (struct aucodec *)&g729);
|
vidisp_register(&vid, baresip_vidispl(), "opengl", allocdispl, NULL, display, hide);
|
vidsrc_register(&mod_avf, baresip_vidsrcl(), "avformat", allocsrc, NULL);
|
|
//aufilt_register(baresip_aufiltl(), &sndfile); 声音保存demo
|
|
baresipobj-> baresipstate=1;
|
LOGD("Running main loop\n");
|
err = re_main(signal_handler);
|
LOGD("end Running main loop\n");
|
out:
|
if (err) {
|
LOGE("stopping UAs due to error: (%d)\n", err);
|
ua_stop_all(true);
|
} else {
|
LOGE("main loop exit\n");
|
}
|
LOGD("closing");
|
ua_close();
|
module_app_unload();
|
conf_close();
|
baresip_close();
|
uag_event_unregister(ua_event_handler);
|
LOGD("unloading modules end ...");
|
// mod_close();
|
|
// libre_close();
|
return 0;
|
}
|
void BaresipObj::startbaresip() {
|
pthread_create(&baresipthread,NULL,baresipthreadrun,this);
|
}
|
void BaresipObj::stopbaresip() {
|
LOGD("unloading modules 111...");
|
ua_stop_all(true);
|
pthread_join(baresipthread ,NULL);
|
LOGD("unloading modules 222 ...");
|
//ua_close();
|
// module_app_unload();
|
//conf_close();
|
// baresip_close();
|
// mod_close();
|
//libre_close();
|
}
|
void BaresipObj::baresipreg(const char *sipaddress) {
|
re_thread_enter();
|
if(bareua!= NULL)ua_destroy(bareua);
|
int err= ua_alloc( &bareua, sipaddress);
|
ua_register(bareua);
|
re_thread_leave();
|
}
|
|
void BaresipObj::baresipjie() {
|
re_thread_enter();
|
if(barecall!=NULL){
|
mem_deref(bareplay); bareplay=NULL;
|
|
if(call_has_video(barecall) ){
|
javaListener->onBaresipVstart();
|
}
|
ua_answer(bareua, barecall );
|
}
|
re_thread_leave();
|
}
|
|
int BaresipObj::bareisreg() {
|
re_thread_enter();
|
int state =ua_isregistered(bareua)?1:0;
|
if(state==0){ ua_register(bareua);state=1; LOGE("重新注册了");}
|
re_thread_leave();
|
return state;
|
}
|
|
void BaresipObj::baresipgua() {
|
if( barecall !=nullptr ){
|
re_thread_enter();
|
ua_hangup(bareua, barecall, 0, NULL);
|
re_thread_leave();
|
}
|
}
|
|
int BaresipObj::baresipcall(const char *sipaddress) {
|
int err =-1;
|
if (list_count(ua_calls(bareua)) > 1) {
|
LOGE("YOU TONG HUA!!");return err;
|
}
|
re_thread_enter();
|
//reset
|
err= ua_connect(bareua,&barecall,NULL,sipaddress,VIDMODE_OFF);
|
|
re_thread_leave();
|
return err;
|
}
|
|
int BaresipObj::baresipcallv(const char *sipaddress) {
|
int err =-1;
|
if (list_count(ua_calls(bareua)) > 1) {
|
LOGE("YOU TONG HUA!!");return err;
|
}
|
re_thread_enter();
|
//reset
|
err= ua_connect(bareua,&barecall,NULL,sipaddress,VIDMODE_ON);
|
javaListener->onBaresipVstart();
|
re_thread_leave();
|
return err;
|
}
|
|
|