in src/source/PeerConnection/SessionDescription.c [387:640]
STATUS populateSingleMediaSection(PKvsPeerConnection pKvsPeerConnection, PKvsRtpTransceiver pKvsRtpTransceiver,
PSdpMediaDescription pSdpMediaDescription, PSessionDescription pRemoteSessionDescription,
PCHAR pCertificateFingerprint, UINT32 mediaSectionId, PCHAR pDtlsRole)
{
ENTERS();
STATUS retStatus = STATUS_SUCCESS;
UINT64 payloadType, rtxPayloadType;
BOOL containRtx = FALSE;
BOOL directionFound = FALSE;
UINT32 i, remoteAttributeCount, attributeCount = 0;
PRtcMediaStreamTrack pRtcMediaStreamTrack = &(pKvsRtpTransceiver->sender.track);
PSdpMediaDescription pSdpMediaDescriptionRemote;
PCHAR currentFmtp = NULL;
CHK_STATUS(hashTableGet(pKvsPeerConnection->pCodecTable, pRtcMediaStreamTrack->codec, &payloadType));
currentFmtp = fmtpForPayloadType(payloadType, &(pKvsPeerConnection->remoteSessionDescription));
if (pRtcMediaStreamTrack->codec == RTC_CODEC_H264_PROFILE_42E01F_LEVEL_ASYMMETRY_ALLOWED_PACKETIZATION_MODE ||
pRtcMediaStreamTrack->codec == RTC_CODEC_VP8) {
if (pRtcMediaStreamTrack->codec == RTC_CODEC_H264_PROFILE_42E01F_LEVEL_ASYMMETRY_ALLOWED_PACKETIZATION_MODE) {
retStatus = hashTableGet(pKvsPeerConnection->pRtxTable, RTC_RTX_CODEC_H264_PROFILE_42E01F_LEVEL_ASYMMETRY_ALLOWED_PACKETIZATION_MODE,
&rtxPayloadType);
} else {
retStatus = hashTableGet(pKvsPeerConnection->pRtxTable, RTC_RTX_CODEC_VP8, &rtxPayloadType);
}
CHK(retStatus == STATUS_SUCCESS || retStatus == STATUS_HASH_KEY_NOT_PRESENT, retStatus);
containRtx = (retStatus == STATUS_SUCCESS);
retStatus = STATUS_SUCCESS;
if (containRtx) {
SPRINTF(pSdpMediaDescription->mediaName, "video 9 UDP/TLS/RTP/SAVPF %" PRId64 " %" PRId64, payloadType, rtxPayloadType);
} else {
SPRINTF(pSdpMediaDescription->mediaName, "video 9 UDP/TLS/RTP/SAVPF %" PRId64, payloadType);
}
} else if (pRtcMediaStreamTrack->codec == RTC_CODEC_OPUS || pRtcMediaStreamTrack->codec == RTC_CODEC_MULAW ||
pRtcMediaStreamTrack->codec == RTC_CODEC_ALAW) {
SPRINTF(pSdpMediaDescription->mediaName, "audio 9 UDP/TLS/RTP/SAVPF %" PRId64, payloadType);
}
CHK_STATUS(iceAgentPopulateSdpMediaDescriptionCandidates(pKvsPeerConnection->pIceAgent, pSdpMediaDescription, MAX_SDP_ATTRIBUTE_VALUE_LENGTH,
&attributeCount));
if (containRtx) {
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "msid");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%s %sRTX", pRtcMediaStreamTrack->streamId,
pRtcMediaStreamTrack->trackId);
attributeCount++;
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "ssrc-group");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "FID %u %u", pKvsRtpTransceiver->sender.ssrc,
pKvsRtpTransceiver->sender.rtxSsrc);
attributeCount++;
} else {
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "msid");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%s %s", pRtcMediaStreamTrack->streamId,
pRtcMediaStreamTrack->trackId);
attributeCount++;
}
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "ssrc");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%u cname:%s", pKvsRtpTransceiver->sender.ssrc,
pKvsPeerConnection->localCNAME);
attributeCount++;
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "ssrc");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%u msid:%s %s", pKvsRtpTransceiver->sender.ssrc,
pRtcMediaStreamTrack->streamId, pRtcMediaStreamTrack->trackId);
attributeCount++;
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "ssrc");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%u mslabel:%s", pKvsRtpTransceiver->sender.ssrc,
pRtcMediaStreamTrack->streamId);
attributeCount++;
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "ssrc");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%u label:%s", pKvsRtpTransceiver->sender.ssrc,
pRtcMediaStreamTrack->trackId);
attributeCount++;
if (containRtx) {
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "ssrc");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%u cname:%s", pKvsRtpTransceiver->sender.rtxSsrc,
pKvsPeerConnection->localCNAME);
attributeCount++;
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "ssrc");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%u msid:%s %sRTX", pKvsRtpTransceiver->sender.rtxSsrc,
pRtcMediaStreamTrack->streamId, pRtcMediaStreamTrack->trackId);
attributeCount++;
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "ssrc");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%u mslabel:%sRTX", pKvsRtpTransceiver->sender.rtxSsrc,
pRtcMediaStreamTrack->streamId);
attributeCount++;
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "ssrc");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%u label:%sRTX", pKvsRtpTransceiver->sender.rtxSsrc,
pRtcMediaStreamTrack->trackId);
attributeCount++;
}
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "rtcp");
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "9 IN IP4 0.0.0.0");
attributeCount++;
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "ice-ufrag");
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, pKvsPeerConnection->localIceUfrag);
attributeCount++;
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "ice-pwd");
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, pKvsPeerConnection->localIcePwd);
attributeCount++;
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "ice-options");
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "trickle");
attributeCount++;
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "fingerprint");
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "sha-256 ");
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue + 8, pCertificateFingerprint);
attributeCount++;
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "setup");
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, pDtlsRole);
attributeCount++;
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "mid");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%d", mediaSectionId);
attributeCount++;
if (pKvsPeerConnection->isOffer) {
switch (pKvsRtpTransceiver->transceiver.direction) {
case RTC_RTP_TRANSCEIVER_DIRECTION_SENDRECV:
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "sendrecv");
break;
case RTC_RTP_TRANSCEIVER_DIRECTION_SENDONLY:
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "sendonly");
break;
case RTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY:
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "recvonly");
break;
default:
// https://www.w3.org/TR/webrtc/#dom-rtcrtptransceiverdirection
DLOGW("Incorrect/no transceiver direction set...this attribute will be set to inactive");
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "inactive");
}
} else {
pSdpMediaDescriptionRemote = &pRemoteSessionDescription->mediaDescriptions[mediaSectionId];
remoteAttributeCount = pSdpMediaDescriptionRemote->mediaAttributesCount;
for (i = 0; i < remoteAttributeCount && directionFound == FALSE; i++) {
if (STRCMP(pSdpMediaDescriptionRemote->sdpAttributes[i].attributeName, "sendrecv") == 0) {
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "sendrecv");
directionFound = TRUE;
} else if (STRCMP(pSdpMediaDescriptionRemote->sdpAttributes[i].attributeName, "recvonly") == 0) {
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "sendonly");
directionFound = TRUE;
} else if (STRCMP(pSdpMediaDescriptionRemote->sdpAttributes[i].attributeName, "sendonly") == 0) {
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "recvonly");
directionFound = TRUE;
}
}
}
attributeCount++;
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "rtcp-mux");
attributeCount++;
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "rtcp-rsize");
attributeCount++;
if (pRtcMediaStreamTrack->codec == RTC_CODEC_H264_PROFILE_42E01F_LEVEL_ASYMMETRY_ALLOWED_PACKETIZATION_MODE) {
if (pKvsPeerConnection->isOffer) {
currentFmtp = DEFAULT_H264_FMTP;
}
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "rtpmap");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%" PRId64 " H264/90000", payloadType);
attributeCount++;
// TODO: If level asymmetry is allowed, consider sending back DEFAULT_H264_FMTP instead of the received fmtp value.
if (currentFmtp != NULL) {
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "fmtp");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%" PRId64 " %s", payloadType, currentFmtp);
attributeCount++;
}
if (containRtx) {
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "rtpmap");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%" PRId64 " " RTX_VALUE, rtxPayloadType);
attributeCount++;
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "fmtp");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%" PRId64 " apt=%" PRId64 "", rtxPayloadType, payloadType);
attributeCount++;
}
} else if (pRtcMediaStreamTrack->codec == RTC_CODEC_OPUS) {
if (pKvsPeerConnection->isOffer) {
currentFmtp = DEFAULT_OPUS_FMTP;
}
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "rtpmap");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%" PRId64 " opus/48000/2", payloadType);
attributeCount++;
if (currentFmtp != NULL) {
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "fmtp");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%" PRId64 " %s", payloadType, currentFmtp);
attributeCount++;
}
} else if (pRtcMediaStreamTrack->codec == RTC_CODEC_VP8) {
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "rtpmap");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%" PRId64 " " VP8_VALUE, payloadType);
attributeCount++;
if (containRtx) {
CHK_STATUS(hashTableGet(pKvsPeerConnection->pRtxTable, RTC_RTX_CODEC_VP8, &rtxPayloadType));
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "rtpmap");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%" PRId64 " " RTX_VALUE, rtxPayloadType);
attributeCount++;
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "fmtp");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%" PRId64 " apt=%" PRId64 "", rtxPayloadType, payloadType);
attributeCount++;
}
} else if (pRtcMediaStreamTrack->codec == RTC_CODEC_MULAW) {
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "rtpmap");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%" PRId64 " " MULAW_VALUE, payloadType);
attributeCount++;
} else if (pRtcMediaStreamTrack->codec == RTC_CODEC_ALAW) {
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "rtpmap");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%" PRId64 " " ALAW_VALUE, payloadType);
attributeCount++;
}
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "rtcp-fb");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%" PRId64 " nack", payloadType);
attributeCount++;
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "rtcp-fb");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%" PRId64 " goog-remb", payloadType);
attributeCount++;
if (pKvsPeerConnection->twccExtId != 0) {
STRCPY(pSdpMediaDescription->sdpAttributes[attributeCount].attributeName, "rtcp-fb");
SPRINTF(pSdpMediaDescription->sdpAttributes[attributeCount].attributeValue, "%" PRId64 " " TWCC_SDP_ATTR, payloadType);
attributeCount++;
}
pSdpMediaDescription->mediaAttributesCount = attributeCount;
CleanUp:
LEAVES();
return retStatus;
}