mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-12 21:30:45 +01:00
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:
parent
9596002743
commit
ae82df718c
45 changed files with 217 additions and 8 deletions
4
BUILD.gn
4
BUILD.gn
|
@ -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" ]
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -89,6 +89,9 @@ class PacketBuilder {
|
|||
case PayloadFormat::kAv1: {
|
||||
return kVideoCodecAV1;
|
||||
}
|
||||
case PayloadFormat::kH265: {
|
||||
return kVideoCodecH265;
|
||||
}
|
||||
case PayloadFormat::kGeneric: {
|
||||
return kVideoCodecGeneric;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ enum VideoCodecType {
|
|||
kVideoCodecAV1,
|
||||
kVideoCodecH264,
|
||||
kVideoCodecMultiplex,
|
||||
kVideoCodecH265,
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -339,6 +339,7 @@ message FrameDecodedEvents {
|
|||
CODEC_VP9 = 3;
|
||||
CODEC_AV1 = 4;
|
||||
CODEC_H264 = 5;
|
||||
CODEC_H265 = 6;
|
||||
}
|
||||
|
||||
// required
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
|
|
@ -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_);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ class VideoTestConstants {
|
|||
kRtxRedPayloadType = 99,
|
||||
kVideoSendPayloadType = 100,
|
||||
kAudioSendPayloadType = 103,
|
||||
kPayloadTypeH265 = 117,
|
||||
kRedPayloadType = 118,
|
||||
kUlpfecPayloadType = 119,
|
||||
kFlexfecPayloadType = 120,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue