live555实现TS码流RTSP传输
2016-09-19 18:02
507 查看
查阅网上各种资料,发现live555作为服务器实现h264码流的rtsp传输的例子很多,但关于live555实现ts流的rtsp传输的资料很少。由于项目需要,我的客户端只能实现rtsp的TS流解码,故只能自己摸索。
以下参考h264相关资料和自己理解进行编写,不当之处请理解。本工程以ts文件为数据源,通过live555服务器推送ts流,从而实现rtsp传输。
1.概述
liveMedia 库中有一系列类,基类是Medium,这些类针对不同的流媒体类型和编码。 其中的StreamFrame类文件(如MPEG4VideoStreamFramer)为流传输关键。
重要概念:
StreamFrame类:该类继承FramedSource基类,实现数据流的控制和传输。
StreamFrame(ByteStreamLiveSource) -->FramedFilter--> FramedSource----> MediaSource
FramedSource 派继承MediaSource父类,一帧码流的实现。
注意:unsigned char* fTo;
为指向发送的码流的指针,采集到视频数据后填充到该指针中即可实现码流的传输。针对TS流,必选保证每次放入fTO的数据个数为188的整数倍。
为何?因为188为TS流每帧数据的个数,如果放置个数不对,不够188的结尾帧会被舍弃,而从新放置在fto中的数据开头不是以0x47开始的,就出现了循环解析错误,于是大量马赛克就产生了。
主要步骤:1.定义自己的StreamFramer类,实现
void FramedSource::getNextFrame(unsigned char* to, unsigned maxSize,
afterGettingFunc* afterGettingFunc,
void* afterGettingClientData,
onCloseFunc* onCloseFunc,
void* onCloseClientData) {
// Make sure we're not already being read:
if (fIsCurrentlyAwaitingData) {
envir() << "FramedSource[" << this << "]::getNextFrame(): attempting to read more than once at the same time!\n";
envir().internalError();
}
fTo = to;
fMaxSize = maxSize;
fNumTruncatedBytes = 0; // by default; could be changed by doGetNextFrame()
fDurationInMicroseconds = 0; // by default; could be changed by doGetNextFrame()
fAfterGettingFunc = afterGettingFunc;
fAfterGettingClientData = afterGettingClientData;
fOnCloseFunc = onCloseFunc;
fOnCloseClientData = onCloseClientData;
fIsCurrentlyAwaitingData = True;
doGetNextFrame();
}
2.实现fTO与会话连接,自定义
主要最后返回的ByteStreamLiveSource 继承自FramedSource,定义了从文件获取source的方法,从而将ServerMedia 与source联系起来。
代码为vs2008工程,采用VLC测试,测试结果如下图所示
代码见
http://download.csdn.net/detail/xiahua882/9634000
以下参考h264相关资料和自己理解进行编写,不当之处请理解。本工程以ts文件为数据源,通过live555服务器推送ts流,从而实现rtsp传输。
1.概述
liveMedia 库中有一系列类,基类是Medium,这些类针对不同的流媒体类型和编码。 其中的StreamFrame类文件(如MPEG4VideoStreamFramer)为流传输关键。
重要概念:
StreamFrame类:该类继承FramedSource基类,实现数据流的控制和传输。
StreamFrame(ByteStreamLiveSource) -->FramedFilter--> FramedSource----> MediaSource
FramedSource 派继承MediaSource父类,一帧码流的实现。
注意:unsigned char* fTo;
为指向发送的码流的指针,采集到视频数据后填充到该指针中即可实现码流的传输。针对TS流,必选保证每次放入fTO的数据个数为188的整数倍。
为何?因为188为TS流每帧数据的个数,如果放置个数不对,不够188的结尾帧会被舍弃,而从新放置在fto中的数据开头不是以0x47开始的,就出现了循环解析错误,于是大量马赛克就产生了。
主要步骤:1.定义自己的StreamFramer类,实现
getNextFrame
重写。
getNextFrame函数来自live\liveMedia\
FramedSource
文件
void FramedSource::getNextFrame(unsigned char* to, unsigned maxSize,
afterGettingFunc* afterGettingFunc,
void* afterGettingClientData,
onCloseFunc* onCloseFunc,
void* onCloseClientData) {
// Make sure we're not already being read:
if (fIsCurrentlyAwaitingData) {
envir() << "FramedSource[" << this << "]::getNextFrame(): attempting to read more than once at the same time!\n";
envir().internalError();
}
fTo = to;
fMaxSize = maxSize;
fNumTruncatedBytes = 0; // by default; could be changed by doGetNextFrame()
fDurationInMicroseconds = 0; // by default; could be changed by doGetNextFrame()
fAfterGettingFunc = afterGettingFunc;
fAfterGettingClientData = afterGettingClientData;
fOnCloseFunc = onCloseFunc;
fOnCloseClientData = onCloseClientData;
fIsCurrentlyAwaitingData = True;
doGetNextFrame();
}
其中最后的doGetNextFrame(); 是一个虚函数,具体各种编码模式,我们可以根据自己的码流类型定义一个派生自FramedSource的类(本工程ByteStreamLiveSource
类), 重新再定义doGetNextFrame如何获得下一帧的码流,在自己重定义的doGetNextFrame() 中将fTo指向要发送的缓存即可。这样我们就实现了流的传输而非文件传输。
本工程中doGetNextFrame()代码如下:
void ByteStreamLiveSource::doGetNextFrame() { printf("doGetNextFrame=%d\n",fMaxSize); if( filesize(fp) > fMaxSize) { printf("doGetNextFrame111\n"); // fFrameSize = fread(fTo,1,fMaxSize,fp); fFrameSize = fread(fTo,1,188,fp); //取数值去TS流每帧整数倍(*n),否则容易丢包或解包错误 for(int i=0;i<10;i++) { printf("%x ",fTo[i]); } printf("\n"); } else { printf("doGetNextFrame222\n"); fFrameSize = fread(fTo,1,filesize(fp),fp); fseek(fp, 0, SEEK_SET); for(int i=0;i<10;i++) { printf("%x ",fTo[i]); } printf("\n"); } //fFrameSize = fMaxSize; nextTask() = envir().taskScheduler().scheduleDelayedTask( 0, (TaskFunc*)FramedSource::afterGetting, this); return; }
2.实现fTO与会话连接,自定义
ServerMediaSubsession
类
定义ServerMediaSubsession类H264LiveVideoServerMediaSubssion,该类由ServerMediaSubsession 派生而来。该类中有私有函数virtual
FramedSource* createNewStreamSource
,在该函数中进行重新定义即可实现。
ByteStreamLiveSource* ByteStreamLiveSource::createNew(UsageEnvironment& env, char const* fileName, unsigned preferredFrameSize, unsigned playTimePerFrame) { printf("\nByteStreamLiveSource::createNew\n"); ByteStreamLiveSource* newSource = new ByteStreamLiveSource(env, fileName, preferredFrameSize, playTimePerFrame); return newSource; }
主要最后返回的ByteStreamLiveSource 继承自FramedSource,定义了从文件获取source的方法,从而将ServerMedia 与source联系起来。
代码为vs2008工程,采用VLC测试,测试结果如下图所示
代码见
http://download.csdn.net/detail/xiahua882/9634000
相关文章推荐
- Android传感器的使用
- ListView 改变数据源后 notifyDateSetChanged不起作用
- shell脚本操作oracle数据库
- XML和对象相互转换的方法
- JAVA 8 方法引用 - Method References
- python(24)urlencode和urldecode
- [GeekBand] 探讨C++新标准之新语法——C++ 11~14
- 基于Linux的WebSphere性能调优与故障诊断
- JDK安装与环境变量配置
- TZImagePickerController 的使用
- Java对象和类
- hibernate级联关系思考
- java中Map按值排序
- 安卓版本更新的逻辑
- ALSA缓存的理解
- python_day4装饰器小结
- 格式化输出
- 解决SVN 提交时出现Attempted to lock an already-locked dir svn: Commit failed (details follow):
- http://stackoverflow.com/questions/12318062/pass-parameters-to-spring-methodinvokingfactorybean-arguments-list?answertab=votes
- PHP实现微信公众平台开发 全套视频资源下载