From f7411db180ba244f2de7b509fe35a583bf8c7010 Mon Sep 17 00:00:00 2001 From: Xiaofeng Wang Date: Mon, 10 Jun 2024 23:51:12 +0800 Subject: [PATCH] send config frames once before sending DirectProxy RTP packets --- webrtc/WebRtcPlayer.cpp | 46 +++++++++++++++++++++++++++++++++++++++++ webrtc/WebRtcPlayer.h | 6 ++++++ 2 files changed, 52 insertions(+) diff --git a/webrtc/WebRtcPlayer.cpp b/webrtc/WebRtcPlayer.cpp index cfafae2b..b410a154 100644 --- a/webrtc/WebRtcPlayer.cpp +++ b/webrtc/WebRtcPlayer.cpp @@ -9,7 +9,10 @@ */ #include "WebRtcPlayer.h" + #include "Common/config.h" +#include "Extension/Factory.h" +#include "Util/base64.h" using namespace std; @@ -32,6 +35,9 @@ WebRtcPlayer::WebRtcPlayer(const EventPoller::Ptr &poller, _media_info = info; _play_src = src; CHECK(src); + + GET_CONFIG(bool, direct_proxy, Rtsp::kDirectProxy); + _send_config_frames_once = direct_proxy; } void WebRtcPlayer::onStartWebRTC() { @@ -56,6 +62,13 @@ void WebRtcPlayer::onStartWebRTC() { if (!strong_self) { return; } + + if (strong_self->_send_config_frames_once && !pkt->empty()) { + const auto &first_rtp = pkt->front(); + strong_self->sendConfigFrames(first_rtp->getSeq(), first_rtp->sample_rate, first_rtp->getStamp(), first_rtp->ntp_stamp); + strong_self->_send_config_frames_once = false; + } + size_t i = 0; pkt->for_each([&](const RtpPacket::Ptr &rtp) { //TraceL<<"send track type:"<type<<" ts:"<getStamp()<<" ntp:"<ntp_stamp<<" size:"<getPayloadSize()<<" i:"<getSdp()); } +void WebRtcPlayer::sendConfigFrames(uint32_t before_seq, uint32_t sample_rate, uint32_t timestamp, uint64_t ntp_timestamp) { + auto play_src = _play_src.lock(); + if (!play_src) { + return; + } + auto video_track = std::dynamic_pointer_cast(play_src->getTrack(mediakit::TrackVideo)); + if (!video_track) { + return; + } + auto frames = video_track->getConfigFrames(); + if (frames.empty()) { + return; + } + auto encoder = mediakit::Factory::getRtpEncoderByCodecId(video_track->getCodecId(), 0); + if (!encoder) { + return; + } + + GET_CONFIG(uint32_t, video_mtu, Rtp::kVideoMtuSize); + encoder->setRtpInfo(0, video_mtu, sample_rate, 0, 0, 0); + + auto seq = before_seq - frames.size(); + for (const auto &frame : video_track->getConfigFrames()) { + auto rtp = encoder->getRtpInfo().makeRtp( + TrackVideo, frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize(), false, 0); + auto header = rtp->getHeader(); + header->seq = htons(seq++); + header->stamp = htonl(timestamp); + rtp->ntp_stamp = ntp_timestamp; + onSendRtp(rtp, false); + } +} + }// namespace mediakit \ No newline at end of file diff --git a/webrtc/WebRtcPlayer.h b/webrtc/WebRtcPlayer.h index ccacd410..96e9e830 100644 --- a/webrtc/WebRtcPlayer.h +++ b/webrtc/WebRtcPlayer.h @@ -31,11 +31,17 @@ protected: private: WebRtcPlayer(const EventPoller::Ptr &poller, const RtspMediaSource::Ptr &src, const MediaInfo &info); + void sendConfigFrames(uint32_t before_seq, uint32_t sample_rate, uint32_t timestamp, uint64_t ntp_timestamp); + private: //媒体相关元数据 MediaInfo _media_info; //播放的rtsp源 std::weak_ptr _play_src; + + // rtp 直接转发情况下通常会缺少 sps/pps, 在转发 rtp 前, 先发送一次相关帧信息, 部分情况下是可以播放的 + bool _send_config_frames_once { false }; + //播放rtsp源的reader对象 RtspMediaSource::RingType::RingReader::Ptr _reader; };