ZLMediaKit中RTSP的创建过程
- 首先是初始化
_rtsp
,在 publish消息中的setProtocolTranslation,在_muxer(MultiMediaSourceMuxer)里面的_muxer(MultiMuxerPrivate)的构造函数中,创建了_rtsp(RtspMediaSourceMuxer),在_rtsp的构造函数中,创建了_media_src (RtspMediaSource),并将RtpRing的delegate设置为_media_src
RtspMediaSourceMuxer(const string &vhost,
const string &strApp,
const string &strId,
const TitleSdp::Ptr &title = nullptr) : RtspMuxer(title){
_media_src = std::make_shared<RtspMediaSource>(vhost,strApp,strId);
getRtpRing()->setDelegate(_media_src);
}
- 后面就是接收音视频数据后,对应 _rtsp 相应的处理过程了,在接收音视频的过程中,会创建track并检测track是否ready,如果track已经ready的话,会调用以下函数,对于 _rtsp来说就是初始化其对象 _encoder,根据打印表名,_rtsp 会添加的两个code分别为 H264RtpEncoder和AACRtpEncoder,并且 _encoder 会设置 rtpRing为_rtpRing
void MultiMuxerPrivate::onTrackReady(const Track::Ptr &track) {
if (_rtmp) {
_rtmp->addTrack(track);
}
if (_rtsp) {
_rtsp->addTrack(track);
}
if (_ts) {
_ts->addTrack(track);
}
#if defined(ENABLE_MP4)
if (_fmp4) {
_fmp4->addTrack(track);
}
#endif
auto hls = _hls;
if (hls) {
hls->addTrack(track);
}
auto mp4 = _mp4;
if (mp4) {
mp4->addTrack(track);
}
}
rtsp的AddTrack:
void RtspMuxer::addTrack(const Track::Ptr &track) {
InfoL<<"enter RtspMuxer::addTrack";
Sdp::Ptr sdp = track->getSdp();
if (!sdp) {
return;
}
InfoL<<"enter RtspMuxer::addTrack trackType: "<<track->getTrackType();
auto &encoder = _encoder[track->getTrackType()];
encoder = Factory::getRtpEncoderBySdp(sdp);
if (!encoder) {
return;
}
encoder->setRtpRing(_rtpRing);
_sdp.append(sdp->getSdp());
}
- 在track回调AllTrackAready之后,收到的音视频数据会进入 _rtsp的流程中,具体流程是先进入 _rtsp中,然后再进入 H264RtpEncoder 最后再回到 _media_src 的onWrite 中
void inputFrame(const Frame::Ptr &frame) override {
InfoL<<"enter RtspMediaSourceMuxer inputFrame";
GET_CONFIG(bool, rtsp_demand, General::kRtspDemand);
if (_clear_cache && rtsp_demand) {
InfoL<<"rtsp inputFrame _clear_cache && rtsp_demand";
_clear_cache = false;
_media_src->clearCache();
}
if (_enabled || !rtsp_demand) {
InfoL<<"rtsp inputFrame _enabled || !rtsp_demand";
RtspMuxer::inputFrame(frame);
}
}
void RtspMuxer::inputFrame(const Frame::Ptr &frame) {
auto &encoder = _encoder[frame->getTrackType()];
if(encoder){
InfoL<<"RtspMuxer::inputFrame encoder";
encoder->inputFrame(frame);
}
}
void H264RtpEncoder::inputFrame(const Frame::Ptr &frame) {
auto ptr = frame->data() + frame->prefixSize();
auto len = frame->size() - frame->prefixSize();
auto pts = frame->pts();
auto nal_type = H264_TYPE(ptr[0]);
auto packet_size = getMaxSize() - 2;
auto fu_char_0 = (ptr[0] & (~0x1F)) | 28;
auto fu_char_1 = nal_type;
FuFlags *fu_flags = (FuFlags *) (&fu_char_1);
fu_flags->start_bit = 1;
if (len > packet_size + 1) {
InfoL<<"H264RtpEncoder::inputFrame if";
size_t offset = 1;
while (!fu_flags->end_bit) {
if (!fu_flags->start_bit && len <= offset + packet_size) {
packet_size = len - offset;
fu_flags->end_bit = 1;
}
auto rtp = makeRtp(getTrackType(), nullptr, packet_size + 2, fu_flags->end_bit, pts);
uint8_t *payload = rtp->getPayload();
payload[0] = fu_char_0;
payload[1] = fu_char_1;
memcpy(payload + 2, (uint8_t *) ptr + offset, packet_size);
RtpCodec::inputRtp(rtp, fu_flags->start_bit && nal_type == H264Frame::NAL_IDR);
offset += packet_size;
fu_flags->start_bit = 0;
}
} else {
InfoL<<"H264RtpEncoder::inputFrame else";
makeH264Rtp(ptr, len, false, false, pts);
}
}
virtual bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos){
if(_rtpRing){
_rtpRing->write(rtp,key_pos);
}
return key_pos;
}
void write(T in, bool is_key = true) {
if (_delegate) {
_delegate->onWrite(std::move(in), is_key);
return;
}
LOCK_GUARD(_mtx_map);
for (auto &pr : _dispatcher_map) {
auto &second = pr.second;
pr.first->async([second, in, is_key]() {
second->write(std::move(const_cast<T &>(in)), is_key);
}, false);
}
_storage->write(std::move(in), is_key);
}
void onWrite(RtpPacket::Ptr rtp, bool keyPos) override {
_speed[rtp->type] += rtp->size();
assert(rtp->type >= 0 && rtp->type < TrackMax);
auto &track = _tracks[rtp->type];
auto stamp = rtp->getStampMS();
if (track) {
track->_seq = rtp->getSeq();
track->_time_stamp = stamp;
track->_ssrc = rtp->getSSRC();
}
if (!_ring) {
weak_ptr<RtspMediaSource> weakSelf = dynamic_pointer_cast<RtspMediaSource>(shared_from_this());
auto lam = [weakSelf](int size) {
auto strongSelf = weakSelf.lock();
if (!strongSelf) {
return;
}
strongSelf->onReaderChanged(size);
};
_ring = std::make_shared<RingType>(_ring_size, std::move(lam));
onReaderChanged(0);
if (!_sdp.empty()) {
InfoL<<"RtspMediaSource onWrite regist";
regist();
}
}
bool is_video = rtp->type == TrackVideo;
PacketCache<RtpPacket>::inputPacket(stamp, is_video, std::move(rtp), keyPos);
}
- 最后梳理一下,便于自己理解, _rtsp 是类(RtspMediaSourceMuxer) 的对象,其中有 RtpRing 、 _encoder 和 _media_src,其中 RtpRing的代理是 _media_src ,_encoder中的rtpRing就是上述的RtpRing, _rtsp 收到数据之后,会把数据回调给 _encoder ,encoder会回调给 RtpRing,至此就是回调到了 _rtsp中的 RtpRing ,然后RtpRing再次将数据回调给代理_media_src,最终数据就是在上面的函数中最后调用
PacketCache<RtpPacket>::inputPacket
,其中RtpRing就是一个缓存数据的环形队列