做了一段时间的视频后,最先碰到的是花屏,解码端丢包的花屏,先是通过抓取编码后的BITMAP,发现解码出来就是花屏的,所以考虑优化编码来减少因为丢包产生的花屏;另外调整丢包策略规避解码花屏的问题.
1、X264编码参数调整:
H264 FF_PROFILE_H264_BASELINE、 FF_PROFILE_H264_MAIN两种编码差异,其中最明显的差异是profile_idc_baseline没有B帧,而profile_idc_main带B帧,这个差异体现在解码时,带B帧的不仅依赖之前的帧,还依赖之后到来的帧,通常在实时视频类应用中不建议带B帧的编码。
质量和码率控制:
最开始也是用bit_rate 来控制:
encoder.context->bit_rate = (self->encoder.max_bw_kpbs * 1024);// bps
但bit_rate是平均码率,总是达不到理想的结果(包括编码后的视频帧大小和质量),后来查看网上关于移动设备X264编码优化,提到了通过CRF来控制质量和码率,认为: x264默认是使用”crf”压缩算法, 默认值为23, 代表了编码速度,画质与码流的均衡.并且对各种取值做了编码大小和帧率的比较:
ultrafast baseline crf 28
encoded 467 frames, 58.94 fps, 515.58 kb/s 2006474
superfast baseline crf 26
encoded 467 frames, 41.73 fps, 460.02 kb/s 1790244
superfast baseline crf 28
encoded 467 frames, 43.64 fps, 366.28 kb/s 1425436
配置crf
if((ret = av_opt_set_double(self->encoder.context->priv_data, "crf", (double)30, 0))){
TSK_DEBUG_ERROR("Failed to set x264 crf 28.0");
return;
}
//ultrafast veryfast superfast
if((ret = av_opt_set(self->encoder.context->priv_data, "preset", "superfast", 0))){
TSK_DEBUG_ERROR("Failed to set x264 preset to veryfast");
}
编码后视频NALU单元大小控制:
encoder.context->rtp_payload_size = H264_RTP_PAYLOAD_SIZE;//H264_RTP_PAYLOAD_SIZE大小为1300
if((ret = av_opt_set_int(self->encoder.context->priv_data, "slice-max-size", H264_RTP_PAYLOAD_SIZE, 0))){
TSK_DEBUG_ERROR("Failed to set x264 slice-max-size to %d", H264_RTP_PAYLOAD_SIZE);
}
两个I帧之间帧个数的控制:
encoder.context->gop_size = TMEDIA_CODEC_VIDEO(self)->out.fps * TDAV_H264_GOP_SIZE_IN_SECONDS
2、丢包策略:
基于BP的H264编码,P帧只依赖之前的帧就能解码,所以出现丢包时的处理策略会比较简单,如果发现有P帧丢了,则丢弃后面的所有P帧,直到有I帧到来;如果是I帧丢了,则丢弃I帧及之后的P帧,直到有I帧到来。