题记:在上个月,用hi3518c+live555,实现在局域网中传输视频后,然后延时太大,大概延时域网中720p的画面延时在8s,640*480 在5s,320*240在3s左右,当时没有多去研究,然后直接去根据其他人的帖子写了在客户端播放的android程序。最近,想在放假之前将延时问题解决掉。经过在网上的答疑,现在将可能引起延时问题以及解决的方法做一总结,但是有的方法还没有去试。
海思压缩好H.264放在里面,程序去取,但是live555,直接去取,网络发送的速度肯定赶不上他采集压缩的速度,所以这个时候,就要做一个fifo,当一个中间的作用,把海思自带缓冲池里面的数据,实时的取出来放到fifo,里面。比如定义fifo的空间为1024K,这个时候,如果超出1024K就丢掉一些数据,这样保证每次取到的数据都是最新的视频数据,这样看起来延时就稍多了。
这种方法,想之后再去试下,现在贴出,用fifo的测试程序:
//============================================================================ // Name : FIFOTest01.cpp // Author : frank // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //============================================================================ //http://blog.chinaunix.net/uid-12045105-id-2963178.html #includeusing namespace std; #define BUFSIZE 2048 #define WR 1 //写数据标志 #define RD 0 //读数据标志 typedef struct FifoType{ unsigned int buffer[BUFSIZE]; /* Circular buffer */ unsigned int w_idx; /* Index of write */ unsigned int r_idx; /* Index of read */ }*pFifoType; int fifoctl(pFifoType priv ,int data ,const unsigned char flag) { int temp = -1; unsigned int widx = 0; widx = priv->w_idx; /* Save the old index before proceeding */ if (flag == WR) //write data { /* Save it to buffer */ if (((priv->w_idx + 1)) == priv->r_idx) { /* Adjust read index since buffer is full */ /* Keep the latest one and drop the oldest one */ priv->r_idx = (priv->r_idx + 1); cout<< "buffer full\n"; } priv->buffer[priv->w_idx] = data; //cout <<"before priv->w_idx= "<< priv->w_idx + 1<< endl; priv->w_idx = (priv->w_idx + 1); cout <<"after priv->w_idx= "<< priv->w_idx<< endl; } else //read data { if ((priv->r_idx == widx)) cout << "buffer empty\n"; else { temp= priv->buffer[priv->r_idx]; priv->r_idx = (priv->r_idx + 1); cout<< "priv->r_idx " << priv->r_idx << endl; } } return temp; } int main() { int i = 0; int data = 0; pFifoType priv = new FifoType; priv->r_idx = 0; priv->w_idx = 0; for(i = 0; i < 3; i++) fifoctl(priv,i,WR); for(i = 0; i < 4 ; i++)// { data = fifoctl(priv,data,RD); cout << data << endl; } delete priv; priv = NULL; return 0; }
这个问题也是在海思群里问的各位同学,说可能l在将数据打包成RTP数据包的时候出现时间戳问题;附上聊天记录
海思-延时-问题同 10:42:51 http://bbs.csdn.net/topics/360174753 海思-延时-问题同 10:43:00 live555 MediaSubsession有个函数:getNormalPlayTime帮你计算了你想要的pts。 海思-延时-问题同 10:43:38 视频90K的采样率,根据帧率打。 海思-延时-问题同 10:44:11 好像它这个时间戳,并不是绝对时间,而是相对时间 海思-延时-问题同 10:44:20 所以可能就会越放越慢 海思-延时-问题同 10:44:27 延时越大 Frank范 10:44:41 不是越放越慢。而是一直差不多是一个速度 海思-延时-问题同 10:44:40 我之前好像就是这样的 Frank范 10:45:12 难道不是编码的速度快,而传输的速度慢么 海思-延时-问题同 10:47:13 http://xingyunbaijunwei.blog.163.com/blog/static/765380672012362040605/ 这个文章不错 Frank范 10:50:50 好, Frank范 10:51:11 你觉得是不是编码速度快,传输速度慢呢 Frank范 10:51:22 昨天有个人是这样建议我的 Frank范 10:51:29 让我做个fifo 海思-延时-问题同 10:51:29 嗯 海思-延时-问题同 10:51:39 编码不用怀疑,不会慢的 海思-延时-问题同 10:52:03 我当时是用共享内存 Frank范 10:52:12 就是编码的数据都放到缓存池中,然后来不及发 海思-延时-问题同 10:52:55 也不是,应该是时间戳问题,live555存者不发
这是另外一个热心朋友提示我的:
1、看看是不是编码本身造成的
2、时间戳有没有更新
你抓包看,看不同的数据包时间戳是不是打对了
发现epochtime数据包大概70/s,也就是说打包的时间戳是没问题的。
分包的时间戳是不变的
但是如果不同的不包的时间戳都一样,那播放器会等好久才会解一包数据
那么延时会很大
3还有即使查查每次调用到你拷贝数据的那个地方的时间,看看他调用到你拷贝数据哪里的时间每次是多少
4你可以启用一个线程编码,编码后放到队列里面,然后发送时候直接从队列里面取已经编码好的数据。
这个缓存池问题,是我刚开始知道有延迟的时候就认为是这个问题。但是后来又写了个客户端播放器,然后再去看海思这部分代码的时候就忘了一些,
再加上最近快放假了,学习效率有点地,进度比较慢。最近一周把海思的代码以及当时自己加的live555部分代码又都过了一遍,然后过完之后想先试试缓存池的问题。还真发现问题了。
(1)测试通道1,也就是640*460情况时。发现修改
stVbConf.astCommPool[1].u32BlkSize= ××;
stVbConf.astCommPool[1].u32BlkCnt= ××;
这两个参数,播放器没有反应,修改[2]的参数的时候也没有反应,但是修改[0]的时候就有反应了,我修改:
stVbConf.astCommPool[0].u32BlkSize = u32BlkSize;
stVbConf.astCommPool[0].u32BlkCnt = 5;//尤其是这个地方
发现再用我的客户端软件再去播放的时候就延时在1s之内,具体没测。难道,海思在MPP系统初始化之前所创建的视频缓存池0 ,1,2 ,视频输入的时候不管分辨率是什么样的都是先在视频缓存池0中取么。估计应该是这样的吧。之前是因为缓存池设置过大包括0,1,2所以播放延时会很大都存储在了缓存池中。
但是为什么用vlc的时候,播放一段时间之后就会卡住呢,只有自己的播放器是可以用的。
(2)测试通道0,720p情况
缓存池设置和上面的相同。可以,但是还是vlc播放不出来,只有自己的播放器可以播放。
(3)测试通道2,320*240的时候
这种情况有点特殊,应该这种低分辨率的需要的缓存小才对,但是测试的结果确是:
必须要设置
stVbConf.astCommPool[0].u32BlkSize= u32BlkSize; //每个缓存块大小768*576*2
stVbConf.astCommPool[0].u32BlkCnt= 8;//8的时候才可以
后面还要继续研究下问题所在,到底是怎么回事,更行ing.