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
原创粉丝点击