ZLMediaKit / ZLMediaKit

WebRTC/RTSP/RTMP/HTTP/HLS/HTTP-FLV/WebSocket-FLV/HTTP-TS/HTTP-fMP4/WebSocket-TS/WebSocket-fMP4/GB28181/SRT server and client framework based on C++11
https://docs.zlmediakit.com
Other
13.67k stars 3.37k forks source link

webrtc answer 错误 #1687

Closed sha-long-ba-si closed 2 years ago

sha-long-ba-si commented 2 years ago

现象描述

提交offer后,生成的answer的 m-lines次序不正确,导致setRemoteDescription失败 setRemoteDescription: onSetFailure == Failed to set remote answer sdp: The order of m-lines in answer doesn't match order in offer. Rejecting answer.

相关日志或截图

展开查看详细日志 offer:
v=0
o=- 6717794513202614704 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0 1 2
a=msid-semantic: WMS
m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 127 123 125
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:EHoQ
a=ice-pwd:KcPej/z1MLTwfa5z1yvGW361
a=ice-options:trickle renomination
a=fingerprint:sha-256 C6:52:B3:B0:AD:8A:C0:5C:74:91:0A:55:6A:08:FB:11:4A:A3:F1:89:43:4F:6C:96:15:CA:6B:0A:93:13:DB:0D
a=setup:actpass
a=mid:0
a=extmap:1 urn:ietf:params:rtp-hdrext:toffset
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:3 urn:3gpp:video-orientation
a=extmap:4 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space
a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendonly
a=msid:- local_video_track
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:96 VP8/90000
a=rtcp-fb:96 goog-remb
a=rtcp-fb:96 transport-cc
a=rtcp-fb:96 ccm fir
a=rtcp-fb:96 nack
a=rtcp-fb:96 nack pli
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=96
a=rtpmap:98 VP9/90000
a=rtcp-fb:98 goog-remb
a=rtcp-fb:98 transport-cc
a=rtcp-fb:98 ccm fir
a=rtcp-fb:98 nack
a=rtcp-fb:98 nack pli
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=98
a=rtpmap:100 H264/90000
a=rtcp-fb:100 goog-remb
a=rtcp-fb:100 transport-cc
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=fmtp:100 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtpmap:101 rtx/90000
a=fmtp:101 apt=100
a=rtpmap:127 red/90000
a=rtpmap:123 rtx/90000
a=fmtp:123 apt=127
a=rtpmap:125 ulpfec/90000
a=ssrc-group:FID 2583027262 1475105360
a=ssrc:2583027262 cname:Vj1Jx0Q/LJA+cEeP
a=ssrc:2583027262 msid:- local_video_track
a=ssrc:2583027262 mslabel:-
a=ssrc:2583027262 label:local_video_track
a=ssrc:1475105360 cname:Vj1Jx0Q/LJA+cEeP
a=ssrc:1475105360 msid:- local_video_track
a=ssrc:1475105360 mslabel:-
a=ssrc:1475105360 label:local_video_track
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 102 0 8 106 105 13 110 112 113 126
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:EHoQ
a=ice-pwd:KcPej/z1MLTwfa5z1yvGW361
a=ice-options:trickle renomination
a=fingerprint:sha-256 C6:52:B3:B0:AD:8A:C0:5C:74:91:0A:55:6A:08:FB:11:4A:A3:F1:89:43:4F:6C:96:15:CA:6B:0A:93:13:DB:0D
a=setup:actpass
a=mid:1
a=extmap:14 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:4 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendonly
a=msid:- local_audio_track
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:102 ILBC/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:112 telephone-event/32000
a=rtpmap:113 telephone-event/16000
a=rtpmap:126 telephone-event/8000
a=ssrc:3061392948 cname:Vj1Jx0Q/LJA+cEeP
a=ssrc:3061392948 msid:- local_audio_track
a=ssrc:3061392948 mslabel:-
a=ssrc:3061392948 label:local_audio_track
m=application 9 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 0.0.0.0
a=ice-ufrag:EHoQ
a=ice-pwd:KcPej/z1MLTwfa5z1yvGW361
a=ice-options:trickle renomination
a=fingerprint:sha-256 C6:52:B3:B0:AD:8A:C0:5C:74:91:0A:55:6A:08:FB:11:4A:A3:F1:89:43:4F:6C:96:15:CA:6B:0A:93:13:DB:0D
a=setup:actpass
a=mid:2
a=sctp-port:5000
a=max-message-size:262144
answer:
v=0
o=- 6717794513202614704 2 IN IP4 192.168.1.200
s=-
t=0 0
a=group:BUNDLE 1 0 2
a=msid-semantic: WMS
m=audio 10002 UDP/TLS/RTP/SAVPF 111
c=IN IP4 192.168.1.200
a=rtcp:10002 IN IP4 192.168.1.200
a=ice-ufrag:zlm_1
a=ice-pwd:55pPlZPrIrwI2A6zZo7uNKlg
a=ice-options:trickle
a=fingerprint:sha-256 CC:3F:C7:AE:50:55:13:26:D6:82:91:B0:BE:B3:78:F0:E2:5F:1D:67:C4:64:CB:46:D2:1A:20:E1:F3:5E:35:0B
a=setup:passive
a=mid:1
a=ice-lite
a=extmap:14 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=recvonly
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10;useinbandfec=1
a=candidate:udpcandidate 1 udp 110 192.168.1.200 10002 typ host
m=video 10002 UDP/TLS/RTP/SAVPF 100 101
c=IN IP4 192.168.1.200
a=rtcp:10002 IN IP4 192.168.1.200
a=ice-ufrag:zlm_1
a=ice-pwd:55pPlZPrIrwI2A6zZo7uNKlg
a=ice-options:trickle
a=fingerprint:sha-256 CC:3F:C7:AE:50:55:13:26:D6:82:91:B0:BE:B3:78:F0:E2:5F:1D:67:C4:64:CB:46:D2:1A:20:E1:F3:5E:35:0B
a=setup:passive
a=mid:0
a=ice-lite
a=extmap:1 urn:ietf:params:rtp-hdrext:toffset
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:3 urn:3gpp:video-orientation
a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space
a=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=recvonly
a=rtcp-mux
a=rtpmap:100 H264/90000
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 goog-remb
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=fmtp:100 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtpmap:101 rtx/90000
a=fmtp:101 apt=100
a=candidate:udpcandidate 1 udp 110 192.168.1.200 10002 typ host
m=application 10002 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 192.168.1.200
a=rtcp:10002 IN IP4 192.168.1.200
a=ice-ufrag:EHoQ
a=ice-pwd:KcPej/z1MLTwfa5z1yvGW361
a=ice-options:trickle renomination
a=fingerprint:sha-256 C6:52:B3:B0:AD:8A:C0:5C:74:91:0A:55:6A:08:FB:11:4A:A3:F1:89:43:4F:6C:96:15:CA:6B:0A:93:13:DB:0D
a=setup:passive
a=mid:2
a=sctp-port:5000
a=candidate:udpcandidate 1 udp 110 192.168.1.200 10002 typ host

各种环境信息

android系统,使用 org.webrtc:google-webrtc:1.0.32006

xia-chu commented 2 years ago

这个问题 我待会修复下

xia-chu commented 2 years ago

你打个补丁试试,如果测试通过了,麻烦提个pr

Index: webrtc/Sdp.h
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/webrtc/Sdp.h b/webrtc/Sdp.h
--- a/webrtc/Sdp.h  (revision 8553502b7cb8dc7f1b3e55dbd6ad49121c6501a8)
+++ b/webrtc/Sdp.h  (date 1654588253730)
@@ -720,7 +720,7 @@
     void setDefaultSetting(std::string ice_ufrag, std::string ice_pwd, RtpDirection direction, const SdpAttrFingerprint &fingerprint);
     void addCandidate(const SdpAttrCandidate &candidate, mediakit::TrackType type = mediakit::TrackInvalid);

-    std::shared_ptr<RtcSession> createAnswer(const RtcSession &offer);
+    std::shared_ptr<RtcSession> createAnswer(const RtcSession &offer) const;

     void setPlayRtspInfo(const std::string &sdp);

@@ -728,9 +728,9 @@
     void enableREMB(bool enable = true, mediakit::TrackType type = mediakit::TrackInvalid);

 private:
-    void matchMedia(const std::shared_ptr<RtcSession> &ret, mediakit::TrackType type, const std::vector<RtcMedia> &medias, const RtcTrackConfigure &configure);
-    bool onCheckCodecProfile(const RtcCodecPlan &plan, mediakit::CodecId codec);
-    void onSelectPlan(RtcCodecPlan &plan, mediakit::CodecId codec);
+    void matchMedia(const std::shared_ptr<RtcSession> &ret, const RtcMedia &media) const;
+    bool onCheckCodecProfile(const RtcCodecPlan &plan, mediakit::CodecId codec) const;
+    void onSelectPlan(RtcCodecPlan &plan, mediakit::CodecId codec) const;

 private:
     RtcCodecPlan::Ptr _rtsp_video_plan;
Index: webrtc/Sdp.cpp
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/webrtc/Sdp.cpp b/webrtc/Sdp.cpp
--- a/webrtc/Sdp.cpp    (revision 8553502b7cb8dc7f1b3e55dbd6ad49121c6501a8)
+++ b/webrtc/Sdp.cpp    (date 1654588224206)
@@ -1521,15 +1521,17 @@
     }
 }

-shared_ptr<RtcSession> RtcConfigure::createAnswer(const RtcSession &offer){
+shared_ptr<RtcSession> RtcConfigure::createAnswer(const RtcSession &offer) const {
     shared_ptr<RtcSession> ret = std::make_shared<RtcSession>();
     ret->version = offer.version;
     ret->origin = offer.origin;
     ret->session_name = offer.session_name;
     ret->msid_semantic = offer.msid_semantic;
-    matchMedia(ret, TrackAudio, offer.media, audio);
-    matchMedia(ret, TrackVideo, offer.media, video);
-    matchMedia(ret, TrackApplication, offer.media, application);
+
+    for (auto &m : offer.media) {
+        matchMedia(ret, m);
+    }
+
     //设置音视频端口复用
     if (!offer.group.mids.empty()) {
         for (auto &m : ret->media) {
@@ -1573,153 +1575,157 @@
     }
 }

-void RtcConfigure::matchMedia(const shared_ptr<RtcSession> &ret, TrackType type, const vector<RtcMedia> &medias, const RtcTrackConfigure &configure){
+void RtcConfigure::matchMedia(const std::shared_ptr<RtcSession> &ret,const RtcMedia &offer_media) const {
     bool check_profile = true;
     bool check_codec = true;
+    const RtcTrackConfigure *cfg_ptr = nullptr;
+
+    switch (offer_media.type) {
+        case TrackAudio: cfg_ptr = &audio; break;
+        case TrackVideo: cfg_ptr = &video; break;
+        case TrackApplication: cfg_ptr = &application; break;
+        default: return;
+    }
+    auto &configure = *cfg_ptr;

 RETRY:

-    for (auto &offer_media : medias) {
-        if (offer_media.type != type) {
-            continue;
-        }
-        if (type == TrackApplication) {
-            RtcMedia answer_media = offer_media;
-            answer_media.role = mathDtlsRole(offer_media.role);
+    if (offer_media.type == TrackApplication) {
+        RtcMedia answer_media = offer_media;
+        answer_media.role = mathDtlsRole(offer_media.role);
 #ifdef ENABLE_SCTP
-            answer_media.direction = matchDirection(offer_media.direction, configure.direction);
-            answer_media.candidate = configure.candidate;
+        answer_media.direction = matchDirection(offer_media.direction, configure.direction);
+        answer_media.candidate = configure.candidate;
 #else
-            answer_media.direction = RtpDirection::inactive;
+        answer_media.direction = RtpDirection::inactive;
 #endif
-            ret->media.emplace_back(answer_media);
-            return;
-        }
-        for (auto &codec : configure.preferred_codec) {
-            if (offer_media.ice_lite && configure.ice_lite) {
-                WarnL << "answer sdp配置为ice_lite模式,与offer sdp中的ice_lite模式冲突";
-                continue;
-            }
-            const RtcCodecPlan *selected_plan = nullptr;
-            for (auto &plan : offer_media.plan) {
-                //先检查编码格式是否为偏好
-                if (check_codec && getCodecId(plan.codec) != codec) {
-                    continue;
-                }
-                //命中偏好的编码格式,然后检查规格
-                if (check_profile && !onCheckCodecProfile(plan, codec)) {
-                    continue;
-                }
-                //找到中意的codec
-                selected_plan = &plan;
-                break;
-            }
-            if (!selected_plan) {
-                //offer中该媒体的所有的codec都不支持
-                continue;
-            }
-            RtcMedia answer_media;
-            answer_media.type = offer_media.type;
-            answer_media.mid = offer_media.mid;
-            answer_media.proto = offer_media.proto;
-            answer_media.port = offer_media.port;
-            answer_media.addr = offer_media.addr;
-            answer_media.rtcp_addr = offer_media.rtcp_addr;
-            answer_media.rtcp_mux = offer_media.rtcp_mux && configure.rtcp_mux;
-            answer_media.rtcp_rsize = offer_media.rtcp_rsize && configure.rtcp_rsize;
-            answer_media.ice_trickle = offer_media.ice_trickle && configure.ice_trickle;
-            answer_media.ice_renomination = offer_media.ice_renomination && configure.ice_renomination;
-            answer_media.ice_ufrag = configure.ice_ufrag;
-            answer_media.ice_pwd = configure.ice_pwd;
-            answer_media.fingerprint = configure.fingerprint;
-            answer_media.ice_lite = configure.ice_lite;
-            answer_media.candidate = configure.candidate;
-            // copy simulicast setting
-            answer_media.rtp_rids = offer_media.rtp_rids;
-            answer_media.rtp_ssrc_sim = offer_media.rtp_ssrc_sim;
+        ret->media.emplace_back(answer_media);
+        return;
+    }
+    for (auto &codec : configure.preferred_codec) {
+        if (offer_media.ice_lite && configure.ice_lite) {
+            WarnL << "answer sdp配置为ice_lite模式,与offer sdp中的ice_lite模式冲突";
+            continue;
+        }
+        const RtcCodecPlan *selected_plan = nullptr;
+        for (auto &plan : offer_media.plan) {
+            //先检查编码格式是否为偏好
+            if (check_codec && getCodecId(plan.codec) != codec) {
+                continue;
+            }
+            //命中偏好的编码格式,然后检查规格
+            if (check_profile && !onCheckCodecProfile(plan, codec)) {
+                continue;
+            }
+            //找到中意的codec
+            selected_plan = &plan;
+            break;
+        }
+        if (!selected_plan) {
+            //offer中该媒体的所有的codec都不支持
+            continue;
+        }
+        RtcMedia answer_media;
+        answer_media.type = offer_media.type;
+        answer_media.mid = offer_media.mid;
+        answer_media.proto = offer_media.proto;
+        answer_media.port = offer_media.port;
+        answer_media.addr = offer_media.addr;
+        answer_media.rtcp_addr = offer_media.rtcp_addr;
+        answer_media.rtcp_mux = offer_media.rtcp_mux && configure.rtcp_mux;
+        answer_media.rtcp_rsize = offer_media.rtcp_rsize && configure.rtcp_rsize;
+        answer_media.ice_trickle = offer_media.ice_trickle && configure.ice_trickle;
+        answer_media.ice_renomination = offer_media.ice_renomination && configure.ice_renomination;
+        answer_media.ice_ufrag = configure.ice_ufrag;
+        answer_media.ice_pwd = configure.ice_pwd;
+        answer_media.fingerprint = configure.fingerprint;
+        answer_media.ice_lite = configure.ice_lite;
+        answer_media.candidate = configure.candidate;
+        // copy simulicast setting
+        answer_media.rtp_rids = offer_media.rtp_rids;
+        answer_media.rtp_ssrc_sim = offer_media.rtp_ssrc_sim;

-            answer_media.role = mathDtlsRole(offer_media.role);
+        answer_media.role = mathDtlsRole(offer_media.role);

-            //如果codec匹配失败,那么禁用该track
-            answer_media.direction = check_codec ? matchDirection(offer_media.direction, configure.direction)
-                                                 : RtpDirection::inactive;
-            if (answer_media.direction == RtpDirection::invalid) {
-                continue;
-            }
-            if (answer_media.direction == RtpDirection::sendrecv) {
-                //如果是收发双向,那么我们拷贝offer sdp的ssrc,确保ssrc一致
-                answer_media.rtp_rtx_ssrc = offer_media.rtp_rtx_ssrc;
-            }
+        //如果codec匹配失败,那么禁用该track
+        answer_media.direction = check_codec ? matchDirection(offer_media.direction, configure.direction)
+                                             : RtpDirection::inactive;
+        if (answer_media.direction == RtpDirection::invalid) {
+            continue;
+        }
+        if (answer_media.direction == RtpDirection::sendrecv) {
+            //如果是收发双向,那么我们拷贝offer sdp的ssrc,确保ssrc一致
+            answer_media.rtp_rtx_ssrc = offer_media.rtp_rtx_ssrc;
+        }

-            //添加媒体plan
-            answer_media.plan.emplace_back(*selected_plan);
-            onSelectPlan(answer_media.plan.back(), codec);
+        //添加媒体plan
+        answer_media.plan.emplace_back(*selected_plan);
+        onSelectPlan(answer_media.plan.back(), codec);

-            set<uint8_t> pt_selected = {selected_plan->pt};
+        set<uint8_t> pt_selected = {selected_plan->pt};

-            //添加rtx,red,ulpfec plan
-            if (configure.support_red || configure.support_rtx || configure.support_ulpfec) {
-                for (auto &plan : offer_media.plan) {
-                    if (!strcasecmp(plan.codec.data(), "rtx")) {
-                        if (configure.support_rtx && atoi(plan.getFmtp("apt").data()) == selected_plan->pt) {
-                            answer_media.plan.emplace_back(plan);
-                            pt_selected.emplace(plan.pt);
-                        }
-                        continue;
-                    }
-                    if (!strcasecmp(plan.codec.data(), "red")) {
-                        if (configure.support_red) {
-                            answer_media.plan.emplace_back(plan);
-                            pt_selected.emplace(plan.pt);
-                        }
-                        continue;
-                    }
-                    if (!strcasecmp(plan.codec.data(), "ulpfec")) {
-                        if (configure.support_ulpfec) {
-                            answer_media.plan.emplace_back(plan);
-                            pt_selected.emplace(plan.pt);
-                        }
-                        continue;
-                    }
-                }
-            }
+        //添加rtx,red,ulpfec plan
+        if (configure.support_red || configure.support_rtx || configure.support_ulpfec) {
+            for (auto &plan : offer_media.plan) {
+                if (!strcasecmp(plan.codec.data(), "rtx")) {
+                    if (configure.support_rtx && atoi(plan.getFmtp("apt").data()) == selected_plan->pt) {
+                        answer_media.plan.emplace_back(plan);
+                        pt_selected.emplace(plan.pt);
+                    }
+                    continue;
+                }
+                if (!strcasecmp(plan.codec.data(), "red")) {
+                    if (configure.support_red) {
+                        answer_media.plan.emplace_back(plan);
+                        pt_selected.emplace(plan.pt);
+                    }
+                    continue;
+                }
+                if (!strcasecmp(plan.codec.data(), "ulpfec")) {
+                    if (configure.support_ulpfec) {
+                        answer_media.plan.emplace_back(plan);
+                        pt_selected.emplace(plan.pt);
+                    }
+                    continue;
+                }
+            }
+        }

-            //对方和我方都支持的扩展,那么我们才支持
-            for (auto &ext : offer_media.extmap) {
-                auto it = configure.extmap.find(RtpExt::getExtType(ext.ext));
-                if (it != configure.extmap.end()) {
-                    auto new_dir = matchDirection(ext.direction, it->second);
-                    switch (new_dir) {
-                        case RtpDirection::invalid:
-                        case RtpDirection::inactive: continue;
-                        default: break;
-                    }
-                    answer_media.extmap.emplace_back(ext);
-                    answer_media.extmap.back().direction = new_dir;
-                }
-            }
+        //对方和我方都支持的扩展,那么我们才支持
+        for (auto &ext : offer_media.extmap) {
+            auto it = configure.extmap.find(RtpExt::getExtType(ext.ext));
+            if (it != configure.extmap.end()) {
+                auto new_dir = matchDirection(ext.direction, it->second);
+                switch (new_dir) {
+                    case RtpDirection::invalid:
+                    case RtpDirection::inactive: continue;
+                    default: break;
+                }
+                answer_media.extmap.emplace_back(ext);
+                answer_media.extmap.back().direction = new_dir;
+            }
+        }

-            auto &rtcp_fb_ref = answer_media.plan[0].rtcp_fb;
-            rtcp_fb_ref.clear();
-            //对方和我方都支持的rtcpfb,那么我们才支持
-            for (auto &fp : selected_plan->rtcp_fb) {
-                if (configure.rtcp_fb.find(fp) != configure.rtcp_fb.end()) {
-                    //对方该rtcp被我们支持
-                    rtcp_fb_ref.emplace(fp);
-                }
-            }
+        auto &rtcp_fb_ref = answer_media.plan[0].rtcp_fb;
+        rtcp_fb_ref.clear();
+        //对方和我方都支持的rtcpfb,那么我们才支持
+        for (auto &fp : selected_plan->rtcp_fb) {
+            if (configure.rtcp_fb.find(fp) != configure.rtcp_fb.end()) {
+                //对方该rtcp被我们支持
+                rtcp_fb_ref.emplace(fp);
+            }
+        }

 #if 0
-            //todo 此处为添加无效的plan,webrtc sdp通过调节plan pt顺序选择匹配的codec,意味着后面的codec其实放在sdp中是无意义的
-            for (auto &plan : offer_media.plan) {
-                if (pt_selected.find(plan.pt) == pt_selected.end()) {
-                    answer_media.plan.emplace_back(plan);
-                }
-            }
+        //todo 此处为添加无效的plan,webrtc sdp通过调节plan pt顺序选择匹配的codec,意味着后面的codec其实放在sdp中是无意义的
+        for (auto &plan : offer_media.plan) {
+            if (pt_selected.find(plan.pt) == pt_selected.end()) {
+                answer_media.plan.emplace_back(plan);
+            }
+        }
 #endif
-            ret->media.emplace_back(answer_media);
-            return;
-        }
+        ret->media.emplace_back(answer_media);
+        return;
     }

     if (check_profile) {
@@ -1765,7 +1771,7 @@
 static const string kProfile{"profile-level-id"};
 static const string kMode{"packetization-mode"};

-bool RtcConfigure::onCheckCodecProfile(const RtcCodecPlan &plan, CodecId codec){
+bool RtcConfigure::onCheckCodecProfile(const RtcCodecPlan &plan, CodecId codec) const {
     if (_rtsp_audio_plan && codec == getCodecId(_rtsp_audio_plan->codec)) {
         if (plan.sample_rate != _rtsp_audio_plan->sample_rate || plan.channel != _rtsp_audio_plan->channel) {
             //音频采样率和通道数必须相同
@@ -1785,7 +1791,7 @@
     return true;
 }

-void RtcConfigure::onSelectPlan(RtcCodecPlan &plan, CodecId codec){
+void RtcConfigure::onSelectPlan(RtcCodecPlan &plan, CodecId codec) const {
     if (_rtsp_video_plan && codec == CodecH264 && getCodecId(_rtsp_video_plan->codec) == CodecH264) {
         //h264时,设置packetization-mod为一致
         auto mode = _rtsp_video_plan->fmtp[kMode];
sha-long-ba-si commented 2 years ago

好的,我试试

xia-chu commented 2 years ago

1695