ffmpeg和live555的关系,怎么ndk 使用live555?

1941人阅读
& & 本人视频监控行业的码农一枚,将平时快速学习的内容进行记录和分享,因水平有限,没学过音视频的高深理论和技术,所写内容多侧重开源库的使用,比较肤浅,如果文中有什么不足,希望大家多多指点。&
& & 如本文题目所述,文中介绍一下如何用接收rtsp实时流后对实时流进行解码,解码成yuv420。
& & live555 中的例子testRTSPClient.cpp 提供了一个创建rtsp客户端接收视频流的例子,使用该例子可从支持rtsp协议的摄像机获取视频流。因为我用的相机提供的是h264编码的实时流,并且我希望在接收实时流的时候保存录像,因此对testRTSPClient.cpp进行了简单的修改。 continueAfterSETUP 函数中,进行如下修改:
scs.subsession-&sink=H264VideoFileSink::createNew(env,&test.h264&,NULL,550000,false);&&& 使用H264VideoFileSink处理接收到的h264视频流。(我用的相机多是只有视频,如果有音频需要根据实际情况处理,本文所做的相应编码全部是只接收视频流的。如果对于有音频的相机,只想接收视频流可以在MediaSession.cpp &的createSourceObjects 函数中,在if
(createSimpleRTPSource)&之前把createSimpleRTPSource 置为 false)。经过后期反思,可以自己继承filesink后添加和自己业务相关的逻辑。
& & H264VideoFileSink继承了FileSink,实际上,每一帧视频都是在filesink中写入test.h264文件的。因此在filesink中进行处理。void FileSink::addData(unsigned char const* data, unsigned dataSize,struct timeval presentationTime) 函数的传入参数,unsigned
char const* data, unsigned dataSize 分别是一帧的内容和一帧的长度(这个视频帧没有h264的开头0001,void H264VideoFileSink::afterGettingFrame 这个函数中有添加0001的 代码)。FileSink::addData 中获取的一帧视频(接收到的rtp包,有一个mark算一帧,因此NAL nal_unit_type中的6(SEI)、7(SPS)、8(PPS)都是分开的)。关于如何判断帧类型,可以利用可以利用data[1]和0x1f进行位或运算。在用ffmpeg解码时,sps,pps和之后的idr帧是要一起传入解码器的,其他的sei我是直接丢弃,其实也可以sps+pps+sei+idr一起传入ffmpeg。先上一段代码,这段代码用于将需要解码的一帧存入一个缓存区中,之后ffmpeg
解码缓存区的数据。
进行如下定义:
typedef struct
unsigned char *//存储接收到的完整一帧
}//存储一帧
bufnum 200
mybuf encodebuf[bufnum];& & & && if (fOutFid != NULL && data != NULL) {
int iRet=-1;
iRet=data[0] & 0x1f;
if ((iRet==6||iRet==9)&&(m_start==1))//sei等直接丢弃
// fwrite(data, 1, dataSize, fOutFid);
if ((iRet==7)&&(m_start==1))
memmove(encodebuf[index].realbuf,sHead,4);
encodebuf[index].realsize+=4;
memmove(encodebuf[index].realbuf+ encodebuf[index].realsize,data,dataSize);
encodebuf[index].realsize+=dataS
if ((iRet==8)&&(m_start==1))//pps
memmove(encodebuf[index].realbuf+encodebuf[index].realsize,sHead,4);
encodebuf[index].realsize+=4;
memmove(encodebuf[index].realbuf+ encodebuf[index].realsize,data,dataSize);
encodebuf[index].realsize+=dataS
if((iRet==7)&&(m_start==0))//sps
memmove(encodebuf[index].realbuf,sHead,4);
encodebuf[index].realsize+=4;
fwrite(sHead,1,4,fOutFid);
memmove(encodebuf[index].realbuf+ 4,data,dataSize);
encodebuf[index].realsize+=dataS
m_start++;
if (m_start&0)
fwrite(data, 1, dataSize, fOutFid);
if (iRet!=0&&iRet!=7&&iRet!=8)
memmove(encodebuf[index].realbuf+ encodebuf[index].realsize,sHead,4);
encodebuf[index].realsize+=4;
memmove(encodebuf[index].realbuf+ encodebuf[index].realsize,data,dataSize);
encodebuf[index].realsize+=dataS
if (iRet==5)//idr
if (m_pos==1)
if (encodebuf[index-1].realsize==0)
printf(&&);
PostThreadMessage(ThreadID,MY_MSG_WRITE,index,0);
if (index==bufnum)
以上是在live555中针对拼凑解码一帧的修改逻辑。再重复一次:解码的第一帧要把sps+pps+idr传入ffmpeg进行解码,因此要把这三帧拼到一起。再从ffmpeg解码说起,本人对ffmpeg的学习,大多倚仗雷霄骅在csdn上的博客,具体对ffmpeg的讲解就不在赘述,雷神在csdn上对ffmpeg有很好的讲解。简而言之就是初始化ffmpeg
相关的变量后调用avcodec_decode_video2函数解码视频。
直接上解码的那小段代码,说明一下:
char* input=encodebuf[myindex].
int nLen=encodebuf[myindex].
AVFrame *frame = NULL;
frame = av_frame_alloc();
av_init_packet(&packet);
packet.size = nL//一帧的长度
packet.data =//从缓冲区取出的一帧
packet.pts=i_
if (!frame) {
ret = AVERROR(ENOMEM);
ret = avcodec_decode_video2(dec_ctx, frame,&got_frame, &packet);经过以上过程,解码后的yuv数据就到了frame中 。yuv可以用来进行重新编码,也可以直接用来显示:如用opengl或者d3d进行渲染。
&& &对应该文,上传一份完整的测试代码,用了live555接收实时视频,ffmpeg 解码, x264编码,rtp打包 。代码比较乱,测试用,不过文中所述内容在代码中都有体现。上传的代码因为平时测试用所以有些地方有比较粗暴的修改,比如H264VideoFileSink中删除了一些函数,还有FileSink种的一些修改。
&下篇博客会讲解一下解码后的实时流如何重新编码。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:4801次
排名:千里之外基于live555的rtsp客户端接收及ffmpeg解码_点撒打算_天涯博客
今日访问:[$DayVisitCount$]
总访问量:12565
开博时间:
博客排名:86040
(21)(26)(25)(21)(24)(46)(36)(53)(39)(41)(42)(32)(60)(37)(12)(6)(10)(17)(32)
  很多人用live555都是为了做一个rtsp的客户端。
Live555提供了一个功能丰富的rtsp客户端:openRTSP。很多初学者都是通过它来学习live及rtsp的。这个程序修改做单路播放很容易,不过,一般客户端需要同时做多路播放或录像,这时再采用这个程序就比较麻烦了。而且,程序里也注明:
//&NOTE:&If&you&want&to&develop&your&own&RTSP&client&application&(or&embed&RTSP&client&functionality&into&your&own&application),
//&then&we&don't&recommend&using&this&code&as&a&model,&because&it&is&too&complex&(with&many&options).
//&Instead,&we&recommend&using&the&"testRTSPClient"&application&code&as&a&model.
建议用testRTSPClient,代码简洁,但也足够用了。
testRTSPClient.cpp,本地接收流数据后,简单log一下,没做任何处理,这样正合适改造,而且它支持多路。下面简单以这个cpp为例,封装一个可重用的class&demo来。
先简单分析一下流程:
1&openURL,&开始播放。
2&在openURL里面,调用sendDescribeCommand,向服务器端发请求。然后,通过回调函数处理。
3&如果没有错误的话,env-&taskScheduler().doEventLoop(&eventLoopWatchVariable);这里阻塞执行。
4&DummySink,这个是数据的回调,DummySink::afterGettingFrame这里取到数据。
在这个程序里,main里面调用:
for&(int&i&=&1;&i&&=&argc-1;&++i)&{
&&&&openURL(*env,&argv[0],&argv[i]);
void&shutdownStream(RTSPClient*&rtspClient,&int&exitCode&=&1);
这里是结束某个流,rtspClient是由openURL创建的。
这就实现了多路的同时播放。
如果要简单地处理,其实只要把openURL和shutdownStream封装成起来就可以了。
下面是简单接口的示例:
class&CRTSPSession&
&CRTSPSession();
&virtual&~CRTSPSession();
&int&startRTSPClient(char&const*&progName,&char&const*&rtspURL,&int&debugLevel);
&int&stopRTSPClient();
&int&openURL(UsageEnvironment&&env,&char&const*&progName,&char&const*&rtspURL,&int&debugLevel);
&RTSPClient*&m_rtspC
&char&eventLoopWatchV
&pthread_t&
&string&m_rtspU
&string&m_progN
&int&m_debugL
&static&void&*rtsp_thread_fun&(void&*param);
&void&rtsp_fun();
CRTSPSession::CRTSPSession()
&m_rtspClient&=&NULL;
&m_running&=&
&eventLoopWatchVariable&=&0;
CRTSPSession::~CRTSPSession()
int&CRTSPSession::startRTSPClient(char&const*&progName,&char&const*&rtspURL,&int&debugLevel)
&m_progName&=&progN
&m_rtspUrl&=&rtspURL;
&m_debugLevel&=&debugL
&eventLoopWatchVariable&=&0;
&int&r&=&pthread_create(&tid,&NULL,&rtsp_thread_fun,&this);
&perror&("pthread_create()");
&return&-1;
&return&0;
int&CRTSPSession::stopRTSPClient()
&eventLoopWatchVariable&=&1;
&return&0;
void&*CRTSPSession::rtsp_thread_fun(void&*param)
&CRTSPSession&*pThis&=&(CRTSPSession*)
&pThis-&rtsp_fun&();
&return&NULL;
void&CRTSPSession::rtsp_fun()
&//::startRTSP(m_progName.c_str(),&m_rtspUrl.c_str(),&m_ndebugLever);
&TaskScheduler*&scheduler&=&BasicTaskScheduler::createNew();
&UsageEnvironment*&env&=&BasicUsageEnvironment::createNew(*scheduler);
&if&(openURL(*env,&m_progName.c_str(),&m_rtspUrl.c_str(),&m_debugLevel)&==&0)
&m_nStatus&=&1;
&env-&taskScheduler().doEventLoop(&eventLoopWatchVariable);
&m_running&=&
&eventLoopWatchVariable&=&0;
&if&(m_rtspClient)
&shutdownStream(m_rtspClient,0);
&m_rtspClient&=&NULL;
&env-&reclaim();&
&env&=&NULL;
&scheduler&=&NULL;
&m_nStatus&=&2;
int&CRTSPSession::openURL(UsageEnvironment&&env,&char&const*&progName,&char&const*&rtspURL,&int&debugLevel)
&m_rtspClient&=&ourRTSPClient::createNew(env,&rtspURL,&debugLevel,&progName);
&if&(m_rtspClient&==&NULL)&
&env&&&&"Failed&to&create&a&RTSP&client&for&URL&\""&&&&rtspURL&&&&"\":&"&&&&env.getResultMsg()&&&&"\n";
&return&-1;
&((ourRTSPClient*)m_rtspClient)-&m_nID&=&m_nID;
&m_rtspClient-&sendDescribeCommand(continueAfterDESCRIBE);&
&return&0;
//&A&function&that&outputs&a&string&that&identifies&each&stream&(for&debugging&output).&Modify&this&if&you&wish:
UsageEnvironment&&operator&&(UsageEnvironment&&env,&const&RTSPClient&&rtspClient)&{
&return&env&&&&"[URL:\""&&&&rtspClient.url()&&&&"\"]:&";
//&A&function&that&outputs&a&string&that&identifies&each&subsession&(for&debugging&output).&Modify&this&if&you&wish:
UsageEnvironment&&operator&&(UsageEnvironment&&env,&const&MediaSubsession&&subsession)&{
&return&env&&&&subsession.mediumName()&&&&"/"&&&&subsession.codecName();
void&usage(UsageEnvironment&&env,&char&const*&progName)&{
&env&&&&"Usage:&"&&&&progName&&&&"&&rtsp-url-1&&...&&rtsp-url-N&\n";
&env&&&&"\t(where&each&&rtsp-url-i&&is&a&\"rtsp://\"&URL)\n";
这个简单的class,是在testRTSPClient.cpp上简单修改的,其他的函数都保持不变,只是把open和shutdown合在了一个class里面,然后启动一个线程。
因为这里的
&env-&taskScheduler().doEventLoop(&eventLoopWatchVariable);是阻塞的。当eventLoopWatchVariable为1的时候,live的doEventLoop结束循环。
testRTSPClient.cpp里的做法是,当eventLoopWatchVariable为1的时候,结束所有流。而实际的客户端可以任意选择某一路停止,其他还是播放,所以为每一路创建一个线程,这样可以控制只停止该路。
上海青大实训,最务实的,我们的口号是:解决80,90后们与用人单位的&最后一公里&问题,我们将充分调研,根据市场用人需求的变动设置更加科学的科目,同时积极拓展就业渠道,为我们的学员提供最大的就业保障,就到青大实训查看: 6797|回复: 6
在线时间10 小时注册时间最后登录阅读权限100帖子精华0积分8UID180986
新手上路, 积分 8, 距离下一级还需 42 积分
各位大虾,本人刚开始接触ffmpeg,想把网络摄像头捕获的视频流进行转码。
摄像头传入视频流是mjpeg格式的,用ffmpeg转码成h264的格式,并使用RTP进行传输。转码是成功了,但是使用ffplay播放的时候有延迟,而且随着时间的推移,这个延迟变得越来越大,最后视频会卡住。
请教各位大虾,这是什么原因导致的,该怎么解决啊?
使用ffmpeg进行转码的命令我是这么写的
ffmpeg –f mjpeg –i http://(IP Camara地址)/videostream.cgi?user=admin\&pwd= -s 320*240 -r 25 –vcodec libx264 –an
其中的feed0.ffm是在ffserver.conf里面配置的,在ffserver.conf里面设置了Format是avi,VideoBitRate是64,VideoBufferSize是40,VideoFrameRate是25,VideoSize是320x240
网络摄像头的帧率是25fps,但这条命令的输出帧率好像不固定,刚开始是100多,然后逐渐的往下降,但是降到26~27fps的时候就基本恒定,不知道是不是因为帧率不同而导致的解码后播放延迟越来越大。
在线时间10 小时注册时间最后登录阅读权限100帖子精华0积分8UID180986
新手上路, 积分 8, 距离下一级还需 42 积分
经过这两天的研究测试结果发现,在进行转码的时候,加上一个-b:v 500k(默认200k)参数,貌似没有了解码延迟的问题。
但接下来又碰到个问题,我需要将转码后的h264码流使用RTP发送到Android手机上进行播放,由RTSP协议负责控制。但是播放的过程中发现延迟也是越来越大,最后导致视频卡住。
Android的VideoView控件可以作为RTSP的客户端,播放RTSP串流,我做了个RTSP的服务器端,不知道是协议的通信字段出了问题,还是SDP描述信息出了问题,导致播放延迟越来越大的现象。
后来我用VLC播放器试了一下,也出现了这样的现象。
各位大虾有知道是怎么回事的么?
在线时间10 小时注册时间最后登录阅读权限100帖子精华0积分8UID180986
新手上路, 积分 8, 距离下一级还需 42 积分
今天使用VLC播放器播放同样的RTP流,也是使用RTSP协议负责控制,竟然发现延迟比较小(2s左右),而且这个延迟基本是固定的。
但使用Android的VideoView控件播放时,就出现了上面的现象,网上有人说VideoView只能播放恒定帧率的实时流。我把mjpeg格式的视频流转成h264格式后,输出结果显示帧率是变化的,不知道是不是这个原因导致延迟的问题。
想请教下各位大虾。。。
在线时间10 小时注册时间最后登录阅读权限100帖子精华0积分8UID180986
新手上路, 积分 8, 距离下一级还需 42 积分
哎,没回复。。。问题丢给后援团
在线时间10 小时注册时间最后登录阅读权限100帖子精华0积分8UID180986
新手上路, 积分 8, 距离下一级还需 42 积分
最近发现Android上面也有VLC播放器,下载了个试用版,使用结果跟PC上的VLC一样,没有多少延迟,看来是播放器的播放策略的问题。
据说VLC是使用FFMpeg+Live555实现的,不知能否作为Android的控件使用,就像VideoView一样。
在线时间27 小时注册时间最后登录阅读权限100帖子精华0积分20UID84393
新手上路, 积分 20, 距离下一级还需 30 积分
楼主rtp打包是如何设计的
在线时间49 小时注册时间最后登录阅读权限100帖子精华0积分86UID204529
注册会员, 积分 86, 距离下一级还需 114 积分
不要只生成H264文件,试一下生成某种多媒体容器的格式,例如生成包含h264视频的mkv文件试一下,看一下播放是否还会有延迟
good good study
day day up
Powered by用live555+ffmpeg做iOS平台的实时视频播放
[问题点数:80分,结帖人wj]
用live555+ffmpeg做iOS平台的实时视频播放
[问题点数:80分,结帖人wj]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2015年4月 移动开发大版内专家分月排行榜第二
2015年5月 移动开发大版内专家分月排行榜第三2015年3月 移动开发大版内专家分月排行榜第三2014年10月 移动开发大版内专家分月排行榜第三
2015年4月 移动开发大版内专家分月排行榜第二
2015年5月 移动开发大版内专家分月排行榜第三2015年3月 移动开发大版内专家分月排行榜第三2014年10月 移动开发大版内专家分月排行榜第三
2015年4月 移动开发大版内专家分月排行榜第二
2015年5月 移动开发大版内专家分月排行榜第三2015年3月 移动开发大版内专家分月排行榜第三2014年10月 移动开发大版内专家分月排行榜第三
匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。&vlc+ffmpeg+live555_install
秒后自动跳转到登录页
(奖励10下载豆)
快捷登录:
举报类型:
不规范:上传重复资源
不规范:标题与实际内容不符
不规范:资源无法下载或使用
其他不规范行为
违规:资源涉及侵权
违规:含有危害国家安全等内容
违规:含有反动/色情等内容
违规:广告内容
详细原因:
任何违反下载中心规定的资源,欢迎Down友监督举报,第一举报人可获5-10下载豆奖励。
戴尔服务器新品来袭
Weblogic10.3.6集群
OpenStack错误排除(
OpenStack错误排除(
openstack虚拟化云计
Redis入门学习必备教
Windows2008故障转移
vlc+ffmpeg+live555_install
上传时间:
技术分类:
资源评价:
(4位用户参与评价)
已被下载&27&次
(1)安装环境 最近要进行流播放,需要安装VLC,安装了ubuntu10.04,在一个干净的环境中安装,终于安装成功,先总结以备参考。1.安装编译环境 1)gcc/gcc-c++/gdb/make等工具
sudo apt-get install build-essential 2)
sudo apt-get install automake 3)
sudo apt-get install libtool 4)
sudo apt-get install libgtk2.0-dev 2.ffmpeg所需要的包 一、FFMEPG安装前的支持软件包1、lame 支持mp3
(4位用户参与评价)
down友评价
51CTO下载中心常见问题:
1.如何获得下载豆?
1)上传资料
2)评论资料
3)每天在首页签到领取
4)购买VIP会员服务,无需下载豆下载资源
5)更多途径:点击此处
2.如何删除自己的资料?
下载资料意味着您已同意遵守以下协议:
1.资料的所有权益归上传用户所有
2.未经权益所有人同意,不得将资料中的内容挪作商业或盈利用途
3.51CTO下载中心仅提供资料交流平台,并不对任何资料负责
4.本站资料中如有侵权或不适当内容,请邮件与我们联系()
5.本站不保证资源的准确性、安全性和完整性, 同时也不承担用户因使用这些资料对自己和他人造成任何形式的伤害或损失
下载1000次
下载1057次
下载1693次
相关专题推荐
磁盘阵列简称RAID,有“价格便宜且多
网络存储系统的搭建能够为我们带来极
VMware是提供一套虚拟机解决方案的软
从开发、测试、生产三部曲这样的运作
本专题为vmware中文视频教程,在线视
本专题介绍了weblogic服务器在企业应
Vmware View是Vmware的桌面和应用虚拟
vSphere不是一个单独的产品,它由一系
本专题全面深入讲解Windows Server 2
本专题收集了高俊峰老师讲解的系统集
IBM TSM 备份软件实战教学视频,包含
菜鸟腾飞安全网VIP_精通VMware虚拟机
2013年传智播客WebService视频教程,
Active Directory 实操作参考系列,本
服务器虚拟化技术以VMware公司的vSph
LoadRunner,是一种预测系统行为和性
本周下载热点
意见或建议:
联系方式:
您已提交成功!感谢您的宝贵意见,我们会尽快处理

我要回帖

更多关于 live555 ffmpeg 的文章

 

随机推荐