不久之前我们对SkeyeRTMPClient库扩展支持了HEVC(H.265),在后续的长期性能测试中,我们发现拉多路流时,会出现拉流播放一直都播不出来的问题,甚至有一定概率出现崩溃,经过长期的测试和排查,我们发现这是由于音视频数据发送比较频繁的时候出现的tcp粘包的问题,下面将详细讲述粘包问题的解决过程。
1. SkeyeRTMPClient流接收流程
SkeyeRTMPClient底层采用rtmp协议官方提供的librtmp库来实现rtmp流协议流程的连接建立,读取流数据,接收FLV数据组包分包等,然后将接收到的FLV数据包进行解析,从中解析出H264、H265、AAC等音视频编码帧数据,回调给上层库调用接口做解码播放以及进一步数据处理;流接收函数如下代码所示:
int RecvPacket(char * buf,uint32_t & buflen)
{
if(rtmp_object_ == NULL && Reconnect())
{
return RTMP_UNCONNECTED;
}
if(!RTMP_IsConnected(rtmp_object_) && (Reconnect() !=0))
{
return RTMP_RECONNECTED_FAILED;
}
if(NULL == buf|| buflen < 100)
{
return RTMP_RECV_PARAMERROR;
}
if(!rtmp_object_)
{
return RTMP_UNCONNECTED;
}
int ret = RTMP_Read(rtmp_object_,buf,buflen);
if(ret > 0)
{
SkeyeRTMPClient_AV_Frame av_frame = {0};
if(ParserRecvPacket(av_frame,buf,ret,process_buf_) != 0)
{
return RTMP_PARSE_FAILED;
}
if(av_frame.u32FrameType == SKEYE_SDK_VIDEO_FRAME_FLAG && av_frame.u32VFrameType == SKEYE_SDK_VIDEO_FRAME_I && !bGetFirstKeyFrame_)
{
if(audio_channels_ == -1)
{
audio_channels_ = 0;
}
else
{
bGetFirstKeyFrame_ = true;
SKEYE_MEDIA_INFO_T mediaInfo;
memset(&mediaInfo, 0, sizeof(SKEYE_MEDIA_INF