QuteCom手记:phapi发送和接收音频数据的流程(ortp & portaudio)
2011-06-28 17:11
585 查看
phapi发送和接收音频数据的流程简介。
通过ortp库(完整的源代码在ortp工程中)实现。
oRTP协议将在另外一篇中介绍,这里只要知道它是用来发送和接收媒体流(音频和视频)的协议。
本篇只记录使用ortp发送、接收音频数据的流程。
@1 phapi使用ortp的简单流程:
-----------------------------------------------
$1、初始化库
在整个程序的生命周期中只初始化一次ortp库
qutecom/wifo/phapi/phmedia.c
ph_media_init()==>ortp_init()
$2、初始化一个RTP会话以及设置RTP会话的参数
qutecom/wifo/phapi/phmedia-audio.c
ph_msession_audio_stream_hardstart()函数
LINE 3019:session = rtp_session_new(RTP_SESSION_SENDRECV);
至
LINE 3242:rtp_session_signal_connect(session, "cng_packet", (RtpCallback)ph_on_cng_packet, s);
$3、接收一个RTP数据包
e:/works/qutecom/wifo/phapi/phmedia-audio.c
ph_audio_play_cbk()==>ph_media_retrieve_decoded_frame()==>rtp_session_recvm_with_ts()
$4、发送一个RTP数据包
qutecom/wifo/phapi/phmedia-audio.c
ph_audio_rec_cbk()==>ph_encode_and_send_audio_frame()==>rtp_session_sendm_with_ts()||rtp_session_send_with_ts()
$5、销毁一个RTP会话
e:/works/qutecom/wifo/phapi/phmedia-audio.c
ph_msession_audio_stream_stop()==>rtp_session_destroy()
@2 从PortAudio获取音频数据到ortp发送音频数据的流程。
----------------------------------------------
$1、PortAudio在phapi中的驱动封装
注意:结构体的第6、7项为NULL,这两个地方是放从mic读取和写入speaker的接口的地方。PortAudio不提供获取音频/写入音频的接口而是采用回调方式。
portAudio要求使用者提供一个回调函数,PortAudio根据对它的设定,定时获得mic数据或者写入speaker时自动调用该函数。该回调函数必须在打开portaudio (Pa_OpenStream)时指定。Phapi中该回调函数是ph_pa_callback
File:/qutecom/wifo/phapi/phmedia-portaudio.c
注意:
ADEV(as)->cbk(as, (void *) input, (int) frameCount * 2, output, &outCount);
这个cbk指向:ph_audio_callback() (pa_stream_open()函数的最后一个参数设置这个cbk)
File:/qutecom/wifo/phapi/phmedia-audio.c
代码中分别调用了ph_audio_rec_cbk和ph_audio_play_cbk两个函数,结合上面@1($3$4)的流程就构成了一个从portAudio获取数据到使用RTP接收和发送数据的完整流程。
通过ortp库(完整的源代码在ortp工程中)实现。
oRTP协议将在另外一篇中介绍,这里只要知道它是用来发送和接收媒体流(音频和视频)的协议。
本篇只记录使用ortp发送、接收音频数据的流程。
@1 phapi使用ortp的简单流程:
-----------------------------------------------
$1、初始化库
在整个程序的生命周期中只初始化一次ortp库
qutecom/wifo/phapi/phmedia.c
ph_media_init()==>ortp_init()
$2、初始化一个RTP会话以及设置RTP会话的参数
qutecom/wifo/phapi/phmedia-audio.c
ph_msession_audio_stream_hardstart()函数
LINE 3019:session = rtp_session_new(RTP_SESSION_SENDRECV);
至
LINE 3242:rtp_session_signal_connect(session, "cng_packet", (RtpCallback)ph_on_cng_packet, s);
$3、接收一个RTP数据包
e:/works/qutecom/wifo/phapi/phmedia-audio.c
ph_audio_play_cbk()==>ph_media_retrieve_decoded_frame()==>rtp_session_recvm_with_ts()
$4、发送一个RTP数据包
qutecom/wifo/phapi/phmedia-audio.c
ph_audio_rec_cbk()==>ph_encode_and_send_audio_frame()==>rtp_session_sendm_with_ts()||rtp_session_send_with_ts()
$5、销毁一个RTP会话
e:/works/qutecom/wifo/phapi/phmedia-audio.c
ph_msession_audio_stream_stop()==>rtp_session_destroy()
@2 从PortAudio获取音频数据到ortp发送音频数据的流程。
----------------------------------------------
$1、PortAudio在phapi中的驱动封装
struct ph_audio_driver ph_pa_driver = { "pa", PH_SNDDRVR_REC_CALLBACK|PH_SNDDRVR_PLAY_CALLBACK, 0, pa_stream_start, pa_stream_open, NULL, NULL, pa_stream_get_out_space, pa_stream_get_avail_data, pa_stream_close, NULL, NULL };
注意:结构体的第6、7项为NULL,这两个地方是放从mic读取和写入speaker的接口的地方。PortAudio不提供获取音频/写入音频的接口而是采用回调方式。
portAudio要求使用者提供一个回调函数,PortAudio根据对它的设定,定时获得mic数据或者写入speaker时自动调用该函数。该回调函数必须在打开portaudio (Pa_OpenStream)时指定。Phapi中该回调函数是ph_pa_callback
File:/qutecom/wifo/phapi/phmedia-portaudio.c
static intph_pa_callback(const void *input, void *output, unsigned long frameCount, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData ){ phastream_t *as = (phastream_t *) userData; int outCount = (int) frameCount * 2; int needMore; ADEV(as)->cbk(as, (void *) input, (int) frameCount * 2, output, &outCount); needMore = frameCount * 2 - outCount; if (needMore > 0) { memset(outCount + (char *)output, 0, needMore); } return as->ms.running ? paContinue : paAbort; }
注意:
ADEV(as)->cbk(as, (void *) input, (int) frameCount * 2, output, &outCount);
这个cbk指向:ph_audio_callback() (pa_stream_open()函数的最后一个参数设置这个cbk)
File:/qutecom/wifo/phapi/phmedia-audio.c
/** * @brief callback used by the audio subsystems to communicate with the phapi audio engine * @param stream the concerned audio stream * @param recbuf buffer that has just been recorded by the subsystem * @param recbufsize size of the recorded buffer (maybe 0) * @param playbuf * @param playbufsize */ static int ph_audio_callback(phastream_t *stream, void *recbuf, int recbufsize, void *playbuf, int *playbufsize) { int i = 0; if (stream->ms.running) { if (recbuf && recbufsize > 0) { ph_audio_rec_cbk(stream, recbuf, recbufsize); } if ((playbuf != 0) && playbufsize && (*playbufsize > 0)) { i = ph_audio_play_cbk(stream, playbuf, *playbufsize); *playbufsize = i; } } return 0; }
代码中分别调用了ph_audio_rec_cbk和ph_audio_play_cbk两个函数,结合上面@1($3$4)的流程就构成了一个从portAudio获取数据到使用RTP接收和发送数据的完整流程。
相关文章推荐
- JAVA编码转换的详细过程理解—>浏览器和服务器的接收和发送数据的编码
- kafka的数据发送和接收java_API
- STM32 USB数据接收与数据发送程序流程分析
- stm32 usb数据接收与数据发送程序流程分析
- 关于servlet服务端接收客户端发送的List<?>数据的问题
- 26 API-网络编程(网络概述,Socket通信机制,UDP协议发送和接收数据,TCP协议发送和接收数据)
- Linux Socket CAN驱动 <4.接收数据流程>
- kafka的数据发送和接收java_API
- Linux内核协议栈之数据发送与接收流程详图(v2.6.18)
- 网络协议栈14:Connect函数分解之网卡发送/接收数据流程
- iOS 网络请求接收数据流程 (NSURLRequest&NSURLConnection)
- QuteCom手记:Phapi/exosip事件②INVITE的响应
- Qt采用Qextserialport 接收发送16进制数据
- C#通过API获取接收数据窗体控件句柄,并向该句柄发送文本信息
- JAVA编码转换的详细过程理解—>浏览器和服务器的接收和发送数据的编码
- 向API 接口发送和接收json数据(php,js)
- OSAL串口接收发送数据流程简介
- Apache Beam Fn API如何接收和发送数据
- STM32 USB数据接收与数据发送程序流程分析
- 2015/01/12:研究1>振动 2>session 3>audiofocus 4>数据传输流程