我关注这个问题是从视频的bitrate开始的,linphone-android 2.0版本的默认编码格式是VP8,在avprofile.c里定义了vp8的payload信息:
PayloadType payload_type_vp8={
TYPE( PAYLOAD_VIDEO),
CLOCK_RATE(90000),
BITS_PER_SAMPLE(0),
ZERO_PATTERN(NULL),
PATTERN_LENGTH(0),
NORMAL_BITRATE(256000),
MIME_TYPE ("VP8"),
CHANNELS(0)
};
写的很明白,bitrate是25600。但是在呼叫过程中,我却从打印信息里看到这么一段:
01-01 12:45:15.091: I/Linphone(11972): Limiting bitrate of video encoder to 458000 bits/s
01-01 12:45:15.091: I/Linphone(11972): bitrate requested...: 458000 (320 x 240)
bitrate变成了458000,这是怎么回事呢?跟踪代码分析发现,linphone在呼叫时会先检查当前网络带宽,然后计算音频传输所需要的带宽,最后将剩余带宽分配给视频传输。
代码流程如下:
1.开启linphone时,会初始化linphone 内核,调用:
->linphone_core_init(){
...
linphone_core_assign_payload_type(lc,&payload_type_vp8,103,NULL);
...
}
此时,vp8的payload被初始化,使用avprofile里定义的值,bitrate为256000;
2.发起呼叫时,会调用:
->linphone_core_invite_address_with_params()
->linphone_core_start_invite()
->sal_call_set_local_media_description()
->make_codec_list()
->linphone_core_check_payload_type_usability()
{
double codec_band;
int allowed_bw,video_bw;
bool_t ret=FALSE;
linphone_core_update_allocated_audio_bandwidth(lc); //计算音频传输所需带宽 audio_bw
allowed_bw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc),
linphone_core_get_upload_bandwidth(lc)); // 获取当前可用带宽
if (allowed_bw==0) {
allowed_bw=-1;
video_bw=1500; /*around 1.5 Mbit/s*/
}else
video_bw=get_video_bandwidth(allowed_bw,lc->audio_bw); //计算视频可用带宽:(total - audio_bw-10)
switch (pt->type){
case PAYLOAD_AUDIO_CONTINUOUS:
case PAYLOAD_AUDIO_PACKETIZED:
codec_band=get_audio_payload_bandwidth(lc,pt);
ret=bandwidth_is_greater(allowed_bw*1000,codec_band);
/*hack to avoid using uwb codecs when having low bitrate and video*/
if (bandwidth_is_greater(199,allowed_bw)){
if (linphone_core_video_enabled(lc) && pt->clock_rate>16000){
ret=FALSE;
}
}
break;
case PAYLOAD_VIDEO:
if (video_bw>0){
pt->normal_bitrate=video_bw*1000; // 修改视频的payload 信息
ret=TRUE;
}
else ret=FALSE;
break;
}
return ret;
}
这个函数根据当前的网络带宽和音频传输带宽计算并修正了视频的bitrate,这就完了吗?还没有。
3.在电话被接听之后,会调用:
->linphone_call_start_video_stream()
->call->video_profile=make_profile()
{
...
if (desc->bandwidth>0) remote_bw=desc->bandwidth;
else if (md->bandwidth>0) {
/*case where b=AS is given globally, not per stream*/
remote_bw=md->bandwidth;
if (desc->type==SalVideo){
remote_bw=get_video_bandwidth(remote_bw,call->audio_bw);
}
}
...
bw=get_min_bandwidth(get_video_bandwidth(linphone_core_get_upload_bandwidth (lc),call->audio_bw),remote_bw);
if (bw>0) pt->normal_bitrate=bw*1000;
...
}
此处根据remote_bw,即呼叫对方的带宽,再次计算了音频和视频的传输带宽,修改了bitrate。