void ParseFmtpParam(absl::string_view line,
std::string* parameter,
std::string* value) {
if (!tokenize_first(line, kSdpDelimiterEqualChar, parameter, value)) { // Support for non-key-value lines like RFC 2198 or RFC 4733.
*parameter = "";
*value = std::string(line);
} // a=fmtp:<payload_type> <param1>=<value1>; <param2>=<value2>; ...
}
bool IsFmtpParam(absl::string_view name) { // RFC 4855, section 3 specifies the mapping of media format parameters to SDP // parameters. Only ptime, maxptime, channels and rate are placed outside of // the fmtp line. In WebRTC, channels and rate are already handled separately // and thus not included in the CodecParameterMap. return name != kCodecParamPTime && name != kCodecParamMaxPTime;
}
void WriteFmtpParameter(absl::string_view parameter_name,
absl::string_view parameter_value,
StringBuilder& os) {
if (parameter_name.empty()) { // RFC 2198 and RFC 4733 don't use key-value pairs.
os << parameter_value;
} else { // fmtp parameters: `parameter_name`=`parameter_value`
os << parameter_name << kSdpDelimiterEqual << parameter_value;
}
}
} // namespace
const char* DegradationPreferenceToString(
DegradationPreference degradation_preference) { switch (degradation_preference) { case DegradationPreference::MAINTAIN_FRAMERATE_AND_RESOLUTION: return"maintain-framerate-and-resolution"; case DegradationPreference::MAINTAIN_FRAMERATE: return"maintain-framerate"; case DegradationPreference::MAINTAIN_RESOLUTION: return"maintain-resolution"; case DegradationPreference::BALANCED: return"balanced";
}
RTC_CHECK_NOTREACHED();
}
constdouble kDefaultBitratePriority = 1.0;
bool WriteFmtpParameters(const CodecParameterMap& parameters,
StringBuilder& os) { bool empty = true; const char* delimiter = ""; // No delimiter before first parameter.
for (constauto& entry : parameters) { const std::string& key = entry.first; const std::string& value = entry.second;
if (IsFmtpParam(key)) {
os << delimiter; // A semicolon before each subsequent parameter.
delimiter = kSdpDelimiterSemicolon;
WriteFmtpParameter(key, value, os);
empty = false;
}
}
return !empty;
}
RTCError ParseFmtpParameterSet(absl::string_view line_params,
CodecParameterMap& codec_params) { // Parse out format specific parameters.
for (absl::string_view param :
split(line_params, kSdpDelimiterSemicolonChar)) {
std::string name;
std::string value;
ParseFmtpParam(absl::StripAsciiWhitespace(param), &name, &value);
if (codec_params.find(name) != codec_params.end()) {
RTC_LOG(LS_INFO) << "Overwriting duplicate fmtp parameter with key \""
<< name << "\".";
}
codec_params[name] = value;
} return RTCError::OK();
}
bool RtpExtension::IsSupportedForAudio(absl::string_view uri) { return uri == RtpExtension::kAudioLevelUri ||
uri == RtpExtension::kAbsSendTimeUri ||
uri == RtpExtension::kAbsoluteCaptureTimeUri ||
uri == RtpExtension::kTransportSequenceNumberUri ||
uri == RtpExtension::kTransportSequenceNumberV2Uri ||
uri == RtpExtension::kMidUri || uri == RtpExtension::kRidUri ||
uri == RtpExtension::kRepairedRidUri ||
uri == RtpExtension::kCsrcAudioLevelsUri;
}
bool RtpExtension::IsSupportedForVideo(absl::string_view uri) { return uri == RtpExtension::kTimestampOffsetUri ||
uri == RtpExtension::kAbsSendTimeUri ||
uri == RtpExtension::kAbsoluteCaptureTimeUri ||
uri == RtpExtension::kVideoRotationUri ||
uri == RtpExtension::kTransportSequenceNumberUri ||
uri == RtpExtension::kTransportSequenceNumberV2Uri ||
uri == RtpExtension::kPlayoutDelayUri ||
uri == RtpExtension::kVideoContentTypeUri ||
uri == RtpExtension::kVideoTimingUri || uri == RtpExtension::kMidUri ||
uri == RtpExtension::kGenericFrameDescriptorUri00 ||
uri == RtpExtension::kDependencyDescriptorUri ||
uri == RtpExtension::kColorSpaceUri || uri == RtpExtension::kRidUri ||
uri == RtpExtension::kRepairedRidUri ||
uri == RtpExtension::kVideoLayersAllocationUri ||
uri == RtpExtension::kVideoFrameTrackingIdUri ||
uri == RtpExtension::kCorruptionDetectionUri;
}
bool RtpExtension::IsEncryptionSupported(absl::string_view uri) { return
uri != RtpExtension::kEncryptHeaderExtensionsUri;
}
// Returns whether a header extension with the given URI exists. // Note: This does not differentiate between encrypted and non-encrypted // extensions, so use with care! staticbool HeaderExtensionWithUriExists( const std::vector<RtpExtension>& extensions,
absl::string_view uri) {
for (constauto& extension : extensions) {
if (extension.uri == uri) { returntrue;
}
} return false;
}
switch (filter) { case kDiscardEncryptedExtension: // We only accept an unencrypted extension.
if (!extension.encrypt) { return &extension;
} break;
case kPreferEncryptedExtension: // We prefer an encrypted extension but we can fall back to an // unencrypted extension.
if (extension.encrypt) { return &extension;
} else {
fallback_extension = &extension;
} break;
case kRequireEncryptedExtension: // We only accept an encrypted extension.
if (extension.encrypt) { return &extension;
} break;
}
}
// If we do not discard encrypted extensions, add them first
if (filter != kDiscardEncryptedExtension) {
for (constauto& extension : extensions) {
if (!extension.encrypt) { continue;
}
if (!HeaderExtensionWithUriExists(filtered, extension.uri)) {
filtered.push_back(extension);
}
}
}
// If we do not require encrypted extensions, add missing, non-encrypted // extensions.
if (filter != kRequireEncryptedExtension) {
for (constauto& extension : extensions) {
if (extension.encrypt) { continue;
}
if (!HeaderExtensionWithUriExists(filtered, extension.uri)) {
filtered.push_back(extension);
}
}
}
// Sort the returned vector to make comparisons of header extensions reliable. // In order of priority, we sort by uri first, then encrypt and id last.
std::sort(filtered.begin(), filtered.end(),
[](const RtpExtension& a, const RtpExtension& b) { return std::tie(a.uri, a.encrypt, a.id) <
std::tie(b.uri, b.encrypt, b.id);
});
return filtered;
}
bool RtpParameters::IsMixedCodec() const {
std::optional<std::optional<RtpCodec>> first_codec;
for (const RtpEncodingParameters& encoding : encodings) {
if (!encoding.active) { continue;
}
if (!first_codec) {
first_codec = encoding.codec; continue;
}
if (*first_codec != encoding.codec) { returntrue;
}
} return false;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.