live555学习三:RTP数据流的获取
来源:互联网 发布:linux漏洞英文怎么说 编辑:程序博客网 时间:2024/05/18 00:10
前面有说到流struct streamState ,该结构体中包含了Track和source,这里就先说说这个source的获取
FramedSource* mediaSource = createNewStreamSource(clientSessionId,streamBitrate);这个函数是一个纯虚函数,用来获取数据流,
对于h264数据流,会调用这个函数
FramedSource* H264VideoFileServerMediaSubsession::createNewStreamSource(unsigned /*clientSessionId*/, unsigned& estBitrate) { estBitrate = 500; // kbps, estimate // Create the video source: ByteStreamFileSource* fileSource = ByteStreamFileSource::createNew(envir(), fFileName); if (fileSource == NULL) return NULL; fFileSize = fileSource->fileSize(); // Create a framer for the Video Elementary Stream: return H264VideoStreamFramer::createNew(envir(), fileSource);}这个函数实现了本地文件的流化并生成数据流,fFileName就是本地文件。若要实现实时数据流的传输,需要重写这个函数,借鉴ProxyServerMediaSource.cpp文件中的函数:
FramedSource* ProxyServerMediaSubsession::createNewStreamSource(unsigned clientSessionId, unsigned& estBitrate) { ProxyServerMediaSession* const sms = (ProxyServerMediaSession*)fParentSession; if (verbosityLevel() > 0) { envir() << *this << "::createNewStreamSource(session id " << clientSessionId << ")\n"; } // If we haven't yet created a data source from our 'media subsession' object, initiate() it to do so: if (fClientMediaSubsession.readSource() == NULL) { fClientMediaSubsession.receiveRawMP3ADUs(); // hack for MPA-ROBUST streams fClientMediaSubsession.receiveRawJPEGFrames(); // hack for proxying JPEG/RTP streams. (Don't do this if we're transcoding.) fClientMediaSubsession.initiate(); if (verbosityLevel() > 0) { envir() << "\tInitiated: " << *this << "\n"; } if (fClientMediaSubsession.readSource() != NULL) { // Add to the front of all data sources a filter that will 'normalize' their frames' presentation times, // before the frames get re-transmitted by our server: char const* const codecName = fClientMediaSubsession.codecName(); FramedFilter* normalizerFilter = sms->fPresentationTimeSessionNormalizer->createNewPresentationTimeSubsessionNormalizer(fClientMediaSubsession.readSource(), fClientMediaSubsession.rtpSource(),codecName); fClientMediaSubsession.addFilter(normalizerFilter); // Some data sources require a 'framer' object to be added, before they can be fed into // a "RTPSink". Adjust for this now: if (strcmp(codecName, "H264") == 0) {fClientMediaSubsession.addFilter(H264VideoStreamDiscreteFramer ::createNew(envir(), fClientMediaSubsession.readSource())); } else if (strcmp(codecName, "H265") == 0) {fClientMediaSubsession.addFilter(H265VideoStreamDiscreteFramer ::createNew(envir(), fClientMediaSubsession.readSource())); } else if (strcmp(codecName, "MP4V-ES") == 0) {fClientMediaSubsession.addFilter(MPEG4VideoStreamDiscreteFramer ::createNew(envir(), fClientMediaSubsession.readSource(), True/* leave PTs unmodified*/)); } else if (strcmp(codecName, "MPV") == 0) {fClientMediaSubsession.addFilter(MPEG1or2VideoStreamDiscreteFramer ::createNew(envir(), fClientMediaSubsession.readSource(), False, 5.0, True/* leave PTs unmodified*/)); } else if (strcmp(codecName, "DV") == 0) {fClientMediaSubsession.addFilter(DVVideoStreamFramer ::createNew(envir(), fClientMediaSubsession.readSource(), False, True/* leave PTs unmodified*/)); } } if (fClientMediaSubsession.rtcpInstance() != NULL) { fClientMediaSubsession.rtcpInstance()->setByeHandler(subsessionByeHandler, this); } } ProxyRTSPClient* const proxyRTSPClient = sms->fProxyRTSPClient; if (clientSessionId != 0) { // We're being called as a result of implementing a RTSP "SETUP". if (!fHaveSetupStream) { // This is our first "SETUP". Send RTSP "SETUP" and later "PLAY" commands to the proxied server, to start streaming: // (Before sending "SETUP", enqueue ourselves on the "RTSPClient"s 'SETUP queue', so we'll be able to get the correct // "ProxyServerMediaSubsession" to handle the response. (Note that responses come back in the same order as requests.)) Boolean queueWasEmpty = proxyRTSPClient->fSetupQueueHead == NULL; if (queueWasEmpty) {proxyRTSPClient->fSetupQueueHead = this; } else {proxyRTSPClient->fSetupQueueTail->fNext = this; } proxyRTSPClient->fSetupQueueTail = this; // Hack: If there's already a pending "SETUP" request (for another track), don't send this track's "SETUP" right away, because // the server might not properly handle 'pipelined' requests. Instead, wait until after previous "SETUP" responses come back. if (queueWasEmpty) {proxyRTSPClient->sendSetupCommand(fClientMediaSubsession, ::continueAfterSETUP, False, proxyRTSPClient->fStreamRTPOverTCP, False, proxyRTSPClient->auth());++proxyRTSPClient->fNumSetupsDone;fHaveSetupStream = True; } } else { // This is a "SETUP" from a new client. We know that there are no other currently active clients (otherwise we wouldn't // have been called here), so we know that the substream was previously "PAUSE"d. Send "PLAY" downstream once again, // to resume the stream: if (!proxyRTSPClient->fLastCommandWasPLAY) { // so that we send only one "PLAY"; not one for each subsessionproxyRTSPClient->sendPlayCommand(fClientMediaSubsession.parentSession(), NULL, -1.0f/*resume from previous point*/, -1.0f, 1.0f, proxyRTSPClient->auth());proxyRTSPClient->fLastCommandWasPLAY = True; } } } estBitrate = fClientMediaSubsession.bandwidth(); if (estBitrate == 0) estBitrate = 50; // kbps, estimate return fClientMediaSubsession.readSource();}
上面两个函数分别实现了本地文件的流化和实时文件的流化
0 0
- live555学习三:RTP数据流的获取
- live555学习一:数据流的处理
- live555 rtsp rtp学习笔记
- live555 rtsp rtp学习笔记
- live555学习二:数据流的发送(PLAY请求的处理)
- live555学习(十) --RTP的打包与发送
- Live555学习笔记(三)—— RTSP命令处理及RTP,RTCP服务建立
- 基于live555的rtp/rtcp研究
- 基于live555的rtp/rtcp研究
- live555里的rtp时间戳算法
- 基于live555的rtp/rtcp研究
- live555学习笔记12-h264 rtp包的时间戳
- live555学习笔记12-h264 rtp包的时间戳
- live555学习笔记12-h264 rtp包的时间戳
- live555学习笔记12-h264 rtp包的时间戳
- 流媒体Live555学习(三)
- 流媒体Live555学习(三)
- live555学习笔记6-建立RTP会话
- Centos yum源管理
- Python快速教程
- 套接字编程简介
- Framework Manager入门教程(五) - 固定显示4个季度(FM建模)(下)
- fatal error C1083: Cannot open precompiled header file: 'Debug/Graphic2.pch'
- live555学习三:RTP数据流的获取
- C++ const
- Camera服务之--Client
- css中.class和id选择器的异同点
- QlikView报表显示连续若干个月内活跃用户的数量
- C/C++常用头文件
- Jabber 协议概述XMPP即时通讯
- 互联网产业吸引全球风投来蓉
- Oracle 百万行数据查询优化