不同的分机端使用的语音编码格式各不相同,asterisk需要进行相应的转换,然后再进行语音数据的传输处理。比如fxs使用G729的语音编码,当fxs拨号呼叫sip分机时(假设该sip分机只能支持ulaw格式语音),asterisk需要把fxs收到的语音数据转换成ulaw,再发送给sip分机。若不进行转换,直接把G729格式的语音数据发送给sip分机,sip分机端就会听到杂音。同样的,asterisk需要把sip分机收到的语音数据转换成G729,再发送给fxs分机。完成一次语音交换。
目前asterisk支持的语音编解码较多,包括:G711(u/alw),G729(pcm),G722(adpcm),G726, gsm等等。一般的,压缩比高的编解码,编解码后的语音数据量比较小,利于网络传输,但语音失真就比较严重。
asterisk的语音编解码代码放置在codecs目录下,每一种编解码编写自己的.c文件,注册编码转换的结构。如:
static struct ast_translator lintog729 = {
.name ="lintog729",
.srcfmt = AST_FORMAT_SLINEAR,
.dstfmt = AST_FORMAT_G729A,
.newpvt = lintog729_new,
.framein =lintog729_framein,
.frameout =lintog729_frameout,
.destroy =lintog729_release,
.sample = lintog729_sample,
.desc_size = sizeof(structg729_coder_pvt),
.buf_size = 1000 };
该指明把源格式AST_FORMAT_SLINEAR 转换成目标格式 AST_FORMAT_G729A,
收到语音数据时调用lintog729_framein 函数
生成语音数据时调用lintog729_frameout函数
通话时,上层的调用在translate.c的ast_translate函数中。
#0 g722tolin_framein(pvt=0x9794368, f=0x94d665c)at codec_g722.c:110
#1 0x08160592 in framein (path=0x9794368, f=0x94d665c, consume=0) at translate.c:176
#2 ast_translate (path=0x9794368, f=0x94d665c, consume=0) at translate.c:322
#3 0x080a6457 in ast_write (chan=0x9788f38, fr=0x94d665c) at channel.c:3850
#4 0x080a85eein ast_generic_bridge (c0=0x94dca78, c1=0x9788f38,config=0xb6eb53e8, fo=0xb6eb50e0, rc=0xb6eb50dc) at channel.c:5331
#5 ast_channel_bridge (c0=0x94dca78, c1=0x9788f38, config=0xb6eb53e8,fo=0xb6eb50e0, rc=0xb6eb50dc) at channel.c:5669
#6 0x080cfcc8 inast_bridge_call (chan=0x94dca78, peer=0x9788f38,config=0xb6eb53e8) at features.c:3053
#7 0x00e19894 in dial_exec_full (chan=<value optimized out>,data=<value optimized out>, peerflags=0xb6eb5c68, continue_exec=0x0) at app_dial.c:2317
#8 0x00e1b21d in dial_exec (chan=0x94dca78,data=0xb6eb7f5c) at app_dial.c:2400
#9 0x08110a65 in pbx_exec (c=0x94dca78,app=0xb753da48, data=0xb6eb7f5c) at pbx.c:1359
#100x0811d857 inpbx_extension_helper (c=0x94dca78, con=<value optimized out>,context=<value optimized out>, exten=0x94dcd3c "s", priority=11, label=0x0,callerid=0x94d5d58 "500", action=E_SPAWN,
found=0xb6eba25c, combined_find_spawn=1) at pbx.c:3726
#110x008ba47d in _macro_exec (chan=0x94dca78, data=<value optimized out>,exclusive=0) at app_macro.c:398
#12 0x08110a65 in pbx_exec (c=0x94dca78, app=0xb753a160, data=0xb6ebd00c) at pbx.c:1359
#130x0811d857 inpbx_extension_helper (c=0x94dca78, con=<value optimized out>,context=<value optimized out>, exten=0x94dcd3c "s", priority=2, label=0x0,callerid=0x94d5d58 "500", action=E_SPAWN,
found=0xb6ebf30c, combined_find_spawn=1) at pbx.c:3726
#140x008ba47d in _macro_exec (chan=0x94dca78, data=<value optimized out>,exclusive=0) at app_macro.c:398
#15 0x08110a65 in pbx_exec (c=0x94dca78, app=0xb753a160, data=0xb6ec20bc) at pbx.c:1359
#160x0811d857 inpbx_extension_helper (c=0x94dca78, con=<value optimized out>,context=<value optimized out>, exten=0x94dcd3c "s", priority=1, label=0x0,callerid=0x94d5d58 "500", action=E_SPAWN,
found=0xb6ec41f8, combined_find_spawn=1) at pbx.c:3726
#170x0811fcfe in ast_spawn_extension (c=0x94dca78, args=<value optimizedout>) at pbx.c:4228
#18__ast_pbx_run (c=0x94dca78, args=<value optimized out>) at pbx.c:4322
#190x081212fe in pbx_thread (data=0x94dca78) at pbx.c:4609
#200x081670eb in dummy_start (data=0x94d5d98) at utils.c:970
#210x0026b96e in start_thread () from /lib/tls/i686/cmov/libpthread.so.0
#22 0x00536a4e in clone () from/lib/tls/i686/cmov/libc.so.6
以下为*3转移时过程,转移发起者的编解码设置过程。
步骤-1
MyPBX播放"pbx-transfer"提示音时,根据提示音格式,设置转移发起者的写格式:
/main/file.c
ast_openstream函数:
/* Set the channel to a formatwe can work with */
res = ast_set_write_format(chan,format);
被保留的通道听moh提示音,其写格式设置成提示音的格式:
/res/res_musiconhold.c
moh_alloc函数:
ast_set_write_format(chan,class->format);
步骤-2
当"pbx-transfer"提示音播放结束时,还原转移发起者的写格式:
/main/file.c
ast_stopstream函数:
if (tmp->oldwriteformat&& ast_set_write_format(tmp, tmp->oldwriteformat))
函数调用栈:
#0 set_format (chan=0x9755af8,fmt=4, rawformat=0x9755d0c,format=0x9755d04, trans=0x9755b3c,direction=1) at channel.c:4011
#1 0x0809b7cf inast_set_write_format (chan=0x9755af8, fmt=4) at channel.c:4080
#2 0x080dc52c in ast_stopstream (tmp=0x9755af8) at file.c:130
#3 0x080dce29 in waitstream_core (c=0x9755af8, breakon=<valueoptimized out>, forward=<value optimized out>, reverse=0x0, skip_ms=0,audiofd=-1, cmdfd=-1, context=0x0) at file.c:1206
#4 0x080ded8a in ast_waitstream (chan=0x9755af8, file=0x81a264f"pbx-transfer", digits=0x818fbf8 "0123456789#*ABCD") atfile.c:1323
#5 ast_stream_and_wait(chan=0x9755af8, file=0x81a264f "pbx-transfer",digits=0x818fbf8 "0123456789#*ABCD") at file.c:1354
#6 0x080d8628 in builtin_atxfer (chan=0x9783a00, peer=0x9755af8, config=0xb6c3a3e8,code=0xb6c3a274 "*3", sense=2, data=0x0) atfeatures.c:1628
#7 0x080cf5f0 infeature_interpret_helper (chan=<value optimized out>, peer=<valueoptimized out>, config=<value optimized out>, code=0xb6c3a274"*3", sense=2,
dynamic_features_buf=0xb6c39f4c "twstart#", features=0xb6c39d6c,operation=FEATURE_INTERPRET_DO, feature=0xb6c39d70)at features.c:2278
#8 0x080cf953 in feature_interpret (chan=0x9783a00, peer=0x9755af8, config=<value optimizedout>, code=0xb6c3a274 "*3", sense=2) atfeatures.c:2392
#9 0x080d02ec in ast_bridge_call(chan=0x9783a00,peer=0x9755af8, config=0xb6c3a3e8) at features.c:3236
#10 0x00e19894 indial_exec_full (chan=<value optimized out>, data=<value optimizedout>, peerflags=0xb6c3ac68, continue_exec=0x0) at app_dial.c:2317
#11 0x00e1b21d in dial_exec (chan=0x9783a00,data=0xb6c3cf5c) at app_dial.c:2400
#12 0x08110a65 in pbx_exec (c=0x9783a00, app=0xb753da48, data=0xb6c3cf5c)at pbx.c:1359
#13 0x0811d857 inpbx_extension_helper (c=0x9783a00,con=<value optimized out>, context=<value optimized out>,exten=0x9783cc4 "s", priority=11, label=0x0, callerid=0x94d6958"504", action=E_SPAWN,
found=0xb6c3f25c, combined_find_spawn=1) at pbx.c:3726
#14 0x008ba47d in _macro_exec (chan=0x9783a00,data=<value optimized out>, exclusive=0) at app_macro.c:398
#15 0x08110a65 in pbx_exec (c=0x9783a00, app=0xb753a160, data=0xb6c4200c) at pbx.c:1359
#16 0x0811d857 inpbx_extension_helper (c=0x9783a00,con=<value optimized out>, context=<value optimized out>,exten=0x9783cc4 "s", priority=2, label=0x0, callerid=0x94d6958"504", action=E_SPAWN,
found=0xb6c4430c,combined_find_spawn=1) at pbx.c:3726
#17 0x008ba47d in _macro_exec (chan=0x9783a00,data=<value optimized out>, exclusive=0) at app_macro.c:398
#18 0x08110a65 in pbx_exec (c=0x9783a00, app=0xb753a160, data=0xb6c470bc)at pbx.c:1359
#19 0x0811d857 inpbx_extension_helper (c=0x9783a00,con=<value optimized out>, context=<value optimized out>,exten=0x9783cc4 "s", priority=1, label=0x0, callerid=0x94d6958"504", action=E_SPAWN,
found=0xb6c491f8, combined_find_spawn=1) atpbx.c:3726
#20 0x0811fcfe in ast_spawn_extension (c=0x9783a00, args=<value optimized out>) atpbx.c:4228
#21 __ast_pbx_run (c=0x9783a00,args=<value optimized out>) at pbx.c:4322
#22 0x081212fe in pbx_thread (data=0x9783a00)at pbx.c:4609
#23 0x081670eb in dummy_start (data=0x9796a30)at utils.c:970
#24 0x0026b96e in start_thread () from /lib/tls/i686/cmov/libpthread.so.0
#250x00536a4e in clone ()from /lib/tls/i686/cmov/libc.so.6
步骤-3
MyPBX播放拨号音给转移发起者,此时,设置转移发起者的写格式为线性(MyPBX系统音调都为线性):
/main/indications.c
playtones_alloc函数:
if (ast_set_write_format(chan,AST_FORMAT_SLINEAR))
函数调用栈:
#0 set_format (chan=0x9755af8,fmt=64, rawformat=0x9755d0c,format=0x9755d04, trans=0x9755b3c,direction=1) at channel.c:4011
#1 0x0809b7cf inast_set_write_format (chan=0x9755af8, fmt=64) at channel.c:4080
#2 0x080ed0b7 in playtones_alloc (chan=0x9755af8, params=0xb6c39a04)at indications.c:138
#3 0x080a701ain ast_activate_generator (chan=0x9755af8, gen=0x81c8038, params=0xb6c39a04)at channel.c:2164
#4 0x080ecc5c in ast_playtones_start (chan=0x9755af8, vol=0,playlst=0x935b6f8"350+440", interruptible=0) at indications.c:382
#5 0x0806ab98 in ast_app_dtget (chan=0x9755af8, context=0x9755d6c "DLPN_DialPlan505",collect=0xb6c39b6c "", size=<value optimizedout>, maxlen=100, timeout=8000) at app.c:132
#6 0x080d867a in builtin_atxfer (chan=0x9783a00, peer=0x9755af8, config=0xb6c3a3e8,code=0xb6c3a274 "*3", sense=2, data=0x0) atfeatures.c:1637
#7 0x080cf5f0 infeature_interpret_helper (chan=<value optimized out>, peer=<valueoptimized out>, config=<value optimized out>, code=0xb6c3a274"*3", sense=2,
dynamic_features_buf=0xb6c39f4c "twstart#", features=0xb6c39d6c,operation=FEATURE_INTERPRET_DO, feature=0xb6c39d70)at features.c:2278
#8 0x080cf953 in feature_interpret (chan=0x9783a00, peer=0x9755af8, config=<value optimizedout>, code=0xb6c3a274 "*3", sense=2) atfeatures.c:2392
#9 0x080d02ec in ast_bridge_call(chan=0x9783a00,peer=0x9755af8, config=0xb6c3a3e8) at features.c:3236
#10 0x00e19894 indial_exec_full (chan=<value optimized out>, data=<value optimizedout>, peerflags=0xb6c3ac68, continue_exec=0x0) atapp_dial.c:2317
#11 0x00e1b21d in dial_exec (chan=0x9783a00,data=0xb6c3cf5c) at app_dial.c:2400
#12 0x08110a65 in pbx_exec (c=0x9783a00, app=0xb753da48, data=0xb6c3cf5c)at pbx.c:1359
#13 0x0811d857 inpbx_extension_helper (c=0x9783a00,con=<value optimized out>, context=<value optimized out>,exten=0x9783cc4 "s", priority=11, label=0x0, callerid=0x94d6958"504", action=E_SPAWN,
found=0xb6c3f25c, combined_find_spawn=1) at pbx.c:3726
#14 0x008ba47d in _macro_exec (chan=0x9783a00,data=<value optimized out>, exclusive=0) at app_macro.c:398
#15 0x08110a65 in pbx_exec (c=0x9783a00, app=0xb753a160, data=0xb6c4200c) at pbx.c:1359
#16 0x0811d857 inpbx_extension_helper (c=0x9783a00,con=<value optimized out>, context=<value optimized out>,exten=0x9783cc4 "s", priority=2, label=0x0, callerid=0x94d6958"504", action=E_SPAWN,
found=0xb6c4430c,combined_find_spawn=1) at pbx.c:3726
#17 0x008ba47d in _macro_exec (chan=0x9783a00,data=<value optimized out>, exclusive=0) at app_macro.c:398
#18 0x08110a65 in pbx_exec (c=0x9783a00, app=0xb753a160, data=0xb6c470bc)at pbx.c:1359
#19 0x0811d857 inpbx_extension_helper (c=0x9783a00,con=<value optimized out>, context=<value optimized out>,exten=0x9783cc4 "s", priority=1, label=0x0, callerid=0x94d6958"504", action=E_SPAWN,
found=0xb6c491f8,combined_find_spawn=1) at pbx.c:3726
#20 0x0811fcfe in ast_spawn_extension (c=0x9783a00, args=<value optimized out>) atpbx.c:4228
#21 __ast_pbx_run (c=0x9783a00,args=<value optimized out>) at pbx.c:4322
#22 0x081212fe in pbx_thread (data=0x9783a00)at pbx.c:4609
#23 0x081670eb in dummy_start (data=0x9796a30)at utils.c:970
#24 0x0026b96e in start_thread () from /lib/tls/i686/cmov/libpthread.so.0
#250x00536a4e in clone ()from /lib/tls/i686/cmov/libc.so.6
步骤-4
转移发起者拨打要呼叫的号码.当按了第一个dtmf时,停止系统的拨号音.此时,还原转移发起者的写格式:
/main/indications.c
playtones_release函数:
ast_set_write_format(chan,ps->origwfmt);
函数调用栈:
#0 set_format (chan=0x9755af8,fmt=4, rawformat=0x9755d0c,format=0x9755d04, trans=0x9755b3c,direction=1) at channel.c:4011
#1 0x0809b7cf inast_set_write_format (chan=0x9755af8, fmt=4) at channel.c:4080
#2 0x080ec8f0 inplaytones_release (chan=0x4, params=0x979e250) at indications.c:116
#3 0x0809c2e7 inast_deactivate_generator (chan=0x9755af8) at channel.c:2114
#4 0x0806ac45 inast_app_dtget (chan=0x9755af8, context=0x9755d6c "DLPN_DialPlan505", collect=0xb6c39b6c"", size=<value optimized out>, maxlen=100, timeout=8000) atapp.c:141
#5 0x080d867a in builtin_atxfer (chan=0x9783a00, peer=0x9755af8, config=0xb6c3a3e8,code=0xb6c3a274 "*3", sense=2, data=0x0) atfeatures.c:1637
#6 0x080cf5f0 infeature_interpret_helper (chan=<value optimized out>, peer=<valueoptimized out>, config=<value optimized out>, code=0xb6c3a274"*3", sense=2,
dynamic_features_buf=0xb6c39f4c "twstart#", features=0xb6c39d6c,operation=FEATURE_INTERPRET_DO, feature=0xb6c39d70)at features.c:2278
#7 0x080cf953 in feature_interpret (chan=0x9783a00, peer=0x9755af8, config=<value optimizedout>, code=0xb6c3a274 "*3", sense=2) atfeatures.c:2392
#8 0x080d02ec in ast_bridge_call(chan=0x9783a00, peer=0x9755af8,config=0xb6c3a3e8) at features.c:3236
#9 0x00e19894 in dial_exec_full (chan=<valueoptimized out>, data=<value optimized out>, peerflags=0xb6c3ac68,continue_exec=0x0) at app_dial.c:2317
#10 0x00e1b21d in dial_exec (chan=0x9783a00,data=0xb6c3cf5c) at app_dial.c:2400
#11 0x08110a65 in pbx_exec (c=0x9783a00, app=0xb753da48, data=0xb6c3cf5c)at pbx.c:1359
#12 0x0811d857 inpbx_extension_helper (c=0x9783a00,con=<value optimized out>, context=<value optimized out>,exten=0x9783cc4 "s", priority=11, label=0x0, callerid=0x94d6958"504", action=E_SPAWN,
found=0xb6c3f25c, combined_find_spawn=1) at pbx.c:3726
#13 0x008ba47d in _macro_exec (chan=0x9783a00,data=<value optimized out>, exclusive=0) at app_macro.c:398
#14 0x08110a65 in pbx_exec (c=0x9783a00, app=0xb753a160, data=0xb6c4200c) at pbx.c:1359
#15 0x0811d857 inpbx_extension_helper (c=0x9783a00,con=<value optimized out>, context=<value optimized out>,exten=0x9783cc4 "s", priority=2, label=0x0, callerid=0x94d6958"504", action=E_SPAWN,
found=0xb6c4430c,combined_find_spawn=1) at pbx.c:3726
#16 0x008ba47d in _macro_exec (chan=0x9783a00,data=<value optimized out>, exclusive=0) at app_macro.c:398
#17 0x08110a65 in pbx_exec (c=0x9783a00, app=0xb753a160, data=0xb6c470bc)at pbx.c:1359
#18 0x0811d857 inpbx_extension_helper (c=0x9783a00,con=<value optimized out>, context=<value optimized out>,exten=0x9783cc4 "s", priority=1, label=0x0, callerid=0x94d6958"504", action=E_SPAWN,
found=0xb6c491f8,combined_find_spawn=1) at pbx.c:3726
#19 0x0811fcfe in ast_spawn_extension (c=0x9783a00, args=<value optimized out>) atpbx.c:4228
#20 __ast_pbx_run (c=0x9783a00,args=<value optimized out>) at pbx.c:4322
#21 0x081212fe in pbx_thread (data=0x9783a00)at pbx.c:4609
#22 0x081670eb in dummy_start (data=0x9796a30)at utils.c:970
#23 0x0026b96e in start_thread () from /lib/tls/i686/cmov/libpthread.so.0
#240x00536a4e in clone ()from /lib/tls/i686/cmov/libc.so.6
步骤-5
拨号成功,转移发起者听到回铃音.此时,设置转移发起者的写格式为线性.类似步骤-3.
步骤-6
转移目标摘机接听.此时,停止系统的回铃音,还原转移发起者的写格式.类似步骤-4.
ast_channel_bridge桥接转移发起者和转移目标.
步骤-7
转移发起者挂机.此时,把被保留的通道接回,还原其写格式.
/res/res_musiconhold.c
moh_files_release函数:
if (state->origwfmt&& ast_set_write_format(chan, state->origwfmt))
步骤-8
系统播放"beep"提示音给转移目标听.类似步骤-1.
播放结束,还原其写格式.类似步骤-2.
步骤-9
ast_channel_bridge桥接转移目标和被保留方.类似步骤-6.