添加sdp信息中的视频部分主要通过下面两个步骤处理。
主要在endpoint.c的pjmedia_endpt_create_sdp()函数中添加。具体的可以看其中的代码,以及代码中的注释。
注意pjmedia_endpt_create_sdp( pjmedia_endpt *endpt,
pj_pool_t *pool,
unsigned stream_cnt,
const pjmedia_sock_info sock_info[2],
pjmedia_sdp_session **p_sdp )函数的第三个参数stream_cnt,第四个参数sock_info在使用pjsua_media_channel_create_sdp()调用时,重新调整了输入的参数值。
在pjus_media.c文件中的pjsua_media_subsys_start()函数使用pjsua_media_transports_create添加创建rtp要使用的transport端口(也就是socket端口)。这样在1中的sdp信息中就可以获取到视频通讯的本地创建的rtp端口。
视频处理模块主要完成视频的采集、编码、解码、回放、以及将数据送给rtp或者从rtp获取到数据的功能。其工程为pjmedia-videodev。
CCameraMgr主要实现摄像头的管理功能。如果移植mobile可以考虑修改这部分。
CCodecVideo主要实现视频编解码的功能。如果添加H.263、H.264编解码可以直接修改这部分代码。
CCodecDataChannel主要实现整个视频模块的管理功能。视频的采集、编码、解码、回放、以及将数据送给rtp或者从rtp获取到数据的功能。
Videodev主要实现pjmedia-videodev对Pjsip的外部接口功能。这些接口可以根据需要继续添加。目前应该够用。具体实现见注释。
注意这部分跟rtp交互的接口主要通过两个函数实现。Rtp模块通过pjmedia_video_query_frame_attach接口将回调设置到Pjmedia-videdev模块。Pjmedia-videodev模块,在获取到编码数据后,通过put_frame_video_data将数据送给pjmedia的rtp层,进行rtp打包传输。
在stream.c中pjmedia_stream_create_video处理过程中通过调用pjmedia_video_query_frame_attach将回调函数设置给pjmedia-videodev模块。这样,在启动视频工作线程后,就可以通过put_frame_video_data源源不断的将编码后的数据送给stream.c的rtp的put_frame_video接口进行视频的rtp发送。注意这里对于视频包需要拆包处理。
对于从rtp接收到的数据。都在stream.c的on_rx_rtp回调来处理。这里处理了视频和音频以及dtmf数据。我们对于解析后pt类型为34(H.263)、31(H.261)的数据直接进行视频处理on_rx_video_rtp。通过on_rx_video_rtp将接收到的视频数据写入pjmedia-videodev的Jitterbuffer(NetPool)中,这样就完成了rtp数据接收视频数据源源不断的输入到pjmedia-videodev模块。
对于接收到的视频数据,已经放入netpool中。我们通过启动本地线程不断地从缓冲中获取到数据(视频数据需要重新组赈,然后解码回放),这个通过CCocecDataChnanel:: ShowRemoteVideo来实现。
这个简单,也就是直接获取到摄像头的数据,在本地显示的过程。主要通过CCodecDataChannl:: ShowLocalVideo来实现。
worker_proc_video主要完成对pjmedia-videdev的pjmedia_video_get_frame_and_send接口的调用。完成视频采集编码并将数据送给rtp的过程。这里注意,对于在pjsip工程中的线程,必须使用pj_thread_create创建,例如:
//add with lianhy in 20090902 创建视频工作线程
status = pj_thread_create( endpt->pool, "video", &worker_proc_video,
endpt, 0, 0, &endpt->thread_video);
主要通过Pjmedia-vidodev的接口pjmedia_video_query_frame_start来启动。当然对应的停止应该是pjmedia_video_query_frame_stop。
对于以上说的线程以及socket、session、mediapoint的创建,注意一定要释放(销毁)。