Fix force H264 and add unit tests to SDPMunging

pull/600/head
cruizba 2020-09-08 12:27:35 +02:00
parent 0f958baf39
commit e5cbc75377
8 changed files with 784 additions and 11 deletions

View File

@ -374,13 +374,15 @@ public class KurentoSessionManager extends SessionManager {
boolean isTranscodingAllowed = kSession.getSessionProperties().isTranscodingAllowed();
VideoCodec forcedVideoCodec = kSession.getSessionProperties().forcedVideoCodec();
log.debug("PARTICIPANT '{}' in Session '{}' publishing SDP before munging: \n {}",
participant.getParticipantPublicId(), kSession.getSessionId(), kurentoOptions.sdpOffer);
// Modify sdp if forced codec is defined
if (forcedVideoCodec != VideoCodec.NONE) {
String sdpOffer = kurentoOptions.sdpOffer;
try {
log.debug("PARTICIPANT '{}' in Session '{}' SDP Offer before munging: \n {}",
participant.getParticipantPublicId(), kSession.getSessionId(), kurentoOptions.sdpOffer);
kurentoOptions.sdpOffer = this.sdpMunging.setCodecPreference(forcedVideoCodec, sdpOffer);
log.debug("PARTICIPANT '{}' in Session '{}' publishing SDP Offer after munging: \n {}",
participant.getParticipantPublicId(), kSession.getSessionId(), kurentoOptions.sdpOffer);
} catch (OpenViduException e) {
String errorMessage = "Error forcing codec: '" + forcedVideoCodec + "', for PARTICIPANT"
+ participant.getParticipantPublicId() + "' publishing in Session: '"
@ -535,8 +537,6 @@ public class KurentoSessionManager extends SessionManager {
String sdpOffer = null;
Session session = null;
try {
log.debug("Request [SUBSCRIBE] remoteParticipant={} sdpOffer={} ({})", senderPublicId, sdpOffer,
participant.getParticipantPublicId());
KurentoParticipant kParticipant = (KurentoParticipant) participant;
session = ((KurentoParticipant) participant).getSession();
@ -564,6 +564,32 @@ public class KurentoSessionManager extends SessionManager {
}
sdpOffer = kParticipant.prepareReceiveMediaFrom(senderParticipant);
VideoCodec forcedVideoCodec = session.getSessionProperties().forcedVideoCodec();
boolean isTranscodingAllowed = session.getSessionProperties().isTranscodingAllowed();
if (forcedVideoCodec != VideoCodec.NONE) {
try {
log.debug("PARTICIPANT '{}' in Session '{}' SDP Offer before munging: \n {}",
participant.getParticipantPublicId(), session.getSessionId(), sdpOffer);
sdpOffer = this.sdpMunging.setCodecPreference(forcedVideoCodec, sdpOffer);
if (forcedVideoCodec == VideoCodec.H264) {
sdpOffer = this.sdpMunging.setfmtpH264(sdpOffer);
}
} catch (OpenViduException e) {
String errorMessage = "Error forcing codec: '" + forcedVideoCodec + "', for PARTICIPANT: '"
+ participant.getParticipantPublicId() + "' subscribing in Session: '"
+ session.getSessionId() + "'\nException: " + e.getMessage() + "\nSDP:\n" + sdpOffer;
if(!isTranscodingAllowed) {
throw new OpenViduException(Code.FORCED_CODEC_NOT_FOUND_IN_SDPOFFER, errorMessage);
}
log.info("Codec: '" + forcedVideoCodec + "' is not supported for PARTICIPANT: '" + participant.getParticipantPublicId()
+ " subscribing in Session: '" + session.getSessionId() + "'. Transcoding will be allowed");
}
}
log.debug("Request [SUBSCRIBE] remoteParticipant={} sdpOffer={} ({})", senderPublicId, sdpOffer,
participant.getParticipantPublicId());
if (sdpOffer == null) {
throw new OpenViduException(Code.MEDIA_SDP_ERROR_CODE, "Unable to generate SDP offer when subscribing '"
+ participant.getParticipantPublicId() + "' to '" + senderPublicId + "'");
@ -591,12 +617,14 @@ public class KurentoSessionManager extends SessionManager {
boolean isTranscodingAllowed = session.getSessionProperties().isTranscodingAllowed();
VideoCodec forcedVideoCodec = session.getSessionProperties().forcedVideoCodec();
log.debug("PARTICIPANT '{}' subscribing in Session '{}' SDP Answer before munging: \n {}",
participant.getParticipantPublicId(), session.getSessionId(), sdpAnswer);
// Modify sdp if forced codec is defined
if (forcedVideoCodec != VideoCodec.NONE) {
try {
log.debug("PARTICIPANT '{}' in Session '{}' SDP Answer before munging: \n {}",
participant.getParticipantPublicId(), session.getSessionId(), sdpAnswer);
sdpAnswer = this.sdpMunging.setCodecPreference(forcedVideoCodec, sdpAnswer);
sdpAnswer = this.sdpMunging.setCodecPreference(forcedVideoCodec, sdpAnswer);
log.debug("PARTICIPANT '{}' subscribing in Session '{}' SDP Answer after munging: \n {}",
participant.getParticipantPublicId(), session.getSessionId(), sdpAnswer);
} catch (OpenViduException e) {
String errorMessage = "Error forcing codec: '" + forcedVideoCodec + "', for PARTICIPANT: '"
+ participant.getParticipantPublicId() + "' subscribing in Session: '"
@ -609,6 +637,7 @@ public class KurentoSessionManager extends SessionManager {
+ " subscribing in Session: '" + session.getSessionId() + "'. Transcoding will be allowed");
}
}
if (senderParticipant == null) {
log.warn(
@ -1144,12 +1173,14 @@ public class KurentoSessionManager extends SessionManager {
boolean isTranscodingAllowed = kSession.getSessionProperties().isTranscodingAllowed();
VideoCodec forcedVideoCodec = kSession.getSessionProperties().forcedVideoCodec();
log.debug("PARTICIPANT '{}' in Session '{}' reconnecting SDP before munging: \n {}",
participant.getParticipantPublicId(), kSession.getSessionId(), sdpString);
// Modify sdp if forced codec is defined
if (forcedVideoCodec != VideoCodec.NONE) {
try {
log.debug("PARTICIPANT '{}' in Session '{}' reconnecting SDP before munging: \n {}",
participant.getParticipantPublicId(), kSession.getSessionId(), sdpString);
sdpString = sdpMunging.setCodecPreference(forcedVideoCodec, sdpString);
log.debug("PARTICIPANT '{}' in Session '{}' reconnecting SDP after munging: \n {}",
participant.getParticipantPublicId(), kSession.getSessionId(), sdpString);
} catch (OpenViduException e) {
String errorMessage = "Error in reconnect and forcing codec: '" + forcedVideoCodec + "', for PARTICIPANT: '"
+ participant.getParticipantPublicId() + "' " + (isPublisher ? "publishing" : "subscribing")

View File

@ -2,6 +2,7 @@ package io.openvidu.server.utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -127,7 +128,78 @@ public class SDPMunging {
lines[sl] = newLine.toString();
}
return String.join("\r\n", lines);
return String.join("\r\n", lines) + "\r\n";
}
/**
* Possible Kurento's bug
* Some browsers can't use H264 as a video codec if in the offerer SDP
* the parameter "a=fmtp: <...> profile-level-id=42e01f" is not defined.
* This munging is only used when the forced codec needs to be H264
* References:
* https://stackoverflow.com/questions/38432137/cannot-establish-webrtc-connection-different-codecs-and-payload-type-in-sdp
*/
public String setfmtpH264(String sdp) {
String codecStr = VideoCodec.H264.name();
// Get all lines
List<String> lines = new LinkedList<String>(Arrays.asList(sdp.split("\\R+")));
// Index to reference the line with "m=video"
int mVideoLineIndex = -1;
List<String> validCodecsPayload = new ArrayList<>();
for(int i = 0; i < lines.size(); i++) {
String sdpLine = lines.get(i);
// Check that we are in "m=video"
if (sdpLine.startsWith("m=video")) {
mVideoLineIndex = i;
// Search for payload-type for the specified codec
for(int j = i+1; j < lines.size(); j++) {
String auxLine = lines.get(j);
// Check that the line we're going to analizae is not anoter "m="
if(auxLine.startsWith("m=")) {
break;
}
if (auxLine.startsWith("a=rtpmap")) {
String[] rtpmapInfo = auxLine.split(":")[1].split(" ");
String possiblePayload = rtpmapInfo[0];
String possibleCodec = rtpmapInfo[1];
if (possibleCodec.contains(codecStr)) {
validCodecsPayload.add(possiblePayload);
}
}
}
// If a payload is not found, then the codec is not in the SDP
if (validCodecsPayload.size() == 0) {
throw new OpenViduException(Code.FORCED_CODEC_NOT_FOUND_IN_SDPOFFER, String.format("Codec %s not found", codecStr));
}
continue;
}
}
if (mVideoLineIndex == -1) {
throw new OpenViduException(Code.FORCED_CODEC_NOT_FOUND_IN_SDPOFFER, "This SDP does not offer video");
}
if (mVideoLineIndex != -1) {
for (String codecPayload: validCodecsPayload) {
if (!sdp.contains(String.format("a=fmtp:%s", codecPayload))) {
String newfmtpLine = String.format("a=fmtp:%s level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f", codecPayload);
lines.add(mVideoLineIndex + 1, newfmtpLine);
}
}
}
// Return munging sdp!!
String[] munguedSdpLines = lines.toArray(new String[lines.size()]);
return String.join("\r\n", munguedSdpLines) + "\r\n";
}
}

View File

@ -0,0 +1,253 @@
package io.openvidu.server.test.unit;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.junit.jupiter.api.DisplayName;
import io.openvidu.client.OpenViduException;
import io.openvidu.java.client.VideoCodec;
import io.openvidu.server.utils.SDPMunging;
public class SDPMungingTest {
private SDPMunging sdpMungin = new SDPMunging();
private String oldSdp;
private String newSdp;
List<String> h264codecPayloads;
List<String> forceCodecPayloads;
String validSDPH264Files[] = new String[]{
"sdp_kurento_h264_with_profile_id.txt",
"sdp_kurento_h264_without_profile_id_1.txt",
"sdp_chrome84.txt",
"sdp_firefox79.txt",
"sdp_safari13-1.txt"
};
String validSDPVP8Files[] = new String[]{
"sdp_kurento_h264_with_profile_id.txt",
"sdp_kurento_h264_without_profile_id_1.txt",
"sdp_chrome84.txt",
"sdp_firefox79.txt",
"sdp_safari13-1.txt"
};
String validSDPVP9Files[] = new String[] {
"sdp_chrome84.txt",
"sdp_firefox79.txt"
};
String notValidVP9Files[] = new String[] {
"sdp_kurento_h264_with_profile_id.txt",
"sdp_kurento_h264_without_profile_id_1.txt",
"sdp_safari13-1.txt"
};
@Test
@DisplayName("[setfmtpH264] Compare 'profile-level-id' ocurrences with Payload-Type H264 ocurrences")
public void checkSDPOcurrenciesOfProfileIdForH264() throws IOException {
for(String sdpFileName: validSDPH264Files) {
initTestsSetfmtp(sdpFileName);
checkOcurrences();
}
}
@Test
@DisplayName("[setfmtpH264] In the generated SDP for each H264 Payload-Type, exists one" +
"'a=fmtp:' with a 'profile-level-id' defined")
public void checkOneProfileIdForEachH264Payload() throws IOException {
for(String sdpFileName: validSDPH264Files) {
initTestsSetfmtp(sdpFileName);
checkOneProfileIdForEachH264();
}
}
@Test
@DisplayName("[setCodecPreference] Force VP8 Codec prevalence in 'm=video' line")
public void checkPreferenceCodecVP8() throws IOException {
for(String sdpFileName: validSDPVP8Files) {
initTestsSetCodecPrevalence(VideoCodec.VP8, sdpFileName);
checkPrevalenceCodecInML();
}
}
@Test
@DisplayName("[setCodecPreference] Force VP8 Codec prevalence in 'm=video' line")
public void checkPreferenceCodecVP9() throws IOException {
for(String sdpFileName: validSDPVP9Files) {
initTestsSetCodecPrevalence(VideoCodec.VP9, sdpFileName);
checkPrevalenceCodecInML();
}
}
@Test
@DisplayName("[setCodecPreference] Force H264 Codec prevalence in 'm=video' line")
public void checkPreferenceCodecH264() throws IOException {
for(String sdpFileName: validSDPH264Files) {
initTestsSetCodecPrevalence(VideoCodec.H264, sdpFileName);
checkPrevalenceCodecInML();
}
}
@Test
@DisplayName("[setCodecPreference] Exception when codec does not exists on SDP")
public void checkPreferenceCodecException() throws IOException {
for(String sdpFile: notValidVP9Files) {
Exception exception = assertThrows(OpenViduException.class, () -> {
initTestsSetCodecPrevalence(VideoCodec.VP9, sdpFile);
});
String expectedMessage = "The specified forced codec VP9 is not present in the SDP";
assertTrue(exception.getMessage().contains(expectedMessage));
}
}
private String getSdpFile(String sdpNameFile) throws IOException {
Path sdpFile = Files.createTempFile("sdp-test", ".tmp");
Files.copy(getClass().getResourceAsStream("/sdp/" + sdpNameFile), sdpFile, StandardCopyOption.REPLACE_EXISTING);
String sdpUnformatted = new String(Files.readAllBytes(sdpFile));
return String.join("\r\n", sdpUnformatted.split("\\R+")) + "\r\n";
}
private void checkOcurrences() {
// Check that new sdp actually contains a line with a=fmtp for
// each h264 defined payload
int allOcurrences = 0;
for(String h264pt: this.h264codecPayloads) {
allOcurrences += ( newSdp.split("m=video")[1].split("a=fmtp:" + h264pt).length ) - 1;
}
assertEquals(allOcurrences, h264codecPayloads.size());
}
private void initTestsSetfmtp(String sdpNameFile) throws IOException {
this.oldSdp = getSdpFile(sdpNameFile);
this.newSdp = this.sdpMungin.setfmtpH264(oldSdp);
this.h264codecPayloads = new ArrayList<>();
// Get all Payload-Type for h264
for(String oldSdpLine: oldSdp.split("\\R+")) {
if(oldSdpLine.startsWith("a=rtpmap") && oldSdpLine.endsWith("H264/90000")) {
String pt = oldSdpLine.split(":")[1].split(" ")[0];
this.h264codecPayloads.add(pt);
}
}
}
private void initTestsSetCodecPrevalence(VideoCodec codec, String sdpNameFile) throws IOException {
this.oldSdp = getSdpFile(sdpNameFile);
this.newSdp = this.sdpMungin.setCodecPreference(codec, oldSdp);
this.forceCodecPayloads = new ArrayList<>();
// Get all Payload-Type for video Codec
for(String oldSdpLine: oldSdp.split("\\R+")) {
if(oldSdpLine.startsWith("a=rtpmap") && oldSdpLine.endsWith(codec.name() + "/90000")) {
String pt = oldSdpLine.split(":")[1].split(" ")[0];
this.forceCodecPayloads.add(pt);
}
}
// Get all Payload-Types rtx related with codec
// Not the best way to do it, but enough to check if the sdp
// generated is correct
String[] oldSdpLines = oldSdp.split("\\R+");
List<String> rtxForcedCodecs = new ArrayList<>();
for(String oldSdpLine: oldSdpLines) {
if(oldSdpLine.startsWith("a=rtpmap") && oldSdpLine.endsWith("rtx/90000")) {
String rtxPayload = oldSdpLine.split(":")[1].split(" ")[0];
for (String auxOldSdpLine: oldSdpLines) {
if (auxOldSdpLine.contains("a=fmtp:" + rtxPayload + " apt=")) {
for (String auxForcedCodec: this.forceCodecPayloads) {
if (auxOldSdpLine.contains("a=fmtp:" + rtxPayload + " apt=" + auxForcedCodec)) {
String pt = oldSdpLine.split(":")[1].split(" ")[0];
rtxForcedCodecs.add(pt);
}
}
}
}
}
}
this.forceCodecPayloads.addAll(rtxForcedCodecs);
}
private void checkOneProfileIdForEachH264() throws IOException {
// Check one profile-id for each h264 Payload-Type
boolean inVideoBlock = false;
int numFoundProfileIds = 0;
for(String newSdpLine: newSdp.split("\\R+")) {
if (!inVideoBlock && newSdpLine.startsWith("m=video")) {
inVideoBlock = true;
continue;
}
if (inVideoBlock && newSdpLine.startsWith("m=")) {
break;
}
if (inVideoBlock && newSdpLine.startsWith("a=fmtp:")) {
boolean foundProfileId = false;
for(String h264pt: this.h264codecPayloads) {
foundProfileId = newSdpLine.contains("a=fmtp:")
&& newSdpLine.contains(h264pt) && newSdpLine.contains("profile-level-id");
if (foundProfileId) {
numFoundProfileIds++;
}
}
}
}
assertEquals(numFoundProfileIds, this.h264codecPayloads.size());
}
private void checkPrevalenceCodecInML() {
String newml = null;
String[] newSdpLines = this.newSdp.split("\\R+");
for(String newSdpLine: newSdpLines) {
if (newSdpLine.startsWith("m=video")) {
newml = newSdpLine;
break;
}
}
if (newml == null) {
fail("'m=video' line not found in SDP");
}
List<String> newMlCodecPrevalenceList = new ArrayList<>();
String[] lmParams = newml.split(" ");
int numOfCodecsWithPrevalence = this.forceCodecPayloads.size();
int indexStartCodecs = 3;
int indexEndPreferencedCodecs = 3 + numOfCodecsWithPrevalence;
for(int i = indexStartCodecs; i < indexEndPreferencedCodecs; i++) {
newMlCodecPrevalenceList.add(lmParams[i]);
}
for(int j = 0; j < numOfCodecsWithPrevalence; j++) {
String codecToCheck = newMlCodecPrevalenceList.get(j);
boolean codecFoundInPrevalenceList = false;
for(String codecToForce: this.forceCodecPayloads) {
if (codecToCheck.equals(codecToForce)) {
codecFoundInPrevalenceList = true;
break;
}
}
assertTrue(codecFoundInPrevalenceList);
}
}
}

View File

@ -0,0 +1,143 @@
v=0
o=- 5217540180782877494 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0 1
a=msid-semantic: WMS eEMVYR4txYWGErUa55KnHm0mMBdfrqSbtQul
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 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:RWim
a=ice-pwd:seCgmyE+AkRJKgqD4SdIuALd
a=ice-options:trickle
a=fingerprint:sha-256 59:47:FE:36:82:34:B1:7B:4C:D5:D4:76:78:24:89:67:5E:3C:84:4F:52:BD:86:83:67:10:98:8C:79:9D:89:7D
a=setup:actpass
a=mid:0
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendonly
a=msid:eEMVYR4txYWGErUa55KnHm0mMBdfrqSbtQul 7bbc37fe-6e36-479f-990f-988a07ac3f00
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: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:913601848 cname:BkItF+kVUhq9L3k4
a=ssrc:913601848 msid:eEMVYR4txYWGErUa55KnHm0mMBdfrqSbtQul 7bbc37fe-6e36-479f-990f-988a07ac3f00
a=ssrc:913601848 mslabel:eEMVYR4txYWGErUa55KnHm0mMBdfrqSbtQul
a=ssrc:913601848 label:7bbc37fe-6e36-479f-990f-988a07ac3f00
m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 102 122 127 121 125 107 108 109 124 120 123
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:RWim
a=ice-pwd:seCgmyE+AkRJKgqD4SdIuALd
a=ice-options:trickle
a=fingerprint:sha-256 59:47:FE:36:82:34:B1:7B:4C:D5:D4:76:78:24:89:67:5E:3C:84:4F:52:BD:86:83:67:10:98:8C:79:9D:89:7D
a=setup:actpass
a=mid:1
a=extmap:14 urn:ietf:params:rtp-hdrext:toffset
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:13 urn:3gpp:video-orientation
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:12 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=extmap:11 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://tools.ietf.org/html/draft-ietf-avtext-framemarking-07
a=extmap:9 http://www.webrtc.org/experiments/rtp-hdrext/color-space
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendonly
a=msid:eEMVYR4txYWGErUa55KnHm0mMBdfrqSbtQul 29491954-cc1e-4ca3-b290-cb8d5d0ad685
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=fmtp:98 profile-id=0
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=98
a=rtpmap:100 VP9/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 profile-id=2
a=rtpmap:101 rtx/90000
a=fmtp:101 apt=100
a=rtpmap:102 H264/90000
a=rtcp-fb:102 goog-remb
a=rtcp-fb:102 transport-cc
a=rtcp-fb:102 ccm fir
a=rtcp-fb:102 nack
a=rtcp-fb:102 nack pli
a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
a=rtpmap:122 rtx/90000
a=fmtp:122 apt=102
a=rtpmap:127 H264/90000
a=rtcp-fb:127 goog-remb
a=rtcp-fb:127 transport-cc
a=rtcp-fb:127 ccm fir
a=rtcp-fb:127 nack
a=rtcp-fb:127 nack pli
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f
a=rtpmap:121 rtx/90000
a=fmtp:121 apt=127
a=rtpmap:125 H264/90000
a=rtcp-fb:125 goog-remb
a=rtcp-fb:125 transport-cc
a=rtcp-fb:125 ccm fir
a=rtcp-fb:125 nack
a=rtcp-fb:125 nack pli
a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtpmap:107 rtx/90000
a=fmtp:107 apt=125
a=rtpmap:108 H264/90000
a=rtcp-fb:108 goog-remb
a=rtcp-fb:108 transport-cc
a=rtcp-fb:108 ccm fir
a=rtcp-fb:108 nack
a=rtcp-fb:108 nack pli
a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f
a=rtpmap:109 rtx/90000
a=fmtp:109 apt=108
a=rtpmap:124 red/90000
a=rtpmap:120 rtx/90000
a=fmtp:120 apt=124
a=rtpmap:123 ulpfec/90000
a=ssrc-group:FID 796117241 4235816742
a=ssrc:796117241 cname:BkItF+kVUhq9L3k4
a=ssrc:796117241 msid:eEMVYR4txYWGErUa55KnHm0mMBdfrqSbtQul 29491954-cc1e-4ca3-b290-cb8d5d0ad685
a=ssrc:796117241 mslabel:eEMVYR4txYWGErUa55KnHm0mMBdfrqSbtQul
a=ssrc:796117241 label:29491954-cc1e-4ca3-b290-cb8d5d0ad685
a=ssrc:4235816742 cname:BkItF+kVUhq9L3k4
a=ssrc:4235816742 msid:eEMVYR4txYWGErUa55KnHm0mMBdfrqSbtQul 29491954-cc1e-4ca3-b290-cb8d5d0ad685
a=ssrc:4235816742 mslabel:eEMVYR4txYWGErUa55KnHm0mMBdfrqSbtQul
a=ssrc:4235816742 label:29491954-cc1e-4ca3-b290-cb8d5d0ad685

View File

@ -0,0 +1,67 @@
v=0
o=mozilla...THIS_IS_SDPARTA-79.0 1574413241511582424 0 IN IP4 0.0.0.0
s=-
t=0 0
a=sendrecv
a=fingerprint:sha-256 43:63:A0:1A:D4:F3:6A:0B:B9:DC:AD:8B:A4:20:22:17:B9:BD:FC:81:9F:EC:E9:46:E0:61:3B:8B:2A:05:9A:D9
a=group:BUNDLE 0 1
a=ice-options:trickle
a=msid-semantic:WMS *
m=audio 9 UDP/TLS/RTP/SAVPF 109 9 0 8 101
c=IN IP4 0.0.0.0
a=sendonly
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2/recvonly urn:ietf:params:rtp-hdrext:csrc-audio-level
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
a=fmtp:109 maxplaybackrate=48000;stereo=1;useinbandfec=1
a=fmtp:101 0-15
a=ice-pwd:4be109f1ce637a5423d9229aa10c43bd
a=ice-ufrag:03567d22
a=mid:0
a=msid:{77708aaa-ed09-403a-b19a-26b8f44aff96} {f18baa5e-b689-4b17-9db8-83620b6c1f2b}
a=rtcp-mux
a=rtpmap:109 opus/48000/2
a=rtpmap:9 G722/8000/1
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=setup:actpass
a=ssrc:2626852385 cname:{4ff79710-1727-45f8-bbe7-7532884b9652}
m=video 9 UDP/TLS/RTP/SAVPF 120 121 126 97
c=IN IP4 0.0.0.0
a=sendonly
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:4 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:5 urn:ietf:params:rtp-hdrext:toffset
a=extmap:6/recvonly http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=fmtp:126 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1
a=fmtp:97 profile-level-id=42e01f;level-asymmetry-allowed=1
a=fmtp:120 max-fs=12288;max-fr=60
a=fmtp:121 max-fs=12288;max-fr=60
a=ice-pwd:4be109f1ce637a5423d9229aa10c43bd
a=ice-ufrag:03567d22
a=mid:1
a=msid:{77708aaa-ed09-403a-b19a-26b8f44aff96} {a68009be-6483-45fd-a48d-7bc60fa6f055}
a=rtcp-fb:120 nack
a=rtcp-fb:120 nack pli
a=rtcp-fb:120 ccm fir
a=rtcp-fb:120 goog-remb
a=rtcp-fb:121 nack
a=rtcp-fb:121 nack pli
a=rtcp-fb:121 ccm fir
a=rtcp-fb:121 goog-remb
a=rtcp-fb:126 nack
a=rtcp-fb:126 nack pli
a=rtcp-fb:126 ccm fir
a=rtcp-fb:126 goog-remb
a=rtcp-fb:97 nack
a=rtcp-fb:97 nack pli
a=rtcp-fb:97 ccm fir
a=rtcp-fb:97 goog-remb
a=rtcp-mux
a=rtpmap:120 VP8/90000
a=rtpmap:121 VP9/90000
a=rtpmap:126 H264/90000
a=rtpmap:97 H264/90000
a=setup:actpass
a=ssrc:3743317987 cname:{4ff79710-1727-45f8-bbe7-7532884b9652}

View File

@ -0,0 +1,61 @@
v=0
o=- 3808465464 3808465464 IN IP4 0.0.0.0
s=Kurento Media Server
c=IN IP4 0.0.0.0
t=0 0
a=msid-semantic: WMS m0W2gMak7LgkgzgJeDQhxBX0ivcsejWjQ0jD
a=group:BUNDLE 0 1
m=audio 1 UDP/TLS/RTP/SAVPF 111 0
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=recvonly
a=mid:0
a=rtcp:9 IN IP4 0.0.0.0
a=rtpmap:111 opus/48000/2
a=rtpmap:0 PCMU/8000
a=setup:active
a=rtcp-mux
a=fmtp:111 minptime=10;useinbandfec=1
a=ssrc:1929271881 cname:user4129876135@host-ed881df6
a=ice-ufrag:cXmf
a=ice-pwd:9giZcfpsuoHRuxCgbnCLRy
a=fingerprint:sha-256 C8:D4:B5:56:A7:89:E5:E1:C8:28:0A:47:2B:49:F6:7A:E2:2E:B3:0A:40:10:AD:79:82:E7:FD:A0:ED:6C:F6:51
m=video 1 UDP/TLS/RTP/SAVPF 96 102 127 125 108
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=recvonly
a=mid:1
a=rtcp:9 IN IP4 0.0.0.0
a=rtpmap:96 VP8/90000
a=rtpmap:102 H264/90000
a=rtpmap:127 H264/90000
a=rtpmap:125 H264/90000
a=rtpmap:108 H264/90000
a=rtcp-fb:96 goog-remb
a=rtcp-fb:96 ccm fir
a=rtcp-fb:96 nack
a=rtcp-fb:96 nack pli
a=rtcp-fb:102 goog-remb
a=rtcp-fb:102 ccm fir
a=rtcp-fb:102 nack
a=rtcp-fb:102 nack pli
a=rtcp-fb:127 goog-remb
a=rtcp-fb:127 ccm fir
a=rtcp-fb:127 nack
a=rtcp-fb:127 nack pli
a=rtcp-fb:125 goog-remb
a=rtcp-fb:125 ccm fir
a=rtcp-fb:125 nack
a=rtcp-fb:125 nack pli
a=rtcp-fb:108 goog-remb
a=rtcp-fb:108 ccm fir
a=rtcp-fb:108 nack
a=rtcp-fb:108 nack pli
a=setup:active
a=rtcp-mux
a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f
a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f
a=ssrc:3762875210 cname:user4129876135@host-ed881df6
a=ice-ufrag:cXmf
a=ice-pwd:9giZcfpsuoHRuxCgbnCLRy
a=fingerprint:sha-256 C8:D4:B5:56:A7:89:E5:E1:C8:28:0A:47:2B:49:F6:7A:E2:2E:B3:0A:40:10:AD:79:82:E7:FD:A0:ED:6C:F6:51

View File

@ -0,0 +1,39 @@
v=0
o=- 3808468344 3808468344 IN IP4 0.0.0.0
s=Kurento Media Server
c=IN IP4 0.0.0.0
t=0 0
a=group:BUNDLE audio0 video0
m=audio 1 RTP/SAVPF 96 0
a=setup:actpass
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=rtpmap:96 opus/48000/2
a=rtcp:9 IN IP4 0.0.0.0
a=rtcp-mux
a=sendrecv
a=mid:audio0
a=ssrc:2357386425 cname:user3039051834@host-3860d219
a=ice-ufrag:cbwA
a=ice-pwd:sgFJgRt8te7axq+VVp7L9S
a=fingerprint:sha-256 C8:D4:B5:56:A7:89:E5:E1:C8:28:0A:47:2B:49:F6:7A:E2:2E:B3:0A:40:10:AD:79:82:E7:FD:A0:ED:6C:F6:51
m=video 1 RTP/SAVPF 100 101
b=AS:1000
a=setup:actpass
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=rtpmap:100 VP8/90000
a=rtpmap:101 H264/90000
a=rtcp:9 IN IP4 0.0.0.0
a=rtcp-mux
a=sendrecv
a=mid:video0
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtcp-fb:100 goog-remb
a=rtcp-fb:100 ccm fir
a=rtcp-fb:101 nack
a=rtcp-fb:101 nack pli
a=rtcp-fb:101 ccm fir
a=ssrc:728841848 cname:user3039051834@host-3860d219
a=ice-ufrag:cbwA
a=ice-pwd:sgFJgRt8te7axq+VVp7L9S
a=fingerprint:sha-256 C8:D4:B5:56:A7:89:E5:E1:C8:28:0A:47:2B:49:F6:7A:E2:2E:B3:0A:40:10:AD:79:82:E7:FD:A0:ED:6C:F6:51

View File

@ -0,0 +1,107 @@
v=0
o=- 4920969914039852086 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0 1
a=msid-semantic: WMS 90c21009-8d9f-4b31-8091-d98deb8361c8
m=audio 61842 UDP/TLS/RTP/SAVPF 111 103 9 102 0 8 105 13 110 113 126
c=IN IP4 192.168.1.105
a=rtcp:9 IN IP4 0.0.0.0
a=candidate:2222700650 1 udp 2113937151 192.168.1.105 61842 typ host generation 0 network-cost 999
a=ice-ufrag:zbK7
a=ice-pwd:o4ZsJFGBXHNzOWqX23brKpiG
a=ice-options:trickle
a=fingerprint:sha-256 18:BD:1F:64:28:C6:BC:7B:AD:83:42:E0:B1:78:BA:13:F4:BF:F5:5E:AD:20:62:CC:AF:DF:99:AD:20:CB:1B:7E
a=setup:actpass
a=mid:0
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendonly
a=msid:90c21009-8d9f-4b31-8091-d98deb8361c8 1d7a65f7-59c9-42a7-abbb-d9fb5548e3ba
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:9 G722/8000
a=rtpmap:102 ILBC/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:113 telephone-event/16000
a=rtpmap:126 telephone-event/8000
a=ssrc:1052596434 cname:L3DqI2bKTDkcNVsn
a=ssrc:1052596434 msid:90c21009-8d9f-4b31-8091-d98deb8361c8 1d7a65f7-59c9-42a7-abbb-d9fb5548e3ba
a=ssrc:1052596434 mslabel:90c21009-8d9f-4b31-8091-d98deb8361c8
a=ssrc:1052596434 label:1d7a65f7-59c9-42a7-abbb-d9fb5548e3ba
m=video 62559 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 127 125 104
c=IN IP4 192.168.1.105
a=rtcp:9 IN IP4 0.0.0.0
a=candidate:2222700650 1 udp 2113937151 192.168.1.105 62559 typ host generation 0 network-cost 999
a=ice-ufrag:zbK7
a=ice-pwd:o4ZsJFGBXHNzOWqX23brKpiG
a=ice-options:trickle
a=fingerprint:sha-256 18:BD:1F:64:28:C6:BC:7B:AD:83:42:E0:B1:78:BA:13:F4:BF:F5:5E:AD:20:62:CC:AF:DF:99:AD:20:CB:1B:7E
a=setup:actpass
a=mid:1
a=extmap:14 urn:ietf:params:rtp-hdrext:toffset
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:13 urn:3gpp:video-orientation
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:12 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=extmap:11 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://tools.ietf.org/html/draft-ietf-avtext-framemarking-07
a=extmap:9 http://www.webrtc.org/experiments/rtp-hdrext/color-space
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendonly
a=msid:90c21009-8d9f-4b31-8091-d98deb8361c8 fc45e668-c301-41fe-ae8a-1265a5a355e7
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:96 H264/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=fmtp:96 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=640c1f
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=96
a=rtpmap:98 H264/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=fmtp:98 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=98
a=rtpmap:100 VP8/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=rtpmap:101 rtx/90000
a=fmtp:101 apt=100
a=rtpmap:127 red/90000
a=rtpmap:125 rtx/90000
a=fmtp:125 apt=127
a=rtpmap:104 ulpfec/90000
a=ssrc-group:FID 2734983896 3694891391
a=ssrc:2734983896 cname:L3DqI2bKTDkcNVsn
a=ssrc:2734983896 msid:90c21009-8d9f-4b31-8091-d98deb8361c8 fc45e668-c301-41fe-ae8a-1265a5a355e7
a=ssrc:2734983896 mslabel:90c21009-8d9f-4b31-8091-d98deb8361c8
a=ssrc:2734983896 label:fc45e668-c301-41fe-ae8a-1265a5a355e7
a=ssrc:3694891391 cname:L3DqI2bKTDkcNVsn
a=ssrc:3694891391 msid:90c21009-8d9f-4b31-8091-d98deb8361c8 fc45e668-c301-41fe-ae8a-1265a5a355e7
a=ssrc:3694891391 mslabel:90c21009-8d9f-4b31-8091-d98deb8361c8
a=ssrc:3694891391 label:fc45e668-c301-41fe-ae8a-1265a5a355e7