一种通过在服务器端建立动态内存去网络抖动的方法.docx
《一种通过在服务器端建立动态内存去网络抖动的方法.docx》由会员分享,可在线阅读,更多相关《一种通过在服务器端建立动态内存去网络抖动的方法.docx(10页珍藏版)》请在冰点文库上搜索。
一种通过在服务器端建立动态内存去网络抖动的方法
说明书摘要
本发明涉及一种通过在服务器端建立动态内存去网络抖动的方法。
视频监控终端与视频监控前端设备通常按照B/S或者C/S的架构一对一或者多对一的方式通信。
在传输层使用TCP协议,提高数据传输的可靠性,保证每帧数据到达的完整性及有序性;服务器端采集的视频数据经H.264视频编码后,以图像帧为单位存放到发送数据缓冲区,发送缓冲区以环形方式组织,保证数据的实时性;服务器端定时检查当前视频流状态及连接数量来判断是否采用为每个连接独立分配缓存的方式,来解决网络抖动的问题。
本发明以动态分配独立内存的方式解决了网络传输的丢包和乱序问题,将视频图像以帧为单位存放于每个独立环形缓冲区中,提高了视频监控系统整体抗干扰能力,为终端用户提供较好的视频图像质量。
权利要求书
1.一种通过在服务器端建立动态内存去网络抖动的方法,其特征在于,包括步骤:
步骤S1:
服务器端初始化公共环形缓冲区。
步骤S2:
服务器端为新的访问端建立TCP连接,并记录当前连接数。
步骤S3:
服务器端检测当前视频流状态,如果满足一定阈值,则为每个访问端新分配环形缓冲区,用于视频流的独立传输,如果不是,则恢复使用公共环形缓冲区。
步骤S4:
返回步骤S2进行循环执行。
2.根据权利要求1所述的一种通过在服务器端建立动态内存去网络抖动的方法,其特征在于,上述步骤S1中新建的客户端连接均以此公共环形缓冲区为默认视频流发送缓冲区。
3.根据权利要求1所述的一种通过在服务器端建立动态内存去网络抖动的方法,其特征在于,上述步骤S2中为了保证链接可靠性,服务器端为新的访问端建立TCP连接,并记录当前连接数。
3.根据权利要求1所述的一种通过在服务器端建立动态内存去网络抖动的方法,其特征在于,上述步骤S3中如果CurLinkNum*CurBitRate>THRESHOLD_PAYLOAD条件成立,则将为每一个新建连接单独分配环形缓冲区存放待发送码流,而不再是公用同一个缓冲区。
其中,CurLinkNum为当前连接数,CurBitRate为当前码流码率大小,THRESHOLD_PAYLOAD为负载阈值,根据实际网络带宽等条件设定。
如果条件不成立,则仍然使用公共缓冲区存放待发送码流。
3.根据权利要求1所述的一种通过在服务器端建立动态内存去网络抖动的方法,其特征在于,上述步骤S4中,通过步骤S2所建立之线程循环判断,在公共缓冲区方式与使用新分配内存方式间切换。
说明书
一种通过在服务器端建立动态内存去网络抖动的方法
技术领域
本发明涉及一种通过在服务器端建立动态内存去网络抖动的方法,尤其可应用于网络视频服务器在QoS(网络服务质量)较差下多点实时视频的传输。
背景技术
随着EtherNet技术的不断发展,IPC(网络视频监控设备)逐渐成为安防领域发展的一个热点。
利用现有的IP宽带网络,便可以实现远程视频监控,而不用单独建设视频专线。
在实际监控应用中,通常会出现多个客户端同时连接同一个监控前端进行视频监控的案例,即多个客户端同时连接同一个前端服务器。
且随着高清视频监控的普及,视频码流码率更是与日俱增,因为数据量大,就容易使传输的视频流出现丢包、乱序的问题,导致了接收客户端的解码器不能正确解码视频流,给终端用户呈现的就是解码错误的视频图像。
现在主要采用的技术为连接同一个服务器的多个客户端共同使用同一个缓冲池,对同一帧码流,只有对每个客户端发送码流数据包完毕之后,再释放这片缓存,这样对数据量不大、网络环境较好的条件下可以减少网络延迟,但是,对于高清视频来说,数据量大,现有方法就存在局限性,容易导致丢包和乱序的问题,因此,现有的技术存在改进和发展的空间。
发明内容
为了克服前端高清设备在被多路客户端同时访问时,因为数据量大,容易使视频图像产生网络抖动的缺点,本发明提供了一种通过在服务器端建立动态内存去网络抖动的方法,在视频高码率及多客户端同时访问条件下,通过在服务器端为每个访问端独立分配内存,这样使得为每个访问端的码流传输具有独立性,防止了丢包和乱序等现象。
本发明解决其技术问题所采用的技术方案是:
一种通过在服务器端建立动态内存去网络抖动的方法,包括如下步骤:
步骤S1:
服务器端初始化公共环形缓冲区。
步骤S2:
服务器端为新的访问端建立TCP连接,并记录当前连接数。
步骤S3:
服务器端检测当前视频流状态,如果满足一定阈值,则为每个访问端新分配环形缓冲区,用于视频流的独立传输,如果不是,则恢复使用公共环形缓冲区。
步骤S4:
返回步骤S2进行循环执行。
上述步骤S1中新建的连接均以此公共环形缓冲区为默认视频流发送缓冲区。
上述步骤S2中为了保证链接可靠性,服务器端为新的访问端建立TCP连接,并记录当前连接数。
上述步骤S3中如果CurLinkNum*CurBitRate>THRESHOLD_PAYLOAD条件成立,则将为每一个新建连接单独分配环形缓冲区存放待发送码流,而不再是公用同一个缓冲区。
其中,CurLinkNum为当前连接数,CurBitRate为当前码流码率大小,THRESHOLD_PAYLOAD为负载阈值,根据实际网络带宽等条件设定。
如果条件不成立,则仍然使用公共缓冲区存放待发送码流。
上述步骤S4中,通过步骤S2所建立之线程循环判断,在公共缓冲区方式与使用新分配内存方式间切换。
与现有技术相比,本发明的积极效果是:
通过在服务器端为新的访问点建立动态内存,有效提高视频传输的可靠性,解决了视频网络传输抖动的问题。
具体表现如下:
1、基于TCP作为传输层协议,建立公共环形缓冲区,以帧为单位将视频图像信息存放于其中,循环覆盖,有效解决了视频延时的问题;2、在高码率多连接条件下,采用动态独立分配内存的方法,有效保障了视频流的正常传输,解决了因码率过大或者访问端过多导致了视频流传输丢包、乱序而产生的网络抖动问题。
附图说明
附图1为系统结构图。
附图2为公共环形缓冲区示意图。
附图3多访问端独立分配环形缓冲区示意图。
具体实施方式
下面结合附图2、3和具体实施例对本发明的原理进行详细说明。
本发明所建立的整个系统均实现于服务器端,服务器端进行视频实时采集、H264编码,将码流存放于发送缓冲区中;服务器端在设定的TCP端口进行监听,等待来自客户端的视频连接请求,将视频数据包通过TCP报文分发给客户端;服务器端判断当前连接状态,决定是否启用为每个客户端独立分配环形缓冲区的处理方式。
步骤S1:
初始化公共环形缓冲区,结构如图2所示,服务器端检测到码流状态在未达到阈值时,均使用此公共环形缓冲区存储待传输视频码流。
公共环形缓冲区通过链表实现,如下代码描述了缓冲区每个节点的数据结构:
structFifoElement
{
tFifoElement*next;//链表指针,指向缓冲区队列
inttype;
tElement*chunk;
};
structElement{
pthread_mutex_tlock;//缓冲区操作锁
intref;
tElement*next;//链表指针,指向每个缓冲区中的每个片区
void*data;//缓冲区数据指针
intsize;
};
对于环形缓冲区的操作:
系统定义两个读写指针Pread/Pwrite,在完成缓冲区的初始化以后读写指针重合。
工作过程中,如果Pread不等于Pwrite,那么输出当前Pread指向的内容,并将Pread移到下一个节点,否则返回无数据状态。
如果Pwrite的下一个节点不是Pread,那么将数据写入Pwrite指向节点的数据缓冲部分,并将Pwrite移向下一个节点。
如果Pwrite的下一个节点是Pread,那么首先将Pread指向下一个节点,同时将数据写入Pwrite的指向节点的数据缓冲部分,最后将Pwrite指向下一个节点。
覆盖旧数据的写入方式用于确保缓冲区数据的实时性。
由于缓冲区的读写由两个单独的线程完成,因此需要在读写前对缓冲区指针进行加锁操作。
在通常情况下,服务器使用上述公共缓冲池向多个客户端发送数据,当某一图像帧发送给了当前全部有效连接之后,方能移动Pread至下一个节点,以此保证每个视频连接所接收数据帧的完整性。
步骤S2:
服务器建立TCP服务器,监听来自客户端服务请求。
步骤S3:
定时检测服务器端码流及客户端连接状态,如果CurLinkNum*CurBitRate>THRESHOLD_PAYLOAD条件成立,则将为每一个新建连接单独分配内存作为发送缓冲区存放待发送码流,而不再是公用同一个缓冲区。
其中,CurLinkNum为当前连接数,CurBitRate为当前码流码率大小,THRESHOLD_PAYLOAD为负载阈值,根据实际网络带宽等条件设定。
如果条件不成立,则仍然使用公共缓冲区存放待发送码流。
以下代码实现了在新建连接中初始化一个独立的环形缓冲区:
structDispatch
{
pthread_mutex_tlock;
tFifoBuffer*rdFifo;
tPool*pool;
ReadSessionrdSession[MAX_READERS];//连接数
};
intGetMemReadID()
{
inti=0;
tDispatch*pDispatch=&gDispatch;
tFifoBuffer*fifoHead=NULL;
tFifoBuffer*tFifo=NULL;
pthread_mutex_lock(&pDispatch->lock);//加锁
for(i=0;i{
if(pDispatch->rdSession[i].freeFlag)//有效连接建立
{
pDispatch->rdSession[i].freeFlag=0;
tFifo=fifo_buffer_init();//分配单独缓冲区
if(NULL==tFifo)
i=-1;
else
{
pDispatch->rdSession[i].readFifo=tFifo;
if(NULL==pDispatch->rdFifo)
pDispatch->rdFifo=tFifo;
else
{
for(fifoHead=pDispatch->rdFifo;fifoHead->next;fifoHead=fifoHead->next);
fifoHead->next=tFifo;
}
}
pthread_mutex_unlock(&pDispatch->lock);
returni;
}
}
pthread_mutex_unlock(&pDispatch->lock);
return-1;
}
通过上述代码,为每个新建立的连接都分配了一个如图3所示的缓冲区,在此之后,经H.264编码后的视频码流直接复制于各个独立的缓冲区,并分别发送至客户端,以下代码实现了码流存储于独立分配的缓冲区:
voidPutChunkForWrite(tElement*chunk)
{
tDispatch*pDispatch=&gDispatch;
tFifoBuffer*readFifo=NULL;
tFifoElement*elm=NULL;
tPool*pool=pDispatch->pool;
intlen;
char*pos=NULL;
if(!
chunk)
return;
pthread_mutex_lock(&pDispatch->lock);//线程锁
if(!
pDispatch->rdFifo)
{
pthread_mutex_unlock(&pDispatch->lock);
pthread_mutex_lock(&chunk->lock);
pool->free(pool,chunk);
pthread_mutex_unlock(&chunk->lock);
return;
}
pthread_mutex_lock(&pool->mutex);//缓冲区锁
pthread_mutex_lock(&chunk->lock);
len=*(int*)(chunk->data);
pos=(char*)((int*)(chunk->data)+1);
for(readFifo=pDispatch->rdFifo;readFifo!
=NULL;readFifo=readFifo->next)
{
elm=readFifo->get(readFifo,BLOCK_ALLOW,_LIST_PRODUCER_);
if(NULL==elm)
{
continue;
}
*((int*)elm->chunk->data)=*((int*)(&len));
memcpy((char*)(((int*)elm->chunk->data)+1),pos,len);//复制码流至缓冲区
readFifo->put(readFifo,elm,_LIST_CONSUMER_);
}
chunk->ref=0;
pthread_mutex_unlock(&pool->mutex);
pool->free(pool,chunk);
pthread_mutex_unlock(&pDispatch->lock);
pthread_mutex_unlock(&chunk->lock);
return;
}
上述的实施样例中所给出的参数和代码,是提供给本领域的技术人员来参考实现或使用本发明的,本发明并不限定仅取前述公开的数值和代码,在不脱离本发明的发明思想的情况下,本领域的技术人员可以对上述实施例作出种种修改或调整,因而本发明的保护范围并不被上述实施例所限,而应该是符合权利要求书提到的创新性特征的最大范围。
图1系统结构图
图2公共环形缓冲区法结构图
图3各个独立环形缓冲区法结构图