您的位置:首页 > 编程语言

live555源代码详细分析解析,教你如何使用live555接收rtsp数据

2014-12-03 11:30 726 查看
最近继续看了看live555的代码,进行了一些具体的实验。

对live555的部分特性有了一定的了解。

稍微看了网上的一些关于live555的文章,千篇一律。

大部分都是转载自一个人的博客。

很少人进行一些实验或进行一些比较深入的代码阅读,然后写出一些其他的经验之谈。

我想应该是很多人都进行了代码阅读,理解了代码,但是就是懒的写一些东西吧。

这里自夸一下自己,哈,hanyionet真是大好人,大闲人。

这里我尽我自己一份小小的力,给大家写一些小小的经验之谈。如果有时间的话,我将写一些更多的文章关于live555。
以前在网上看到一个论坛有人问:

使用live555的testMpeg1or2VideoReceiver在其FrameSink的afterGettingFrame1(unsigned frameSize, struct timeval presentationTime) 接受的buffer是否是代表一个帧。

大概是这个问题。
当时看到没有太在意。

因为没有搞这部分。

刚刚做了一些实验。

根据实验的结果。我可以得出:

live555如果采用 A test program that reads a MPEG-1 or 2 Video Elementary Stream file就是testMpeg1or2VideoStreamer.cpp发送rtp包,那么得到的rtp包包含的就不是一个完整的帧。
如果不是完整的一帧那么我们该如何进行“正确”的解码呢。

例如我们使用的是FFmpeg的avcodec_decode_video()进行解码。

那么如果要正确解码,就必须将一个完整的帧的buffer放入这个解码API中去。

如果没有正确的一帧,我们直接将buffer放入avcodec_decode_video()进行解码,会有什么结果呢。

我们就会得到抖动的画面,带着马赛克,或者画面模糊等等。

这说明了,我们没有正确的解码。
接下来的问题是,我们该如何得到完整的一帧呢。

因为我们现在得到的是一些buffer(它为unsigned char*)。

很多人会想到要使用avcodec_decode_video()进行解码然后得到的例如AVFrame *_decoded_frame这样的_decoded_frame的指针。

通过类似_decoded_frame->pict_type == FF_I_TYPE 或FF_P_TYPE,进行判断。

但是我进行的实验证明这是不可以的,也就是说无法正确地判断这些buffer是否为同一帧的buffer。

我使用的avcodec_find_decoder( CODEC_ID_MPEG2VIDEO );

可能其他的codec可以通过_decoded_frame->pict_type == FF_I_TYPE 或FF_P_TYPE,进行判断。

但是在CODEC_ID_MPEG2VIDEO或CODEC_ID_MPEG1VIDEO的情况下不行。
经过一点思考。

我发现使用live555中afterGettingFrame1(unsigned frameSize, struct timeval presentationTime) 的presentationTime进行判断就可以判断出是得到的buffer是否是同一帧的。

具体实现如下,我只是提供一点思路。

具体实现请自己搞定。

请不要问我如何编。

很简单,请想想吧,请不要写信要源代码。
一点思路:
可以将每次进入afterGettingFrame1的presentationTime进行判断,如果是相同的

那么将相同的buffer存入一个buffer中去,也就是两个buffer连接在一起,不知道我是否表述的清晰。

其实就是使用memcpy这个函数。

当presntationTime不同时候,将以前存的buffer(已经是完整一帧)传给avcodec_decode_video()就可以正确地解一帧了。
当然了,这里在提一下,我们最好设两个thread,一个thread进行live555的接受,另一个thread进行解码使用FFmpeg或其他。

两个thread如果读取同一变量,请设定mutex进行锁。
在进行一些延伸的思考,为什么可以使用presentationTime判断是否为同一帧呢。

如果读过live555的http://www.live555.com/liveMedia ... ce_8cpp-source.html

liveMedia/DeviceSource.cpp的朋友就知道了,非常非常不负责任的简单地说,如果我们想自己进行编码然后再播放那么就要使用DeviceSource这个类,自己进行一些拓展,DeviceSource是在服务器端,进行rtp包发送前的处理。

DeviceSource里的deliverFrame()函数的用途就是将编码后产生的buffer连同想对应的presentationTime一起“发送出去”,如果熟悉FFmpeg可以使用avcodec_encode_video()进行编码。

看到了吧,在这里就可以找到了presentationTime和一帧里的buffer之间的联系。

当然了,我的这个解释很不负责任,极度简单。

只是通过一个例子进行说明。

有兴趣的朋友可以通过进行更进一步的代码阅读了解presentationTime和一帧里的buffer之间的关系。
好了,随手写一些东西,比较不见条理性。希望大家见谅。

希望大家在需要的时候,能搜索到这篇文章,并得到一点帮助。
注意,以上的解释和记录比较不负责任,极度简单,因为没有进行更系统的代码阅读和分析,不能保证以上所诉完全正确
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: