live555实现TS码流RTSP传输

    xiaoxiao2023-03-16  7

        查阅网上各种资料,发现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的整数倍。

    为何?因为188TS流每帧数据的个数,如果放置个数不对,不够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

    转载请注明原文地址: https://ju.6miu.com/read-1152662.html
    最新回复(0)