基于LIVE555的RTSP QoS实现
如何从OnDemandServerMediaSubsession类以及继承类对象中获取RTCP信息(句柄)
OnDemandServerMediaSubsession.cpp void StreamState::startPlaying函数中添加:
fRTCPInstance->setRRHandler(fMaster.fRRHandlerTask, fMaster.fRRHandlerClientData);
OnDemandServerMediaSubsession.hh 中OnDemandServerMediaSubsession添加两个成员:
TaskFunc* fRRHandlerTask; void* fRRHandlerClientData;
以及成员函数
setRTCPRRPacketHandler(TaskFunc* handler, void* clientData) { fRRHandlerTask = handler; fRRHandlerClientData = clientData; }
创建CamServerMediaSubsession 对象时,设置回调。(CamServerMediaSubsession 是继承于 OnDemandServerMediaSubsession,重写createNewStreamSource和createNewRTPSink即可)
CamServerMediaSubsession *sub = CamServerMediaSubsession::createNew(*env, inputDevice, &device); ... sub->setRTCPRRPacketHandler(RTCPRRHandler, (void *)sub); ...
函调函数中获取RTCP RR信息
void RTCPRRHandler(void* clientData) { using namespace CamStream; CamServerMediaSubsession *sub = (CamServerMediaSubsession *)clientData; RTPSink *sink = sub->get_rtp_sink(); if (!sink) { std::cout<<"unable to get sink obj, not ready"<<std::endl; return; } bool ignore_firstRR = true; RTPTransmissionStatsDB& transmissionStats = sink->transmissionStatsDB(); RTPTransmissionStatsDB::Iterator iter(transmissionStats); RTPTransmissionStats* substat; while ((substat = iter.next()) != NULL) { auto cam = sub->get_cam_instance(); auto jitter = substat->jitter(); auto loss_ratio = ((float)substat->packetLossRatio()/256)*100; // % auto rtt = (int)(((float)substat->roundTripDelay()/65536)*1000); //ms auto last_bitrate = cam->get_bitrate(); std::cout<<"SSRC "<<substat->SSRC() <<" RTT "<<rtt<<" ms" <<" jitter "<<jitter <<" loss "<<(int)loss_ratio<<"%"<<std::endl;
} }
最后,根据丢帧率以及RTTD等信息,我们可以调整视频源的码率,实现QoS。
关于CamServerMediaSubsession的实现(实现下面两个函数,就可以蒋H264视频流转为RTP传输流,从而实现RTSP服务器)
/*source */
FramedSource* CamServerMediaSubsession::createNewStreamSource(unsigned clientSessionId, unsigned& estBitrate) { estBitrate = static_cast<unsigned int>(this->bit_rate_); FramedSource *source = replicator_->createStreamReplica(); //H264VideoStreamDiscreteFramer的输入是离散的NALU //H264VideoStreamFramer的输入是stream bit流 FramedSource *h264_source = H264VideoStreamDiscreteFramer::createNew(envir(), source); return h264_source; } /*sink */ RTPSink* CamServerMediaSubsession::createNewRTPSink(Groupsock* rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, FramedSource* inputSource) { auto sink = H264VideoRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic, sps_nal_, sps_nal_size_, pps_nal_, pps_nal_size_); return sink; }
总结,上面的实现修改了live555源码,官方推荐的方式是通过继承现有类重写方法来实现,不过代码看了半天没头绪,有知道怎么弄的告诉我声(vslinux@qq.com)