asterisk的编解码转换

前言

不同的分机端使用的语音编码格式各不相同,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.


你可能感兴趣的:(asterisk的编解码转换)