嵌入式流媒体音视频服务器EasyIPCamera中live555发送性能优化点

来源:互联网 发布:淘宝网修改手机号码 编辑:程序博客网 时间:2024/06/07 00:06

EasyIPCamera流媒体服务器

今年EasyDarwin团队在给国内某最大的金融安防公司做技术咨询的时候,开发了一款适用于嵌入式IPCamera、NVR的RTSP流媒体服务器:EasyIPCamera,EasyIPCamera的核心是基于live555进行封装的,外围增加对live555 RTSPServer的调用接口,更加方便海思等安防芯片进行RTSPServer服务的建立,EasyIPCamera在海思3156A芯片上的性能经过我们半年多的调试,目前已经可以稳定在4路1080P并发:

  • TCP/UDP 方式分别连接3路下,1080P 4M 定码率,音频格式G711(64K)G726(16K 24K 32K 40K)AAC(64K 96K 128K)都没问题;
  • TCP/UDP 方式分别连接4路下,1080P 4M 定码率,音频格式G711(64K)G726(16K 24K 32K 40K)AAC(64K 96K 128K)都没问题;

    EasyIPCamera嵌入式流媒体服务器

live555网络发送优化

在live555的RTP发送类MultiFramedRTPSink中的sendPacketIfNecessary()函数中,我们改造原有的live555发送过程,增加了live555在嵌入式arm中网络发送的速度,提升了嵌入式RTSPServer流媒体服务器的发送性能,具体代码:

void MultiFramedRTPSink::sendPacketIfNecessary() {  if (fNumFramesUsedSoFar > 0) {    // Send the packet:#ifdef TEST_LOSS    if ((our_random()%10) != 0) // simulate 10% packet loss ######endif      if (!fRTPInterface.sendPacket(fOutBuf->packet(), fOutBuf->curPacketSize())) {    // if failure handler has been specified, call it    if (fOnSendErrorFunc != NULL) (*fOnSendErrorFunc)(fOnSendErrorData);      }    ++fPacketCount;    fTotalOctetCount += fOutBuf->curPacketSize();    fOctetCount += fOutBuf->curPacketSize()      - rtpHeaderSize - fSpecialHeaderSize - fTotalFrameSpecificHeaderSizes;    ++fSeqNo; // for next time  }  if (fOutBuf->haveOverflowData()      && fOutBuf->totalBytesAvailable() > fOutBuf->totalBufferSize()/2) {    // Efficiency hack: Reset the packet start pointer to just in front of    // the overflow data (allowing for the RTP header and special headers),    // so that we probably don't have to "memmove()" the overflow data    // into place when building the next packet:    unsigned newPacketStart = fOutBuf->curPacketSize()      - (rtpHeaderSize + fSpecialHeaderSize + frameSpecificHeaderSize());    fOutBuf->adjustPacketStart(newPacketStart);  } else {    // Normal case: Reset the packet start pointer back to the start:    fOutBuf->resetPacketStart();  }  fOutBuf->resetOffset();  fNumFramesUsedSoFar = 0;  if (fNoFramesLeft) {    // We're done:    onSourceClosure();  } else {#if 0   //原有方法是重新计算一个Task时间,让live555下一次循环再将未发送完的包继续发送完成    // We have more frames left to send.  Figure out when the next frame    // is due to start playing, then make sure that we wait this long before    // sending the next packet.    struct timeval timeNow;    gettimeofday(&timeNow, NULL);    int secsDiff = fNextSendTime.tv_sec - timeNow.tv_sec;    int64_t uSecondsToGo = secsDiff*1000000 + (fNextSendTime.tv_usec - timeNow.tv_usec);    if (uSecondsToGo < 0 || secsDiff < 0) { // sanity check: Make sure that the time-to-delay is non-negative:      uSecondsToGo = 0;    }    // Delay this amount of time:    //nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecondsToGo, (TaskFunc*)sendNext, this);#else   //现有方法是不经过循环,直接将未发送的包全部发完再进行live555的eventLoop循环    sendNext(this);#endif  }}

获取更多信息

邮件:support@easydarwin.org

WEB:www.EasyDarwin.org

Copyright © EasyDarwin.org 2012-2016

EasyDarwin

0 0