Add codec name H265 to support H265 in WebRTC
Bug: webrtc:13485
Change-Id: I352b15a65867f0d56fc8e9a9e03081bd3258108e
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/316283
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Sergey Silkin <ssilkin@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#40773}
diff --git a/BUILD.gn b/BUILD.gn
index 130e1a2..c247afb 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -302,6 +302,10 @@
defines += [ "RTC_ENABLE_VP9" ]
}
+ if (rtc_use_h265) {
+ defines += [ "RTC_ENABLE_H265" ]
+ }
+
if (rtc_include_dav1d_in_internal_decoder_factory) {
defines += [ "RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY" ]
}
diff --git a/api/video/rtp_video_frame_assembler.cc b/api/video/rtp_video_frame_assembler.cc
index 3d041ca..a19fcdc 100644
--- a/api/video/rtp_video_frame_assembler.cc
+++ b/api/video/rtp_video_frame_assembler.cc
@@ -51,6 +51,10 @@
return std::make_unique<VideoRtpDepacketizerAv1>();
case RtpVideoFrameAssembler::kGeneric:
return std::make_unique<VideoRtpDepacketizerGeneric>();
+ case RtpVideoFrameAssembler::kH265:
+ // TODO(bugs.webrtc.org/13485): Implement VideoRtpDepacketizerH265
+ RTC_DCHECK_NOTREACHED();
+ return nullptr;
}
RTC_DCHECK_NOTREACHED();
return nullptr;
diff --git a/api/video/rtp_video_frame_assembler.h b/api/video/rtp_video_frame_assembler.h
index 83162cb..099c962 100644
--- a/api/video/rtp_video_frame_assembler.h
+++ b/api/video/rtp_video_frame_assembler.h
@@ -52,7 +52,7 @@
// FrameVector is just a vector-like type of std::unique_ptr<EncodedFrame>.
// The vector type may change without notice.
using FrameVector = absl::InlinedVector<AssembledFrame, 3>;
- enum PayloadFormat { kRaw, kH264, kVp8, kVp9, kAv1, kGeneric };
+ enum PayloadFormat { kRaw, kH264, kVp8, kVp9, kAv1, kGeneric, kH265 };
explicit RtpVideoFrameAssembler(PayloadFormat payload_format);
RtpVideoFrameAssembler(const RtpVideoFrameAssembler& other) = delete;
diff --git a/api/video/rtp_video_frame_assembler_unittests.cc b/api/video/rtp_video_frame_assembler_unittests.cc
index 82defb8..50d1aaa 100644
--- a/api/video/rtp_video_frame_assembler_unittests.cc
+++ b/api/video/rtp_video_frame_assembler_unittests.cc
@@ -89,6 +89,9 @@
case PayloadFormat::kAv1: {
return kVideoCodecAV1;
}
+ case PayloadFormat::kH265: {
+ return kVideoCodecH265;
+ }
case PayloadFormat::kGeneric: {
return kVideoCodecGeneric;
}
diff --git a/api/video/video_codec_type.h b/api/video/video_codec_type.h
index 74a4bc4..444eb9b 100644
--- a/api/video/video_codec_type.h
+++ b/api/video/video_codec_type.h
@@ -22,6 +22,7 @@
kVideoCodecAV1,
kVideoCodecH264,
kVideoCodecMultiplex,
+ kVideoCodecH265,
};
} // namespace webrtc
diff --git a/api/video_codecs/sdp_video_format.cc b/api/video_codecs/sdp_video_format.cc
index cb7e98a..51ae18c 100644
--- a/api/video_codecs/sdp_video_format.cc
+++ b/api/video_codecs/sdp_video_format.cc
@@ -15,6 +15,9 @@
#include "api/array_view.h"
#include "api/video_codecs/av1_profile.h"
#include "api/video_codecs/h264_profile_level_id.h"
+#ifdef RTC_ENABLE_H265
+#include "api/video_codecs/h265_profile_tier_level.h"
+#endif
#include "api/video_codecs/video_codec.h"
#include "api/video_codecs/vp9_profile.h"
#include "rtc_base/checks.h"
@@ -61,6 +64,10 @@
return VP9IsSameProfile(format1.parameters, format2.parameters);
case kVideoCodecAV1:
return AV1IsSameProfile(format1.parameters, format2.parameters);
+#ifdef RTC_ENABLE_H265
+ case kVideoCodecH265:
+ return H265IsSameProfileTierLevel(format1.parameters, format2.parameters);
+#endif
default:
return true;
}
diff --git a/api/video_codecs/test/sdp_video_format_unittest.cc b/api/video_codecs/test/sdp_video_format_unittest.cc
index bb158ae..797a9a2 100644
--- a/api/video_codecs/test/sdp_video_format_unittest.cc
+++ b/api/video_codecs/test/sdp_video_format_unittest.cc
@@ -25,12 +25,18 @@
EXPECT_TRUE(Sdp("VP8").IsSameCodec(Sdp("vp8")));
EXPECT_TRUE(Sdp("VP9").IsSameCodec(Sdp("vp9")));
EXPECT_TRUE(Sdp("AV1").IsSameCodec(Sdp("Av1")));
+#ifdef RTC_ENABLE_H265
+ EXPECT_TRUE(Sdp("H265").IsSameCodec(Sdp("h265")));
+#endif
}
TEST(SdpVideoFormatTest, DifferentCodecNameNoParameters) {
EXPECT_FALSE(Sdp("H264").IsSameCodec(Sdp("VP8")));
EXPECT_FALSE(Sdp("VP8").IsSameCodec(Sdp("VP9")));
EXPECT_FALSE(Sdp("AV1").IsSameCodec(Sdp("VP8")));
+#ifdef RTC_ENABLE_H265
+ EXPECT_FALSE(Sdp("H265").IsSameCodec(Sdp("VP8")));
+#endif
}
TEST(SdpVideoFormatTest, SameCodecNameSameParameters) {
@@ -50,6 +56,17 @@
.IsSameCodec(Sdp("AV1", Params{{"profile", "0"}})));
EXPECT_TRUE(Sdp("AV1", Params{{"profile", "2"}})
.IsSameCodec(Sdp("AV1", Params{{"profile", "2"}})));
+#ifdef RTC_ENABLE_H265
+ EXPECT_TRUE(Sdp("H265").IsSameCodec(Sdp(
+ "H265",
+ Params{{"profile-id", "1"}, {"tier-flag", "0"}, {"level-id", "93"}})));
+ EXPECT_TRUE(
+ Sdp("H265",
+ Params{{"profile-id", "2"}, {"tier-flag", "0"}, {"level-id", "93"}})
+ .IsSameCodec(Sdp("H265", Params{{"profile-id", "2"},
+ {"tier-flag", "0"},
+ {"level-id", "93"}})));
+#endif
}
TEST(SdpVideoFormatTest, SameCodecNameDifferentParameters) {
@@ -69,6 +86,35 @@
.IsSameCodec(Sdp("AV1", Params{{"profile", "1"}})));
EXPECT_FALSE(Sdp("AV1", Params{{"profile", "1"}})
.IsSameCodec(Sdp("AV1", Params{{"profile", "2"}})));
+#ifdef RTC_ENABLE_H265
+ EXPECT_FALSE(Sdp("H265").IsSameCodec(Sdp(
+ "H265",
+ Params{{"profile-id", "0"}, {"tier-flag", "0"}, {"level-id", "93"}})));
+ EXPECT_FALSE(Sdp("H265").IsSameCodec(Sdp(
+ "H265",
+ Params{{"profile-id", "1"}, {"tier-flag", "1"}, {"level-id", "93"}})));
+ EXPECT_FALSE(Sdp("H265").IsSameCodec(Sdp(
+ "H265",
+ Params{{"profile-id", "1"}, {"tier-flag", "0"}, {"level-id", "90"}})));
+ EXPECT_FALSE(
+ Sdp("H265",
+ Params{{"profile-id", "2"}, {"tier-flag", "0"}, {"level-id", "93"}})
+ .IsSameCodec(Sdp("H265", Params{{"profile-id", "1"},
+ {"tier-flag", "0"},
+ {"level-id", "93"}})));
+ EXPECT_FALSE(
+ Sdp("H265",
+ Params{{"profile-id", "1"}, {"tier-flag", "1"}, {"level-id", "120"}})
+ .IsSameCodec(Sdp("H265", Params{{"profile-id", "1"},
+ {"tier-flag", "0"},
+ {"level-id", "120"}})));
+ EXPECT_FALSE(
+ Sdp("H265",
+ Params{{"profile-id", "1"}, {"tier-flag", "0"}, {"level-id", "93"}})
+ .IsSameCodec(Sdp("H265", Params{{"profile-id", "1"},
+ {"tier-flag", "0"},
+ {"level-id", "90"}})));
+#endif
}
TEST(SdpVideoFormatTest, DifferentCodecNameSameParameters) {
@@ -86,6 +132,12 @@
.IsSameCodec(Sdp("H264", Params{{"profile", "0"}})));
EXPECT_FALSE(Sdp("AV1", Params{{"profile", "2"}})
.IsSameCodec(Sdp("VP9", Params{{"profile", "2"}})));
+#ifdef RTC_ENABLE_H265
+ EXPECT_FALSE(Sdp("H265", Params{{"profile-id", "0"}})
+ .IsSameCodec(Sdp("H264", Params{{"profile-id", "0"}})));
+ EXPECT_FALSE(Sdp("H265", Params{{"profile-id", "2"}})
+ .IsSameCodec(Sdp("VP9", Params{{"profile-id", "2"}})));
+#endif
}
TEST(SdpVideoFormatTest, H264PacketizationMode) {
diff --git a/api/video_codecs/video_codec.cc b/api/video_codecs/video_codec.cc
index dfd2e21..39a345d 100644
--- a/api/video_codecs/video_codec.cc
+++ b/api/video_codecs/video_codec.cc
@@ -28,6 +28,7 @@
constexpr char kPayloadNameH264[] = "H264";
constexpr char kPayloadNameGeneric[] = "Generic";
constexpr char kPayloadNameMultiplex[] = "Multiplex";
+constexpr char kPayloadNameH265[] = "H265";
} // namespace
bool VideoCodecVP8::operator==(const VideoCodecVP8& other) const {
@@ -126,6 +127,8 @@
return kPayloadNameMultiplex;
case kVideoCodecGeneric:
return kPayloadNameGeneric;
+ case kVideoCodecH265:
+ return kPayloadNameH265;
}
RTC_CHECK_NOTREACHED();
}
@@ -142,6 +145,8 @@
return kVideoCodecH264;
if (absl::EqualsIgnoreCase(name, kPayloadNameMultiplex))
return kVideoCodecMultiplex;
+ if (absl::EqualsIgnoreCase(name, kPayloadNameH265))
+ return kVideoCodecH265;
return kVideoCodecGeneric;
}
diff --git a/api/video_codecs/video_decoder_software_fallback_wrapper.cc b/api/video_codecs/video_decoder_software_fallback_wrapper.cc
index c52ddbe..2af4d39 100644
--- a/api/video_codecs/video_decoder_software_fallback_wrapper.cc
+++ b/api/video_codecs/video_decoder_software_fallback_wrapper.cc
@@ -170,6 +170,10 @@
RTC_HISTOGRAM_COUNTS_100000(kFallbackHistogramsUmaPrefix + "Multiplex",
hw_decoded_frames_since_last_fallback_);
break;
+ case kVideoCodecH265:
+ RTC_HISTOGRAM_COUNTS_100000(kFallbackHistogramsUmaPrefix + "H265",
+ hw_decoded_frames_since_last_fallback_);
+ break;
}
}
diff --git a/call/rtp_payload_params.cc b/call/rtp_payload_params.cc
index f4b09ce..4b63ebe 100644
--- a/call/rtp_payload_params.cc
+++ b/call/rtp_payload_params.cc
@@ -100,6 +100,7 @@
case kVideoCodecGeneric:
rtp->codec = kVideoCodecGeneric;
return;
+ // TODO(bugs.webrtc.org/13485): Implement H265 codec specific info
default:
return;
}
@@ -341,6 +342,9 @@
return;
case VideoCodecType::kVideoCodecMultiplex:
return;
+ case VideoCodecType::kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485): Implement H265 to generic descriptor.
+ return;
}
RTC_DCHECK_NOTREACHED() << "Unsupported codec.";
}
@@ -402,6 +406,7 @@
}
case VideoCodecType::kVideoCodecAV1:
case VideoCodecType::kVideoCodecH264:
+ case VideoCodecType::kVideoCodecH265:
case VideoCodecType::kVideoCodecMultiplex:
return absl::nullopt;
}
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc b/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc
index 5d83c72..2c9e42e 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc
@@ -110,6 +110,8 @@
case VideoCodecType::kVideoCodecMultiplex:
// This codec type is afaik not used.
return rtclog2::FrameDecodedEvents::CODEC_UNKNOWN;
+ case VideoCodecType::kVideoCodecH265:
+ return rtclog2::FrameDecodedEvents::CODEC_H265;
}
RTC_DCHECK_NOTREACHED();
return rtclog2::FrameDecodedEvents::CODEC_UNKNOWN;
diff --git a/logging/rtc_event_log/rtc_event_log2.proto b/logging/rtc_event_log/rtc_event_log2.proto
index 658df6b..a417ded 100644
--- a/logging/rtc_event_log/rtc_event_log2.proto
+++ b/logging/rtc_event_log/rtc_event_log2.proto
@@ -339,6 +339,7 @@
CODEC_VP9 = 3;
CODEC_AV1 = 4;
CODEC_H264 = 5;
+ CODEC_H265 = 6;
}
// required
diff --git a/logging/rtc_event_log/rtc_event_log_parser.cc b/logging/rtc_event_log/rtc_event_log_parser.cc
index 0ea9643..37bb70a 100644
--- a/logging/rtc_event_log/rtc_event_log_parser.cc
+++ b/logging/rtc_event_log/rtc_event_log_parser.cc
@@ -261,6 +261,8 @@
return VideoCodecType::kVideoCodecAV1;
case rtclog2::FrameDecodedEvents::CODEC_H264:
return VideoCodecType::kVideoCodecH264;
+ case rtclog2::FrameDecodedEvents::CODEC_H265:
+ return VideoCodecType::kVideoCodecH265;
case rtclog2::FrameDecodedEvents::CODEC_UNKNOWN:
RTC_LOG(LS_ERROR) << "Unknown codec type. Assuming "
"VideoCodecType::kVideoCodecMultiplex";
diff --git a/logging/rtc_event_log/rtc_event_log_unittest_helper.cc b/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
index b378e8f..aece4b5 100644
--- a/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
+++ b/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
@@ -169,11 +169,11 @@
constexpr int kMaxHeight = 8640;
constexpr int kMinWidth = 16;
constexpr int kMinHeight = 16;
- constexpr int kNumCodecTypes = 5;
+ constexpr int kNumCodecTypes = 6;
constexpr VideoCodecType kCodecList[kNumCodecTypes] = {
- kVideoCodecGeneric, kVideoCodecVP8, kVideoCodecVP9, kVideoCodecAV1,
- kVideoCodecH264};
+ kVideoCodecGeneric, kVideoCodecVP8, kVideoCodecVP9,
+ kVideoCodecAV1, kVideoCodecH264, kVideoCodecH265};
const int64_t render_time_ms =
rtc::TimeMillis() + prng_.Rand(kMinRenderDelayMs, kMaxRenderDelayMs);
const int width = prng_.Rand(kMinWidth, kMaxWidth);
diff --git a/modules/rtp_rtcp/source/create_video_rtp_depacketizer.cc b/modules/rtp_rtcp/source/create_video_rtp_depacketizer.cc
index f1e4edd..95db212 100644
--- a/modules/rtp_rtcp/source/create_video_rtp_depacketizer.cc
+++ b/modules/rtp_rtcp/source/create_video_rtp_depacketizer.cc
@@ -33,6 +33,9 @@
return std::make_unique<VideoRtpDepacketizerVp9>();
case kVideoCodecAV1:
return std::make_unique<VideoRtpDepacketizerAv1>();
+ case kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485): Implement VideoRtpDepacketizerH265.
+ return nullptr;
case kVideoCodecGeneric:
case kVideoCodecMultiplex:
return std::make_unique<VideoRtpDepacketizerGeneric>();
diff --git a/modules/rtp_rtcp/source/rtp_format.cc b/modules/rtp_rtcp/source/rtp_format.cc
index 7550b70..2c11a29 100644
--- a/modules/rtp_rtcp/source/rtp_format.cc
+++ b/modules/rtp_rtcp/source/rtp_format.cc
@@ -57,6 +57,7 @@
return std::make_unique<RtpPacketizerAv1>(
payload, limits, rtp_video_header.frame_type,
rtp_video_header.is_last_frame_in_picture);
+ // TODO(bugs.webrtc.org/13485): Implement RtpPacketizerH265.
default: {
return std::make_unique<RtpPacketizerGeneric>(payload, limits,
rtp_video_header);
diff --git a/modules/rtp_rtcp/source/rtp_sender_video.cc b/modules/rtp_rtcp/source/rtp_sender_video.cc
index b846f7f..4d819a8 100644
--- a/modules/rtp_rtcp/source/rtp_sender_video.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_video.cc
@@ -92,6 +92,10 @@
// TODO(kron): Implement logic for H264 once WebRTC supports temporal
// layers for H264.
break;
+ case kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485): Implement logic for H265 once WebRTC
+ // supports temporal layers for H265.
+ break;
default:
break;
}
diff --git a/modules/rtp_rtcp/source/rtp_video_header.cc b/modules/rtp_rtcp/source/rtp_video_header.cc
index b07a7be..c4ab609 100644
--- a/modules/rtp_rtcp/source/rtp_video_header.cc
+++ b/modules/rtp_rtcp/source/rtp_video_header.cc
@@ -59,6 +59,9 @@
metadata.SetRTPVideoHeaderCodecSpecifics(
absl::get<RTPVideoHeaderH264>(video_type_header));
break;
+ case VideoCodecType::kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485)
+ break;
default:
// Codec-specifics are not supported for this codec.
break;
diff --git a/modules/video_coding/codecs/multiplex/multiplex_encoder_adapter.cc b/modules/video_coding/codecs/multiplex/multiplex_encoder_adapter.cc
index 80744e2..80d01dc 100644
--- a/modules/video_coding/codecs/multiplex/multiplex_encoder_adapter.cc
+++ b/modules/video_coding/codecs/multiplex/multiplex_encoder_adapter.cc
@@ -93,6 +93,9 @@
key_frame_interval_ = video_codec.H264()->keyFrameInterval;
video_codec.H264()->keyFrameInterval = 0;
break;
+ case kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485)
+ break;
default:
break;
}
diff --git a/modules/video_coding/codecs/test/videocodec_test_fixture_impl.cc b/modules/video_coding/codecs/test/videocodec_test_fixture_impl.cc
index 7543372..eb264e5 100644
--- a/modules/video_coding/codecs/test/videocodec_test_fixture_impl.cc
+++ b/modules/video_coding/codecs/test/videocodec_test_fixture_impl.cc
@@ -137,6 +137,9 @@
ss << "\nnum_temporal_layers: "
<< static_cast<int>(codec.H264().numberOfTemporalLayers);
break;
+ case kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485)
+ break;
default:
break;
}
@@ -246,6 +249,9 @@
codec_settings.H264()->numberOfTemporalLayers =
static_cast<uint8_t>(num_temporal_layers);
break;
+ case kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485)
+ break;
default:
break;
}
diff --git a/modules/video_coding/encoded_frame.cc b/modules/video_coding/encoded_frame.cc
index 637a20c..565a127 100644
--- a/modules/video_coding/encoded_frame.cc
+++ b/modules/video_coding/encoded_frame.cc
@@ -140,6 +140,10 @@
_codecSpecificInfo.codecType = kVideoCodecAV1;
break;
}
+ case kVideoCodecH265: {
+ _codecSpecificInfo.codecType = kVideoCodecH265;
+ break;
+ }
default: {
_codecSpecificInfo.codecType = kVideoCodecGeneric;
break;
diff --git a/modules/video_coding/utility/ivf_file_reader.cc b/modules/video_coding/utility/ivf_file_reader.cc
index 13092b5..9fc2332 100644
--- a/modules/video_coding/utility/ivf_file_reader.cc
+++ b/modules/video_coding/utility/ivf_file_reader.cc
@@ -29,6 +29,7 @@
constexpr uint8_t kVp9Header[kCodecTypeBytesCount] = {'V', 'P', '9', '0'};
constexpr uint8_t kAv1Header[kCodecTypeBytesCount] = {'A', 'V', '0', '1'};
constexpr uint8_t kH264Header[kCodecTypeBytesCount] = {'H', '2', '6', '4'};
+constexpr uint8_t kH265Header[kCodecTypeBytesCount] = {'H', '2', '6', '5'};
// RTP standard required 90kHz clock rate.
constexpr int32_t kRtpClockRateHz = 90000;
@@ -192,6 +193,9 @@
if (memcmp(&buffer[start_pos], kH264Header, kCodecTypeBytesCount) == 0) {
return VideoCodecType::kVideoCodecH264;
}
+ if (memcmp(&buffer[start_pos], kH265Header, kCodecTypeBytesCount) == 0) {
+ return VideoCodecType::kVideoCodecH265;
+ }
has_error_ = true;
RTC_LOG(LS_ERROR) << "Unknown codec type: "
<< std::string(
diff --git a/modules/video_coding/utility/ivf_file_writer.cc b/modules/video_coding/utility/ivf_file_writer.cc
index 0102598..cc5aed3 100644
--- a/modules/video_coding/utility/ivf_file_writer.cc
+++ b/modules/video_coding/utility/ivf_file_writer.cc
@@ -92,6 +92,12 @@
ivf_header[10] = '6';
ivf_header[11] = '4';
break;
+ case kVideoCodecH265:
+ ivf_header[8] = 'H';
+ ivf_header[9] = '2';
+ ivf_header[10] = '6';
+ ivf_header[11] = '5';
+ break;
default:
// For unknown codec type use **** code. You can specify actual payload
// format when playing the video with ffplay: ffplay -f H263 file.ivf
diff --git a/modules/video_coding/utility/qp_parser.cc b/modules/video_coding/utility/qp_parser.cc
index 18f2254..3b9aaa3 100644
--- a/modules/video_coding/utility/qp_parser.cc
+++ b/modules/video_coding/utility/qp_parser.cc
@@ -36,6 +36,8 @@
}
} else if (codec_type == kVideoCodecH264) {
return h264_parsers_[spatial_idx].Parse(frame_data, frame_size);
+ } else if (codec_type == kVideoCodecH265) {
+ // TODO(bugs.webrtc.org/13485)
}
return absl::nullopt;
diff --git a/modules/video_coding/utility/simulcast_utility.cc b/modules/video_coding/utility/simulcast_utility.cc
index 95e9488..824f4b0 100644
--- a/modules/video_coding/utility/simulcast_utility.cc
+++ b/modules/video_coding/utility/simulcast_utility.cc
@@ -94,6 +94,9 @@
case kVideoCodecH264:
num_temporal_layers = codec.H264().numberOfTemporalLayers;
break;
+ case kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485)
+ break;
default:
break;
}
diff --git a/modules/video_coding/video_codec_initializer.cc b/modules/video_coding/video_codec_initializer.cc
index 43fab8c..79421ff 100644
--- a/modules/video_coding/video_codec_initializer.cc
+++ b/modules/video_coding/video_codec_initializer.cc
@@ -344,6 +344,9 @@
kMaxTemporalStreams);
break;
}
+ case kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485)
+ break;
default:
// TODO(pbos): Support encoder_settings codec-agnostically.
RTC_DCHECK(!config.encoder_specific_settings)
diff --git a/rtc_base/experiments/balanced_degradation_settings.cc b/rtc_base/experiments/balanced_degradation_settings.cc
index 1652e31..1a269b4 100644
--- a/rtc_base/experiments/balanced_degradation_settings.cc
+++ b/rtc_base/experiments/balanced_degradation_settings.cc
@@ -159,6 +159,8 @@
low = config.vp9.GetQpLow();
high = config.vp9.GetQpHigh();
break;
+ case kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485): Use H264 QP thresholds for now.
case kVideoCodecH264:
low = config.h264.GetQpLow();
high = config.h264.GetQpHigh();
@@ -194,6 +196,8 @@
case kVideoCodecVP8:
fps = config->vp8.GetFps();
break;
+ case kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485): Use VP9 bitrate limits for now.
case kVideoCodecVP9:
fps = config->vp9.GetFps();
break;
@@ -226,6 +230,8 @@
case kVideoCodecVP8:
kbps = config->vp8.GetKbps();
break;
+ case kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485): Use VP9 bitrate limits for now.
case kVideoCodecVP9:
kbps = config->vp9.GetKbps();
break;
@@ -259,6 +265,8 @@
case kVideoCodecVP8:
kbps_res = config->vp8.GetKbpsRes();
break;
+ case kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485): Use VP9 bitrate limits for now.
case kVideoCodecVP9:
kbps_res = config->vp9.GetKbpsRes();
break;
diff --git a/rtc_base/experiments/min_video_bitrate_experiment.cc b/rtc_base/experiments/min_video_bitrate_experiment.cc
index f37c4e9..f9e7613 100644
--- a/rtc_base/experiments/min_video_bitrate_experiment.cc
+++ b/rtc_base/experiments/min_video_bitrate_experiment.cc
@@ -94,6 +94,8 @@
switch (type) {
case kVideoCodecVP8:
return min_bitrate_vp8.GetOptional();
+ case kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485): Use VP9 bitrate limits for now.
case kVideoCodecVP9:
return min_bitrate_vp9.GetOptional();
case kVideoCodecAV1:
diff --git a/rtc_base/experiments/quality_scaling_experiment.cc b/rtc_base/experiments/quality_scaling_experiment.cc
index 7d5722b..0c4ec22 100644
--- a/rtc_base/experiments/quality_scaling_experiment.cc
+++ b/rtc_base/experiments/quality_scaling_experiment.cc
@@ -81,6 +81,8 @@
return GetThresholds(settings->vp8_low, settings->vp8_high, kMaxVp8Qp);
case kVideoCodecVP9:
return GetThresholds(settings->vp9_low, settings->vp9_high, kMaxVp9Qp);
+ case kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485): Use H264 QP thresholds for now.
case kVideoCodecH264:
return GetThresholds(settings->h264_low, settings->h264_high, kMaxH264Qp);
case kVideoCodecGeneric:
diff --git a/rtc_tools/rtc_event_log_to_text/converter.cc b/rtc_tools/rtc_event_log_to_text/converter.cc
index f171260..90d568f 100644
--- a/rtc_tools/rtc_event_log_to_text/converter.cc
+++ b/rtc_tools/rtc_event_log_to_text/converter.cc
@@ -430,7 +430,8 @@
{VideoCodecType::kVideoCodecVP9, "VP9"},
{VideoCodecType::kVideoCodecAV1, "AV1"},
{VideoCodecType::kVideoCodecH264, "H264"},
- {VideoCodecType::kVideoCodecMultiplex, "MULTIPLEX"}};
+ {VideoCodecType::kVideoCodecMultiplex, "MULTIPLEX"},
+ {VideoCodecType::kVideoCodecH265, "H265"}};
fprintf(output,
"FRAME_DECODED %" PRId64 " render_time=%" PRId64
diff --git a/rtc_tools/video_encoder/video_encoder.cc b/rtc_tools/video_encoder/video_encoder.cc
index a2eeef8..74f59c4 100644
--- a/rtc_tools/video_encoder/video_encoder.cc
+++ b/rtc_tools/video_encoder/video_encoder.cc
@@ -295,7 +295,9 @@
RTC_LOG(LS_WARNING) << "Failed to configure svc bitrates for av1.";
}
break;
-
+ case kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485)
+ break;
default:
RTC_CHECK_NOTREACHED();
break;
diff --git a/rtc_tools/video_replay.cc b/rtc_tools/video_replay.cc
index 242ce1b..c8bfec2 100644
--- a/rtc_tools/video_replay.cc
+++ b/rtc_tools/video_replay.cc
@@ -267,6 +267,8 @@
video_codec_type_ = VideoCodecType::kVideoCodecH264;
} else if (codec == "AV1") {
video_codec_type_ = VideoCodecType::kVideoCodecAV1;
+ } else if (codec == "H265") {
+ video_codec_type_ = VideoCodecType::kVideoCodecH265;
} else {
RTC_LOG(LS_ERROR) << "Unsupported video codec " << codec;
RTC_DCHECK_NOTREACHED();
diff --git a/sdk/android/src/jni/video_decoder_wrapper.cc b/sdk/android/src/jni/video_decoder_wrapper.cc
index 22bfe77..8c231c0 100644
--- a/sdk/android/src/jni/video_decoder_wrapper.cc
+++ b/sdk/android/src/jni/video_decoder_wrapper.cc
@@ -255,6 +255,13 @@
qp = h264_bitstream_parser_.GetLastSliceQp();
break;
}
+#ifdef RTC_ENABLE_H265
+ case kVideoCodecH265:
+ h265_bitstream_parser_.ParseBitstream(buffer);
+ qp = h265_bitstream_parser_.GetLastSliceQp().value_or(-1);
+ success = (qp >= 0);
+ break;
+#endif
default:
break; // Default is to not provide QP.
}
diff --git a/sdk/android/src/jni/video_decoder_wrapper.h b/sdk/android/src/jni/video_decoder_wrapper.h
index 04b083c..53246f3 100644
--- a/sdk/android/src/jni/video_decoder_wrapper.h
+++ b/sdk/android/src/jni/video_decoder_wrapper.h
@@ -19,6 +19,9 @@
#include "api/sequence_checker.h"
#include "api/video_codecs/video_decoder.h"
#include "common_video/h264/h264_bitstream_parser.h"
+#ifdef RTC_ENABLE_H265
+#include "common_video/h265/h265_bitstream_parser.h"
+#endif
#include "rtc_base/race_checker.h"
#include "rtc_base/synchronization/mutex.h"
#include "sdk/android/src/jni/jni_helpers.h"
@@ -96,6 +99,10 @@
bool initialized_ RTC_GUARDED_BY(decoder_thread_checker_);
H264BitstreamParser h264_bitstream_parser_
RTC_GUARDED_BY(decoder_thread_checker_);
+#ifdef RTC_ENABLE_H265
+ H265BitstreamParser h265_bitstream_parser_
+ RTC_GUARDED_BY(decoder_thread_checker_);
+#endif
DecodedImageCallback* callback_ RTC_GUARDED_BY(callback_race_checker_);
diff --git a/sdk/android/src/jni/video_encoder_wrapper.cc b/sdk/android/src/jni/video_encoder_wrapper.cc
index 3912ede..6cd8acb 100644
--- a/sdk/android/src/jni/video_encoder_wrapper.cc
+++ b/sdk/android/src/jni/video_encoder_wrapper.cc
@@ -227,6 +227,8 @@
return VideoEncoder::ScalingSettings(kLowVp9QpThreshold,
kHighVp9QpThreshold);
}
+ case kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485): Use H264 QP thresholds for now.
case kVideoCodecH264: {
// Same as in h264_encoder_impl.cc.
static const int kLowH264QpThreshold = 24;
@@ -355,6 +357,13 @@
qp = h264_bitstream_parser_.GetLastSliceQp().value_or(-1);
success = (qp >= 0);
break;
+#ifdef RTC_ENABLE_H265
+ case kVideoCodecH265:
+ h265_bitstream_parser_.ParseBitstream(buffer);
+ qp = h265_bitstream_parser_.GetLastSliceQp().value_or(-1);
+ success = (qp >= 0);
+ break;
+#endif
default: // Default is to not provide QP.
success = false;
break;
diff --git a/sdk/android/src/jni/video_encoder_wrapper.h b/sdk/android/src/jni/video_encoder_wrapper.h
index d3eb220..04d70f3 100644
--- a/sdk/android/src/jni/video_encoder_wrapper.h
+++ b/sdk/android/src/jni/video_encoder_wrapper.h
@@ -21,6 +21,9 @@
#include "absl/types/optional.h"
#include "api/video_codecs/video_encoder.h"
#include "common_video/h264/h264_bitstream_parser.h"
+#ifdef RTC_ENABLE_H265
+#include "common_video/h265/h265_bitstream_parser.h"
+#endif
#include "modules/video_coding/codecs/vp9/include/vp9_globals.h"
#include "modules/video_coding/svc/scalable_video_controller_no_layering.h"
#include "rtc_base/synchronization/mutex.h"
@@ -103,6 +106,9 @@
VideoCodec codec_settings_;
EncoderInfo encoder_info_;
H264BitstreamParser h264_bitstream_parser_;
+#ifdef RTC_ENABLE_H265
+ H265BitstreamParser h265_bitstream_parser_;
+#endif
// Fills frame dependencies in codec-agnostic format.
ScalableVideoControllerNoLayering svc_controller_;
diff --git a/test/fuzzers/rtp_frame_reference_finder_fuzzer.cc b/test/fuzzers/rtp_frame_reference_finder_fuzzer.cc
index b1cabc3..ea66c4a 100644
--- a/test/fuzzers/rtp_frame_reference_finder_fuzzer.cc
+++ b/test/fuzzers/rtp_frame_reference_finder_fuzzer.cc
@@ -120,6 +120,9 @@
reader.CopyTo(
&video_header.video_type_header.emplace<RTPVideoHeaderH264>());
break;
+ case kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485)
+ break;
default:
break;
}
diff --git a/test/scenario/video_stream.cc b/test/scenario/video_stream.cc
index e082aa3..d376a8f 100644
--- a/test/scenario/video_stream.cc
+++ b/test/scenario/video_stream.cc
@@ -51,6 +51,8 @@
return VideoTestConstants::kPayloadTypeVP9;
case VideoCodecType::kVideoCodecH264:
return VideoTestConstants::kPayloadTypeH264;
+ case VideoCodecType::kVideoCodecH265:
+ return VideoTestConstants::kPayloadTypeH265;
default:
RTC_DCHECK_NOTREACHED();
}
@@ -66,6 +68,8 @@
return cricket::kVp9CodecName;
case VideoCodecType::kVideoCodecH264:
return cricket::kH264CodecName;
+ case VideoCodecType::kVideoCodecH265:
+ return cricket::kH265CodecName;
default:
RTC_DCHECK_NOTREACHED();
}
@@ -203,6 +207,7 @@
return CreateVp9SpecificSettings(config);
case Codec::kVideoCodecGeneric:
case Codec::kVideoCodecAV1:
+ case Codec::kVideoCodecH265:
return nullptr;
case Codec::kVideoCodecMultiplex:
RTC_DCHECK_NOTREACHED();
diff --git a/test/testsupport/ivf_video_frame_generator.cc b/test/testsupport/ivf_video_frame_generator.cc
index ec3c948..0dec113 100644
--- a/test/testsupport/ivf_video_frame_generator.cc
+++ b/test/testsupport/ivf_video_frame_generator.cc
@@ -148,6 +148,9 @@
if (codec_type == VideoCodecType::kVideoCodecAV1) {
return CreateDav1dDecoder();
}
+ if (codec_type == VideoCodecType::kVideoCodecH265) {
+ // TODO(bugs.webrtc.org/13485): implement H265 decoder
+ }
return nullptr;
}
diff --git a/test/video_test_constants.h b/test/video_test_constants.h
index 732d4f0..b908398 100644
--- a/test/video_test_constants.h
+++ b/test/video_test_constants.h
@@ -31,6 +31,7 @@
kRtxRedPayloadType = 99,
kVideoSendPayloadType = 100,
kAudioSendPayloadType = 103,
+ kPayloadTypeH265 = 117,
kRedPayloadType = 118,
kUlpfecPayloadType = 119,
kFlexfecPayloadType = 120,
diff --git a/video/encoder_overshoot_detector.cc b/video/encoder_overshoot_detector.cc
index 2c4efdb..d5c1f91 100644
--- a/video/encoder_overshoot_detector.cc
+++ b/video/encoder_overshoot_detector.cc
@@ -266,6 +266,12 @@
RTC_HISTOGRAMS_COUNTS_10000(index, overshoot_histogram_prefix + "H264",
average_overshoot_percent);
break;
+ case VideoCodecType::kVideoCodecH265:
+ RTC_HISTOGRAMS_COUNTS_10000(index, rmse_histogram_prefix + "H265",
+ bitrate_rmse);
+ RTC_HISTOGRAMS_COUNTS_10000(index, overshoot_histogram_prefix + "H265",
+ average_overshoot_percent);
+ break;
case VideoCodecType::kVideoCodecGeneric:
case VideoCodecType::kVideoCodecMultiplex:
break;
diff --git a/video/encoder_overshoot_detector_unittest.cc b/video/encoder_overshoot_detector_unittest.cc
index bdc2676..2178957 100644
--- a/video/encoder_overshoot_detector_unittest.cc
+++ b/video/encoder_overshoot_detector_unittest.cc
@@ -35,6 +35,8 @@
return "Av1";
case kVideoCodecH264:
return "H264";
+ case kVideoCodecH265:
+ return "H265";
case kVideoCodecGeneric:
return "Generic";
case kVideoCodecMultiplex:
@@ -275,6 +277,8 @@
{VideoCodecType::kVideoCodecAV1, false},
{VideoCodecType::kVideoCodecAV1, true},
{VideoCodecType::kVideoCodecH264, false},
- {VideoCodecType::kVideoCodecH264, true}}));
+ {VideoCodecType::kVideoCodecH264, true},
+ {VideoCodecType::kVideoCodecH265, false},
+ {VideoCodecType::kVideoCodecH265, true}}));
} // namespace webrtc
diff --git a/video/send_statistics_proxy.cc b/video/send_statistics_proxy.cc
index 9a5f69d..9504bda 100644
--- a/video/send_statistics_proxy.cc
+++ b/video/send_statistics_proxy.cc
@@ -47,6 +47,7 @@
kVideoVp9 = 2,
kVideoH264 = 3,
kVideoAv1 = 4,
+ kVideoH265 = 5,
kVideoMax = 64,
};
@@ -76,6 +77,8 @@
return kVideoH264;
case kVideoCodecAV1:
return kVideoAv1;
+ case kVideoCodecH265:
+ return kVideoH265;
default:
return kVideoUnknown;
}
diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc
index c367510..5eeb740 100644
--- a/video/video_stream_encoder.cc
+++ b/video/video_stream_encoder.cc
@@ -135,7 +135,9 @@
return true;
}
break;
-
+ case kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485): Implement new send codec H265
+ [[fallthrough]];
default:
break;
}
@@ -1351,6 +1353,7 @@
// TODO(sprang): Add a better way to disable frame dropping.
num_layers = codec.simulcastStream[0].numberOfTemporalLayers;
} else {
+ // TODO(bugs.webrtc.org/13485): Implement H265 temporal layer
num_layers = 1;
}
diff --git a/video/video_stream_encoder_unittest.cc b/video/video_stream_encoder_unittest.cc
index 44fc53f..53b4a0f 100644
--- a/video/video_stream_encoder_unittest.cc
+++ b/video/video_stream_encoder_unittest.cc
@@ -8822,6 +8822,9 @@
mock_encoder_factory_for_multiplex_.get(), SdpVideoFormat("VP8"),
false);
break;
+ case kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485): Use a fake encoder
+ break;
default:
RTC_DCHECK_NOTREACHED();
}