您的位置:首页 > 其它

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类,实现
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: