| /* | |
| * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | |
| * | |
| * Use of this source code is governed by a BSD-style license | |
| * that can be found in the LICENSE file in the root of the source | |
| * tree. An additional intellectual property rights grant can be found | |
| * in the file PATENTS. All contributing project authors may | |
| * be found in the AUTHORS file in the root of the source tree. | |
| */ | |
| #include "api/video_codecs/video_codec.h" | |
| #include <cstring> | |
| #include <optional> | |
| #include <string> | |
| #include "absl/strings/match.h" | |
| #include "absl/strings/string_view.h" | |
| #include "api/video/video_codec_type.h" | |
| #include "api/video_codecs/scalability_mode.h" | |
| #include "api/video_codecs/sdp_video_format.h" | |
| #include "api/video_codecs/simulcast_stream.h" | |
| #include "rtc_base/checks.h" | |
| #include "rtc_base/strings/string_builder.h" | |
| namespace webrtc { | |
| namespace { | |
| constexpr char kPayloadNameVp8[] = "VP8"; | |
| constexpr char kPayloadNameVp9[] = "VP9"; | |
| constexpr char kPayloadNameAv1[] = "AV1"; | |
| // TODO(bugs.webrtc.org/13166): Remove AV1X when backwards compatibility is not | |
| // needed. | |
| constexpr char kPayloadNameAv1x[] = "AV1X"; | |
| constexpr char kPayloadNameH264[] = "H264"; | |
| constexpr char kPayloadNameGeneric[] = "Generic"; | |
| constexpr char kPayloadNameH265[] = "H265"; | |
| } // namespace | |
| bool VideoCodecVP8::operator==(const VideoCodecVP8& other) const { | |
| return (numberOfTemporalLayers == other.numberOfTemporalLayers && | |
| denoisingOn == other.denoisingOn && | |
| automaticResizeOn == other.automaticResizeOn && | |
| keyFrameInterval == other.keyFrameInterval); | |
| } | |
| bool VideoCodecVP9::operator==(const VideoCodecVP9& other) const { | |
| return (numberOfTemporalLayers == other.numberOfTemporalLayers && | |
| denoisingOn == other.denoisingOn && | |
| keyFrameInterval == other.keyFrameInterval && | |
| adaptiveQpMode == other.adaptiveQpMode && | |
| automaticResizeOn == other.automaticResizeOn && | |
| numberOfSpatialLayers == other.numberOfSpatialLayers && | |
| flexibleMode == other.flexibleMode); | |
| } | |
| bool VideoCodecH264::operator==(const VideoCodecH264& other) const { | |
| return (keyFrameInterval == other.keyFrameInterval && | |
| numberOfTemporalLayers == other.numberOfTemporalLayers); | |
| } | |
| VideoCodec::VideoCodec() | |
| : codecType(kVideoCodecGeneric), | |
| width(0), | |
| height(0), | |
| startBitrate(0), | |
| maxBitrate(0), | |
| minBitrate(0), | |
| maxFramerate(0), | |
| active(true), | |
| qpMax(0), | |
| numberOfSimulcastStreams(0), | |
| simulcastStream(), | |
| spatialLayers(), | |
| mode(VideoCodecMode::kRealtimeVideo), | |
| expect_encode_from_texture(false), | |
| timing_frame_thresholds({.delay_ms = 0, .outlier_ratio_percent = 0}), | |
| legacy_conference_mode(false), | |
| codec_specific_(), | |
| complexity_(VideoCodecComplexity::kComplexityNormal) {} | |
| std::string VideoCodec::ToString() const { | |
| StringBuilder ss; | |
| ss << "VideoCodec {" << "type: " << CodecTypeToPayloadString(codecType) | |
| << ", mode: " | |
| << (mode == VideoCodecMode::kRealtimeVideo ? "RealtimeVideo" | |
| : "Screensharing"); | |
| if (IsSinglecast()) { | |
| ss << ", Singlecast: {" << width << "x" << height << " " | |
| << ScalabilityModeToString(GetScalabilityMode()) | |
| << (active ? ", active" : ", inactive") << "}"; | |
| } else { | |
| ss << ", Simulcast: {"; | |
| for (size_t i = 0; i < numberOfSimulcastStreams; ++i) { | |
| const SimulcastStream stream = simulcastStream[i]; | |
| ss << "[" << stream.width << "x" << stream.height << " " | |
| << ScalabilityModeToString(stream.GetScalabilityMode()) | |
| << (stream.active ? ", active" : ", inactive") << "]"; | |
| } | |
| ss << "}"; | |
| } | |
| ss << "}"; | |
| return ss.Release(); | |
| } | |
| VideoCodecVP8* VideoCodec::VP8() { | |
| RTC_DCHECK_EQ(codecType, kVideoCodecVP8); | |
| return &codec_specific_.VP8; | |
| } | |
| const VideoCodecVP8& VideoCodec::VP8() const { | |
| RTC_DCHECK_EQ(codecType, kVideoCodecVP8); | |
| return codec_specific_.VP8; | |
| } | |
| VideoCodecVP9* VideoCodec::VP9() { | |
| RTC_DCHECK_EQ(codecType, kVideoCodecVP9); | |
| return &codec_specific_.VP9; | |
| } | |
| const VideoCodecVP9& VideoCodec::VP9() const { | |
| RTC_DCHECK_EQ(codecType, kVideoCodecVP9); | |
| return codec_specific_.VP9; | |
| } | |
| VideoCodecH264* VideoCodec::H264() { | |
| RTC_DCHECK_EQ(codecType, kVideoCodecH264); | |
| return &codec_specific_.H264; | |
| } | |
| const VideoCodecH264& VideoCodec::H264() const { | |
| RTC_DCHECK_EQ(codecType, kVideoCodecH264); | |
| return codec_specific_.H264; | |
| } | |
| VideoCodecAV1* VideoCodec::AV1() { | |
| RTC_DCHECK_EQ(codecType, kVideoCodecAV1); | |
| return &codec_specific_.AV1; | |
| } | |
| const VideoCodecAV1& VideoCodec::AV1() const { | |
| RTC_DCHECK_EQ(codecType, kVideoCodecAV1); | |
| return codec_specific_.AV1; | |
| } | |
| const char* CodecTypeToPayloadString(VideoCodecType type) { | |
| switch (type) { | |
| case kVideoCodecVP8: | |
| return kPayloadNameVp8; | |
| case kVideoCodecVP9: | |
| return kPayloadNameVp9; | |
| case kVideoCodecAV1: | |
| return kPayloadNameAv1; | |
| case kVideoCodecH264: | |
| return kPayloadNameH264; | |
| case kVideoCodecGeneric: | |
| return kPayloadNameGeneric; | |
| case kVideoCodecH265: | |
| return kPayloadNameH265; | |
| } | |
| RTC_CHECK_NOTREACHED(); | |
| } | |
| VideoCodecType PayloadStringToCodecType(absl::string_view name) { | |
| if (absl::EqualsIgnoreCase(name, kPayloadNameVp8)) | |
| return kVideoCodecVP8; | |
| if (absl::EqualsIgnoreCase(name, kPayloadNameVp9)) | |
| return kVideoCodecVP9; | |
| if (absl::EqualsIgnoreCase(name, kPayloadNameAv1) || | |
| absl::EqualsIgnoreCase(name, kPayloadNameAv1x)) | |
| return kVideoCodecAV1; | |
| if (absl::EqualsIgnoreCase(name, kPayloadNameH264)) | |
| return kVideoCodecH264; | |
| if (absl::EqualsIgnoreCase(name, kPayloadNameH265)) | |
| return kVideoCodecH265; | |
| return kVideoCodecGeneric; | |
| } | |
| VideoCodecComplexity VideoCodec::GetVideoEncoderComplexity() const { | |
| return complexity_; | |
| } | |
| void VideoCodec::SetVideoEncoderComplexity( | |
| VideoCodecComplexity complexity_setting) { | |
| complexity_ = complexity_setting; | |
| } | |
| bool VideoCodec::GetFrameDropEnabled() const { | |
| return frame_drop_enabled_; | |
| } | |
| void VideoCodec::SetFrameDropEnabled(bool enabled) { | |
| frame_drop_enabled_ = enabled; | |
| } | |
| bool VideoCodec::IsMixedCodec() const { | |
| std::optional<SdpVideoFormat> first_format; | |
| for (size_t i = 0; i < numberOfSimulcastStreams; ++i) { | |
| if (!simulcastStream[i].active) { | |
| continue; | |
| } | |
| if (!simulcastStream[i].format.has_value()) { | |
| return false; // Format is always set for active layers in mixed-codec. | |
| } | |
| if (!first_format.has_value()) { | |
| first_format = simulcastStream[i].format; // First active layer's format. | |
| } else if (!first_format->IsSameCodec(*simulcastStream[i].format)) { | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| } // namespace webrtc |