当前位置: 首页 > 工具软件 > QuteCom > 使用案例 >

QuteCom手记:phapi发送和接收音频数据的流程(ortp & portaudio)

商同化
2023-12-01

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中的驱动封装

 

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接收和发送数据的完整流程。

 

 

 

 类似资料: