博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
音视频即时通讯的分包与重组
阅读量:5775 次
发布时间:2019-06-18

本文共 2434 字,大约阅读时间需要 8 分钟。

在音视频开发中音视频的传输主要用UDP来发送视频当发送的数据大于1500时分包发送保证每包小于1500关键是视频接收时的处理。

本文依据UDP库数据传输作为代码演示.

intCUDPSession::SplitData(char* pBuff, uint32_t nLen)
{
int nBlockNum =nLen / UDP_BLOCK_SIZE;
if (nLen %UDP_BLOCK_SIZE != 0)
{
nBlockNum++;
}
int sendlen = 0;
for (int i = 0; i< nBlockNum; i++)
{
int poayload_size =UDP_BLOCK_SIZE;
char* payload =pBuff + UDP_BLOCK_SIZE * (i);
if (nLen -UDP_BLOCK_SIZE * (i) < UDP_BLOCK_SIZE)
poayload_size =nLen - UDP_BLOCK_SIZE * (i);
CPackOut* pack =new CPackOut;
(*pack) <<PACK_TYPE_DATA;
(*pack) <<m_nFrameIndex;
if (i == nBlockNum- 1)
{
(*pack) << 1;
}
else
{
(*pack) << 0;
}
(*pack) <<poayload_size;
(*pack).SetBuffer(payload,poayload_size);
int ret =SendPacket(pack, m_destIP, m_destPort);
printf("SendPacketret = %d\n", ret);
sendlen += ret;
delete pack;
pack = NULL;
}
return sendlen;
}
    以下具体说一下接收端,由于UDP是不可靠的不保证数据帧一定正常到达即使收到顺序也可能发生变化比方先发的后到当然丢包的可能最大乱序的情况比較少。

    正确的处理方法是
    如果一个port仅仅接收固定一个对方数据源,这样收到一个数据包放到缓冲里然后在缓冲里依据帧的序号排序(每一帧的大序号是同样的自己能够给每个小片加上小序号,包头里能够加上本次数据帧一共分多少片收到一片就统计一下推断是否收齐)

当收齐后这个帧去掉包头回调给上层。

当在一定时间内该帧数据还没有收齐就说明传输过程有丢包了把已收到的都丢掉就能够。

 

    当上层的应该收到回调的数据后能够进行解码播放。

在解码之前先推断一下帧序列是否连续。

假设中间有缺少的就把这一序列都丢掉直到下一个I帧。每一个帧的序号最好收发之间协商好在发送的时候带上。

    假设把上面整个过程都实现全然自己写的话须要几天的时间。只是从非常多RTP开源库里发现处理的都非常easy非常多都没有管乱序情况简单地来一份数据就向缓冲里追加一份直到发现mark1。我们这里做为简单使用的项目也採用了这样的简单方法先把功能完毕之后有时间再来优化。

简单的重组代码:
intCUDPSession::Reassemble(CPackIn& pack, uint32_t ip, uint32_t port)
{
int nSeq = 0;
int nMark = 0;
int nLen = 0;
pack >> nSeq;
pack >> nMark;
pack >> nLen;
if(m_nRecvFrameIndex != nSeq)
{
if (m_buffer)
{
evbuffer_free(m_buffer);
m_buffer = NULL;
}
m_nRecvFrameIndex =nSeq;
}
if (m_buffer ==NULL)
{
m_buffer =evbuffer_new();
}
char* pBuf = 0;
int   nSize;
pack.GetBuffer(pBuf,nSize);
evbuffer_add(m_buffer,pBuf, nSize);

if (nMark == 1)

{
//回调
if (m_pCB)
{
m_pCB(m_udpIO.m_handle,(char*)(m_buffer->buffer), m_buffer->off, ip, port, 
m_pParam);
}
evbuffer_free(m_buffer);
m_buffer = NULL;
}
return 0;
}
    程序里使用的evbuffer是从libevent里面拿来的主要用来处理数据缓冲非常好用效率也非常好见evbuffer.hbuffer.cpp
    完整代码在git上这次实现的功能是本机UDP bind5500port-->摄像机採集-->编码-->发送给本机的5500port-->收到后再解码-->显示。

    发送的代码m_Sess.Send((char*)pData, nLen, inet_addr("127.0.0.1"), 5500);
    这个程序能够分别执行在两台机器上一台是发送还有一台是接收。发送方仅仅要把上面这一句里面的127.0.0.1换上你目标的ip还有一台机器就能够接收并解码了。
     本文结束后完整的client功能基本就差点儿相同了下一步開始完毕server端的stun,协商穿透p2p和中转视频。假设对音视频开发还有其它疑问能够登录该论坛进行咨询
http://bbs.anychat.cn/forum.php
!fryuage:ZH-CN;mso-bidi-language:AR-SA'>stun,协商穿透p2p和中转视频。假设对音视频开发还有其它疑问能够登录该论坛进行咨询http://bbs.anychat.cn/forum.php

转载地址:http://nehux.baihongyu.com/

你可能感兴趣的文章
springmvc+swagger2
查看>>
软件评测-信息安全-应用安全-资源控制-用户登录限制(上)
查看>>
我的友情链接
查看>>
Java Web Application 自架构 一 注解化配置
查看>>
如何 debug Proxy.pac文件
查看>>
Python 学习笔记 - 面向对象(特殊成员)
查看>>
Kubernetes 1.11 手动安装并启用ipvs
查看>>
Puppet 配置管理工具安装
查看>>
Bug多,也别乱来,别被Bug主导了开发
查看>>
sed 替换基础使用
查看>>
高性能的MySQL(5)创建高性能的索引一B-Tree索引
查看>>
oracle备份与恢复--rman
查看>>
图片变形的抗锯齿处理方法
查看>>
Effective C++ Item 32 确保你的 public 继承模子里出来 is-a 关联
查看>>
phpstorm安装laravel-ide-helper实现自动完成、代码提示和跟踪
查看>>
python udp编程实例
查看>>
TortoiseSVN中图标的含义
查看>>
js原生继承之——构造函数式继承实例
查看>>
linux定时任务的设置
查看>>
[CareerCup] 13.3 Virtual Functions 虚函数
查看>>