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}
This commit is contained in:
qwu16 2023-09-20 13:10:31 +08:00 committed by WebRTC LUCI CQ
parent 9596002743
commit ae82df718c
45 changed files with 217 additions and 8 deletions

View file

@ -302,6 +302,10 @@ config("common_config") {
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" ]
}

View file

@ -51,6 +51,10 @@ std::unique_ptr<VideoRtpDepacketizer> CreateDepacketizer(
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;

View file

@ -52,7 +52,7 @@ class RtpVideoFrameAssembler {
// 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;

View file

@ -89,6 +89,9 @@ class PacketBuilder {
case PayloadFormat::kAv1: {
return kVideoCodecAV1;
}
case PayloadFormat::kH265: {
return kVideoCodecH265;
}
case PayloadFormat::kGeneric: {
return kVideoCodecGeneric;
}

View file

@ -22,6 +22,7 @@ enum VideoCodecType {
kVideoCodecAV1,
kVideoCodecH264,
kVideoCodecMultiplex,
kVideoCodecH265,
};
} // namespace webrtc

View file

@ -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 @@ bool IsSameCodecSpecific(const SdpVideoFormat& format1,
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;
}

View file

@ -25,12 +25,18 @@ TEST(SdpVideoFormatTest, SameCodecNameNoParameters) {
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 @@ TEST(SdpVideoFormatTest, SameCodecNameSameParameters) {
.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 @@ TEST(SdpVideoFormatTest, SameCodecNameDifferentParameters) {
.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 @@ TEST(SdpVideoFormatTest, DifferentCodecNameSameParameters) {
.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) {

View file

@ -28,6 +28,7 @@ constexpr char kPayloadNameAv1x[] = "AV1X";
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 @@ const char* CodecTypeToPayloadString(VideoCodecType type) {
return kPayloadNameMultiplex;
case kVideoCodecGeneric:
return kPayloadNameGeneric;
case kVideoCodecH265:
return kPayloadNameH265;
}
RTC_CHECK_NOTREACHED();
}
@ -142,6 +145,8 @@ VideoCodecType PayloadStringToCodecType(const std::string& name) {
return kVideoCodecH264;
if (absl::EqualsIgnoreCase(name, kPayloadNameMultiplex))
return kVideoCodecMultiplex;
if (absl::EqualsIgnoreCase(name, kPayloadNameH265))
return kVideoCodecH265;
return kVideoCodecGeneric;
}

View file

@ -170,6 +170,10 @@ void VideoDecoderSoftwareFallbackWrapper::UpdateFallbackDecoderHistograms() {
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;
}
}

View file

@ -100,6 +100,7 @@ void PopulateRtpWithCodecSpecifics(const CodecSpecificInfo& info,
case kVideoCodecGeneric:
rtp->codec = kVideoCodecGeneric;
return;
// TODO(bugs.webrtc.org/13485): Implement H265 codec specific info
default:
return;
}
@ -341,6 +342,9 @@ void RtpPayloadParams::SetGeneric(const CodecSpecificInfo* codec_specific_info,
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 @@ absl::optional<FrameDependencyStructure> RtpPayloadParams::GenericStructure(
}
case VideoCodecType::kVideoCodecAV1:
case VideoCodecType::kVideoCodecH264:
case VideoCodecType::kVideoCodecH265:
case VideoCodecType::kVideoCodecMultiplex:
return absl::nullopt;
}

View file

@ -110,6 +110,8 @@ rtclog2::FrameDecodedEvents::Codec ConvertToProtoFormat(VideoCodecType codec) {
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;

View file

@ -339,6 +339,7 @@ message FrameDecodedEvents {
CODEC_VP9 = 3;
CODEC_AV1 = 4;
CODEC_H264 = 5;
CODEC_H265 = 6;
}
// required

View file

@ -261,6 +261,8 @@ VideoCodecType GetRuntimeCodecType(rtclog2::FrameDecodedEvents::Codec codec) {
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";

View file

@ -169,11 +169,11 @@ std::unique_ptr<RtcEventFrameDecoded> EventGenerator::NewFrameDecodedEvent(
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);

View file

@ -33,6 +33,9 @@ std::unique_ptr<VideoRtpDepacketizer> CreateVideoRtpDepacketizer(
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>();

View file

@ -57,6 +57,7 @@ std::unique_ptr<RtpPacketizer> RtpPacketizer::Create(
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);

View file

@ -92,6 +92,10 @@ bool IsBaseLayer(const RTPVideoHeader& video_header) {
// 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;
}

View file

@ -59,6 +59,9 @@ VideoFrameMetadata RTPVideoHeader::GetAsMetadata() const {
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;

View file

@ -93,6 +93,9 @@ int MultiplexEncoderAdapter::InitEncode(
key_frame_interval_ = video_codec.H264()->keyFrameInterval;
video_codec.H264()->keyFrameInterval = 0;
break;
case kVideoCodecH265:
// TODO(bugs.webrtc.org/13485)
break;
default:
break;
}

View file

@ -137,6 +137,9 @@ std::string CodecSpecificToString(const VideoCodec& codec) {
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 @@ void VideoCodecTestFixtureImpl::Config::SetCodecSettings(
codec_settings.H264()->numberOfTemporalLayers =
static_cast<uint8_t>(num_temporal_layers);
break;
case kVideoCodecH265:
// TODO(bugs.webrtc.org/13485)
break;
default:
break;
}

View file

@ -140,6 +140,10 @@ void VCMEncodedFrame::CopyCodecSpecific(const RTPVideoHeader* header) {
_codecSpecificInfo.codecType = kVideoCodecAV1;
break;
}
case kVideoCodecH265: {
_codecSpecificInfo.codecType = kVideoCodecH265;
break;
}
default: {
_codecSpecificInfo.codecType = kVideoCodecGeneric;
break;

View file

@ -29,6 +29,7 @@ constexpr uint8_t kVp8Header[kCodecTypeBytesCount] = {'V', 'P', '8', '0'};
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 @@ absl::optional<VideoCodecType> IvfFileReader::ParseCodecType(uint8_t* buffer,
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(

View file

@ -92,6 +92,12 @@ bool IvfFileWriter::WriteHeader() {
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

View file

@ -36,6 +36,8 @@ absl::optional<uint32_t> QpParser::Parse(VideoCodecType codec_type,
}
} 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;

View file

@ -94,6 +94,9 @@ int SimulcastUtility::NumberOfTemporalLayers(const VideoCodec& codec,
case kVideoCodecH264:
num_temporal_layers = codec.H264().numberOfTemporalLayers;
break;
case kVideoCodecH265:
// TODO(bugs.webrtc.org/13485)
break;
default:
break;
}

View file

@ -344,6 +344,9 @@ VideoCodec VideoCodecInitializer::VideoEncoderConfigToVideoCodec(
kMaxTemporalStreams);
break;
}
case kVideoCodecH265:
// TODO(bugs.webrtc.org/13485)
break;
default:
// TODO(pbos): Support encoder_settings codec-agnostically.
RTC_DCHECK(!config.encoder_specific_settings)

View file

@ -159,6 +159,8 @@ absl::optional<VideoEncoder::QpThresholds> GetThresholds(
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 @@ int GetFps(VideoCodecType type,
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 @@ absl::optional<int> GetKbps(
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 @@ absl::optional<int> GetKbpsRes(
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;

View file

@ -94,6 +94,8 @@ absl::optional<DataRate> GetExperimentalMinVideoBitrate(VideoCodecType type) {
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:

View file

@ -81,6 +81,8 @@ QualityScalingExperiment::GetQpThresholds(VideoCodecType codec_type) {
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:

View file

@ -430,7 +430,8 @@ bool Convert(std::string inputfile,
{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

View file

@ -295,7 +295,9 @@ class TestVideoEncoderFactoryWrapper final {
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;

View file

@ -267,6 +267,8 @@ class DecoderIvfFileWriter : public test::FakeDecoder {
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();

View file

@ -255,6 +255,13 @@ absl::optional<uint8_t> VideoDecoderWrapper::ParseQP(
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.
}

View file

@ -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 @@ class VideoDecoderWrapper : public VideoDecoder {
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_);

View file

@ -227,6 +227,8 @@ VideoEncoderWrapper::GetScalingSettingsInternal(JNIEnv* jni) const {
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 @@ int VideoEncoderWrapper::ParseQp(rtc::ArrayView<const uint8_t> buffer) {
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;

View file

@ -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 @@ class VideoEncoderWrapper : public VideoEncoder {
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_;

View file

@ -120,6 +120,9 @@ void FuzzOneInput(const uint8_t* data, size_t size) {
reader.CopyTo(
&video_header.video_type_header.emplace<RTPVideoHeaderH264>());
break;
case kVideoCodecH265:
// TODO(bugs.webrtc.org/13485)
break;
default:
break;
}

View file

@ -51,6 +51,8 @@ uint8_t CodecTypeToPayloadType(VideoCodecType codec_type) {
return VideoTestConstants::kPayloadTypeVP9;
case VideoCodecType::kVideoCodecH264:
return VideoTestConstants::kPayloadTypeH264;
case VideoCodecType::kVideoCodecH265:
return VideoTestConstants::kPayloadTypeH265;
default:
RTC_DCHECK_NOTREACHED();
}
@ -66,6 +68,8 @@ std::string CodecTypeToCodecName(VideoCodecType codec_type) {
return cricket::kVp9CodecName;
case VideoCodecType::kVideoCodecH264:
return cricket::kH264CodecName;
case VideoCodecType::kVideoCodecH265:
return cricket::kH265CodecName;
default:
RTC_DCHECK_NOTREACHED();
}
@ -203,6 +207,7 @@ CreateEncoderSpecificSettings(VideoStreamConfig config) {
return CreateVp9SpecificSettings(config);
case Codec::kVideoCodecGeneric:
case Codec::kVideoCodecAV1:
case Codec::kVideoCodecH265:
return nullptr;
case Codec::kVideoCodecMultiplex:
RTC_DCHECK_NOTREACHED();

View file

@ -148,6 +148,9 @@ std::unique_ptr<VideoDecoder> IvfVideoFrameGenerator::CreateVideoDecoder(
if (codec_type == VideoCodecType::kVideoCodecAV1) {
return CreateDav1dDecoder();
}
if (codec_type == VideoCodecType::kVideoCodecH265) {
// TODO(bugs.webrtc.org/13485): implement H265 decoder
}
return nullptr;
}

View file

@ -31,6 +31,7 @@ class VideoTestConstants {
kRtxRedPayloadType = 99,
kVideoSendPayloadType = 100,
kAudioSendPayloadType = 103,
kPayloadTypeH265 = 117,
kRedPayloadType = 118,
kUlpfecPayloadType = 119,
kFlexfecPayloadType = 120,

View file

@ -266,6 +266,12 @@ void EncoderOvershootDetector::UpdateHistograms() {
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;

View file

@ -35,6 +35,8 @@ static std::string CodecTypeToHistogramSuffix(VideoCodecType codec) {
return "Av1";
case kVideoCodecH264:
return "H264";
case kVideoCodecH265:
return "H265";
case kVideoCodecGeneric:
return "Generic";
case kVideoCodecMultiplex:
@ -275,6 +277,8 @@ INSTANTIATE_TEST_SUITE_P(
{VideoCodecType::kVideoCodecAV1, false},
{VideoCodecType::kVideoCodecAV1, true},
{VideoCodecType::kVideoCodecH264, false},
{VideoCodecType::kVideoCodecH264, true}}));
{VideoCodecType::kVideoCodecH264, true},
{VideoCodecType::kVideoCodecH265, false},
{VideoCodecType::kVideoCodecH265, true}}));
} // namespace webrtc

View file

@ -47,6 +47,7 @@ enum HistogramCodecType {
kVideoVp9 = 2,
kVideoH264 = 3,
kVideoAv1 = 4,
kVideoH265 = 5,
kVideoMax = 64,
};
@ -76,6 +77,8 @@ HistogramCodecType PayloadNameToHistogramCodecType(
return kVideoH264;
case kVideoCodecAV1:
return kVideoAv1;
case kVideoCodecH265:
return kVideoH265;
default:
return kVideoUnknown;
}

View file

@ -135,7 +135,9 @@ bool RequiresEncoderReset(const VideoCodec& prev_send_codec,
return true;
}
break;
case kVideoCodecH265:
// TODO(bugs.webrtc.org/13485): Implement new send codec H265
[[fallthrough]];
default:
break;
}
@ -1351,6 +1353,7 @@ void VideoStreamEncoder::ReconfigureEncoder() {
// 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;
}

View file

@ -8822,6 +8822,9 @@ class VideoStreamEncoderWithRealEncoderTest
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();
}