| commit 52ade488b09c6427fbe62663f4b2d10a65353485 |
| Author: Youenn Fablet <youenn@apple.com> |
| Date: Tue Nov 3 17:29:10 2020 +0100 |
| |
| webrtc-new-fix |
| |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/api/audio_codecs/ilbc/audio_encoder_ilbc.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/api/audio_codecs/ilbc/audio_encoder_ilbc.cc |
| index bd653b7979b1..117517b093d7 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/api/audio_codecs/ilbc/audio_encoder_ilbc.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/api/audio_codecs/ilbc/audio_encoder_ilbc.cc |
| @@ -32,7 +32,7 @@ int GetIlbcBitrate(int ptime) { |
| // 50 bytes per frame of 30 ms => (approx) 13333 bits/s. |
| return 13333; |
| default: |
| - FATAL(); |
| + RTC_FATAL(); |
| } |
| } |
| } // namespace |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/api/media_types.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/api/media_types.cc |
| index 6bc693860d38..3eba7cfaebbf 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/api/media_types.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/api/media_types.cc |
| @@ -27,7 +27,7 @@ std::string MediaTypeToString(MediaType type) { |
| case MEDIA_TYPE_DATA: |
| return kMediaTypeData; |
| } |
| - FATAL(); |
| + RTC_FATAL(); |
| // Not reachable; avoids compile warning. |
| return ""; |
| } |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/api/stats/rtc_stats.h b/Source/ThirdParty/libwebrtc/Source/webrtc/api/stats/rtc_stats.h |
| index 5de5b7fbb048..7b1dfd41a22d 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/api/stats/rtc_stats.h |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/api/stats/rtc_stats.h |
| @@ -363,6 +363,14 @@ class RTCStatsMember : public RTCStatsMemberInterface { |
| T value_; |
| }; |
| |
| +#if !defined(WEBRTC_WEBKIT_BUILD) |
| +#define WEBRTC_DECLARE_RTCSTATSMEMBER_AS_EXTERN(T) \ |
| + extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) \ |
| + RTCStatsMember<T> |
| +#else |
| +#define WEBRTC_DECLARE_RTCSTATSMEMBER_AS_EXTERN(T) |
| +#endif // WEBRTC_WEBKIT_BUILD |
| + |
| #define WEBRTC_DECLARE_RTCSTATSMEMBER(T) \ |
| template <> \ |
| RTC_EXPORT RTCStatsMemberInterface::Type RTCStatsMember<T>::StaticType(); \ |
| @@ -374,8 +382,7 @@ class RTCStatsMember : public RTCStatsMemberInterface { |
| RTC_EXPORT std::string RTCStatsMember<T>::ValueToString() const; \ |
| template <> \ |
| RTC_EXPORT std::string RTCStatsMember<T>::ValueToJson() const; \ |
| - extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) \ |
| - RTCStatsMember<T> |
| + WEBRTC_DECLARE_RTCSTATSMEMBER_AS_EXTERN(T) |
| |
| WEBRTC_DECLARE_RTCSTATSMEMBER(bool); |
| WEBRTC_DECLARE_RTCSTATSMEMBER(int32_t); |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/api/video/video_codec_type.h b/Source/ThirdParty/libwebrtc/Source/webrtc/api/video/video_codec_type.h |
| index 12dcfac1b9a6..fdbc5187d86e 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/api/video/video_codec_type.h |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/api/video/video_codec_type.h |
| @@ -22,6 +22,7 @@ enum VideoCodecType { |
| kVideoCodecVP9, |
| kVideoCodecAV1, |
| kVideoCodecH264, |
| + kVideoCodecH265, |
| kVideoCodecMultiplex, |
| }; |
| |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/api/video_codecs/video_codec.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/api/video_codecs/video_codec.cc |
| index 490eced4e0d2..e625e8938aee 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/api/video_codecs/video_codec.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/api/video_codecs/video_codec.cc |
| @@ -25,6 +25,7 @@ constexpr char kPayloadNameVp9[] = "VP9"; |
| // frozen. |
| constexpr char kPayloadNameAv1[] = "AV1X"; |
| constexpr char kPayloadNameH264[] = "H264"; |
| +constexpr char kPayloadNameH265[] = "H265"; |
| constexpr char kPayloadNameGeneric[] = "Generic"; |
| constexpr char kPayloadNameMultiplex[] = "Multiplex"; |
| } // namespace |
| @@ -115,6 +116,10 @@ const char* CodecTypeToPayloadString(VideoCodecType type) { |
| return kPayloadNameAv1; |
| case kVideoCodecH264: |
| return kPayloadNameH264; |
| +#ifndef DISABLE_H265 |
| + case kVideoCodecH265: |
| + return kPayloadNameH265; |
| +#endif |
| case kVideoCodecMultiplex: |
| return kPayloadNameMultiplex; |
| case kVideoCodecGeneric: |
| @@ -131,6 +136,10 @@ VideoCodecType PayloadStringToCodecType(const std::string& name) { |
| return kVideoCodecAV1; |
| if (absl::EqualsIgnoreCase(name, kPayloadNameH264)) |
| return kVideoCodecH264; |
| +#ifndef DISABLE_H265 |
| + if (absl::EqualsIgnoreCase(name, kPayloadNameH265)) |
| + return kVideoCodecH265; |
| +#endif |
| if (absl::EqualsIgnoreCase(name, kPayloadNameMultiplex)) |
| return kVideoCodecMultiplex; |
| return kVideoCodecGeneric; |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/api/video_codecs/video_decoder_software_fallback_wrapper.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/api/video_codecs/video_decoder_software_fallback_wrapper.cc |
| index 128087f20711..20b312cc06e1 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/api/video_codecs/video_decoder_software_fallback_wrapper.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/api/video_codecs/video_decoder_software_fallback_wrapper.cc |
| @@ -181,6 +181,12 @@ void VideoDecoderSoftwareFallbackWrapper::UpdateFallbackDecoderHistograms() { |
| RTC_HISTOGRAM_COUNTS_100000(kFallbackHistogramsUmaPrefix + "H264", |
| hw_decoded_frames_since_last_fallback_); |
| break; |
| +#ifndef DISABLE_H265 |
| + case kVideoCodecH265: |
| + RTC_HISTOGRAM_COUNTS_100000(kFallbackHistogramsUmaPrefix + "H265", |
| + hw_decoded_frames_since_last_fallback_); |
| + break; |
| +#endif |
| case kVideoCodecMultiplex: |
| RTC_HISTOGRAM_COUNTS_100000(kFallbackHistogramsUmaPrefix + "Multiplex", |
| hw_decoded_frames_since_last_fallback_); |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/audio/remix_resample.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/audio/remix_resample.cc |
| index 3694d34e40a8..ebab2f4068b6 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/audio/remix_resample.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/audio/remix_resample.cc |
| @@ -56,7 +56,7 @@ void RemixAndResample(const int16_t* src_data, |
| |
| if (resampler->InitializeIfNeeded(sample_rate_hz, dst_frame->sample_rate_hz_, |
| audio_ptr_num_channels) == -1) { |
| - FATAL() << "InitializeIfNeeded failed: sample_rate_hz = " << sample_rate_hz |
| + RTC_FATAL() << "InitializeIfNeeded failed: sample_rate_hz = " << sample_rate_hz |
| << ", dst_frame->sample_rate_hz_ = " << dst_frame->sample_rate_hz_ |
| << ", audio_ptr_num_channels = " << audio_ptr_num_channels; |
| } |
| @@ -70,7 +70,7 @@ void RemixAndResample(const int16_t* src_data, |
| resampler->Resample(audio_ptr, src_length, dst_frame->mutable_data(), |
| AudioFrame::kMaxDataSizeSamples); |
| if (out_length == -1) { |
| - FATAL() << "Resample failed: audio_ptr = " << audio_ptr |
| + RTC_FATAL() << "Resample failed: audio_ptr = " << audio_ptr |
| << ", src_length = " << src_length |
| << ", dst_frame->mutable_data() = " << dst_frame->mutable_data(); |
| } |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/call/rtp_payload_params.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/call/rtp_payload_params.cc |
| index ad979a590a7a..4d083b1721b2 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/call/rtp_payload_params.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/call/rtp_payload_params.cc |
| @@ -95,6 +95,15 @@ void PopulateRtpWithCodecSpecifics(const CodecSpecificInfo& info, |
| rtp->simulcastIdx = spatial_index.value_or(0); |
| return; |
| } |
| +#ifndef DISABLE_H265 |
| + case kVideoCodecH265: { |
| + auto& h265_header = rtp->video_type_header.emplace<RTPVideoHeaderH265>(); |
| + h265_header.packetization_mode = |
| + info.codecSpecific.H265.packetization_mode; |
| + rtp->simulcastIdx = spatial_index.value_or(0); |
| + return; |
| + } |
| +#endif |
| case kVideoCodecMultiplex: |
| case kVideoCodecGeneric: |
| rtp->codec = kVideoCodecGeneric; |
| @@ -286,6 +295,11 @@ void RtpPayloadParams::SetGeneric(const CodecSpecificInfo* codec_specific_info, |
| is_keyframe, rtp_video_header); |
| } |
| return; |
| +#ifndef DISABLE_H265 |
| + case VideoCodecType::kVideoCodecH265: |
| + // FIXME: Implement H265 to generic descriptor. |
| + return; |
| +#endif |
| case VideoCodecType::kVideoCodecMultiplex: |
| return; |
| } |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/common_audio/fir_filter_factory.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/common_audio/fir_filter_factory.cc |
| index 4bcf05245f95..7b2217c77264 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/common_audio/fir_filter_factory.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/common_audio/fir_filter_factory.cc |
| @@ -36,10 +36,13 @@ FIRFilter* CreateFirFilter(const float* coefficients, |
| // If we know the minimum architecture at compile time, avoid CPU detection. |
| #if defined(WEBRTC_ARCH_X86_FAMILY) |
| // x86 CPU detection required. |
| +#if !defined(WEBRTC_WEBKIT_BUILD) |
| if (GetCPUInfo(kAVX2)) { |
| filter = |
| new FIRFilterAVX2(coefficients, coefficients_length, max_input_length); |
| - } else if (GetCPUInfo(kSSE2)) { |
| + } else |
| +#endif |
| + if (GetCPUInfo(kSSE2)) { |
| filter = |
| new FIRFilterSSE2(coefficients, coefficients_length, max_input_length); |
| } else { |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/common_audio/resampler/sinc_resampler.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/common_audio/resampler/sinc_resampler.cc |
| index 4fa78c5ede32..a2fc072ae322 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/common_audio/resampler/sinc_resampler.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/common_audio/resampler/sinc_resampler.cc |
| @@ -127,9 +127,12 @@ void SincResampler::InitializeCPUSpecificFeatures() { |
| convolve_proc_ = Convolve_NEON; |
| #elif defined(WEBRTC_ARCH_X86_FAMILY) |
| // Using AVX2 instead of SSE2 when AVX2 supported. |
| +#if !defined(WEBRTC_WEBKIT_BUILD) |
| if (GetCPUInfo(kAVX2)) |
| convolve_proc_ = Convolve_AVX2; |
| - else if (GetCPUInfo(kSSE2)) |
| + else |
| +#endif |
| + if (GetCPUInfo(kSSE2)) |
| convolve_proc_ = Convolve_SSE; |
| else |
| convolve_proc_ = Convolve_C; |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_common.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_common.cc |
| new file mode 100644 |
| index 000000000000..c639e135e510 |
| --- /dev/null |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_common.cc |
| @@ -0,0 +1,110 @@ |
| +/* |
| + * Copyright (c) 2018 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 "common_video/h265/h265_common.h" |
| + |
| +namespace webrtc { |
| +namespace H265 { |
| + |
| +const uint8_t kNaluTypeMask = 0x7E; |
| + |
| +std::vector<H264::NaluIndex> FindNaluIndices(const uint8_t* buffer, |
| + size_t buffer_size) { |
| + // This is sorta like Boyer-Moore, but with only the first optimization step: |
| + // given a 3-byte sequence we're looking at, if the 3rd byte isn't 1 or 0, |
| + // skip ahead to the next 3-byte sequence. 0s and 1s are relatively rare, so |
| + // this will skip the majority of reads/checks. |
| + std::vector<H264::NaluIndex> sequences; |
| + if (buffer_size < kNaluShortStartSequenceSize) |
| + return sequences; |
| + |
| + const size_t end = buffer_size - kNaluShortStartSequenceSize; |
| + for (size_t i = 0; i < end;) { |
| + if (buffer[i + 2] > 1) { |
| + i += 3; |
| + } else if (buffer[i + 2] == 1 && buffer[i + 1] == 0 && buffer[i] == 0) { |
| + // We found a start sequence, now check if it was a 3 of 4 byte one. |
| + H264::NaluIndex index = {i, i + 3, 0}; |
| + if (index.start_offset > 0 && buffer[index.start_offset - 1] == 0) |
| + --index.start_offset; |
| + |
| + // Update length of previous entry. |
| + auto it = sequences.rbegin(); |
| + if (it != sequences.rend()) |
| + it->payload_size = index.start_offset - it->payload_start_offset; |
| + |
| + sequences.push_back(index); |
| + |
| + i += 3; |
| + } else { |
| + ++i; |
| + } |
| + } |
| + |
| + // Update length of last entry, if any. |
| + auto it = sequences.rbegin(); |
| + if (it != sequences.rend()) |
| + it->payload_size = buffer_size - it->payload_start_offset; |
| + |
| + return sequences; |
| +} |
| + |
| +NaluType ParseNaluType(uint8_t data) { |
| + return static_cast<NaluType>((data & kNaluTypeMask) >> 1); |
| +} |
| + |
| +std::vector<uint8_t> ParseRbsp(const uint8_t* data, size_t length) { |
| + std::vector<uint8_t> out; |
| + out.reserve(length); |
| + |
| + for (size_t i = 0; i < length;) { |
| + // Be careful about over/underflow here. byte_length_ - 3 can underflow, and |
| + // i + 3 can overflow, but byte_length_ - i can't, because i < byte_length_ |
| + // above, and that expression will produce the number of bytes left in |
| + // the stream including the byte at i. |
| + if (length - i >= 3 && !data[i] && !data[i + 1] && data[i + 2] == 3) { |
| + // Two rbsp bytes. |
| + out.push_back(data[i++]); |
| + out.push_back(data[i++]); |
| + // Skip the emulation byte. |
| + i++; |
| + } else { |
| + // Single rbsp byte. |
| + out.push_back(data[i++]); |
| + } |
| + } |
| + return out; |
| +} |
| + |
| +void WriteRbsp(const uint8_t* bytes, size_t length, rtc::Buffer* destination) { |
| + static const uint8_t kZerosInStartSequence = 2; |
| + static const uint8_t kEmulationByte = 0x03u; |
| + size_t num_consecutive_zeros = 0; |
| + destination->EnsureCapacity(destination->size() + length); |
| + |
| + for (size_t i = 0; i < length; ++i) { |
| + uint8_t byte = bytes[i]; |
| + if (byte <= kEmulationByte && |
| + num_consecutive_zeros >= kZerosInStartSequence) { |
| + // Need to escape. |
| + destination->AppendData(kEmulationByte); |
| + num_consecutive_zeros = 0; |
| + } |
| + destination->AppendData(byte); |
| + if (byte == 0) { |
| + ++num_consecutive_zeros; |
| + } else { |
| + num_consecutive_zeros = 0; |
| + } |
| + } |
| +} |
| + |
| +} // namespace H265 |
| +} // namespace webrtc |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_common.h b/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_common.h |
| new file mode 100644 |
| index 000000000000..d3c5326b72c3 |
| --- /dev/null |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_common.h |
| @@ -0,0 +1,92 @@ |
| +/* |
| + * Copyright (c) 2018 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. |
| + */ |
| + |
| +#ifndef COMMON_VIDEO_H265_H265_COMMON_H_ |
| +#define COMMON_VIDEO_H265_H265_COMMON_H_ |
| + |
| +#include <memory> |
| +#include <vector> |
| + |
| +#include "common_video/h264/h264_common.h" |
| +#include "rtc_base/buffer.h" |
| + |
| +namespace webrtc { |
| + |
| +namespace H265 { |
| +// The size of a full NALU start sequence {0 0 0 1}, used for the first NALU |
| +// of an access unit, and for SPS and PPS blocks. |
| +const size_t kNaluLongStartSequenceSize = 4; |
| + |
| +// The size of a shortened NALU start sequence {0 0 1}, that may be used if |
| +// not the first NALU of an access unit or an SPS or PPS block. |
| +const size_t kNaluShortStartSequenceSize = 3; |
| + |
| +// The size of the NALU type byte (1). |
| +const size_t kNaluTypeSize = 1; |
| + |
| +enum NaluType : uint8_t { |
| + kTrailN = 0, |
| + kTrailR = 1, |
| + kTsaN = 2, |
| + kTsaR = 3, |
| + kStsaN = 4, |
| + kStsaR = 5, |
| + kRadlN = 6, |
| + kRadlR = 7, |
| + kBlaWLp = 16, |
| + kBlaWRadl = 17, |
| + kBlaNLp = 18, |
| + kIdrWRadl = 19, |
| + kIdrNLp = 20, |
| + kCra = 21, |
| + kRsvIrapVcl23 = 23, |
| + kVps = 32, |
| + kSps = 33, |
| + kPps = 34, |
| + kAud = 35, |
| + kPrefixSei = 39, |
| + kSuffixSei = 40, |
| + kAP = 48, |
| + kFU = 49 |
| +}; |
| + |
| +enum SliceType : uint8_t { kP = 0, kB = 1, kI = 2, kSp = 3, kSi = 4 }; |
| + |
| +// Returns a vector of the NALU indices in the given buffer. |
| +std::vector<H264::NaluIndex> FindNaluIndices(const uint8_t* buffer, |
| + size_t buffer_size); |
| + |
| +// Get the NAL type from the header byte immediately following start sequence. |
| +NaluType ParseNaluType(uint8_t data); |
| + |
| +// Methods for parsing and writing RBSP. See section 7.4.2 of the H265 spec. |
| +// |
| +// The following sequences are illegal, and need to be escaped when encoding: |
| +// 00 00 00 -> 00 00 03 00 |
| +// 00 00 01 -> 00 00 03 01 |
| +// 00 00 02 -> 00 00 03 02 |
| +// And things in the source that look like the emulation byte pattern (00 00 03) |
| +// need to have an extra emulation byte added, so it's removed when decoding: |
| +// 00 00 03 -> 00 00 03 03 |
| +// |
| +// Decoding is simply a matter of finding any 00 00 03 sequence and removing |
| +// the 03 emulation byte. |
| + |
| +// Parse the given data and remove any emulation byte escaping. |
| +std::vector<uint8_t> ParseRbsp(const uint8_t* data, size_t length); |
| + |
| +// Write the given data to the destination buffer, inserting and emulation |
| +// bytes in order to escape any data the could be interpreted as a start |
| +// sequence. |
| +void WriteRbsp(const uint8_t* bytes, size_t length, rtc::Buffer* destination); |
| +} // namespace H265 |
| +} // namespace webrtc |
| + |
| +#endif // COMMON_VIDEO_H265_H265_COMMON_H_ |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_pps_parser.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_pps_parser.cc |
| new file mode 100644 |
| index 000000000000..418411ced327 |
| --- /dev/null |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_pps_parser.cc |
| @@ -0,0 +1,209 @@ |
| +/* |
| + * Copyright (c) 2018 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 "common_video/h265/h265_pps_parser.h" |
| + |
| +#include <memory> |
| +#include <vector> |
| + |
| +#include "common_video/h264/h264_common.h" |
| +#include "common_video/h265/h265_common.h" |
| +#include "rtc_base/bit_buffer.h" |
| +#include "rtc_base/logging.h" |
| + |
| +#define RETURN_EMPTY_ON_FAIL(x) \ |
| + if (!(x)) { \ |
| + return absl::nullopt; \ |
| + } |
| + |
| +namespace { |
| +const int kMaxPicInitQpDeltaValue = 25; |
| +const int kMinPicInitQpDeltaValue = -26; |
| +} // namespace |
| + |
| +namespace webrtc { |
| + |
| +// General note: this is based off the 02/2018 version of the H.265 standard. |
| +// You can find it on this page: |
| +// http://www.itu.int/rec/T-REC-H.265 |
| + |
| +absl::optional<H265PpsParser::PpsState> H265PpsParser::ParsePps( |
| + const uint8_t* data, |
| + size_t length) { |
| + // First, parse out rbsp, which is basically the source buffer minus emulation |
| + // bytes (the last byte of a 0x00 0x00 0x03 sequence). RBSP is defined in |
| + // section 7.3.1 of the H.264 standard. |
| + std::vector<uint8_t> unpacked_buffer = H264::ParseRbsp(data, length); |
| + rtc::BitBuffer bit_buffer(unpacked_buffer.data(), unpacked_buffer.size()); |
| + return ParseInternal(&bit_buffer); |
| +} |
| + |
| +bool H265PpsParser::ParsePpsIds(const uint8_t* data, |
| + size_t length, |
| + uint32_t* pps_id, |
| + uint32_t* sps_id) { |
| + RTC_DCHECK(pps_id); |
| + RTC_DCHECK(sps_id); |
| + // First, parse out rbsp, which is basically the source buffer minus emulation |
| + // bytes (the last byte of a 0x00 0x00 0x03 sequence). RBSP is defined in |
| + // section 7.3.1 of the H.265 standard. |
| + std::vector<uint8_t> unpacked_buffer = H264::ParseRbsp(data, length); |
| + rtc::BitBuffer bit_buffer(unpacked_buffer.data(), unpacked_buffer.size()); |
| + return ParsePpsIdsInternal(&bit_buffer, pps_id, sps_id); |
| +} |
| + |
| +absl::optional<uint32_t> H265PpsParser::ParsePpsIdFromSliceSegmentLayerRbsp( |
| + const uint8_t* data, |
| + size_t length, |
| + uint8_t nalu_type) { |
| + rtc::BitBuffer slice_reader(data, length); |
| + |
| + // first_slice_segment_in_pic_flag: u(1) |
| + uint32_t first_slice_segment_in_pic_flag = 0; |
| + RETURN_EMPTY_ON_FAIL( |
| + slice_reader.ReadBits(&first_slice_segment_in_pic_flag, 1)); |
| + |
| + if (nalu_type >= H265::NaluType::kBlaWLp && |
| + nalu_type <= H265::NaluType::kRsvIrapVcl23) { |
| + // no_output_of_prior_pics_flag: u(1) |
| + RETURN_EMPTY_ON_FAIL(slice_reader.ConsumeBits(1)); |
| + } |
| + |
| + // slice_pic_parameter_set_id: ue(v) |
| + uint32_t slice_pic_parameter_set_id = 0; |
| + if (!slice_reader.ReadExponentialGolomb(&slice_pic_parameter_set_id)) |
| + return absl::nullopt; |
| + |
| + return slice_pic_parameter_set_id; |
| +} |
| + |
| +absl::optional<H265PpsParser::PpsState> H265PpsParser::ParseInternal( |
| + rtc::BitBuffer* bit_buffer) { |
| + PpsState pps; |
| + |
| + RETURN_EMPTY_ON_FAIL(ParsePpsIdsInternal(bit_buffer, &pps.id, &pps.sps_id)); |
| + |
| + uint32_t bits_tmp; |
| + uint32_t golomb_ignored; |
| + // entropy_coding_mode_flag: u(1) |
| + uint32_t entropy_coding_mode_flag; |
| + RETURN_EMPTY_ON_FAIL(bit_buffer->ReadBits(&entropy_coding_mode_flag, 1)); |
| + pps.entropy_coding_mode_flag = entropy_coding_mode_flag != 0; |
| + // bottom_field_pic_order_in_frame_present_flag: u(1) |
| + uint32_t bottom_field_pic_order_in_frame_present_flag; |
| + RETURN_EMPTY_ON_FAIL( |
| + bit_buffer->ReadBits(&bottom_field_pic_order_in_frame_present_flag, 1)); |
| + pps.bottom_field_pic_order_in_frame_present_flag = |
| + bottom_field_pic_order_in_frame_present_flag != 0; |
| + |
| + // num_slice_groups_minus1: ue(v) |
| + uint32_t num_slice_groups_minus1; |
| + RETURN_EMPTY_ON_FAIL( |
| + bit_buffer->ReadExponentialGolomb(&num_slice_groups_minus1)); |
| + if (num_slice_groups_minus1 > 0) { |
| + uint32_t slice_group_map_type; |
| + // slice_group_map_type: ue(v) |
| + RETURN_EMPTY_ON_FAIL( |
| + bit_buffer->ReadExponentialGolomb(&slice_group_map_type)); |
| + if (slice_group_map_type == 0) { |
| + for (uint32_t i_group = 0; i_group <= num_slice_groups_minus1; |
| + ++i_group) { |
| + // run_length_minus1[iGroup]: ue(v) |
| + RETURN_EMPTY_ON_FAIL( |
| + bit_buffer->ReadExponentialGolomb(&golomb_ignored)); |
| + } |
| + } else if (slice_group_map_type == 1) { |
| + // TODO(sprang): Implement support for dispersed slice group map type. |
| + // See 8.2.2.2 Specification for dispersed slice group map type. |
| + } else if (slice_group_map_type == 2) { |
| + for (uint32_t i_group = 0; i_group <= num_slice_groups_minus1; |
| + ++i_group) { |
| + // top_left[iGroup]: ue(v) |
| + RETURN_EMPTY_ON_FAIL( |
| + bit_buffer->ReadExponentialGolomb(&golomb_ignored)); |
| + // bottom_right[iGroup]: ue(v) |
| + RETURN_EMPTY_ON_FAIL( |
| + bit_buffer->ReadExponentialGolomb(&golomb_ignored)); |
| + } |
| + } else if (slice_group_map_type == 3 || slice_group_map_type == 4 || |
| + slice_group_map_type == 5) { |
| + // slice_group_change_direction_flag: u(1) |
| + RETURN_EMPTY_ON_FAIL(bit_buffer->ReadBits(&bits_tmp, 1)); |
| + // slice_group_change_rate_minus1: ue(v) |
| + RETURN_EMPTY_ON_FAIL(bit_buffer->ReadExponentialGolomb(&golomb_ignored)); |
| + } else if (slice_group_map_type == 6) { |
| + // pic_size_in_map_units_minus1: ue(v) |
| + uint32_t pic_size_in_map_units_minus1; |
| + RETURN_EMPTY_ON_FAIL( |
| + bit_buffer->ReadExponentialGolomb(&pic_size_in_map_units_minus1)); |
| + uint32_t slice_group_id_bits = 0; |
| + uint32_t num_slice_groups = num_slice_groups_minus1 + 1; |
| + // If num_slice_groups is not a power of two an additional bit is required |
| + // to account for the ceil() of log2() below. |
| + if ((num_slice_groups & (num_slice_groups - 1)) != 0) |
| + ++slice_group_id_bits; |
| + while (num_slice_groups > 0) { |
| + num_slice_groups >>= 1; |
| + ++slice_group_id_bits; |
| + } |
| + for (uint32_t i = 0; i <= pic_size_in_map_units_minus1; i++) { |
| + // slice_group_id[i]: u(v) |
| + // Represented by ceil(log2(num_slice_groups_minus1 + 1)) bits. |
| + RETURN_EMPTY_ON_FAIL( |
| + bit_buffer->ReadBits(&bits_tmp, slice_group_id_bits)); |
| + } |
| + } |
| + } |
| + // num_ref_idx_l0_default_active_minus1: ue(v) |
| + RETURN_EMPTY_ON_FAIL(bit_buffer->ReadExponentialGolomb(&golomb_ignored)); |
| + // num_ref_idx_l1_default_active_minus1: ue(v) |
| + RETURN_EMPTY_ON_FAIL(bit_buffer->ReadExponentialGolomb(&golomb_ignored)); |
| + // weighted_pred_flag: u(1) |
| + uint32_t weighted_pred_flag; |
| + RETURN_EMPTY_ON_FAIL(bit_buffer->ReadBits(&weighted_pred_flag, 1)); |
| + pps.weighted_pred_flag = weighted_pred_flag != 0; |
| + // weighted_bipred_idc: u(2) |
| + RETURN_EMPTY_ON_FAIL(bit_buffer->ReadBits(&pps.weighted_bipred_idc, 2)); |
| + |
| + // pic_init_qp_minus26: se(v) |
| + RETURN_EMPTY_ON_FAIL( |
| + bit_buffer->ReadSignedExponentialGolomb(&pps.pic_init_qp_minus26)); |
| + // Sanity-check parsed value |
| + if (pps.pic_init_qp_minus26 > kMaxPicInitQpDeltaValue || |
| + pps.pic_init_qp_minus26 < kMinPicInitQpDeltaValue) { |
| + RETURN_EMPTY_ON_FAIL(false); |
| + } |
| + // pic_init_qs_minus26: se(v) |
| + RETURN_EMPTY_ON_FAIL(bit_buffer->ReadExponentialGolomb(&golomb_ignored)); |
| + // chroma_qp_index_offset: se(v) |
| + RETURN_EMPTY_ON_FAIL(bit_buffer->ReadExponentialGolomb(&golomb_ignored)); |
| + // deblocking_filter_control_present_flag: u(1) |
| + // constrained_intra_pred_flag: u(1) |
| + RETURN_EMPTY_ON_FAIL(bit_buffer->ReadBits(&bits_tmp, 2)); |
| + // redundant_pic_cnt_present_flag: u(1) |
| + RETURN_EMPTY_ON_FAIL( |
| + bit_buffer->ReadBits(&pps.redundant_pic_cnt_present_flag, 1)); |
| + |
| + return pps; |
| +} |
| + |
| +bool H265PpsParser::ParsePpsIdsInternal(rtc::BitBuffer* bit_buffer, |
| + uint32_t* pps_id, |
| + uint32_t* sps_id) { |
| + // pic_parameter_set_id: ue(v) |
| + if (!bit_buffer->ReadExponentialGolomb(pps_id)) |
| + return false; |
| + // seq_parameter_set_id: ue(v) |
| + if (!bit_buffer->ReadExponentialGolomb(sps_id)) |
| + return false; |
| + return true; |
| +} |
| + |
| +} // namespace webrtc |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_pps_parser.h b/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_pps_parser.h |
| new file mode 100644 |
| index 000000000000..cfa471883dca |
| --- /dev/null |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_pps_parser.h |
| @@ -0,0 +1,64 @@ |
| +/* |
| + * Copyright (c) 2018 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. |
| + */ |
| + |
| +#ifndef COMMON_VIDEO_H265_PPS_PARSER_H_ |
| +#define COMMON_VIDEO_H265_PPS_PARSER_H_ |
| + |
| +#include "absl/types/optional.h" |
| + |
| +namespace rtc { |
| +class BitBuffer; |
| +} |
| + |
| +namespace webrtc { |
| + |
| +// A class for parsing out picture parameter set (PPS) data from a H265 NALU. |
| +class H265PpsParser { |
| + public: |
| + // The parsed state of the PPS. Only some select values are stored. |
| + // Add more as they are actually needed. |
| + struct PpsState { |
| + PpsState() = default; |
| + |
| + bool bottom_field_pic_order_in_frame_present_flag = false; |
| + bool weighted_pred_flag = false; |
| + bool entropy_coding_mode_flag = false; |
| + uint32_t weighted_bipred_idc = false; |
| + uint32_t redundant_pic_cnt_present_flag = 0; |
| + int pic_init_qp_minus26 = 0; |
| + uint32_t id = 0; |
| + uint32_t sps_id = 0; |
| + }; |
| + |
| + // Unpack RBSP and parse PPS state from the supplied buffer. |
| + static absl::optional<PpsState> ParsePps(const uint8_t* data, size_t length); |
| + |
| + static bool ParsePpsIds(const uint8_t* data, |
| + size_t length, |
| + uint32_t* pps_id, |
| + uint32_t* sps_id); |
| + |
| + static absl::optional<uint32_t> ParsePpsIdFromSliceSegmentLayerRbsp( |
| + const uint8_t* data, |
| + size_t length, |
| + uint8_t nalu_type); |
| + |
| + protected: |
| + // Parse the PPS state, for a bit buffer where RBSP decoding has already been |
| + // performed. |
| + static absl::optional<PpsState> ParseInternal(rtc::BitBuffer* bit_buffer); |
| + static bool ParsePpsIdsInternal(rtc::BitBuffer* bit_buffer, |
| + uint32_t* pps_id, |
| + uint32_t* sps_id); |
| +}; |
| + |
| +} // namespace webrtc |
| + |
| +#endif // COMMON_VIDEO_H265_PPS_PARSER_H_ |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_sps_parser.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_sps_parser.cc |
| new file mode 100644 |
| index 000000000000..0433f4b0ee92 |
| --- /dev/null |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_sps_parser.cc |
| @@ -0,0 +1,192 @@ |
| +/* |
| + * Copyright (c) 2018 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 <memory> |
| +#include <vector> |
| + |
| +#include "common_video/h265/h265_common.h" |
| +#include "common_video/h265/h265_sps_parser.h" |
| +#include "rtc_base/bit_buffer.h" |
| +#include "rtc_base/logging.h" |
| + |
| +namespace { |
| +typedef absl::optional<webrtc::H265SpsParser::SpsState> OptionalSps; |
| + |
| +#define RETURN_EMPTY_ON_FAIL(x) \ |
| + if (!(x)) { \ |
| + return OptionalSps(); \ |
| + } |
| +} // namespace |
| + |
| +namespace webrtc { |
| + |
| +H265SpsParser::SpsState::SpsState() = default; |
| + |
| +// General note: this is based off the 02/2018 version of the H.265 standard. |
| +// You can find it on this page: |
| +// http://www.itu.int/rec/T-REC-H.265 |
| + |
| +// Unpack RBSP and parse SPS state from the supplied buffer. |
| +absl::optional<H265SpsParser::SpsState> H265SpsParser::ParseSps( |
| + const uint8_t* data, |
| + size_t length) { |
| + std::vector<uint8_t> unpacked_buffer = H265::ParseRbsp(data, length); |
| + rtc::BitBuffer bit_buffer(unpacked_buffer.data(), unpacked_buffer.size()); |
| + return ParseSpsUpToVui(&bit_buffer); |
| +} |
| + |
| +absl::optional<H265SpsParser::SpsState> H265SpsParser::ParseSpsUpToVui( |
| + rtc::BitBuffer* buffer) { |
| + // Now, we need to use a bit buffer to parse through the actual HEVC SPS |
| + // format. See Section 7.3.2.2.1 ("General sequence parameter set data |
| + // syntax") of the H.265 standard for a complete description. |
| + // Since we only care about resolution, we ignore the majority of fields, but |
| + // we still have to actively parse through a lot of the data, since many of |
| + // the fields have variable size. |
| + // We're particularly interested in: |
| + // chroma_format_idc -> affects crop units |
| + // pic_{width,height}_* -> resolution of the frame in macroblocks (16x16). |
| + // frame_crop_*_offset -> crop information |
| + |
| + SpsState sps; |
| + |
| + // The golomb values we have to read, not just consume. |
| + uint32_t golomb_ignored; |
| + |
| + // separate_colour_plane_flag is optional (assumed 0), but has implications |
| + // about the ChromaArrayType, which modifies how we treat crop coordinates. |
| + uint32_t separate_colour_plane_flag = 0; |
| + |
| + // chroma_format_idc will be ChromaArrayType if separate_colour_plane_flag is |
| + // 0. It defaults to 1, when not specified. |
| + uint32_t chroma_format_idc = 1; |
| + |
| + // sps_video_parameter_set_id: u(4) |
| + uint32_t sps_video_parameter_set_id = 0; |
| + RETURN_EMPTY_ON_FAIL(buffer->ReadBits(&sps_video_parameter_set_id, 4)); |
| + // sps_max_sub_layers_minus1: u(3) |
| + uint32_t sps_max_sub_layers_minus1 = 0; |
| + RETURN_EMPTY_ON_FAIL(buffer->ReadBits(&sps_max_sub_layers_minus1, 3)); |
| + // sps_temporal_id_nesting_flag: u(1) |
| + RETURN_EMPTY_ON_FAIL(buffer->ConsumeBits(1)); |
| + // profile_tier_level(1, sps_max_sub_layers_minus1). We are acutally not |
| + // using them, so read/skip over it. |
| + // general_profile_space+general_tier_flag+general_prfile_idc: u(8) |
| + RETURN_EMPTY_ON_FAIL(buffer->ConsumeBytes(1)); |
| + // general_profile_compatabilitiy_flag[32] |
| + RETURN_EMPTY_ON_FAIL(buffer->ConsumeBytes(4)); |
| + // general_progressive_source_flag + interlaced_source_flag+ |
| + // non-packed_constraint flag + frame_only_constraint_flag: u(4) |
| + RETURN_EMPTY_ON_FAIL(buffer->ConsumeBits(4)); |
| + // general_profile_idc decided flags or reserved. u(43) |
| + RETURN_EMPTY_ON_FAIL(buffer->ConsumeBits(43)); |
| + // general_inbld_flag or reserved 0: u(1) |
| + RETURN_EMPTY_ON_FAIL(buffer->ConsumeBits(1)); |
| + // general_level_idc: u(8) |
| + RETURN_EMPTY_ON_FAIL(buffer->ConsumeBytes(1)); |
| + // if max_sub_layers_minus1 >=1, read the sublayer profile information |
| + std::vector<uint32_t> sub_layer_profile_present_flags; |
| + std::vector<uint32_t> sub_layer_level_present_flags; |
| + uint32_t sub_layer_profile_present = 0; |
| + uint32_t sub_layer_level_present = 0; |
| + for (uint32_t i = 0; i < sps_max_sub_layers_minus1; i++) { |
| + // sublayer_profile_present_flag and sublayer_level_presnet_flag: u(2) |
| + RETURN_EMPTY_ON_FAIL(buffer->ReadBits(&sub_layer_profile_present, 1)); |
| + RETURN_EMPTY_ON_FAIL(buffer->ReadBits(&sub_layer_level_present, 1)); |
| + sub_layer_profile_present_flags.push_back(sub_layer_profile_present); |
| + sub_layer_level_present_flags.push_back(sub_layer_level_present); |
| + } |
| + if (sps_max_sub_layers_minus1 > 0) { |
| + for (uint32_t j = sps_max_sub_layers_minus1; j < 8; j++) { |
| + // reserved 2 bits: u(2) |
| + RETURN_EMPTY_ON_FAIL(buffer->ConsumeBits(2)); |
| + } |
| + } |
| + for (uint32_t k = 0; k < sps_max_sub_layers_minus1; k++) { |
| + if (sub_layer_profile_present_flags[k]) { // |
| + // sub_layer profile_space/tier_flag/profile_idc. ignored. u(8) |
| + RETURN_EMPTY_ON_FAIL(buffer->ConsumeBytes(1)); |
| + // profile_compatability_flag: u(32) |
| + RETURN_EMPTY_ON_FAIL(buffer->ConsumeBytes(4)); |
| + // sub_layer progressive_source_flag/interlaced_source_flag/ |
| + // non_packed_constraint_flag/frame_only_constraint_flag: u(4) |
| + RETURN_EMPTY_ON_FAIL(buffer->ConsumeBits(4)); |
| + // following 43-bits are profile_idc specific. We simply read/skip it. |
| + // u(43) |
| + RETURN_EMPTY_ON_FAIL(buffer->ConsumeBits(43)); |
| + // 1-bit profile_idc specific inbld flag. We simply read/skip it. u(1) |
| + RETURN_EMPTY_ON_FAIL(buffer->ConsumeBits(1)); |
| + } |
| + if (sub_layer_level_present_flags[k]) { |
| + // sub_layer_level_idc: u(8) |
| + RETURN_EMPTY_ON_FAIL(buffer->ConsumeBytes(1)); |
| + } |
| + } |
| + // sps_seq_parameter_set_id: ue(v) |
| + RETURN_EMPTY_ON_FAIL(buffer->ReadExponentialGolomb(&golomb_ignored)); |
| + // chrome_format_idc: ue(v) |
| + RETURN_EMPTY_ON_FAIL(buffer->ReadExponentialGolomb(&chroma_format_idc)); |
| + if (chroma_format_idc == 3) { |
| + // seperate_colour_plane_flag: u(1) |
| + RETURN_EMPTY_ON_FAIL(buffer->ReadBits(&separate_colour_plane_flag, 1)); |
| + } |
| + uint32_t pic_width_in_luma_samples = 0; |
| + uint32_t pic_height_in_luma_samples = 0; |
| + // pic_width_in_luma_samples: ue(v) |
| + RETURN_EMPTY_ON_FAIL( |
| + buffer->ReadExponentialGolomb(&pic_width_in_luma_samples)); |
| + // pic_height_in_luma_samples: ue(v) |
| + RETURN_EMPTY_ON_FAIL( |
| + buffer->ReadExponentialGolomb(&pic_height_in_luma_samples)); |
| + // conformance_window_flag: u(1) |
| + uint32_t conformance_window_flag = 0; |
| + RETURN_EMPTY_ON_FAIL(buffer->ReadBits(&conformance_window_flag, 1)); |
| + |
| + uint32_t conf_win_left_offset = 0; |
| + uint32_t conf_win_right_offset = 0; |
| + uint32_t conf_win_top_offset = 0; |
| + uint32_t conf_win_bottom_offset = 0; |
| + if (conformance_window_flag) { |
| + // conf_win_left_offset: ue(v) |
| + RETURN_EMPTY_ON_FAIL(buffer->ReadExponentialGolomb(&conf_win_left_offset)); |
| + // conf_win_right_offset: ue(v) |
| + RETURN_EMPTY_ON_FAIL(buffer->ReadExponentialGolomb(&conf_win_right_offset)); |
| + // conf_win_top_offset: ue(v) |
| + RETURN_EMPTY_ON_FAIL(buffer->ReadExponentialGolomb(&conf_win_top_offset)); |
| + // conf_win_bottom_offset: ue(v) |
| + RETURN_EMPTY_ON_FAIL( |
| + buffer->ReadExponentialGolomb(&conf_win_bottom_offset)); |
| + } |
| + |
| + // Far enough! We don't use the rest of the SPS. |
| + |
| + sps.vps_id = sps_video_parameter_set_id; |
| + |
| + // Start with the resolution determined by the pic_width/pic_height fields. |
| + sps.width = pic_width_in_luma_samples; |
| + sps.height = pic_height_in_luma_samples; |
| + |
| + if (conformance_window_flag) { |
| + int sub_width_c = ((1 == chroma_format_idc) || (2 == chroma_format_idc)) && |
| + (0 == separate_colour_plane_flag) |
| + ? 2 |
| + : 1; |
| + int sub_height_c = |
| + (1 == chroma_format_idc) && (0 == separate_colour_plane_flag) ? 2 : 1; |
| + // the offset includes the pixel within conformance window. so don't need to |
| + // +1 as per spec |
| + sps.width -= sub_width_c * (conf_win_right_offset + conf_win_left_offset); |
| + sps.height -= sub_height_c * (conf_win_top_offset + conf_win_bottom_offset); |
| + } |
| + |
| + return OptionalSps(sps); |
| +} |
| + |
| +} // namespace webrtc |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_sps_parser.h b/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_sps_parser.h |
| new file mode 100644 |
| index 000000000000..a0f86b698326 |
| --- /dev/null |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_sps_parser.h |
| @@ -0,0 +1,54 @@ |
| +/* |
| + * Copyright (c) 2018 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. |
| + */ |
| + |
| +#ifndef COMMON_VIDEO_H265_H265_SPS_PARSER_H_ |
| +#define COMMON_VIDEO_H265_H265_SPS_PARSER_H_ |
| + |
| +#include "absl/types/optional.h" |
| + |
| +namespace rtc { |
| +class BitBuffer; |
| +} |
| + |
| +namespace webrtc { |
| + |
| +// A class for parsing out sequence parameter set (SPS) data from an H265 NALU. |
| +class H265SpsParser { |
| + public: |
| + // The parsed state of the SPS. Only some select values are stored. |
| + // Add more as they are actually needed. |
| + struct SpsState { |
| + SpsState(); |
| + |
| + uint32_t width = 0; |
| + uint32_t height = 0; |
| + uint32_t delta_pic_order_always_zero_flag = 0; |
| + uint32_t separate_colour_plane_flag = 0; |
| + uint32_t frame_mbs_only_flag = 0; |
| + uint32_t log2_max_frame_num_minus4 = 0; |
| + uint32_t log2_max_pic_order_cnt_lsb_minus4 = 0; |
| + uint32_t pic_order_cnt_type = 0; |
| + uint32_t max_num_ref_frames = 0; |
| + uint32_t vui_params_present = 0; |
| + uint32_t id = 0; |
| + uint32_t vps_id = 0; |
| + }; |
| + |
| + // Unpack RBSP and parse SPS state from the supplied buffer. |
| + static absl::optional<SpsState> ParseSps(const uint8_t* data, size_t length); |
| + |
| + protected: |
| + // Parse the SPS state, up till the VUI part, for a bit buffer where RBSP |
| + // decoding has already been performed. |
| + static absl::optional<SpsState> ParseSpsUpToVui(rtc::BitBuffer* buffer); |
| +}; |
| + |
| +} // namespace webrtc |
| +#endif // COMMON_VIDEO_H265_H265_SPS_PARSER_H_ |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_vps_parser.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_vps_parser.cc |
| new file mode 100644 |
| index 000000000000..2391ae51df0f |
| --- /dev/null |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_vps_parser.cc |
| @@ -0,0 +1,62 @@ |
| +/* |
| + * Copyright (c) 2018 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 <memory> |
| +#include <vector> |
| + |
| +#include "common_video/h265/h265_common.h" |
| +#include "common_video/h265/h265_vps_parser.h" |
| +#include "rtc_base/bit_buffer.h" |
| +#include "rtc_base/logging.h" |
| + |
| +namespace { |
| +typedef absl::optional<webrtc::H265VpsParser::VpsState> OptionalVps; |
| + |
| +#define RETURN_EMPTY_ON_FAIL(x) \ |
| + if (!(x)) { \ |
| + return OptionalVps(); \ |
| + } |
| +} // namespace |
| + |
| +namespace webrtc { |
| + |
| +H265VpsParser::VpsState::VpsState() = default; |
| + |
| +// General note: this is based off the 02/2018 version of the H.265 standard. |
| +// You can find it on this page: |
| +// http://www.itu.int/rec/T-REC-H.265 |
| + |
| +// Unpack RBSP and parse SPS state from the supplied buffer. |
| +absl::optional<H265VpsParser::VpsState> H265VpsParser::ParseVps( |
| + const uint8_t* data, |
| + size_t length) { |
| + std::vector<uint8_t> unpacked_buffer = H265::ParseRbsp(data, length); |
| + rtc::BitBuffer bit_buffer(unpacked_buffer.data(), unpacked_buffer.size()); |
| + return ParseInternal(&bit_buffer); |
| +} |
| + |
| +absl::optional<H265VpsParser::VpsState> H265VpsParser::ParseInternal( |
| + rtc::BitBuffer* buffer) { |
| + // Now, we need to use a bit buffer to parse through the actual HEVC VPS |
| + // format. See Section 7.3.2.1 ("Video parameter set RBSP syntax") of the |
| + // H.265 standard for a complete description. |
| + |
| + VpsState vps; |
| + |
| + // vps_video_parameter_set_id: u(4) |
| + uint32_t vps_video_parameter_set_id = 0; |
| + RETURN_EMPTY_ON_FAIL(buffer->ReadBits(&vps_video_parameter_set_id, 4)); |
| + |
| + vps.id = vps_video_parameter_set_id; |
| + vps.id = 0; |
| + return OptionalVps(vps); |
| +} |
| + |
| +} // namespace webrtc |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_vps_parser.h b/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_vps_parser.h |
| new file mode 100644 |
| index 000000000000..e8a2775f43df |
| --- /dev/null |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_vps_parser.h |
| @@ -0,0 +1,43 @@ |
| +/* |
| + * Copyright (c) 2018 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. |
| + */ |
| + |
| +#ifndef COMMON_VIDEO_H265_H265_VPS_PARSER_H_ |
| +#define COMMON_VIDEO_H265_H265_VPS_PARSER_H_ |
| + |
| +#include "absl/types/optional.h" |
| + |
| +namespace rtc { |
| +class BitBuffer; |
| +} |
| + |
| +namespace webrtc { |
| + |
| +// A class for parsing out sequence parameter set (VPS) data from an H265 NALU. |
| +class H265VpsParser { |
| + public: |
| + // The parsed state of the VPS. Only some select values are stored. |
| + // Add more as they are actually needed. |
| + struct VpsState { |
| + VpsState(); |
| + |
| + uint32_t id = 0; |
| + }; |
| + |
| + // Unpack RBSP and parse VPS state from the supplied buffer. |
| + static absl::optional<VpsState> ParseVps(const uint8_t* data, size_t length); |
| + |
| + protected: |
| + // Parse the VPS state, for a bit buffer where RBSP decoding has already been |
| + // performed. |
| + static absl::optional<VpsState> ParseInternal(rtc::BitBuffer* bit_buffer); |
| +}; |
| + |
| +} // namespace webrtc |
| +#endif // COMMON_VIDEO_H265_H265_VPS_PARSER_H_ |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/video_frame_buffer.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/video_frame_buffer.cc |
| index 823c5ad7a118..dad595b8db31 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/video_frame_buffer.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/common_video/video_frame_buffer.cc |
| @@ -266,7 +266,7 @@ rtc::scoped_refptr<PlanarYuvBuffer> WrapYuvBuffer( |
| return WrapI444Buffer(width, height, y_plane, y_stride, u_plane, u_stride, |
| v_plane, v_stride, no_longer_used); |
| default: |
| - FATAL() << "Unexpected frame buffer type."; |
| + RTC_FATAL() << "Unexpected frame buffer type."; |
| return nullptr; |
| } |
| } |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc |
| index 600cb0c06a23..fb08251e3e71 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc |
| @@ -172,7 +172,7 @@ AudioEncoder::EncodedInfo AudioEncoderCng::EncodeImpl( |
| break; |
| } |
| case Vad::kError: { |
| - FATAL(); // Fails only if fed invalid data. |
| + RTC_FATAL(); // Fails only if fed invalid data. |
| break; |
| } |
| } |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc |
| index 032de20246f3..4bfaa6e478d5 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc |
| @@ -34,7 +34,7 @@ int GetIlbcBitrate(int ptime) { |
| // 50 bytes per frame of 30 ms => (approx) 13333 bits/s. |
| return 13333; |
| default: |
| - FATAL(); |
| + RTC_FATAL(); |
| } |
| } |
| |
| @@ -144,7 +144,7 @@ size_t AudioEncoderIlbcImpl::RequiredOutputSizeBytes() const { |
| case 6: |
| return 2 * 50; |
| default: |
| - FATAL(); |
| + RTC_FATAL(); |
| } |
| } |
| |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.cc |
| index f57806557859..b02ef4479acb 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.cc |
| @@ -91,7 +91,7 @@ bool RtpFileSource::OpenFile(const std::string& file_name) { |
| return true; |
| rtp_reader_.reset(RtpFileReader::Create(RtpFileReader::kPcap, file_name)); |
| if (!rtp_reader_) { |
| - FATAL() << "Couldn't open input file as either a rtpdump or .pcap. Note " |
| + RTC_FATAL() << "Couldn't open input file as either a rtpdump or .pcap. Note " |
| "that .pcapng is not supported."; |
| } |
| return true; |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/adaptive_fir_filter.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/adaptive_fir_filter.cc |
| index bf3a7809f42b..82b01fea2079 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/adaptive_fir_filter.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/adaptive_fir_filter.cc |
| @@ -556,10 +556,12 @@ void AdaptiveFirFilter::Filter(const RenderBuffer& render_buffer, |
| case Aec3Optimization::kSse2: |
| aec3::ApplyFilter_Sse2(render_buffer, current_size_partitions_, H_, S); |
| break; |
| +#if !defined(WEBRTC_WEBKIT_BUILD) |
| case Aec3Optimization::kAvx2: |
| aec3::ApplyFilter_Avx2(render_buffer, current_size_partitions_, H_, S); |
| break; |
| #endif |
| +#endif |
| #if defined(WEBRTC_HAS_NEON) |
| case Aec3Optimization::kNeon: |
| aec3::ApplyFilter_Neon(render_buffer, current_size_partitions_, H_, S); |
| @@ -600,10 +602,12 @@ void AdaptiveFirFilter::ComputeFrequencyResponse( |
| case Aec3Optimization::kSse2: |
| aec3::ComputeFrequencyResponse_Sse2(current_size_partitions_, H_, H2); |
| break; |
| +#if !defined(WEBRTC_WEBKIT_BUILD) |
| case Aec3Optimization::kAvx2: |
| aec3::ComputeFrequencyResponse_Avx2(current_size_partitions_, H_, H2); |
| break; |
| #endif |
| +#endif |
| #if defined(WEBRTC_HAS_NEON) |
| case Aec3Optimization::kNeon: |
| aec3::ComputeFrequencyResponse_Neon(current_size_partitions_, H_, H2); |
| @@ -626,11 +630,13 @@ void AdaptiveFirFilter::AdaptAndUpdateSize(const RenderBuffer& render_buffer, |
| aec3::AdaptPartitions_Sse2(render_buffer, G, current_size_partitions_, |
| &H_); |
| break; |
| +#if !defined(WEBRTC_WEBKIT_BUILD) |
| case Aec3Optimization::kAvx2: |
| aec3::AdaptPartitions_Avx2(render_buffer, G, current_size_partitions_, |
| &H_); |
| break; |
| #endif |
| +#endif |
| #if defined(WEBRTC_HAS_NEON) |
| case Aec3Optimization::kNeon: |
| aec3::AdaptPartitions_Neon(render_buffer, G, current_size_partitions_, |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_erl.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_erl.cc |
| index 45b881397984..baa1986668a9 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_erl.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_erl.cc |
| @@ -85,10 +85,12 @@ void ComputeErl(const Aec3Optimization& optimization, |
| case Aec3Optimization::kSse2: |
| aec3::ErlComputer_SSE2(H2, erl); |
| break; |
| +#if !defined(WEBRTC_WEBKIT_BUILD) |
| case Aec3Optimization::kAvx2: |
| aec3::ErlComputer_AVX2(H2, erl); |
| break; |
| #endif |
| +#endif |
| #if defined(WEBRTC_HAS_NEON) |
| case Aec3Optimization::kNeon: |
| aec3::ErlComputer_NEON(H2, erl); |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/fft_data.h b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/fft_data.h |
| index 9c25e784aa01..141606185fac 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/fft_data.h |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/fft_data.h |
| @@ -63,9 +63,11 @@ struct FftData { |
| power_spectrum[kFftLengthBy2] = re[kFftLengthBy2] * re[kFftLengthBy2] + |
| im[kFftLengthBy2] * im[kFftLengthBy2]; |
| } break; |
| +#if !defined(WEBRTC_WEBKIT_BUILD) |
| case Aec3Optimization::kAvx2: |
| SpectrumAVX2(power_spectrum); |
| break; |
| +#endif |
| #endif |
| default: |
| std::transform(re.begin(), re.end(), im.begin(), power_spectrum.begin(), |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/filter_analyzer.h b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/filter_analyzer.h |
| index b0b7070119f6..f08ae0e79aa7 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/filter_analyzer.h |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/filter_analyzer.h |
| @@ -99,11 +99,11 @@ class FilterAnalyzer { |
| int delay_blocks); |
| |
| private: |
| - bool significant_peak_; |
| - float filter_floor_accum_; |
| - float filter_secondary_peak_; |
| - size_t filter_floor_low_limit_; |
| - size_t filter_floor_high_limit_; |
| + bool significant_peak_ = false; |
| + float filter_floor_accum_ = 0.f; |
| + float filter_secondary_peak_ = 0.f; |
| + size_t filter_floor_low_limit_ = 0; |
| + size_t filter_floor_high_limit_ = 0; |
| const float active_render_threshold_; |
| size_t consistent_estimate_counter_ = 0; |
| int consistent_delay_reference_ = -10; |
| @@ -122,8 +122,8 @@ class FilterAnalyzer { |
| consistent_filter_detector.Reset(); |
| } |
| |
| - float gain; |
| - size_t peak_index; |
| + float gain = 0.f; |
| + size_t peak_index = 0; |
| int filter_length_blocks; |
| bool consistent_estimate = false; |
| ConsistentFilterDetector consistent_filter_detector; |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/matched_filter.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/matched_filter.cc |
| index 64b2d4e697ad..9c93ddc81947 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/matched_filter.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/matched_filter.cc |
| @@ -364,12 +364,14 @@ void MatchedFilter::Update(const DownsampledRenderBuffer& render_buffer, |
| smoothing_, render_buffer.buffer, y, |
| filters_[n], &filters_updated, &error_sum); |
| break; |
| +#if !defined(WEBRTC_WEBKIT_BUILD) |
| case Aec3Optimization::kAvx2: |
| aec3::MatchedFilterCore_AVX2(x_start_index, x2_sum_threshold, |
| smoothing_, render_buffer.buffer, y, |
| filters_[n], &filters_updated, &error_sum); |
| break; |
| #endif |
| +#endif |
| #if defined(WEBRTC_HAS_NEON) |
| case Aec3Optimization::kNeon: |
| aec3::MatchedFilterCore_NEON(x_start_index, x2_sum_threshold, |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/vector_math.h b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/vector_math.h |
| index e4d1381ae176..c8427f848cac 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/vector_math.h |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/audio_processing/aec3/vector_math.h |
| @@ -59,10 +59,12 @@ class VectorMath { |
| x[j] = sqrtf(x[j]); |
| } |
| } break; |
| +#if !defined(WEBRTC_WEBKIT_BUILD) |
| case Aec3Optimization::kAvx2: |
| SqrtAVX2(x); |
| break; |
| #endif |
| +#endif |
| #if defined(WEBRTC_HAS_NEON) |
| case Aec3Optimization::kNeon: { |
| const int x_size = static_cast<int>(x.size()); |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/remote_bitrate_estimator/inter_arrival.h b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/remote_bitrate_estimator/inter_arrival.h |
| index dbc630ff6324..f18d5a078f3c 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/remote_bitrate_estimator/inter_arrival.h |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/remote_bitrate_estimator/inter_arrival.h |
| @@ -60,7 +60,8 @@ class InterArrival { |
| first_timestamp(0), |
| timestamp(0), |
| first_arrival_ms(-1), |
| - complete_time_ms(-1) {} |
| + complete_time_ms(-1), |
| + last_system_time_ms(0) {} |
| |
| bool IsFirstPacket() const { return complete_time_ms == -1; } |
| |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/create_video_rtp_depacketizer.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/create_video_rtp_depacketizer.cc |
| index 724ad8c42edf..a92c2599a4f1 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/create_video_rtp_depacketizer.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/create_video_rtp_depacketizer.cc |
| @@ -13,6 +13,7 @@ |
| #include <memory> |
| |
| #include "api/video/video_codec_type.h" |
| +#include "modules/rtp_rtcp/source/rtp_format_h265.h" |
| #include "modules/rtp_rtcp/source/video_rtp_depacketizer.h" |
| #include "modules/rtp_rtcp/source/video_rtp_depacketizer_av1.h" |
| #include "modules/rtp_rtcp/source/video_rtp_depacketizer_generic.h" |
| @@ -27,6 +28,10 @@ std::unique_ptr<VideoRtpDepacketizer> CreateVideoRtpDepacketizer( |
| switch (codec) { |
| case kVideoCodecH264: |
| return std::make_unique<VideoRtpDepacketizerH264>(); |
| +#ifndef DISABLE_H265 |
| + case kVideoCodecH265: |
| + return std::make_unique<VideoRtpDepacketizerGeneric>(); |
| +#endif |
| case kVideoCodecVP8: |
| return std::make_unique<VideoRtpDepacketizerVp8>(); |
| case kVideoCodecVP9: |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/h265_sps_parser.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/h265_sps_parser.cc |
| new file mode 100644 |
| index 000000000000..3f34630aa87b |
| --- /dev/null |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/h265_sps_parser.cc |
| @@ -0,0 +1,191 @@ |
| +/* |
| + * Intel License |
| + * See https://01.org/open-webrtc-toolkit |
| + * This is released under Apache License 2.0 and it is free for both academic and commercial use. |
| + */ |
| + |
| +#include "webrtc/modules/rtp_rtcp/source/h265_sps_parser.h" |
| + |
| +#include "rtc_base/bit_buffer.h" |
| +#include "rtc_base/byte_buffer.h" |
| +#include "rtc_base/logging.h" |
| + |
| +#include <vector> |
| + |
| +#define RETURN_FALSE_ON_FAIL(x) \ |
| + if (!(x)) { \ |
| + return false; \ |
| + } |
| + |
| +namespace webrtc { |
| + |
| +H265SpsParser::H265SpsParser(const uint8_t* sps, size_t byte_length) |
| + : sps_(sps), byte_length_(byte_length), width_(), height_() { |
| +} |
| + |
| +bool H265SpsParser::Parse() { |
| + // General note: this is based off the 04/2015 version of the H.265 standard. |
| + // You can find it on this page: |
| + // http://www.itu.int/rec/T-REC-H.265 |
| + |
| + const char* sps_bytes = reinterpret_cast<const char*>(sps_); |
| + // First, parse out rbsp, which is basically the source buffer minus emulation |
| + // bytes (the last byte of a 0x00 0x00 0x03 sequence). RBSP is defined in |
| + // section 7.3.1.1 of the H.265 standard, similar to H264. |
| + rtc::ByteBufferWriter rbsp_buffer; |
| + for (size_t i = 0; i < byte_length_;) { |
| + // Be careful about over/underflow here. byte_length_ - 3 can underflow, and |
| + // i + 3 can overflow, but byte_length_ - i can't, because i < byte_length_ |
| + // above, and that expression will produce the number of bytes left in |
| + // the stream including the byte at i. |
| + if (byte_length_ - i >= 3 && sps_[i] == 0 && sps_[i + 1] == 0 && |
| + sps_[i + 2] == 3) { |
| + // Two rbsp bytes + the emulation byte. |
| + rbsp_buffer.WriteBytes(sps_bytes + i, 2); |
| + i += 3; |
| + } else { |
| + // Single rbsp byte. |
| + rbsp_buffer.WriteBytes(sps_bytes + i, 1); |
| + i++; |
| + } |
| + } |
| + |
| + // Now, we need to use a bit buffer to parse through the actual HEVC SPS |
| + // format. See Section 7.3.2.1.1 ("Sequence parameter set data syntax") of the |
| + // H.265 standard for a complete description. |
| + // Since we only care about resolution, we ignore the majority of fields, but |
| + // we still have to actively parse through a lot of the data, since many of |
| + // the fields have variable size. |
| + // Unlike H264, for H265, the picture size is indicated by pic_width_in_luma_samples |
| + // and pic_height_in_luma_samples, if conformance_window_flag !=1; |
| + // When conformance_window_flag is 1, the width is adjusted with con_win_xx_offset |
| + // |
| + rtc::BitBuffer parser(reinterpret_cast<const uint8_t*>(rbsp_buffer.Data()), |
| + rbsp_buffer.Length()); |
| + |
| + // The golomb values we have to read, not just consume. |
| + uint32_t golomb_ignored; |
| + |
| + // separate_colour_plane_flag is optional (assumed 0), but has implications |
| + // about the ChromaArrayType, which modifies how we treat crop coordinates. |
| + uint32_t separate_colour_plane_flag = 0; |
| + // chroma_format_idc will be ChromaArrayType if separate_colour_plane_flag is |
| + // 0. It defaults to 1, when not specified. |
| + uint32_t chroma_format_idc = 1; |
| + |
| + |
| + // sps_video_parameter_set_id: u(4) |
| + RETURN_FALSE_ON_FAIL(parser.ConsumeBits(4)); |
| + // sps_max_sub_layers_minus1: u(3) |
| + uint32_t sps_max_sub_layers_minus1 = 0; |
| + RETURN_FALSE_ON_FAIL(parser.ReadBits(&sps_max_sub_layers_minus1, 3)); |
| + // sps_temporal_id_nesting_flag: u(1) |
| + RETURN_FALSE_ON_FAIL(parser.ConsumeBits(1)); |
| + // profile_tier_level(1, sps_max_sub_layers_minus1). We are acutally not |
| + // using them, so read/skip over it. |
| + // general_profile_space+general_tier_flag+general_prfile_idc: u(8) |
| + RETURN_FALSE_ON_FAIL(parser.ConsumeBytes(1)); |
| + // general_profile_compatabilitiy_flag[32] |
| + RETURN_FALSE_ON_FAIL(parser.ConsumeBytes(4)); |
| + // general_progressive_source_flag + interlaced_source_flag+ non-packed_constraint |
| + // flag + frame_only_constraint_flag: u(4) |
| + RETURN_FALSE_ON_FAIL(parser.ConsumeBits(4)); |
| + // general_profile_idc decided flags or reserved. u(43) |
| + RETURN_FALSE_ON_FAIL(parser.ConsumeBits(43)); |
| + // general_inbld_flag or reserved 0: u(1) |
| + RETURN_FALSE_ON_FAIL(parser.ConsumeBits(1)); |
| + // general_level_idc: u(8) |
| + RETURN_FALSE_ON_FAIL(parser.ConsumeBytes(1)); |
| + // if max_sub_layers_minus1 >=1, read the sublayer profile information |
| + std::vector<uint32_t> sub_layer_profile_present_flags; |
| + std::vector<uint32_t> sub_layer_level_present_flags; |
| + uint32_t sub_layer_profile_present = 0; |
| + uint32_t sub_layer_level_present = 0; |
| + for (uint32_t i = 0; i < sps_max_sub_layers_minus1; i++) { |
| + //sublayer_profile_present_flag and sublayer_level_presnet_flag: u(2) |
| + RETURN_FALSE_ON_FAIL(parser.ReadBits(&sub_layer_profile_present, 1)); |
| + RETURN_FALSE_ON_FAIL(parser.ReadBits(&sub_layer_level_present, 1)); |
| + sub_layer_profile_present_flags.push_back(sub_layer_profile_present); |
| + sub_layer_level_present_flags.push_back(sub_layer_level_present); |
| + } |
| + if (sps_max_sub_layers_minus1 > 0) { |
| + for (uint32_t j = sps_max_sub_layers_minus1; j < 8; j++) { |
| + // reserved 2 bits: u(2) |
| + RETURN_FALSE_ON_FAIL(parser.ConsumeBits(2)); |
| + } |
| + } |
| + for (uint32_t k = 0; k < sps_max_sub_layers_minus1; k++) { |
| + if(sub_layer_profile_present_flags[k]) {// |
| + // sub_layer profile_space/tier_flag/profile_idc. ignored. u(8) |
| + RETURN_FALSE_ON_FAIL(parser.ConsumeBytes(1)); |
| + // profile_compatability_flag: u(32) |
| + RETURN_FALSE_ON_FAIL(parser.ConsumeBytes(4)); |
| + // sub_layer progressive_source_flag/interlaced_source_flag/ |
| + // non_packed_constraint_flag/frame_only_constraint_flag: u(4) |
| + RETURN_FALSE_ON_FAIL(parser.ConsumeBits(4)); |
| + // following 43-bits are profile_idc specific. We simply read/skip it. u(43) |
| + RETURN_FALSE_ON_FAIL(parser.ConsumeBits(43)); |
| + // 1-bit profile_idc specific inbld flag. We simply read/skip it. u(1) |
| + RETURN_FALSE_ON_FAIL(parser.ConsumeBits(1)); |
| + } |
| + if (sub_layer_level_present_flags[k]) { |
| + // sub_layer_level_idc: u(8) |
| + RETURN_FALSE_ON_FAIL(parser.ConsumeBytes(1)); |
| + } |
| + } |
| + //sps_seq_parameter_set_id: ue(v) |
| + RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); |
| + // chrome_format_idc: ue(v) |
| + RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&chroma_format_idc)); |
| + if (chroma_format_idc == 3) { |
| + // seperate_colour_plane_flag: u(1) |
| + RETURN_FALSE_ON_FAIL(parser.ReadBits(&separate_colour_plane_flag, 1)); |
| + } |
| + uint32_t pic_width_in_luma_samples = 0; |
| + uint32_t pic_height_in_luma_samples = 0; |
| + // pic_width_in_luma_samples: ue(v) |
| + RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&pic_width_in_luma_samples)); |
| + // pic_height_in_luma_samples: ue(v) |
| + RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&pic_height_in_luma_samples)); |
| + // conformance_window_flag: u(1) |
| + uint32_t conformance_window_flag = 0; |
| + RETURN_FALSE_ON_FAIL(parser.ReadBits(&conformance_window_flag, 1)); |
| + |
| + uint32_t conf_win_left_offset = 0; |
| + uint32_t conf_win_right_offset = 0; |
| + uint32_t conf_win_top_offset = 0; |
| + uint32_t conf_win_bottom_offset = 0; |
| + if (conformance_window_flag) { |
| + // conf_win_left_offset: ue(v) |
| + RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&conf_win_left_offset)); |
| + // conf_win_right_offset: ue(v) |
| + RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&conf_win_right_offset)); |
| + // conf_win_top_offset: ue(v) |
| + RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&conf_win_top_offset)); |
| + // conf_win_bottom_offset: ue(v) |
| + RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&conf_win_bottom_offset)); |
| + } |
| + |
| + //For enough to get the resolution information. calcaluate according to HEVC spec 7.4.3.2 |
| + int width = 0; |
| + int height = 0; |
| + |
| + width = pic_width_in_luma_samples; |
| + height = pic_height_in_luma_samples; |
| + |
| + if (conformance_window_flag) { |
| + int sub_width_c = ((1 == chroma_format_idc) || (2 == chroma_format_idc)) && |
| + (0 == separate_colour_plane_flag) ? 2 : 1; |
| + int sub_height_c = (1 == chroma_format_idc) && (0 == separate_colour_plane_flag) ? 2 : 1; |
| + //the offset includes the pixel within conformance window. so don't need to +1 as per spec |
| + width -= sub_width_c*(conf_win_right_offset + conf_win_left_offset); |
| + height -= sub_height_c*(conf_win_top_offset + conf_win_bottom_offset); |
| + } |
| + |
| + width_ = width; |
| + height_ = height; |
| + return true; |
| + |
| +} |
| + |
| +} // namespace webrtc |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/h265_sps_parser.h b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/h265_sps_parser.h |
| new file mode 100644 |
| index 000000000000..c642b9bd5376 |
| --- /dev/null |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/h265_sps_parser.h |
| @@ -0,0 +1,34 @@ |
| +/* |
| + * Intel License |
| + * See https://01.org/open-webrtc-toolkit |
| + * This is released under Apache License 2.0 and it is free for both academic and commercial use. |
| + */ |
| + |
| +#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_H265_SPS_PARSER_H_ |
| +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_H265_SPS_PARSER_H_ |
| + |
| +#include <stddef.h> |
| +#include <stdint.h> |
| + |
| +namespace webrtc { |
| + |
| +// A class for parsing out sequence parameter set (SPS) data from an H265 NALU. |
| +// Currently, only resolution is read without being ignored. |
| +class H265SpsParser { |
| + public: |
| + H265SpsParser(const uint8_t* sps, size_t byte_length); |
| + // Parses the SPS to completion. Returns true if the SPS was parsed correctly. |
| + bool Parse(); |
| + uint16_t width() { return width_; } |
| + uint16_t height() { return height_; } |
| + |
| + private: |
| + const uint8_t* const sps_; |
| + const size_t byte_length_; |
| + |
| + uint16_t width_; |
| + uint16_t height_; |
| +}; |
| + |
| +} // namespace webrtc |
| +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_H265_SPS_PARSER_H_ |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_format.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_format.cc |
| index 7703a6bf0f62..62cdea012114 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_format.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_format.cc |
| @@ -14,6 +14,7 @@ |
| |
| #include "absl/types/variant.h" |
| #include "modules/rtp_rtcp/source/rtp_format_h264.h" |
| +#include "modules/rtp_rtcp/source/rtp_format_h265.h" |
| #include "modules/rtp_rtcp/source/rtp_format_video_generic.h" |
| #include "modules/rtp_rtcp/source/rtp_format_vp8.h" |
| #include "modules/rtp_rtcp/source/rtp_format_vp9.h" |
| @@ -56,6 +57,12 @@ std::unique_ptr<RtpPacketizer> RtpPacketizer::Create( |
| case kVideoCodecAV1: |
| return std::make_unique<RtpPacketizerAv1>(payload, limits, |
| rtp_video_header.frame_type); |
| +#ifndef DISABLE_H265 |
| + case kVideoCodecH265: { |
| + return std::make_unique<RtpPacketizerGeneric>(payload, limits, |
| + rtp_video_header); |
| + } |
| +#endif |
| default: { |
| return std::make_unique<RtpPacketizerGeneric>(payload, limits, |
| rtp_video_header); |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_format_h265.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_format_h265.cc |
| new file mode 100644 |
| index 000000000000..2d8717cf65aa |
| --- /dev/null |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_format_h265.cc |
| @@ -0,0 +1,648 @@ |
| +/* |
| + * Intel License |
| + * See https://01.org/open-webrtc-toolkit |
| + * This is released under Apache License 2.0 and it is free for both academic and commercial use. |
| + */ |
| + |
| +#include <string.h> |
| + |
| +#include "common_video/h264/h264_common.h" |
| +#include "common_video/h265/h265_common.h" |
| +#include "common_video/h265/h265_pps_parser.h" |
| +#include "common_video/h265/h265_sps_parser.h" |
| +#include "common_video/h265/h265_vps_parser.h" |
| +#include "modules/include/module_common_types.h" |
| +#include "modules/rtp_rtcp/source/byte_io.h" |
| +#include "modules/rtp_rtcp/source/rtp_format_h265.h" |
| +#include "modules/rtp_rtcp/source/rtp_packet_to_send.h" |
| +#include "modules/video_coding/codecs/h265/include/h265_globals.h" |
| +#include "rtc_base/logging.h" |
| +using namespace rtc; |
| + |
| +namespace webrtc { |
| +namespace { |
| + |
| +enum NaluType { |
| + kTrailN = 0, |
| + kTrailR = 1, |
| + kTsaN = 2, |
| + kTsaR = 3, |
| + kStsaN = 4, |
| + kStsaR = 5, |
| + kRadlN = 6, |
| + kRadlR = 7, |
| + kBlaWLp = 16, |
| + kBlaWRadl = 17, |
| + kBlaNLp = 18, |
| + kIdrWRadl = 19, |
| + kIdrNLp = 20, |
| + kCra = 21, |
| + kVps = 32, |
| + kHevcSps = 33, |
| + kHevcPps = 34, |
| + kHevcAud = 35, |
| + kPrefixSei = 39, |
| + kSuffixSei = 40, |
| + kHevcAp = 48, |
| + kHevcFu = 49 |
| +}; |
| + |
| +/* |
| + 0 1 2 3 |
| + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| + | PayloadHdr (Type=49) | FU header | DONL (cond) | |
| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-| |
| +*/ |
| +// Unlike H.264, HEVC NAL header is 2-bytes. |
| +static const size_t kHevcNalHeaderSize = 2; |
| +// H.265's FU is constructed of 2-byte payload header, and 1-byte FU header |
| +static const size_t kHevcFuHeaderSize = 1; |
| +static const size_t kHevcLengthFieldSize = 2; |
| +static const size_t kHevcApHeaderSize = |
| + kHevcNalHeaderSize + kHevcLengthFieldSize; |
| + |
| +enum HevcNalHdrMasks { |
| + kHevcFBit = 0x80, |
| + kHevcTypeMask = 0x7E, |
| + kHevcLayerIDHMask = 0x1, |
| + kHevcLayerIDLMask = 0xF8, |
| + kHevcTIDMask = 0x7, |
| + kHevcTypeMaskN = 0x81, |
| + kHevcTypeMaskInFuHeader = 0x3F |
| +}; |
| + |
| +// Bit masks for FU headers. |
| +enum HevcFuDefs { kHevcSBit = 0x80, kHevcEBit = 0x40, kHevcFuTypeBit = 0x3F }; |
| + |
| +// TODO(pbos): Avoid parsing this here as well as inside the jitter buffer. |
| +bool ParseApStartOffsets(const uint8_t* nalu_ptr, |
| + size_t length_remaining, |
| + std::vector<size_t>* offsets) { |
| + size_t offset = 0; |
| + while (length_remaining > 0) { |
| + // Buffer doesn't contain room for additional nalu length. |
| + if (length_remaining < sizeof(uint16_t)) |
| + return false; |
| + uint16_t nalu_size = ByteReader<uint16_t>::ReadBigEndian(nalu_ptr); |
| + nalu_ptr += sizeof(uint16_t); |
| + length_remaining -= sizeof(uint16_t); |
| + if (nalu_size > length_remaining) |
| + return false; |
| + nalu_ptr += nalu_size; |
| + length_remaining -= nalu_size; |
| + |
| + offsets->push_back(offset + kHevcApHeaderSize); |
| + offset += kHevcLengthFieldSize + nalu_size; |
| + } |
| + return true; |
| +} |
| + |
| +} // namespace |
| + |
| +RtpPacketizerH265::RtpPacketizerH265( |
| + rtc::ArrayView<const uint8_t> payload, |
| + PayloadSizeLimits limits, |
| + H265PacketizationMode packetization_mode) |
| + : limits_(limits), |
| + num_packets_left_(0) { |
| + // Guard against uninitialized memory in packetization_mode. |
| + RTC_CHECK(packetization_mode == H265PacketizationMode::NonInterleaved || |
| + packetization_mode == H265PacketizationMode::SingleNalUnit); |
| + |
| + for (const auto& nalu : |
| + H265::FindNaluIndices(payload.data(), payload.size())) { |
| + input_fragments_.push_back(Fragment(payload.data() + nalu.payload_start_offset, nalu.payload_size)); |
| + } |
| + |
| + if (!GeneratePackets(packetization_mode)) { |
| + // If failed to generate all the packets, discard already generated |
| + // packets in case the caller would ignore return value and still try to |
| + // call NextPacket(). |
| + num_packets_left_ = 0; |
| + while (!packets_.empty()) { |
| + packets_.pop(); |
| + } |
| + } |
| +} |
| + |
| +RtpPacketizerH265::~RtpPacketizerH265() {} |
| + |
| +size_t RtpPacketizerH265::NumPackets() const { |
| + return num_packets_left_; |
| +} |
| + |
| +RtpPacketizerH265::Fragment::Fragment(const uint8_t* buffer, size_t length) |
| + : buffer(buffer), length(length) {} |
| +RtpPacketizerH265::Fragment::Fragment(const Fragment& fragment) |
| + : buffer(fragment.buffer), length(fragment.length) {} |
| + |
| + |
| +bool RtpPacketizerH265::GeneratePackets( |
| + H265PacketizationMode packetization_mode) { |
| + // For HEVC we follow non-interleaved mode for the packetization, |
| + // and don't support single-nalu mode at present. |
| + for (size_t i = 0; i < input_fragments_.size();) { |
| + int fragment_len = input_fragments_[i].length; |
| + int single_packet_capacity = limits_.max_payload_len; |
| + if (input_fragments_.size() == 1) |
| + single_packet_capacity -= limits_.single_packet_reduction_len; |
| + else if (i == 0) |
| + single_packet_capacity -= limits_.first_packet_reduction_len; |
| + else if (i + 1 == input_fragments_.size()) { |
| + // Pretend that last fragment is larger instead of making last packet |
| + // smaller. |
| + single_packet_capacity -= limits_.last_packet_reduction_len; |
| + } |
| + if (fragment_len > single_packet_capacity) { |
| + PacketizeFu(i); |
| + ++i; |
| + } else { |
| + PacketizeSingleNalu(i); |
| + ++i; |
| + } |
| + } |
| + return true; |
| +} |
| + |
| +bool RtpPacketizerH265::PacketizeFu(size_t fragment_index) { |
| + // Fragment payload into packets (FU). |
| + // Strip out the original header and leave room for the FU header. |
| + const Fragment& fragment = input_fragments_[fragment_index]; |
| + PayloadSizeLimits limits = limits_; |
| + limits.max_payload_len -= kHevcFuHeaderSize + kHevcNalHeaderSize; |
| + |
| + // Update single/first/last packet reductions unless it is single/first/last |
| + // fragment. |
| + if (input_fragments_.size() != 1) { |
| + // if this fragment is put into a single packet, it might still be the |
| + // first or the last packet in the whole sequence of packets. |
| + if (fragment_index == input_fragments_.size() - 1) { |
| + limits.single_packet_reduction_len = limits_.last_packet_reduction_len; |
| + } else if (fragment_index == 0) { |
| + limits.single_packet_reduction_len = limits_.first_packet_reduction_len; |
| + } else { |
| + limits.single_packet_reduction_len = 0; |
| + } |
| + } |
| + if (fragment_index != 0) |
| + limits.first_packet_reduction_len = 0; |
| + if (fragment_index != input_fragments_.size() - 1) |
| + limits.last_packet_reduction_len = 0; |
| + |
| + // Strip out the original header. |
| + size_t payload_left = fragment.length - kHevcNalHeaderSize; |
| + int offset = kHevcNalHeaderSize; |
| + |
| + std::vector<int> payload_sizes = SplitAboutEqually(payload_left, limits); |
| + if (payload_sizes.empty()) |
| + return false; |
| + |
| + for (size_t i = 0; i < payload_sizes.size(); ++i) { |
| + int packet_length = payload_sizes[i]; |
| + RTC_CHECK_GT(packet_length, 0); |
| + uint16_t header = (fragment.buffer[0] << 8) | fragment.buffer[1]; |
| + packets_.push(PacketUnit(Fragment(fragment.buffer + offset, packet_length), |
| + /*first_fragment=*/i == 0, |
| + /*last_fragment=*/i == payload_sizes.size() - 1, |
| + false, header)); |
| + offset += packet_length; |
| + payload_left -= packet_length; |
| + } |
| + num_packets_left_ += payload_sizes.size(); |
| + RTC_CHECK_EQ(0, payload_left); |
| + return true; |
| +} |
| + |
| + |
| +bool RtpPacketizerH265::PacketizeSingleNalu(size_t fragment_index) { |
| + // Add a single NALU to the queue, no aggregation. |
| + size_t payload_size_left = limits_.max_payload_len; |
| + if (input_fragments_.size() == 1) |
| + payload_size_left -= limits_.single_packet_reduction_len; |
| + else if (fragment_index == 0) |
| + payload_size_left -= limits_.first_packet_reduction_len; |
| + else if (fragment_index + 1 == input_fragments_.size()) |
| + payload_size_left -= limits_.last_packet_reduction_len; |
| + const Fragment* fragment = &input_fragments_[fragment_index]; |
| + if (payload_size_left < fragment->length) { |
| + RTC_LOG(LS_ERROR) << "Failed to fit a fragment to packet in SingleNalu " |
| + "packetization mode. Payload size left " |
| + << payload_size_left << ", fragment length " |
| + << fragment->length << ", packet capacity " |
| + << limits_.max_payload_len; |
| + return false; |
| + } |
| + RTC_CHECK_GT(fragment->length, 0u); |
| + packets_.push(PacketUnit(*fragment, true /* first */, true /* last */, |
| + false /* aggregated */, fragment->buffer[0])); |
| + ++num_packets_left_; |
| + return true; |
| +} |
| + |
| +int RtpPacketizerH265::PacketizeAp(size_t fragment_index) { |
| + // Aggregate fragments into one packet (STAP-A). |
| + size_t payload_size_left = limits_.max_payload_len; |
| + if (input_fragments_.size() == 1) |
| + payload_size_left -= limits_.single_packet_reduction_len; |
| + else if (fragment_index == 0) |
| + payload_size_left -= limits_.first_packet_reduction_len; |
| + int aggregated_fragments = 0; |
| + size_t fragment_headers_length = 0; |
| + const Fragment* fragment = &input_fragments_[fragment_index]; |
| + RTC_CHECK_GE(payload_size_left, fragment->length); |
| + ++num_packets_left_; |
| + |
| + auto payload_size_needed = [&] { |
| + size_t fragment_size = fragment->length + fragment_headers_length; |
| + if (input_fragments_.size() == 1) { |
| + // Single fragment, single packet, payload_size_left already adjusted |
| + // with limits_.single_packet_reduction_len. |
| + return fragment_size; |
| + } |
| + if (fragment_index == input_fragments_.size() - 1) { |
| + // Last fragment, so StrapA might be the last packet. |
| + return fragment_size + limits_.last_packet_reduction_len; |
| + } |
| + return fragment_size; |
| + }; |
| + |
| + while (payload_size_left >= payload_size_needed()) { |
| + RTC_CHECK_GT(fragment->length, 0); |
| + packets_.push(PacketUnit(*fragment, aggregated_fragments == 0, false, true, |
| + fragment->buffer[0])); |
| + payload_size_left -= fragment->length; |
| + payload_size_left -= fragment_headers_length; |
| + |
| + fragment_headers_length = kHevcLengthFieldSize; |
| + // If we are going to try to aggregate more fragments into this packet |
| + // we need to add the STAP-A NALU header and a length field for the first |
| + // NALU of this packet. |
| + if (aggregated_fragments == 0) |
| + fragment_headers_length += kHevcNalHeaderSize + kHevcLengthFieldSize; |
| + ++aggregated_fragments; |
| + |
| + // Next fragment. |
| + ++fragment_index; |
| + if (fragment_index == input_fragments_.size()) |
| + break; |
| + fragment = &input_fragments_[fragment_index]; |
| + } |
| + RTC_CHECK_GT(aggregated_fragments, 0); |
| + packets_.back().last_fragment = true; |
| + return fragment_index; |
| +} |
| + |
| +bool RtpPacketizerH265::NextPacket(RtpPacketToSend* rtp_packet) { |
| + RTC_DCHECK(rtp_packet); |
| + |
| + if (packets_.empty()) { |
| + return false; |
| + } |
| + |
| + PacketUnit packet = packets_.front(); |
| + |
| + if (packet.first_fragment && packet.last_fragment) { |
| + // Single NAL unit packet. |
| + size_t bytes_to_send = packet.source_fragment.length; |
| + uint8_t* buffer = rtp_packet->AllocatePayload(bytes_to_send); |
| + memcpy(buffer, packet.source_fragment.buffer, bytes_to_send); |
| + packets_.pop(); |
| + input_fragments_.pop_front(); |
| + } else if (packet.aggregated) { |
| + bool is_last_packet = num_packets_left_ == 1; |
| + NextAggregatePacket(rtp_packet, is_last_packet); |
| + } else { |
| + NextFragmentPacket(rtp_packet); |
| + } |
| + rtp_packet->SetMarker(packets_.empty()); |
| + --num_packets_left_; |
| + return true; |
| +} |
| + |
| +void RtpPacketizerH265::NextAggregatePacket(RtpPacketToSend* rtp_packet, |
| + bool last) { |
| + size_t payload_capacity = rtp_packet->FreeCapacity(); |
| + RTC_CHECK_GE(payload_capacity, kHevcNalHeaderSize); |
| + uint8_t* buffer = rtp_packet->AllocatePayload(payload_capacity); |
| + |
| + PacketUnit* packet = &packets_.front(); |
| + RTC_CHECK(packet->first_fragment); |
| + uint8_t payload_hdr_h = packet->header >> 8; |
| + uint8_t payload_hdr_l = packet->header & 0xFF; |
| + uint8_t layer_id_h = payload_hdr_h & kHevcLayerIDHMask; |
| + |
| + payload_hdr_h = |
| + (payload_hdr_h & kHevcTypeMaskN) | (kHevcAp << 1) | layer_id_h; |
| + |
| + buffer[0] = payload_hdr_h; |
| + buffer[1] = payload_hdr_l; |
| + int index = kHevcNalHeaderSize; |
| + bool is_last_fragment = packet->last_fragment; |
| + while (packet->aggregated) { |
| + // Add NAL unit length field. |
| + const Fragment& fragment = packet->source_fragment; |
| + ByteWriter<uint16_t>::WriteBigEndian(&buffer[index], fragment.length); |
| + index += kHevcLengthFieldSize; |
| + // Add NAL unit. |
| + memcpy(&buffer[index], fragment.buffer, fragment.length); |
| + index += fragment.length; |
| + packets_.pop(); |
| + input_fragments_.pop_front(); |
| + if (is_last_fragment) |
| + break; |
| + packet = &packets_.front(); |
| + is_last_fragment = packet->last_fragment; |
| + } |
| + RTC_CHECK(is_last_fragment); |
| + rtp_packet->SetPayloadSize(index); |
| +} |
| + |
| +void RtpPacketizerH265::NextFragmentPacket(RtpPacketToSend* rtp_packet) { |
| + PacketUnit* packet = &packets_.front(); |
| + // NAL unit fragmented over multiple packets (FU). |
| + // We do not send original NALU header, so it will be replaced by the |
| + // PayloadHdr of the first packet. |
| + uint8_t payload_hdr_h = |
| + packet->header >> 8; // 1-bit F, 6-bit type, 1-bit layerID highest-bit |
| + uint8_t payload_hdr_l = packet->header & 0xFF; |
| + uint8_t layer_id_h = payload_hdr_h & kHevcLayerIDHMask; |
| + uint8_t fu_header = 0; |
| + // S | E |6 bit type. |
| + fu_header |= (packet->first_fragment ? kHevcSBit : 0); |
| + fu_header |= (packet->last_fragment ? kHevcEBit : 0); |
| + uint8_t type = (payload_hdr_h & kHevcTypeMask) >> 1; |
| + fu_header |= type; |
| + // Now update payload_hdr_h with FU type. |
| + payload_hdr_h = |
| + (payload_hdr_h & kHevcTypeMaskN) | (kHevcFu << 1) | layer_id_h; |
| + const Fragment& fragment = packet->source_fragment; |
| + uint8_t* buffer = rtp_packet->AllocatePayload( |
| + kHevcFuHeaderSize + kHevcNalHeaderSize + fragment.length); |
| + buffer[0] = payload_hdr_h; |
| + buffer[1] = payload_hdr_l; |
| + buffer[2] = fu_header; |
| + |
| + if (packet->last_fragment) { |
| + memcpy(buffer + kHevcFuHeaderSize + kHevcNalHeaderSize, fragment.buffer, |
| + fragment.length); |
| + } else { |
| + memcpy(buffer + kHevcFuHeaderSize + kHevcNalHeaderSize, fragment.buffer, |
| + fragment.length); |
| + } |
| + packets_.pop(); |
| +} |
| + |
| +absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> VideoRtpDepacketizerH265::Parse( |
| + rtc::CopyOnWriteBuffer rtp_payload) { |
| + size_t payload_data_length = rtp_payload.size(); |
| + if (payload_data_length == 0) { |
| + RTC_LOG(LS_ERROR) << "Empty payload."; |
| + return absl::nullopt; |
| + } |
| + |
| + ParsedRtpPayload parsed_payload; |
| + |
| + uint8_t* payload_data = rtp_payload.data(); |
| + |
| + offset_ = 0; |
| + length_ = payload_data_length; |
| + modified_buffer_.reset(); |
| + |
| + uint8_t nal_type = (payload_data[0] & kHevcTypeMask) >> 1; |
| + parsed_payload.video_header |
| + .video_type_header.emplace<RTPVideoHeaderH265>(); |
| + |
| + if (nal_type == H265::NaluType::kFU) { |
| + // Fragmented NAL units (FU-A). |
| + if (!ParseFuNalu(&parsed_payload, payload_data)) |
| + return absl::nullopt; |
| + } else { |
| + // We handle STAP-A and single NALU's the same way here. The jitter buffer |
| + // will depacketize the STAP-A into NAL units later. |
| + // TODO(sprang): Parse STAP-A offsets here and store in fragmentation vec. |
| + if (!ProcessApOrSingleNalu(&parsed_payload, payload_data)) |
| + return absl::nullopt; |
| + } |
| + |
| + const uint8_t* payload = |
| + modified_buffer_ ? modified_buffer_->data() : payload_data; |
| + |
| + parsed_payload.video_payload = { payload + offset_, length_ }; |
| + return parsed_payload; |
| +} |
| + |
| +bool VideoRtpDepacketizerH265::ProcessApOrSingleNalu( |
| + ParsedRtpPayload* parsed_payload, |
| + const uint8_t* payload_data) { |
| + parsed_payload->video_header.width = 0; |
| + parsed_payload->video_header.height = 0; |
| + parsed_payload->video_header.codec = kVideoCodecH265; |
| + parsed_payload->video_header.is_first_packet_in_frame = true; |
| + auto& h265_header = absl::get<RTPVideoHeaderH265>( |
| + parsed_payload->video_header.video_type_header); |
| + |
| + const uint8_t* nalu_start = payload_data + kHevcNalHeaderSize; |
| + const size_t nalu_length = length_ - kHevcNalHeaderSize; |
| + uint8_t nal_type = (payload_data[0] & kHevcTypeMask) >> 1; |
| + std::vector<size_t> nalu_start_offsets; |
| + if (nal_type == H265::NaluType::kAP) { |
| + // Skip the StapA header (StapA NAL type + length). |
| + if (length_ <= kHevcApHeaderSize) { |
| + RTC_LOG(LS_ERROR) << "AP header truncated."; |
| + return false; |
| + } |
| + |
| + if (!ParseApStartOffsets(nalu_start, nalu_length, &nalu_start_offsets)) { |
| + RTC_LOG(LS_ERROR) << "AP packet with incorrect NALU packet lengths."; |
| + return false; |
| + } |
| + |
| + h265_header.packetization_type = kH265AP; |
| + // nal_type = (payload_data[kHevcApHeaderSize] & kHevcTypeMask) >> 1; |
| + } else { |
| + h265_header.packetization_type = kH265SingleNalu; |
| + nalu_start_offsets.push_back(0); |
| + } |
| + h265_header.nalu_type = nal_type; |
| + parsed_payload->video_header.frame_type = VideoFrameType::kVideoFrameDelta; |
| + |
| + nalu_start_offsets.push_back(length_ + kHevcLengthFieldSize); // End offset. |
| + for (size_t i = 0; i < nalu_start_offsets.size() - 1; ++i) { |
| + size_t start_offset = nalu_start_offsets[i]; |
| + // End offset is actually start offset for next unit, excluding length field |
| + // so remove that from this units length. |
| + size_t end_offset = nalu_start_offsets[i + 1] - kHevcLengthFieldSize; |
| + if (end_offset - start_offset < kHevcNalHeaderSize) { // Same as H.264. |
| + RTC_LOG(LS_ERROR) << "AP packet too short"; |
| + return false; |
| + } |
| + |
| + H265NaluInfo nalu; |
| + nalu.type = (payload_data[start_offset] & kHevcTypeMask) >> 1; |
| + nalu.vps_id = -1; |
| + nalu.sps_id = -1; |
| + nalu.pps_id = -1; |
| + start_offset += kHevcNalHeaderSize; |
| + switch (nalu.type) { |
| + case H265::NaluType::kVps: { |
| + absl::optional<H265VpsParser::VpsState> vps = H265VpsParser::ParseVps( |
| + &payload_data[start_offset], end_offset - start_offset); |
| + if (vps) { |
| + nalu.vps_id = vps->id; |
| + } else { |
| + RTC_LOG(LS_WARNING) << "Failed to parse VPS id from VPS slice."; |
| + } |
| + break; |
| + } |
| + case H265::NaluType::kSps: { |
| + // Check if VUI is present in SPS and if it needs to be modified to |
| + // avoid excessive decoder latency. |
| + |
| + // Copy any previous data first (likely just the first header). |
| + std::unique_ptr<rtc::Buffer> output_buffer(new rtc::Buffer()); |
| + if (start_offset) |
| + output_buffer->AppendData(payload_data, start_offset); |
| + |
| + absl::optional<H265SpsParser::SpsState> sps = H265SpsParser::ParseSps( |
| + &payload_data[start_offset], end_offset - start_offset); |
| + |
| + if (sps) { |
| + parsed_payload->video_header.width = sps->width; |
| + parsed_payload->video_header.height = sps->height; |
| + nalu.sps_id = sps->id; |
| + nalu.vps_id = sps->vps_id; |
| + } else { |
| + RTC_LOG(LS_WARNING) |
| + << "Failed to parse SPS and VPS id from SPS slice."; |
| + } |
| + parsed_payload->video_header.frame_type = VideoFrameType::kVideoFrameKey; |
| + break; |
| + } |
| + case H265::NaluType::kPps: { |
| + uint32_t pps_id; |
| + uint32_t sps_id; |
| + if (H265PpsParser::ParsePpsIds(&payload_data[start_offset], |
| + end_offset - start_offset, &pps_id, |
| + &sps_id)) { |
| + nalu.pps_id = pps_id; |
| + nalu.sps_id = sps_id; |
| + } else { |
| + RTC_LOG(LS_WARNING) |
| + << "Failed to parse PPS id and SPS id from PPS slice."; |
| + } |
| + break; |
| + } |
| + case H265::NaluType::kIdrWRadl: |
| + case H265::NaluType::kIdrNLp: |
| + case H265::NaluType::kCra: |
| + parsed_payload->video_header.frame_type = VideoFrameType::kVideoFrameKey; |
| + case H265::NaluType::kTrailN: |
| + case H265::NaluType::kTrailR: { |
| + absl::optional<uint32_t> pps_id = |
| + H265PpsParser::ParsePpsIdFromSliceSegmentLayerRbsp( |
| + &payload_data[start_offset], end_offset - start_offset, |
| + nalu.type); |
| + if (pps_id) { |
| + nalu.pps_id = *pps_id; |
| + } else { |
| + RTC_LOG(LS_WARNING) << "Failed to parse PPS id from slice of type: " |
| + << static_cast<int>(nalu.type); |
| + } |
| + break; |
| + } |
| + // Slices below don't contain SPS or PPS ids. |
| + case H265::NaluType::kAud: |
| + case H265::NaluType::kTsaN: |
| + case H265::NaluType::kTsaR: |
| + case H265::NaluType::kStsaN: |
| + case H265::NaluType::kStsaR: |
| + case H265::NaluType::kRadlN: |
| + case H265::NaluType::kRadlR: |
| + case H265::NaluType::kBlaWLp: |
| + case H265::NaluType::kBlaWRadl: |
| + case H265::NaluType::kPrefixSei: |
| + case H265::NaluType::kSuffixSei: |
| + break; |
| + case H265::NaluType::kAP: |
| + case H265::NaluType::kFU: |
| + RTC_LOG(LS_WARNING) << "Unexpected AP or FU received."; |
| + return false; |
| + } |
| + |
| + if (h265_header.nalus_length == kMaxNalusPerPacket) { |
| + RTC_LOG(LS_WARNING) |
| + << "Received packet containing more than " << kMaxNalusPerPacket |
| + << " NAL units. Will not keep track sps and pps ids for all of them."; |
| + } else { |
| + h265_header.nalus[h265_header.nalus_length++] = nalu; |
| + } |
| + } |
| + return true; |
| +} |
| + |
| +bool VideoRtpDepacketizerH265::ParseFuNalu( |
| + ParsedRtpPayload* parsed_payload, |
| + const uint8_t* payload_data) { |
| + if (length_ < kHevcFuHeaderSize + kHevcNalHeaderSize) { |
| + RTC_LOG(LS_ERROR) << "FU NAL units truncated."; |
| + return false; |
| + } |
| + uint8_t f = payload_data[0] & kHevcFBit; |
| + uint8_t layer_id_h = payload_data[0] & kHevcLayerIDHMask; |
| + uint8_t layer_id_l_unshifted = payload_data[1] & kHevcLayerIDLMask; |
| + uint8_t tid = payload_data[1] & kHevcTIDMask; |
| + |
| + uint8_t original_nal_type = payload_data[2] & kHevcTypeMaskInFuHeader; |
| + bool first_fragment = payload_data[2] & kHevcSBit; |
| + H265NaluInfo nalu; |
| + nalu.type = original_nal_type; |
| + nalu.vps_id = -1; |
| + nalu.sps_id = -1; |
| + nalu.pps_id = -1; |
| + if (first_fragment) { |
| + offset_ = 1; |
| + length_ -= 1; |
| + absl::optional<uint32_t> pps_id = |
| + H265PpsParser::ParsePpsIdFromSliceSegmentLayerRbsp( |
| + payload_data + kHevcNalHeaderSize + kHevcFuHeaderSize, |
| + length_ - kHevcFuHeaderSize, nalu.type); |
| + if (pps_id) { |
| + nalu.pps_id = *pps_id; |
| + } else { |
| + RTC_LOG(LS_WARNING) |
| + << "Failed to parse PPS from first fragment of FU NAL " |
| + "unit with original type: " |
| + << static_cast<int>(nalu.type); |
| + } |
| + uint8_t* payload = const_cast<uint8_t*>(payload_data + offset_); |
| + payload[0] = f | original_nal_type << 1 | layer_id_h; |
| + payload[1] = layer_id_l_unshifted | tid; |
| + } else { |
| + offset_ = kHevcNalHeaderSize + kHevcFuHeaderSize; |
| + length_ -= (kHevcNalHeaderSize + kHevcFuHeaderSize); |
| + } |
| + |
| + if (original_nal_type == H265::NaluType::kIdrWRadl |
| + || original_nal_type == H265::NaluType::kIdrNLp |
| + || original_nal_type == H265::NaluType::kCra) { |
| + parsed_payload->video_header.frame_type = VideoFrameType::kVideoFrameKey; |
| + } else { |
| + parsed_payload->video_header.frame_type = VideoFrameType::kVideoFrameDelta; |
| + } |
| + parsed_payload->video_header.width = 0; |
| + parsed_payload->video_header.height = 0; |
| + parsed_payload->video_header.codec = kVideoCodecH265; |
| + parsed_payload->video_header.is_first_packet_in_frame = first_fragment; |
| + auto& h265_header = absl::get<RTPVideoHeaderH265>( |
| + parsed_payload->video_header.video_type_header); |
| + h265_header.packetization_type = kH265FU; |
| + h265_header.nalu_type = original_nal_type; |
| + if (first_fragment) { |
| + h265_header.nalus[h265_header.nalus_length] = nalu; |
| + h265_header.nalus_length = 1; |
| + } |
| + return true; |
| +} |
| + |
| +} // namespace webrtc |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_format_h265.h b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_format_h265.h |
| new file mode 100644 |
| index 000000000000..58ad1202a425 |
| --- /dev/null |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_format_h265.h |
| @@ -0,0 +1,129 @@ |
| +/* |
| + * Intel License |
| + * See https://01.org/open-webrtc-toolkit |
| + * This is released under Apache License 2.0 and it is free for both academic and commercial use. |
| + */ |
| + |
| +#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_H265_H_ |
| +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_H265_H_ |
| + |
| +#include <queue> |
| +#include <string> |
| +#include "api/array_view.h" |
| +#include "modules/include/module_common_types.h" |
| +#include "modules/rtp_rtcp/source/rtp_format.h" |
| +#include "modules/rtp_rtcp/source/rtp_packet_to_send.h" |
| +#include "modules/rtp_rtcp/source/rtp_format.h" |
| +#include "modules/rtp_rtcp/source/video_rtp_depacketizer.h" |
| +#include "modules/video_coding/codecs/h265/include/h265_globals.h" |
| +#include "rtc_base/buffer.h" |
| +#include "rtc_base/constructor_magic.h" |
| + |
| +namespace webrtc { |
| + |
| +class RtpPacketizerH265 : public RtpPacketizer { |
| + public: |
| + // Initialize with payload from encoder. |
| + // The payload_data must be exactly one encoded H.265 frame. |
| + RtpPacketizerH265(rtc::ArrayView<const uint8_t> payload, |
| + PayloadSizeLimits limits, |
| + H265PacketizationMode packetization_mode); |
| + |
| + ~RtpPacketizerH265() override; |
| + |
| + size_t NumPackets() const override; |
| + |
| + // Get the next payload with H.265 payload header. |
| + // buffer is a pointer to where the output will be written. |
| + // bytes_to_send is an output variable that will contain number of bytes |
| + // written to buffer. The parameter last_packet is true for the last packet of |
| + // the frame, false otherwise (i.e., call the function again to get the |
| + // next packet). |
| + // Returns true on success or false if there was no payload to packetize. |
| + bool NextPacket(RtpPacketToSend* rtp_packet) override; |
| + |
| + private: |
| + struct Packet { |
| + Packet(size_t offset, |
| + size_t size, |
| + bool first_fragment, |
| + bool last_fragment, |
| + bool aggregated, |
| + uint16_t header) |
| + : offset(offset), |
| + size(size), |
| + first_fragment(first_fragment), |
| + last_fragment(last_fragment), |
| + aggregated(aggregated), |
| + header(header) {} |
| + |
| + size_t offset; |
| + size_t size; |
| + bool first_fragment; |
| + bool last_fragment; |
| + bool aggregated; |
| + uint16_t header; // Different from H264 |
| + }; |
| + struct Fragment { |
| + Fragment(const uint8_t* buffer, size_t length); |
| + explicit Fragment(const Fragment& fragment); |
| + const uint8_t* buffer = nullptr; |
| + size_t length = 0; |
| + std::unique_ptr<rtc::Buffer> tmp_buffer; |
| + }; |
| + struct PacketUnit { |
| + PacketUnit(const Fragment& source_fragment, |
| + bool first_fragment, |
| + bool last_fragment, |
| + bool aggregated, |
| + uint16_t header) |
| + : source_fragment(source_fragment), |
| + first_fragment(first_fragment), |
| + last_fragment(last_fragment), |
| + aggregated(aggregated), |
| + header(header) {} |
| + |
| + const Fragment source_fragment; |
| + bool first_fragment; |
| + bool last_fragment; |
| + bool aggregated; |
| + uint16_t header; |
| + }; |
| + typedef std::queue<Packet> PacketQueue; |
| + std::deque<Fragment> input_fragments_; |
| + std::queue<PacketUnit> packets_; |
| + |
| + bool GeneratePackets(H265PacketizationMode packetization_mode); |
| + bool PacketizeFu(size_t fragment_index); |
| + int PacketizeAp(size_t fragment_index); |
| + bool PacketizeSingleNalu(size_t fragment_index); |
| + |
| + void NextAggregatePacket(RtpPacketToSend* rtp_packet, bool last); |
| + void NextFragmentPacket(RtpPacketToSend* rtp_packet); |
| + |
| + const PayloadSizeLimits limits_; |
| + size_t num_packets_left_; |
| + |
| + RTC_DISALLOW_COPY_AND_ASSIGN(RtpPacketizerH265); |
| +}; |
| + |
| +// Depacketizer for H.265. |
| +class VideoRtpDepacketizerH265 : public VideoRtpDepacketizer { |
| + public: |
| + virtual ~VideoRtpDepacketizerH265() {} |
| + |
| + absl::optional<ParsedRtpPayload> Parse( |
| + rtc::CopyOnWriteBuffer rtp_payload) override; |
| + |
| + private: |
| + bool ParseFuNalu(ParsedRtpPayload* parsed_payload, |
| + const uint8_t* payload_data); |
| + bool ProcessApOrSingleNalu(ParsedRtpPayload* parsed_payload, |
| + const uint8_t* payload_data); |
| + |
| + size_t offset_; |
| + size_t length_; |
| + std::unique_ptr<rtc::Buffer> modified_buffer_; |
| +}; |
| +} // namespace webrtc |
| +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_H265_H_ |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc |
| index 8ce1eed9139e..c4453cdb8166 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc |
| @@ -749,6 +749,9 @@ uint8_t RTPSenderVideo::GetTemporalId(const RTPVideoHeader& header) { |
| return vp9.temporal_idx; |
| } |
| uint8_t operator()(const RTPVideoHeaderH264&) { return kNoTemporalIdx; } |
| +#ifndef DISABLE_H265 |
| + uint8_t operator()(const RTPVideoHeaderH265&) { return kNoTemporalIdx; } |
| +#endif |
| uint8_t operator()(const RTPVideoHeaderLegacyGeneric&) { |
| return kNoTemporalIdx; |
| } |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_video_header.h b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_video_header.h |
| index ca3415587d75..aff98633d974 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_video_header.h |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_video_header.h |
| @@ -24,6 +24,7 @@ |
| #include "api/video/video_rotation.h" |
| #include "api/video/video_timing.h" |
| #include "modules/video_coding/codecs/h264/include/h264_globals.h" |
| +#include "modules/video_coding/codecs/h265/include/h265_globals.h" |
| #include "modules/video_coding/codecs/vp8/include/vp8_globals.h" |
| #include "modules/video_coding/codecs/vp9/include/vp9_globals.h" |
| |
| @@ -39,6 +40,9 @@ using RTPVideoTypeHeader = absl::variant<absl::monostate, |
| RTPVideoHeaderVP8, |
| RTPVideoHeaderVP9, |
| RTPVideoHeaderH264, |
| +#ifndef DISABLE_H265 |
| + RTPVideoHeaderH265, |
| +#endif |
| RTPVideoHeaderLegacyGeneric>; |
| |
| struct RTPVideoHeader { |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/video_coding/codecs/h265/include/h265_globals.h b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/video_coding/codecs/h265/include/h265_globals.h |
| new file mode 100644 |
| index 000000000000..bc0eef236cfe |
| --- /dev/null |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/video_coding/codecs/h265/include/h265_globals.h |
| @@ -0,0 +1,62 @@ |
| +/* |
| + * Copyright (c) 2018 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. |
| + */ |
| + |
| +// This file contains codec dependent definitions that are needed in |
| +// order to compile the WebRTC codebase, even if this codec is not used. |
| + |
| +#ifndef MODULES_VIDEO_CODING_CODECS_H265_INCLUDE_H265_GLOBALS_H_ |
| +#define MODULES_VIDEO_CODING_CODECS_H265_INCLUDE_H265_GLOBALS_H_ |
| + |
| +#ifndef DISABLE_H265 |
| + |
| +#include "modules/video_coding/codecs/h264/include/h264_globals.h" |
| + |
| +namespace webrtc { |
| + |
| +// The packetization types that we support: single, aggregated, and fragmented. |
| +enum H265PacketizationTypes { |
| + kH265SingleNalu, // This packet contains a single NAL unit. |
| + kH265AP, // This packet contains aggregation Packet. |
| + // If this packet has an associated NAL unit type, |
| + // it'll be for the first such aggregated packet. |
| + kH265FU, // This packet contains a FU (fragmentation |
| + // unit) packet, meaning it is a part of a frame |
| + // that was too large to fit into a single packet. |
| +}; |
| + |
| +struct H265NaluInfo { |
| + uint8_t type; |
| + int vps_id; |
| + int sps_id; |
| + int pps_id; |
| +}; |
| + |
| +enum class H265PacketizationMode { |
| + NonInterleaved = 0, // Mode 1 - STAP-A, FU-A is allowed |
| + SingleNalUnit // Mode 0 - only single NALU allowed |
| +}; |
| + |
| +struct RTPVideoHeaderH265 { |
| + // The NAL unit type. If this is a header for a fragmented packet, it's the |
| + // NAL unit type of the original data. If this is the header for an aggregated |
| + // packet, it's the NAL unit type of the first NAL unit in the packet. |
| + uint8_t nalu_type; |
| + H265PacketizationTypes packetization_type; |
| + H265NaluInfo nalus[kMaxNalusPerPacket]; |
| + size_t nalus_length; |
| + // The packetization type of this buffer - single, aggregated or fragmented. |
| + H265PacketizationMode packetization_mode; |
| +}; |
| + |
| +} // namespace webrtc |
| + |
| +#endif |
| + |
| +#endif // MODULES_VIDEO_CODING_CODECS_H265_INCLUDE_H265_GLOBALS_H_ |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc |
| index 1e37c293873d..abd1b96f4705 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc |
| @@ -984,6 +984,8 @@ int VP9EncoderImpl::Encode(const VideoFrame& input_image, |
| rtc::scoped_refptr<const I010BufferInterface> i010_copy; |
| switch (profile_) { |
| case VP9Profile::kProfile0: { |
| + // FIXME: Update libvpx to enable that code path. |
| +#if !defined(WEBRTC_WEBKIT_BUILD) |
| if (input_image.video_frame_buffer()->type() == |
| VideoFrameBuffer::Type::kNV12) { |
| const NV12BufferInterface* nv12_buffer = |
| @@ -997,6 +999,7 @@ int VP9EncoderImpl::Encode(const VideoFrame& input_image, |
| raw_->stride[VPX_PLANE_U] = nv12_buffer->StrideUV(); |
| raw_->stride[VPX_PLANE_V] = nv12_buffer->StrideUV(); |
| } else { |
| +#endif |
| rtc::scoped_refptr<I420BufferInterface> i420_buffer = |
| input_image.video_frame_buffer()->ToI420(); |
| video_frame_buffer = i420_buffer; |
| @@ -1009,7 +1012,7 @@ int VP9EncoderImpl::Encode(const VideoFrame& input_image, |
| raw_->stride[VPX_PLANE_Y] = i420_buffer->StrideY(); |
| raw_->stride[VPX_PLANE_U] = i420_buffer->StrideU(); |
| raw_->stride[VPX_PLANE_V] = i420_buffer->StrideV(); |
| - } |
| +// } |
| break; |
| } |
| case VP9Profile::kProfile1: { |
| @@ -1682,8 +1685,11 @@ void VP9EncoderImpl::MaybeRewrapRawWithFormat(const vpx_img_fmt fmt) { |
| if (!raw_) { |
| raw_ = vpx_img_wrap(nullptr, fmt, codec_.width, codec_.height, 1, nullptr); |
| } else if (raw_->fmt != fmt) { |
| + // FIXME: Update libvpx to enable that code path. |
| +#if !defined(WEBRTC_WEBKIT_BUILD) |
| RTC_LOG(INFO) << "Switching VP9 encoder pixel format to " |
| << (fmt == VPX_IMG_FMT_NV12 ? "NV12" : "I420"); |
| +#endif |
| vpx_img_free(raw_); |
| raw_ = vpx_img_wrap(nullptr, fmt, codec_.width, codec_.height, 1, nullptr); |
| } |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/video_coding/h265_vps_sps_pps_tracker.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/video_coding/h265_vps_sps_pps_tracker.cc |
| new file mode 100644 |
| index 000000000000..30cb14fddb8d |
| --- /dev/null |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/video_coding/h265_vps_sps_pps_tracker.cc |
| @@ -0,0 +1,312 @@ |
| +/* |
| + * Copyright (c) 2018 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 "modules/video_coding/h265_vps_sps_pps_tracker.h" |
| + |
| +#include <string> |
| +#include <utility> |
| + |
| +#include "common_video/h264/h264_common.h" |
| +#include "common_video/h265/h265_common.h" |
| +#include "common_video/h265/h265_pps_parser.h" |
| +#include "common_video/h265/h265_sps_parser.h" |
| +#include "common_video/h265/h265_vps_parser.h" |
| +#include "modules/video_coding/codecs/h264/include/h264_globals.h" |
| +#include "modules/video_coding/codecs/h265/include/h265_globals.h" |
| +#include "modules/video_coding/frame_object.h" |
| +#include "modules/video_coding/packet_buffer.h" |
| +#include "rtc_base/checks.h" |
| +#include "rtc_base/logging.h" |
| + |
| +namespace webrtc { |
| +namespace video_coding { |
| + |
| +namespace { |
| +const uint8_t start_code_h265[] = {0, 0, 0, 1}; |
| +} // namespace |
| + |
| +H265VpsSpsPpsTracker::FixedBitstream H265VpsSpsPpsTracker::CopyAndFixBitstream(rtc::ArrayView<const uint8_t> bitstream, |
| + RTPVideoHeader* video_header_pointer) { |
| + const uint8_t* data = bitstream.data(); |
| + const size_t data_size = bitstream.size(); |
| + RTPVideoHeader& video_header = *video_header_pointer; |
| + RTC_DCHECK(video_header.codec == kVideoCodecH265); |
| + |
| + auto& h265_header = |
| + absl::get<RTPVideoHeaderH265>(video_header.video_type_header); |
| + |
| + bool append_vps_sps_pps = false; |
| + auto vps = vps_data_.end(); |
| + auto sps = sps_data_.end(); |
| + auto pps = pps_data_.end(); |
| + |
| + for (size_t i = 0; i < h265_header.nalus_length; ++i) { |
| + const H265NaluInfo& nalu = h265_header.nalus[i]; |
| + switch (nalu.type) { |
| + case H265::NaluType::kVps: { |
| + vps_data_[nalu.vps_id].size = 0; |
| + break; |
| + } |
| + case H265::NaluType::kSps: { |
| + sps_data_[nalu.sps_id].vps_id = nalu.vps_id; |
| + sps_data_[nalu.sps_id].width = video_header.width; |
| + sps_data_[nalu.sps_id].height = video_header.height; |
| + break; |
| + } |
| + case H265::NaluType::kPps: { |
| + pps_data_[nalu.pps_id].sps_id = nalu.sps_id; |
| + break; |
| + } |
| + case H265::NaluType::kIdrWRadl: |
| + case H265::NaluType::kIdrNLp: |
| + case H265::NaluType::kCra: { |
| + // If this is the first packet of an IDR, make sure we have the required |
| + // SPS/PPS and also calculate how much extra space we need in the buffer |
| + // to prepend the SPS/PPS to the bitstream with start codes. |
| + if (video_header.is_first_packet_in_frame) { |
| + if (nalu.pps_id == -1) { |
| + RTC_LOG(LS_WARNING) << "No PPS id in IDR nalu."; |
| + return {kRequestKeyframe}; |
| + } |
| + |
| + pps = pps_data_.find(nalu.pps_id); |
| + if (pps == pps_data_.end()) { |
| + RTC_LOG(LS_WARNING) |
| + << "No PPS with id " << nalu.pps_id << " received"; |
| + return {kRequestKeyframe}; |
| + } |
| + |
| + sps = sps_data_.find(pps->second.sps_id); |
| + if (sps == sps_data_.end()) { |
| + RTC_LOG(LS_WARNING) |
| + << "No SPS with id << " << pps->second.sps_id << " received"; |
| + return {kRequestKeyframe}; |
| + } |
| + |
| + vps = vps_data_.find(sps->second.vps_id); |
| + if (vps == vps_data_.end()) { |
| + RTC_LOG(LS_WARNING) |
| + << "No VPS with id " << sps->second.vps_id << " received"; |
| + return {kRequestKeyframe}; |
| + } |
| + |
| + // Since the first packet of every keyframe should have its width and |
| + // height set we set it here in the case of it being supplied out of |
| + // band. |
| + video_header.width = sps->second.width; |
| + video_header.height = sps->second.height; |
| + |
| + // If the VPS/SPS/PPS was supplied out of band then we will have saved |
| + // the actual bitstream in |data|. |
| + // This branch is not verified. |
| + if (vps->second.data && sps->second.data && pps->second.data) { |
| + RTC_DCHECK_GT(vps->second.size, 0); |
| + RTC_DCHECK_GT(sps->second.size, 0); |
| + RTC_DCHECK_GT(pps->second.size, 0); |
| + append_vps_sps_pps = true; |
| + } |
| + } |
| + break; |
| + } |
| + default: |
| + break; |
| + } |
| + } |
| + |
| + RTC_CHECK(!append_vps_sps_pps || |
| + (sps != sps_data_.end() && pps != pps_data_.end())); |
| + |
| + // Calculate how much space we need for the rest of the bitstream. |
| + size_t required_size = 0; |
| + |
| + if (append_vps_sps_pps) { |
| + required_size += vps->second.size + sizeof(start_code_h265); |
| + required_size += sps->second.size + sizeof(start_code_h265); |
| + required_size += pps->second.size + sizeof(start_code_h265); |
| + } |
| + |
| + if (h265_header.packetization_type == kH265AP) { |
| + const uint8_t* nalu_ptr = data + 1; |
| + while (nalu_ptr < data + data_size) { |
| + RTC_DCHECK(video_header.is_first_packet_in_frame); |
| + required_size += sizeof(start_code_h265); |
| + |
| + // The first two bytes describe the length of a segment. |
| + uint16_t segment_length = nalu_ptr[0] << 8 | nalu_ptr[1]; |
| + nalu_ptr += 2; |
| + |
| + required_size += segment_length; |
| + nalu_ptr += segment_length; |
| + } |
| + } else { |
| + if (video_header.is_first_packet_in_frame) |
| + required_size += sizeof(start_code_h265); |
| + required_size += data_size; |
| + } |
| + |
| + // Then we copy to the new buffer. |
| + FixedBitstream fixed; |
| + fixed.bitstream.EnsureCapacity(required_size); |
| + |
| + if (append_vps_sps_pps) { |
| + // Insert VPS. |
| + fixed.bitstream.AppendData(start_code_h265); |
| + fixed.bitstream.AppendData(vps->second.data.get(), vps->second.size); |
| + |
| + // Insert SPS. |
| + fixed.bitstream.AppendData(start_code_h265); |
| + fixed.bitstream.AppendData(sps->second.data.get(), sps->second.size); |
| + |
| + // Insert PPS. |
| + fixed.bitstream.AppendData(start_code_h265); |
| + fixed.bitstream.AppendData(pps->second.data.get(), pps->second.size); |
| + |
| + // Update codec header to reflect the newly added SPS and PPS. |
| + H265NaluInfo vps_info; |
| + vps_info.type = H265::NaluType::kVps; |
| + vps_info.vps_id = vps->first; |
| + vps_info.sps_id = -1; |
| + vps_info.pps_id = -1; |
| + H265NaluInfo sps_info; |
| + sps_info.type = H265::NaluType::kSps; |
| + sps_info.vps_id = vps->first; |
| + sps_info.sps_id = sps->first; |
| + sps_info.pps_id = -1; |
| + H265NaluInfo pps_info; |
| + pps_info.type = H265::NaluType::kPps; |
| + pps_info.vps_id = vps->first; |
| + pps_info.sps_id = sps->first; |
| + pps_info.pps_id = pps->first; |
| + if (h265_header.nalus_length + 2 <= kMaxNalusPerPacket) { |
| + h265_header.nalus[h265_header.nalus_length++] = vps_info; |
| + h265_header.nalus[h265_header.nalus_length++] = sps_info; |
| + h265_header.nalus[h265_header.nalus_length++] = pps_info; |
| + } else { |
| + RTC_LOG(LS_WARNING) << "Not enough space in H.265 codec header to insert " |
| + "SPS/PPS provided out-of-band."; |
| + } |
| + } |
| + |
| + // Copy the rest of the bitstream and insert start codes. |
| + if (h265_header.packetization_type == kH265AP) { |
| + const uint8_t* nalu_ptr = data + 1; |
| + while (nalu_ptr < data + data_size) { |
| + fixed.bitstream.AppendData(start_code_h265); |
| + |
| + // The first two bytes describe the length of a segment. |
| + uint16_t segment_length = nalu_ptr[0] << 8 | nalu_ptr[1]; |
| + nalu_ptr += 2; |
| + |
| + size_t copy_end = nalu_ptr - data + segment_length; |
| + if (copy_end > data_size) { |
| + return {kDrop}; |
| + } |
| + |
| + fixed.bitstream.AppendData(nalu_ptr, segment_length); |
| + nalu_ptr += segment_length; |
| + } |
| + } else { |
| + if (video_header.is_first_packet_in_frame) { |
| + fixed.bitstream.AppendData(start_code_h265); |
| + } |
| + fixed.bitstream.AppendData(bitstream.data(), bitstream.size()); |
| + } |
| + |
| + fixed.action = kInsert; |
| + return fixed; |
| +} |
| + |
| +void H265VpsSpsPpsTracker::InsertVpsSpsPpsNalus( |
| + const std::vector<uint8_t>& vps, |
| + const std::vector<uint8_t>& sps, |
| + const std::vector<uint8_t>& pps) { |
| + constexpr size_t kNaluHeaderOffset = 1; |
| + if (vps.size() < kNaluHeaderOffset) { |
| + RTC_LOG(LS_WARNING) << "VPS size " << vps.size() << " is smaller than " |
| + << kNaluHeaderOffset; |
| + return; |
| + } |
| + if ((vps[0] & 0x7e) >> 1 != H265::NaluType::kSps) { |
| + RTC_LOG(LS_WARNING) << "SPS Nalu header missing"; |
| + return; |
| + } |
| + if (sps.size() < kNaluHeaderOffset) { |
| + RTC_LOG(LS_WARNING) << "SPS size " << sps.size() << " is smaller than " |
| + << kNaluHeaderOffset; |
| + return; |
| + } |
| + if ((sps[0] & 0x7e) >> 1 != H265::NaluType::kSps) { |
| + RTC_LOG(LS_WARNING) << "SPS Nalu header missing"; |
| + return; |
| + } |
| + if (pps.size() < kNaluHeaderOffset) { |
| + RTC_LOG(LS_WARNING) << "PPS size " << pps.size() << " is smaller than " |
| + << kNaluHeaderOffset; |
| + return; |
| + } |
| + if ((pps[0] & 0x7e) >> 1 != H265::NaluType::kPps) { |
| + RTC_LOG(LS_WARNING) << "SPS Nalu header missing"; |
| + return; |
| + } |
| + absl::optional<H265VpsParser::VpsState> parsed_vps = H265VpsParser::ParseVps( |
| + vps.data() + kNaluHeaderOffset, vps.size() - kNaluHeaderOffset); |
| + absl::optional<H265SpsParser::SpsState> parsed_sps = H265SpsParser::ParseSps( |
| + sps.data() + kNaluHeaderOffset, sps.size() - kNaluHeaderOffset); |
| + absl::optional<H265PpsParser::PpsState> parsed_pps = H265PpsParser::ParsePps( |
| + pps.data() + kNaluHeaderOffset, pps.size() - kNaluHeaderOffset); |
| + |
| + if (!parsed_vps) { |
| + RTC_LOG(LS_WARNING) << "Failed to parse VPS."; |
| + } |
| + |
| + if (!parsed_sps) { |
| + RTC_LOG(LS_WARNING) << "Failed to parse SPS."; |
| + } |
| + |
| + if (!parsed_pps) { |
| + RTC_LOG(LS_WARNING) << "Failed to parse PPS."; |
| + } |
| + |
| + if (!parsed_vps || !parsed_pps || !parsed_sps) { |
| + return; |
| + } |
| + |
| + VpsInfo vps_info; |
| + vps_info.size = vps.size(); |
| + uint8_t* vps_data = new uint8_t[vps_info.size]; |
| + memcpy(vps_data, vps.data(), vps_info.size); |
| + vps_info.data.reset(vps_data); |
| + vps_data_[parsed_vps->id] = std::move(vps_info); |
| + |
| + SpsInfo sps_info; |
| + sps_info.size = sps.size(); |
| + sps_info.width = parsed_sps->width; |
| + sps_info.height = parsed_sps->height; |
| + sps_info.vps_id = parsed_sps->vps_id; |
| + uint8_t* sps_data = new uint8_t[sps_info.size]; |
| + memcpy(sps_data, sps.data(), sps_info.size); |
| + sps_info.data.reset(sps_data); |
| + sps_data_[parsed_sps->id] = std::move(sps_info); |
| + |
| + PpsInfo pps_info; |
| + pps_info.size = pps.size(); |
| + pps_info.sps_id = parsed_pps->sps_id; |
| + uint8_t* pps_data = new uint8_t[pps_info.size]; |
| + memcpy(pps_data, pps.data(), pps_info.size); |
| + pps_info.data.reset(pps_data); |
| + pps_data_[parsed_pps->id] = std::move(pps_info); |
| + |
| + RTC_LOG(LS_INFO) << "Inserted SPS id " << parsed_sps->id << " and PPS id " |
| + << parsed_pps->id << " (referencing SPS " |
| + << parsed_pps->sps_id << ")"; |
| +} |
| + |
| +} // namespace video_coding |
| +} // namespace webrtc |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/video_coding/h265_vps_sps_pps_tracker.h b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/video_coding/h265_vps_sps_pps_tracker.h |
| new file mode 100644 |
| index 000000000000..7ac5e2a001cb |
| --- /dev/null |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/video_coding/h265_vps_sps_pps_tracker.h |
| @@ -0,0 +1,74 @@ |
| +/* |
| + * Copyright (c) 2018 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. |
| + */ |
| + |
| +#ifndef MODULES_VIDEO_CODING_H265_VPS_SPS_PPS_TRACKER_H_ |
| +#define MODULES_VIDEO_CODING_H265_VPS_SPS_PPS_TRACKER_H_ |
| + |
| +#include <cstdint> |
| +#include <map> |
| +#include <memory> |
| +#include <vector> |
| + |
| +#include "api/array_view.h" |
| +#include "modules/include/module_common_types.h" |
| +#include "modules/rtp_rtcp/source/rtp_video_header.h" |
| +#include "rtc_base/copy_on_write_buffer.h" |
| + |
| +namespace webrtc { |
| + |
| +class VCMPacket; |
| + |
| +namespace video_coding { |
| + |
| +class H265VpsSpsPpsTracker { |
| + public: |
| + enum PacketAction { kInsert, kDrop, kRequestKeyframe }; |
| + struct FixedBitstream { |
| + PacketAction action; |
| + rtc::CopyOnWriteBuffer bitstream; |
| + }; |
| + |
| + // Returns fixed bitstream and modifies |video_header|. |
| + FixedBitstream CopyAndFixBitstream(rtc::ArrayView<const uint8_t> bitstream, |
| + RTPVideoHeader* video_header); |
| + |
| + void InsertVpsSpsPpsNalus(const std::vector<uint8_t>& vps, |
| + const std::vector<uint8_t>& sps, |
| + const std::vector<uint8_t>& pps); |
| + |
| + private: |
| + struct VpsInfo { |
| + size_t size = 0; |
| + std::unique_ptr<uint8_t[]> data; |
| + }; |
| + |
| + struct PpsInfo { |
| + int sps_id = -1; |
| + size_t size = 0; |
| + std::unique_ptr<uint8_t[]> data; |
| + }; |
| + |
| + struct SpsInfo { |
| + int vps_id = -1; |
| + size_t size = 0; |
| + int width = -1; |
| + int height = -1; |
| + std::unique_ptr<uint8_t[]> data; |
| + }; |
| + |
| + std::map<uint32_t, VpsInfo> vps_data_; |
| + std::map<uint32_t, PpsInfo> pps_data_; |
| + std::map<uint32_t, SpsInfo> sps_data_; |
| +}; |
| + |
| +} // namespace video_coding |
| +} // namespace webrtc |
| + |
| +#endif // MODULES_VIDEO_CODING_H264_SPS_PPS_TRACKER_H_ |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/video_coding/include/video_codec_interface.h b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/video_coding/include/video_codec_interface.h |
| index c7b116f4ae3f..6a0f49cd2cf9 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/video_coding/include/video_codec_interface.h |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/video_coding/include/video_codec_interface.h |
| @@ -20,6 +20,7 @@ |
| #include "common_video/generic_frame_descriptor/generic_frame_info.h" |
| #include "modules/include/module_common_types.h" |
| #include "modules/video_coding/codecs/h264/include/h264_globals.h" |
| +#include "modules/video_coding/codecs/h265/include/h265_globals.h" |
| #include "modules/video_coding/codecs/vp9/include/vp9_globals.h" |
| #include "modules/video_coding/include/video_error_codes.h" |
| #include "rtc_base/system/rtc_export.h" |
| @@ -92,10 +93,20 @@ struct CodecSpecificInfoH264 { |
| }; |
| static_assert(std::is_pod<CodecSpecificInfoH264>::value, ""); |
| |
| +#ifndef DISABLE_H265 |
| +struct CodecSpecificInfoH265 { |
| + H265PacketizationMode packetization_mode; |
| + bool idr_frame; |
| +}; |
| +#endif |
| + |
| union CodecSpecificInfoUnion { |
| CodecSpecificInfoVP8 VP8; |
| CodecSpecificInfoVP9 VP9; |
| CodecSpecificInfoH264 H264; |
| +#ifndef DISABLE_H265 |
| + CodecSpecificInfoH265 H265; |
| +#endif |
| }; |
| static_assert(std::is_pod<CodecSpecificInfoUnion>::value, ""); |
| |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/p2p/base/tcp_port.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/p2p/base/tcp_port.cc |
| index efbf62e49602..1458f8c11008 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/p2p/base/tcp_port.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/p2p/base/tcp_port.cc |
| @@ -364,7 +364,11 @@ TCPConnection::TCPConnection(TCPPort* port, |
| RTC_LOG(LS_VERBOSE) << ToString() << ": socket ipaddr: " |
| << socket_->GetLocalAddress().ToSensitiveString() |
| << ", port() Network:" << port->Network()->ToString(); |
| +#if defined(WEBRTC_WEBKIT_BUILD) |
| + RTC_DCHECK(socket->GetLocalAddress().IsLoopbackIP() || absl::c_any_of( |
| +#else |
| RTC_DCHECK(absl::c_any_of( |
| +#endif |
| port_->Network()->GetIPs(), [this](const rtc::InterfaceAddress& addr) { |
| return socket_->GetLocalAddress().ipaddr() == addr; |
| })); |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/pc/peer_connection_factory.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/pc/peer_connection_factory.cc |
| index 3565c52390a4..37acd5c73fef 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/pc/peer_connection_factory.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/pc/peer_connection_factory.cc |
| @@ -192,7 +192,7 @@ RtpCapabilities PeerConnectionFactory::GetRtpSenderCapabilities( |
| return RtpCapabilities(); |
| } |
| // Not reached; avoids compile warning. |
| - FATAL(); |
| + RTC_FATAL(); |
| } |
| |
| RtpCapabilities PeerConnectionFactory::GetRtpReceiverCapabilities( |
| @@ -217,7 +217,7 @@ RtpCapabilities PeerConnectionFactory::GetRtpReceiverCapabilities( |
| return RtpCapabilities(); |
| } |
| // Not reached; avoids compile warning. |
| - FATAL(); |
| + RTC_FATAL(); |
| } |
| |
| rtc::scoped_refptr<AudioSourceInterface> |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/pc/rtp_parameters_conversion.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/pc/rtp_parameters_conversion.cc |
| index 9c7a337ab416..c4b45607b7db 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/pc/rtp_parameters_conversion.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/pc/rtp_parameters_conversion.cc |
| @@ -77,7 +77,7 @@ RTCErrorOr<cricket::FeedbackParam> ToCricketFeedbackParam( |
| return cricket::FeedbackParam(cricket::kRtcpFbParamTransportCc); |
| } |
| // Not reached; avoids compile warning. |
| - FATAL(); |
| + RTC_FATAL(); |
| } |
| |
| template <typename C> |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/checks.h b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/checks.h |
| index 61c074ac8228..90cef74f07f3 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/checks.h |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/checks.h |
| @@ -95,7 +95,7 @@ RTC_NORETURN void rtc_FatalMessage(const char* file, int line, const char* msg); |
| // messages if the condition doesn't hold. Prefer them to raw RTC_CHECK and |
| // RTC_DCHECK. |
| // |
| -// - FATAL() aborts unconditionally. |
| +// - RTC_FATAL() aborts unconditionally. |
| |
| namespace rtc { |
| namespace webrtc_checks_impl { |
| @@ -431,9 +431,9 @@ class FatalLogCall final { |
| #define RTC_NOTREACHED() RTC_DCHECK(RTC_UNREACHABLE_CODE_HIT) |
| |
| // TODO(bugs.webrtc.org/8454): Add an RTC_ prefix or rename differently. |
| -#define FATAL() \ |
| +#define RTC_FATAL() \ |
| ::rtc::webrtc_checks_impl::FatalLogCall<false>(__FILE__, __LINE__, \ |
| - "FATAL()") & \ |
| + "RTC_FATAL()") & \ |
| ::rtc::webrtc_checks_impl::LogStreamer<>() |
| |
| // Performs the integer division a/b and returns the result. CHECKs that the |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/experiments/min_video_bitrate_experiment.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/experiments/min_video_bitrate_experiment.cc |
| index 11450d084921..be654e8c123d 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/experiments/min_video_bitrate_experiment.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/experiments/min_video_bitrate_experiment.cc |
| @@ -99,6 +99,9 @@ absl::optional<DataRate> GetExperimentalMinVideoBitrate(VideoCodecType type) { |
| case kVideoCodecAV1: |
| return min_bitrate_av1.GetOptional(); |
| case kVideoCodecH264: |
| +#ifndef DISABLE_H265 |
| + case kVideoCodecH265: |
| +#endif |
| return min_bitrate_h264.GetOptional(); |
| case kVideoCodecGeneric: |
| case kVideoCodecMultiplex: |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/logging.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/logging.cc |
| index 13a5f025975a..bc700086fb17 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/logging.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/logging.cc |
| @@ -44,6 +44,7 @@ static const int kMaxLogLineSize = 1024 - 60; |
| #include "absl/base/attributes.h" |
| #include "rtc_base/checks.h" |
| #include "rtc_base/platform_thread_types.h" |
| +#include "rtc_base/never_destroyed.h" |
| #include "rtc_base/string_encode.h" |
| #include "rtc_base/string_utils.h" |
| #include "rtc_base/strings/string_builder.h" |
| @@ -75,7 +76,13 @@ const char* FilenameFromPath(const char* file) { |
| // Global lock for log subsystem, only needed to serialize access to streams_. |
| // TODO(bugs.webrtc.org/11665): this is not currently constant initialized and |
| // trivially destructible. |
| -webrtc::Mutex g_log_mutex_; |
| +webrtc::Mutex& logMutex() { |
| + static auto mutex = NeverDestroyed<webrtc::Mutex>(); |
| + return mutex.get(); |
| +} |
| + |
| +static LogMessage::LogOutputCallback g_log_output_callback = nullptr; |
| + |
| } // namespace |
| |
| ///////////////////////////////////////////////////////////////////////////// |
| @@ -88,7 +95,7 @@ bool LogMessage::log_to_stderr_ = true; |
| // Note: we explicitly do not clean this up, because of the uncertain ordering |
| // of destructors at program exit. Let the person who sets the stream trigger |
| // cleanup by setting to null, or let it leak (safe at program exit). |
| -ABSL_CONST_INIT LogSink* LogMessage::streams_ RTC_GUARDED_BY(g_log_mutex_) = |
| +ABSL_CONST_INIT LogSink* LogMessage::streams_ RTC_GUARDED_BY(logMutex()) = |
| nullptr; |
| ABSL_CONST_INIT std::atomic<bool> LogMessage::streams_empty_ = {true}; |
| |
| @@ -201,7 +208,7 @@ LogMessage::~LogMessage() { |
| #endif |
| } |
| |
| - webrtc::MutexLock lock(&g_log_mutex_); |
| + webrtc::MutexLock lock(&logMutex()); |
| for (LogSink* entry = streams_; entry != nullptr; entry = entry->next_) { |
| if (severity_ >= entry->min_severity_) { |
| #if defined(WEBRTC_ANDROID) |
| @@ -230,6 +237,17 @@ int LogMessage::GetMinLogSeverity() { |
| LoggingSeverity LogMessage::GetLogToDebug() { |
| return g_dbg_sev; |
| } |
| + |
| +#if defined(WEBRTC_WEBKIT_BUILD) |
| +void LogMessage::SetLogOutput(LoggingSeverity min_sev, LogOutputCallback callback) |
| +{ |
| + g_dbg_sev = min_sev; |
| + webrtc::MutexLock lock(&logMutex()); |
| + UpdateMinLogSeverity(); |
| + g_log_output_callback = callback; |
| +} |
| +#endif |
| + |
| int64_t LogMessage::LogStartTime() { |
| static const int64_t g_start = SystemTimeMillis(); |
| return g_start; |
| @@ -250,7 +268,7 @@ void LogMessage::LogTimestamps(bool on) { |
| |
| void LogMessage::LogToDebug(LoggingSeverity min_sev) { |
| g_dbg_sev = min_sev; |
| - webrtc::MutexLock lock(&g_log_mutex_); |
| + webrtc::MutexLock lock(&logMutex()); |
| UpdateMinLogSeverity(); |
| } |
| |
| @@ -259,7 +277,7 @@ void LogMessage::SetLogToStderr(bool log_to_stderr) { |
| } |
| |
| int LogMessage::GetLogToStream(LogSink* stream) { |
| - webrtc::MutexLock lock(&g_log_mutex_); |
| + webrtc::MutexLock lock(&logMutex()); |
| LoggingSeverity sev = LS_NONE; |
| for (LogSink* entry = streams_; entry != nullptr; entry = entry->next_) { |
| if (stream == nullptr || stream == entry) { |
| @@ -270,7 +288,7 @@ int LogMessage::GetLogToStream(LogSink* stream) { |
| } |
| |
| void LogMessage::AddLogToStream(LogSink* stream, LoggingSeverity min_sev) { |
| - webrtc::MutexLock lock(&g_log_mutex_); |
| + webrtc::MutexLock lock(&logMutex()); |
| stream->min_severity_ = min_sev; |
| stream->next_ = streams_; |
| streams_ = stream; |
| @@ -279,7 +297,7 @@ void LogMessage::AddLogToStream(LogSink* stream, LoggingSeverity min_sev) { |
| } |
| |
| void LogMessage::RemoveLogToStream(LogSink* stream) { |
| - webrtc::MutexLock lock(&g_log_mutex_); |
| + webrtc::MutexLock lock(&logMutex()); |
| for (LogSink** entry = &streams_; *entry != nullptr; |
| entry = &(*entry)->next_) { |
| if (*entry == stream) { |
| @@ -341,7 +359,7 @@ void LogMessage::ConfigureLogging(const char* params) { |
| } |
| |
| void LogMessage::UpdateMinLogSeverity() |
| - RTC_EXCLUSIVE_LOCKS_REQUIRED(g_log_mutex_) { |
| + RTC_EXCLUSIVE_LOCKS_REQUIRED(logMutex()) { |
| LoggingSeverity min_sev = g_dbg_sev; |
| for (LogSink* entry = streams_; entry != nullptr; entry = entry->next_) { |
| min_sev = std::min(min_sev, entry->min_severity_); |
| @@ -435,6 +453,9 @@ void LogMessage::OutputToDebug(const std::string& str, |
| } |
| } |
| #endif // WEBRTC_ANDROID |
| + if (g_log_output_callback) { |
| + g_log_output_callback(severity, str.c_str()); |
| + } |
| if (log_to_stderr) { |
| fprintf(stderr, "%s", str.c_str()); |
| fflush(stderr); |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/logging.h b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/logging.h |
| index d2607c28b704..64c1201ec72e 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/logging.h |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/logging.h |
| @@ -460,6 +460,12 @@ class LogMessage { |
| // Debug: Debug console on Windows, otherwise stderr |
| static void LogToDebug(LoggingSeverity min_sev); |
| static LoggingSeverity GetLogToDebug(); |
| + |
| +#if defined(WEBRTC_WEBKIT_BUILD) |
| + typedef void (*LogOutputCallback)(LoggingSeverity severity, const char*); |
| + static void SetLogOutput(LoggingSeverity min_sev, LogOutputCallback); |
| +#endif |
| + |
| // Sets whether logs will be directed to stderr in debug mode. |
| static void SetLogToStderr(bool log_to_stderr); |
| // Stream: Any non-blocking stream interface. |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/never_destroyed.h b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/never_destroyed.h |
| new file mode 100644 |
| index 000000000000..fcc62e355341 |
| --- /dev/null |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/never_destroyed.h |
| @@ -0,0 +1,69 @@ |
| +/* |
| + * Copyright (C) 2018 Apple Inc. All rights reserved. |
| + * |
| + * Redistribution and use in source and binary forms, with or without |
| + * modification, are permitted provided that the following conditions |
| + * are met: |
| + * 1. Redistributions of source code must retain the above copyright |
| + * notice, this list of conditions and the following disclaimer. |
| + * 2. Redistributions in binary form must reproduce the above copyright |
| + * notice, this list of conditions and the following disclaimer in the |
| + * documentation and/or other materials provided with the distribution. |
| + * |
| + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| + * THE POSSIBILITY OF SUCH DAMAGE. |
| + */ |
| + |
| +#pragma once |
| + |
| +#include <type_traits> |
| +#include <utility> |
| + |
| +namespace rtc { |
| + |
| +template<typename T> class NeverDestroyed { |
| +public: |
| + template<typename... Args> NeverDestroyed(Args&&... args) |
| + { |
| + new (storagePointer()) T(std::forward<Args>(args)...); |
| + } |
| + |
| + NeverDestroyed(NeverDestroyed&& other) |
| + { |
| + new (storagePointer()) T(std::move(*other.storagePointer())); |
| + } |
| + |
| + operator T&() { return *storagePointer(); } |
| + T& get() { return *storagePointer(); } |
| + |
| + operator const T&() const { return *storagePointer(); } |
| + const T& get() const { return *storagePointer(); } |
| + |
| +private: |
| + NeverDestroyed(const NeverDestroyed&) = delete; |
| + NeverDestroyed& operator=(const NeverDestroyed&) = delete; |
| + |
| + using PointerType = typename std::remove_const<T>::type*; |
| + |
| + PointerType storagePointer() const { return const_cast<PointerType>(reinterpret_cast<const T*>(&m_storage)); } |
| + |
| + // FIXME: Investigate whether we should allocate a hunk of virtual memory |
| + // and hand out chunks of it to NeverDestroyed instead, to reduce fragmentation. |
| + typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type m_storage; |
| +}; |
| + |
| +template<typename T> inline NeverDestroyed<T> makeNeverDestroyed(T&& argument) |
| +{ |
| + return NeverDestroyed<T>(std::move(argument)); |
| +} |
| + |
| +} // namespace rtc |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/numerics/safe_conversions.h b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/numerics/safe_conversions.h |
| index 5d58672510cf..1fa280cf9f16 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/numerics/safe_conversions.h |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/numerics/safe_conversions.h |
| @@ -63,11 +63,11 @@ inline constexpr Dst saturated_cast(Src value) { |
| |
| // Should fail only on attempting to assign NaN to a saturated integer. |
| case internal::TYPE_INVALID: |
| - FATAL(); |
| + RTC_FATAL(); |
| return std::numeric_limits<Dst>::max(); |
| } |
| |
| - FATAL(); |
| + RTC_FATAL(); |
| return static_cast<Dst>(value); |
| } |
| |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/openssl_certificate.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/openssl_certificate.cc |
| index 9459f76df6c2..887c7b77d6a7 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/openssl_certificate.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/openssl_certificate.cc |
| @@ -245,11 +245,11 @@ std::unique_ptr<SSLCertificate> OpenSSLCertificate::Clone() const { |
| std::string OpenSSLCertificate::ToPEMString() const { |
| BIO* bio = BIO_new(BIO_s_mem()); |
| if (!bio) { |
| - FATAL() << "Unreachable code."; |
| + RTC_FATAL() << "Unreachable code."; |
| } |
| if (!PEM_write_bio_X509(bio, x509_)) { |
| BIO_free(bio); |
| - FATAL() << "Unreachable code."; |
| + RTC_FATAL() << "Unreachable code."; |
| } |
| BIO_write(bio, "\0", 1); |
| char* buffer; |
| @@ -265,11 +265,11 @@ void OpenSSLCertificate::ToDER(Buffer* der_buffer) const { |
| // Calculates the DER representation of the certificate, from scratch. |
| BIO* bio = BIO_new(BIO_s_mem()); |
| if (!bio) { |
| - FATAL() << "Unreachable code."; |
| + RTC_FATAL() << "Unreachable code."; |
| } |
| if (!i2d_X509_bio(bio, x509_)) { |
| BIO_free(bio); |
| - FATAL() << "Unreachable code."; |
| + RTC_FATAL() << "Unreachable code."; |
| } |
| char* data = nullptr; |
| size_t length = BIO_get_mem_data(bio, &data); |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/openssl_stream_adapter.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/openssl_stream_adapter.cc |
| index 0f8c1fcb1381..905bea0dc02b 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/openssl_stream_adapter.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/openssl_stream_adapter.cc |
| @@ -1000,6 +1000,10 @@ SSL_CTX* OpenSSLStreamAdapter::SetupSSLContext() { |
| break; |
| case SSL_PROTOCOL_TLS_12: |
| default: |
| +#if defined(WEBRTC_WEBKIT_BUILD) |
| + SSL_CTX_set_min_proto_version( |
| + ctx, ssl_mode_ == SSL_MODE_DTLS ? DTLS1_2_VERSION : TLS1_2_VERSION); |
| +#endif |
| SSL_CTX_set_max_proto_version( |
| ctx, ssl_mode_ == SSL_MODE_DTLS ? DTLS1_2_VERSION : TLS1_2_VERSION); |
| break; |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/physical_socket_server.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/physical_socket_server.cc |
| index cf6e79279511..1d23a35ee663 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/physical_socket_server.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/physical_socket_server.cc |
| @@ -636,6 +636,10 @@ SocketDispatcher::~SocketDispatcher() { |
| bool SocketDispatcher::Initialize() { |
| RTC_DCHECK(s_ != INVALID_SOCKET); |
| // Must be a non-blocking |
| +#if defined(WEBRTC_WEBKIT_BUILD) |
| + if (s_ < 0 || s_ >= FD_SETSIZE) |
| + return false; |
| +#endif |
| #if defined(WEBRTC_WIN) |
| u_long argp = 1; |
| ioctlsocket(s_, FIONBIO, &argp); |
| @@ -1285,6 +1289,10 @@ bool PhysicalSocketServer::WaitSelect(int cmsWait, bool process_io) { |
| // "select"ing a file descriptor that is equal to or larger than |
| // FD_SETSIZE will result in undefined behavior. |
| RTC_DCHECK_LT(fd, FD_SETSIZE); |
| +#if defined(WEBRTC_WEBKIT_BUILD) |
| + if (fd < 0 || fd >= FD_SETSIZE) |
| + continue; |
| +#endif |
| if (fd > fdmax) |
| fdmax = fd; |
| |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/string_utils.h b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/string_utils.h |
| index 23c55cb89359..3f2b1bb80f89 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/string_utils.h |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/string_utils.h |
| @@ -11,7 +11,10 @@ |
| #ifndef RTC_BASE_STRING_UTILS_H_ |
| #define RTC_BASE_STRING_UTILS_H_ |
| |
| +#if !defined(WEBRTC_WEBKIT_BUILD) |
| #include <ctype.h> |
| +#endif // !defined(WEBRTC_WEBKIT_BUILD) |
| + |
| #include <stdarg.h> |
| #include <stdio.h> |
| #include <string.h> |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/trace_event.h b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/trace_event.h |
| index a0b788fbf943..626597c22be8 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/trace_event.h |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/rtc_base/trace_event.h |
| @@ -1019,4 +1019,4 @@ class TraceEndOnScopeClose { |
| |
| #endif // RTC_TRACE_EVENTS_ENABLED |
| |
| -#endif // RTC_BASE_TRACE_EVENT_H_ |
| \ No newline at end of file |
| +#endif // RTC_BASE_TRACE_EVENT_H_ |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/WebKit/WebKitEncoder.h b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/WebKit/WebKitEncoder.h |
| index e703f628a37a..23d97ecc4ebf 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/WebKit/WebKitEncoder.h |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/WebKit/WebKitEncoder.h |
| @@ -72,29 +72,15 @@ struct WebKitEncodedFrameInfo { |
| template<class Decoder> static bool decode(Decoder&, WebKitEncodedFrameInfo&); |
| }; |
| |
| -class WebKitRTPFragmentationHeader { |
| -public: |
| - explicit WebKitRTPFragmentationHeader(webrtc::RTPFragmentationHeader* = nullptr); |
| - |
| - template<class Encoder> void encode(Encoder&) const; |
| - template<class Decoder> static bool decode(Decoder&, WebKitRTPFragmentationHeader&); |
| - |
| - webrtc::RTPFragmentationHeader* value() { return m_value; }; |
| - |
| -private: |
| - webrtc::RTPFragmentationHeader* m_value { nullptr }; |
| - std::unique_ptr<webrtc::RTPFragmentationHeader> m_ownedHeader; |
| -}; |
| - |
| using LocalEncoder = void*; |
| -using LocalEncoderCallback = void (^)(const uint8_t* buffer, size_t size, const webrtc::WebKitEncodedFrameInfo&, webrtc::RTPFragmentationHeader*); |
| +using LocalEncoderCallback = void (^)(const uint8_t* buffer, size_t size, const webrtc::WebKitEncodedFrameInfo&); |
| void* createLocalEncoder(const webrtc::SdpVideoFormat&, LocalEncoderCallback); |
| void releaseLocalEncoder(LocalEncoder); |
| void initializeLocalEncoder(LocalEncoder, uint16_t width, uint16_t height, unsigned int startBitrate, unsigned int maxBitrate, unsigned int minBitrate, uint32_t maxFramerate); |
| void encodeLocalEncoderFrame(LocalEncoder, CVPixelBufferRef, int64_t timeStampNs, uint32_t timeStamp, webrtc::VideoRotation, bool isKeyframeRequired); |
| void setLocalEncoderRates(LocalEncoder, uint32_t bitRate, uint32_t frameRate); |
| void setLocalEncoderLowLatency(LocalEncoder, bool isLowLatencyEnabled); |
| -void encoderVideoTaskComplete(void*, webrtc::VideoCodecType, uint8_t* buffer, size_t length, const WebKitEncodedFrameInfo&, const webrtc::RTPFragmentationHeader*); |
| +void encoderVideoTaskComplete(void*, webrtc::VideoCodecType, uint8_t* buffer, size_t length, const WebKitEncodedFrameInfo&); |
| |
| template<class Decoder> |
| bool WebKitEncodedFrameInfo::decode(Decoder& decoder, WebKitEncodedFrameInfo& info) |
| @@ -167,58 +153,4 @@ void WebKitEncodedFrameInfo::encode(Encoder& encoder) const |
| encoder << timing.receive_finish_ms; |
| } |
| |
| -inline WebKitRTPFragmentationHeader::WebKitRTPFragmentationHeader(webrtc::RTPFragmentationHeader* header) |
| - : m_value(header) |
| -{ |
| -} |
| - |
| -template<class Encoder> |
| -void WebKitRTPFragmentationHeader::encode(Encoder& encoder) const |
| -{ |
| - encoder << !!m_value; |
| - if (!m_value) |
| - return; |
| - |
| - encoder << static_cast<unsigned>(m_value->Size()); |
| - for (unsigned i = 0; i < m_value->Size(); ++i) { |
| - encoder << static_cast<unsigned>(m_value->Offset(i)); |
| - encoder << static_cast<unsigned>(m_value->Length(i)); |
| - } |
| -} |
| - |
| -template<class Decoder> |
| -bool WebKitRTPFragmentationHeader::decode(Decoder& decoder, WebKitRTPFragmentationHeader& header) |
| -{ |
| - bool hasValue; |
| - if (!decoder.decode(hasValue)) |
| - return false; |
| - |
| - if (!hasValue) { |
| - header.m_value = nullptr; |
| - return true; |
| - } |
| - |
| - unsigned size; |
| - if (!decoder.decode(size)) |
| - return false; |
| - |
| - auto ownedHeader = std::make_unique<webrtc::RTPFragmentationHeader>(); |
| - ownedHeader->VerifyAndAllocateFragmentationHeader(size); |
| - for (size_t i = 0; i < size; ++i) { |
| - unsigned offset, length; |
| - if (!decoder.decode(offset)) |
| - return false; |
| - if (!decoder.decode(length)) |
| - return false; |
| - |
| - ownedHeader->fragmentationOffset[i] = offset; |
| - ownedHeader->fragmentationLength[i] = length; |
| - } |
| - |
| - header.m_ownedHeader = std::move(ownedHeader); |
| - header.m_value = header.m_ownedHeader.get(); |
| - |
| - return true; |
| -} |
| - |
| } |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/WebKit/WebKitEncoder.mm b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/WebKit/WebKitEncoder.mm |
| index d9cf7a5de9af..d7951c6121d6 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/WebKit/WebKitEncoder.mm |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/WebKit/WebKitEncoder.mm |
| @@ -31,7 +31,6 @@ |
| #include "media/engine/encoder_simulcast_proxy.h" |
| #include "modules/video_coding/utility/simulcast_utility.h" |
| #include "sdk/objc/api/peerconnection/RTCEncodedImage+Private.h" |
| -#include "sdk/objc/api/peerconnection/RTCRtpFragmentationHeader+Private.h" |
| #include "sdk/objc/api/peerconnection/RTCVideoCodecInfo+Private.h" |
| #include "sdk/objc/api/peerconnection/RTCVideoEncoderSettings+Private.h" |
| #include "sdk/objc/components/video_codec/RTCDefaultVideoEncoderFactory.h" |
| @@ -291,7 +290,7 @@ int32_t RemoteVideoEncoder::RegisterEncodeCompleteCallback(EncodedImageCallback* |
| return videoEncoderCallbacks().registerEncodeCompleteCallback(m_internalEncoder, callback); |
| } |
| |
| -void encoderVideoTaskComplete(void* callback, webrtc::VideoCodecType codecType, uint8_t* buffer, size_t length, const WebKitEncodedFrameInfo& info, const webrtc::RTPFragmentationHeader* header) |
| +void encoderVideoTaskComplete(void* callback, webrtc::VideoCodecType codecType, uint8_t* buffer, size_t length, const WebKitEncodedFrameInfo& info) |
| { |
| webrtc::EncodedImage encodedImage(buffer, length, length); |
| encodedImage._encodedWidth = info.width; |
| @@ -313,7 +312,7 @@ void encoderVideoTaskComplete(void* callback, webrtc::VideoCodecType codecType, |
| else if (codecType == kVideoCodecH265) |
| codecSpecificInfo.codecSpecific.H265.packetization_mode = H265PacketizationMode::NonInterleaved; |
| |
| - static_cast<EncodedImageCallback*>(callback)->OnEncodedImage(encodedImage, &codecSpecificInfo, header); |
| + static_cast<EncodedImageCallback*>(callback)->OnEncodedImage(encodedImage, &codecSpecificInfo); |
| } |
| |
| void* createLocalEncoder(const webrtc::SdpVideoFormat& format, LocalEncoderCallback callback) |
| @@ -321,7 +320,7 @@ void* createLocalEncoder(const webrtc::SdpVideoFormat& format, LocalEncoderCallb |
| auto *codecInfo = [[RTCVideoCodecInfo alloc] initWithNativeSdpVideoFormat: format]; |
| auto *encoder = [[WK_RTCLocalVideoH264H265Encoder alloc] initWithCodecInfo:codecInfo]; |
| |
| - [encoder setCallback:^BOOL(RTCEncodedImage *_Nonnull frame, id<RTCCodecSpecificInfo> _Nonnull codecSpecificInfo, RTCRtpFragmentationHeader *_Nonnull header) { |
| + [encoder setCallback:^BOOL(RTCEncodedImage *_Nonnull frame, id<RTCCodecSpecificInfo> _Nonnull codecSpecificInfo, RTCRtpFragmentationHeader * _Nullable header) { |
| EncodedImage encodedImage = [frame nativeEncodedImage]; |
| |
| WebKitEncodedFrameInfo info; |
| @@ -337,7 +336,7 @@ void* createLocalEncoder(const webrtc::SdpVideoFormat& format, LocalEncoderCallb |
| info.qp = encodedImage.qp_; |
| info.timing = encodedImage.timing_; |
| |
| - callback(encodedImage.data(), encodedImage.size(), info, [header createNativeFragmentationHeader].get()); |
| + callback(encodedImage.data(), encodedImage.size(), info); |
| return YES; |
| }]; |
| |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodec+Private.h b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodec+Private.h |
| index 3233e4e9f2be..edeb8ad4b9fa 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodec+Private.h |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodec+Private.h |
| @@ -9,7 +9,7 @@ |
| */ |
| |
| #import "api/peerconnection/RTCEncodedImage+Private.h" |
| -#import "api/peerconnection/RTCRtpFragmentationHeader+Private.h" |
| +//#import "api/peerconnection/RTCRtpFragmentationHeader+Private.h" |
| #import "api/peerconnection/RTCVideoCodecInfo+Private.h" |
| #import "api/peerconnection/RTCVideoEncoderSettings+Private.h" |
| #import "components/video_codec/RTCCodecSpecificInfoH264+Private.h" |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/base/RTCVideoEncoder.h b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/base/RTCVideoEncoder.h |
| index c5257674d834..398e57c11cd7 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/base/RTCVideoEncoder.h |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/base/RTCVideoEncoder.h |
| @@ -23,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN |
| /** Callback block for encoder. */ |
| typedef BOOL (^RTCVideoEncoderCallback)(RTCEncodedImage *frame, |
| id<RTCCodecSpecificInfo> info, |
| - RTCRtpFragmentationHeader *header); |
| + RTCRtpFragmentationHeader* __nullable header); |
| |
| /** Protocol for encoder implementations. */ |
| RTC_OBJC_EXPORT |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCDefaultVideoDecoderFactory.m b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCDefaultVideoDecoderFactory.m |
| index 0437e6a34b3d..1e5aac8d240c 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCDefaultVideoDecoderFactory.m |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCDefaultVideoDecoderFactory.m |
| @@ -46,37 +46,39 @@ - (id)initWithH265:(bool)supportsH265 vp9:(bool)supportsVP9 vp9VTB:(bool)support |
| } |
| |
| - (NSArray<RTCVideoCodecInfo *> *)supportedCodecs { |
| - NSDictionary<NSString *, NSString *> *constrainedHighParams = @{ |
| + NSMutableArray<RTCVideoCodecInfo *> *codecs = [[NSMutableArray alloc] initWithCapacity:5]; |
| + |
| + [codecs addObject: [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecH264Name parameters: @{ |
| @"profile-level-id" : kRTCMaxSupportedH264ProfileLevelConstrainedHigh, |
| @"level-asymmetry-allowed" : @"1", |
| @"packetization-mode" : @"1", |
| - }; |
| - RTCVideoCodecInfo *constrainedHighInfo = |
| - [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecH264Name |
| - parameters:constrainedHighParams]; |
| - |
| - NSDictionary<NSString *, NSString *> *constrainedBaselineParams = @{ |
| + }]]; |
| + [codecs addObject: [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecH264Name parameters: @{ |
| @"profile-level-id" : kRTCMaxSupportedH264ProfileLevelConstrainedBaseline, |
| @"level-asymmetry-allowed" : @"1", |
| @"packetization-mode" : @"1", |
| - }; |
| - RTCVideoCodecInfo *constrainedBaselineInfo = |
| - [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecH264Name |
| - parameters:constrainedBaselineParams]; |
| - |
| - RTCVideoCodecInfo *vp8Info = [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecVp8Name]; |
| - |
| - NSMutableArray<RTCVideoCodecInfo *> *codecs = [[NSMutableArray alloc] initWithCapacity:5]; |
| + }]]; |
| + [codecs addObject: [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecH264Name parameters: @{ |
| + @"profile-level-id" : kRTCMaxSupportedH264ProfileLevelConstrainedHigh, |
| + @"level-asymmetry-allowed" : @"1", |
| + @"packetization-mode" : @"0", |
| + }]]; |
| + [codecs addObject: [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecH264Name parameters: @{ |
| + @"profile-level-id" : kRTCMaxSupportedH264ProfileLevelConstrainedBaseline, |
| + @"level-asymmetry-allowed" : @"1", |
| + @"packetization-mode" : @"0", |
| + }]]; |
| |
| - [codecs addObject:constrainedHighInfo]; |
| - [codecs addObject:constrainedBaselineInfo]; |
| #if !defined(RTC_DISABLE_H265) |
| if (_supportsH265) { |
| RTCVideoCodecInfo *h265Info = [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecH265Name]; |
| [codecs addObject:h265Info]; |
| } |
| #endif |
| + |
| + RTCVideoCodecInfo *vp8Info = [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecVp8Name]; |
| [codecs addObject:vp8Info]; |
| + |
| #if defined(RTC_ENABLE_VP9) |
| if (_supportsVP9) { |
| [codecs addObject:[[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecVp9Name parameters: @{ |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCDefaultVideoEncoderFactory.m b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCDefaultVideoEncoderFactory.m |
| index f01447045053..ed3ced3fb0b2 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCDefaultVideoEncoderFactory.m |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCDefaultVideoEncoderFactory.m |
| @@ -45,28 +45,30 @@ - (id)initWithH265:(bool)supportsH265 vp9:(bool)supportsVP9 lowLatencyH264:(bool |
| } |
| |
| + (NSArray<RTCVideoCodecInfo *> *)supportedCodecsWithH265:(bool)supportsH265 vp9:(bool)supportsVP9 { |
| - NSDictionary<NSString *, NSString *> *constrainedHighParams = @{ |
| + |
| + NSMutableArray<RTCVideoCodecInfo *> *codecs = [[NSMutableArray alloc] initWithCapacity:8]; |
| + |
| + [codecs addObject: [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecH264Name parameters: @{ |
| @"profile-level-id" : kRTCMaxSupportedH264ProfileLevelConstrainedHigh, |
| @"level-asymmetry-allowed" : @"1", |
| @"packetization-mode" : @"1", |
| - }; |
| - RTCVideoCodecInfo *constrainedHighInfo = |
| - [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecH264Name |
| - parameters:constrainedHighParams]; |
| - |
| - NSDictionary<NSString *, NSString *> *constrainedBaselineParams = @{ |
| + }]]; |
| + [codecs addObject: [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecH264Name parameters: @{ |
| @"profile-level-id" : kRTCMaxSupportedH264ProfileLevelConstrainedBaseline, |
| @"level-asymmetry-allowed" : @"1", |
| @"packetization-mode" : @"1", |
| - }; |
| - RTCVideoCodecInfo *constrainedBaselineInfo = |
| - [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecH264Name |
| - parameters:constrainedBaselineParams]; |
| - |
| - NSMutableArray<RTCVideoCodecInfo *> *codecs = [[NSMutableArray alloc] initWithCapacity:5]; |
| + }]]; |
| + [codecs addObject: [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecH264Name parameters: @{ |
| + @"profile-level-id" : kRTCMaxSupportedH264ProfileLevelConstrainedHigh, |
| + @"level-asymmetry-allowed" : @"1", |
| + @"packetization-mode" : @"0", |
| + }]]; |
| + [codecs addObject: [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecH264Name parameters: @{ |
| + @"profile-level-id" : kRTCMaxSupportedH264ProfileLevelConstrainedBaseline, |
| + @"level-asymmetry-allowed" : @"1", |
| + @"packetization-mode" : @"0", |
| + }]]; |
| |
| - [codecs addObject:constrainedHighInfo]; |
| - [codecs addObject:constrainedBaselineInfo]; |
| #if !defined(RTC_DISABLE_H265) |
| if (supportsH265) { |
| RTCVideoCodecInfo *h265Info = [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecH265Name]; |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCVideoEncoderH264.mm b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCVideoEncoderH264.mm |
| index 57bedb7f29bd..551318f76d4e 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCVideoEncoderH264.mm |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCVideoEncoderH264.mm |
| @@ -19,7 +19,6 @@ |
| #endif |
| #import "RTCCodecSpecificInfoH264.h" |
| #import "RTCH264ProfileLevelId.h" |
| -#import "api/peerconnection/RTCRtpFragmentationHeader+Private.h" |
| #import "api/peerconnection/RTCVideoCodecInfo+Private.h" |
| #import "base/RTCCodecSpecificInfo.h" |
| #import "base/RTCI420Buffer.h" |
| @@ -997,15 +996,8 @@ NSUInteger GetMaxSampleRate(const webrtc::H264::ProfileLevelId &profile_level_id |
| } |
| |
| __block std::unique_ptr<rtc::Buffer> buffer = std::make_unique<rtc::Buffer>(); |
| - RTCRtpFragmentationHeader *header; |
| - { |
| - std::unique_ptr<webrtc::RTPFragmentationHeader> header_cpp; |
| - bool result = |
| - H264CMSampleBufferToAnnexBBuffer(sampleBuffer, isKeyframe, buffer.get(), &header_cpp); |
| - header = [[RTCRtpFragmentationHeader alloc] initWithNativeFragmentationHeader:header_cpp.get()]; |
| - if (!result) { |
| - return; |
| - } |
| + if (!webrtc::H264CMSampleBufferToAnnexBBuffer(sampleBuffer, isKeyframe, buffer.get())) { |
| + return; |
| } |
| |
| RTCEncodedImage *frame = [[RTCEncodedImage alloc] init]; |
| @@ -1031,7 +1023,7 @@ NSUInteger GetMaxSampleRate(const webrtc::H264::ProfileLevelId &profile_level_id |
| _h264BitstreamParser.GetLastSliceQp(&qp); |
| frame.qp = @(qp); |
| |
| - BOOL res = _callback(frame, codecSpecificInfo, header); |
| + BOOL res = _callback(frame, codecSpecificInfo, nullptr); |
| if (!res) { |
| RTC_LOG(LS_ERROR) << "Encode callback failed"; |
| if (isKeyFrameRequired) |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCVideoEncoderH265.mm b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCVideoEncoderH265.mm |
| index 457c57077ac7..655fbd0f4c1c 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCVideoEncoderH265.mm |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCVideoEncoderH265.mm |
| @@ -15,7 +15,7 @@ |
| #include <vector> |
| |
| #import "RTCCodecSpecificInfoH265.h" |
| -#import "api/peerconnection/RTCRtpFragmentationHeader+Private.h" |
| +//#import "api/peerconnection/RTCRtpFragmentationHeader+Private.h" |
| #import "api/peerconnection/RTCVideoCodecInfo+Private.h" |
| #import "base/RTCI420Buffer.h" |
| #import "base/RTCVideoFrame.h" |
| @@ -540,20 +540,9 @@ void compressionOutputCallback(void* encoder, |
| RTC_LOG(LS_INFO) << "Generated keyframe"; |
| } |
| |
| - // Convert the sample buffer into a buffer suitable for RTP packetization. |
| - // TODO(tkchin): Allocate buffers through a pool. |
| std::unique_ptr<rtc::Buffer> buffer(new rtc::Buffer()); |
| - RTCRtpFragmentationHeader* header; |
| - { |
| - std::unique_ptr<webrtc::RTPFragmentationHeader> header_cpp; |
| - bool result = H265CMSampleBufferToAnnexBBuffer(sampleBuffer, isKeyframe, |
| - buffer.get(), &header_cpp); |
| - header = [[RTCRtpFragmentationHeader alloc] |
| - initWithNativeFragmentationHeader:header_cpp.get()]; |
| - if (!result) { |
| - RTC_LOG(LS_ERROR) << "Failed to convert sample buffer."; |
| - return; |
| - } |
| + if (!webrtc::H265CMSampleBufferToAnnexBBuffer(sampleBuffer, isKeyframe, buffer.get())) { |
| + RTC_LOG(LS_INFO) << "Unable to parse H265 encoded buffer"; |
| } |
| |
| RTCEncodedImage* frame = [[RTCEncodedImage alloc] init]; |
| @@ -575,7 +564,7 @@ void compressionOutputCallback(void* encoder, |
| |
| // FIXME: QP is ignored because there is no H.265 bitstream parser. |
| |
| - BOOL res = _callback(frame, [[RTCCodecSpecificInfoH265 alloc] init], header); |
| + BOOL res = _callback(frame, [[RTCCodecSpecificInfoH265 alloc] init], nullptr); |
| if (!res) { |
| RTC_LOG(LS_ERROR) << "Encode callback failed."; |
| return; |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/nalu_rewriter.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/nalu_rewriter.cc |
| index ddf734605115..a2822b583c6b 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/nalu_rewriter.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/nalu_rewriter.cc |
| @@ -29,14 +29,10 @@ using H264::ParseNaluType; |
| const char kAnnexBHeaderBytes[4] = {0, 0, 0, 1}; |
| const size_t kAvccHeaderByteSize = sizeof(uint32_t); |
| |
| -bool H264CMSampleBufferToAnnexBBuffer( |
| - CMSampleBufferRef avcc_sample_buffer, |
| - bool is_keyframe, |
| - rtc::Buffer* annexb_buffer, |
| - std::unique_ptr<RTPFragmentationHeader>* out_header) { |
| +bool H264CMSampleBufferToAnnexBBuffer(CMSampleBufferRef avcc_sample_buffer, |
| + bool is_keyframe, |
| + rtc::Buffer* annexb_buffer) { |
| RTC_DCHECK(avcc_sample_buffer); |
| - RTC_DCHECK(out_header); |
| - out_header->reset(nullptr); |
| |
| // Get format description from the sample buffer. |
| CMVideoFormatDescriptionRef description = |
| @@ -61,10 +57,6 @@ bool H264CMSampleBufferToAnnexBBuffer( |
| // Truncate any previous data in the buffer without changing its capacity. |
| annexb_buffer->SetSize(0); |
| |
| - size_t nalu_offset = 0; |
| - std::vector<size_t> frag_offsets; |
| - std::vector<size_t> frag_lengths; |
| - |
| // Place all parameter sets at the front of buffer. |
| if (is_keyframe) { |
| size_t param_set_size = 0; |
| @@ -80,10 +72,6 @@ bool H264CMSampleBufferToAnnexBBuffer( |
| annexb_buffer->AppendData(kAnnexBHeaderBytes, sizeof(kAnnexBHeaderBytes)); |
| annexb_buffer->AppendData(reinterpret_cast<const char*>(param_set), |
| param_set_size); |
| - // Update fragmentation. |
| - frag_offsets.push_back(nalu_offset + sizeof(kAnnexBHeaderBytes)); |
| - frag_lengths.push_back(param_set_size); |
| - nalu_offset += sizeof(kAnnexBHeaderBytes) + param_set_size; |
| } |
| } |
| |
| @@ -132,10 +120,6 @@ bool H264CMSampleBufferToAnnexBBuffer( |
| // Update buffer. |
| annexb_buffer->AppendData(kAnnexBHeaderBytes, sizeof(kAnnexBHeaderBytes)); |
| annexb_buffer->AppendData(data_ptr + nalu_header_size, packet_size); |
| - // Update fragmentation. |
| - frag_offsets.push_back(nalu_offset + sizeof(kAnnexBHeaderBytes)); |
| - frag_lengths.push_back(packet_size); |
| - nalu_offset += sizeof(kAnnexBHeaderBytes) + packet_size; |
| |
| size_t bytes_written = packet_size + sizeof(kAnnexBHeaderBytes); |
| bytes_remaining -= bytes_written; |
| @@ -143,14 +127,6 @@ bool H264CMSampleBufferToAnnexBBuffer( |
| } |
| RTC_DCHECK_EQ(bytes_remaining, (size_t)0); |
| |
| - std::unique_ptr<RTPFragmentationHeader> header(new RTPFragmentationHeader()); |
| - header->VerifyAndAllocateFragmentationHeader(frag_offsets.size()); |
| - RTC_DCHECK_EQ(frag_lengths.size(), frag_offsets.size()); |
| - for (size_t i = 0; i < frag_offsets.size(); ++i) { |
| - header->fragmentationOffset[i] = frag_offsets[i]; |
| - header->fragmentationLength[i] = frag_lengths[i]; |
| - } |
| - *out_header = std::move(header); |
| CFRelease(contiguous_buffer); |
| return true; |
| } |
| @@ -252,11 +228,8 @@ bool H264AnnexBBufferToCMSampleBuffer(const uint8_t* annexb_buffer, |
| bool H265CMSampleBufferToAnnexBBuffer( |
| CMSampleBufferRef hvcc_sample_buffer, |
| bool is_keyframe, |
| - rtc::Buffer* annexb_buffer, |
| - std::unique_ptr<RTPFragmentationHeader> *out_header) { |
| + rtc::Buffer* annexb_buffer) { |
| RTC_DCHECK(hvcc_sample_buffer); |
| - RTC_DCHECK(out_header); |
| - out_header->reset(nullptr); |
| |
| // Get format description from the sample buffer. |
| CMVideoFormatDescriptionRef description = |
| @@ -363,15 +336,8 @@ bool H265CMSampleBufferToAnnexBBuffer( |
| } |
| RTC_DCHECK_EQ(bytes_remaining, (size_t)0); |
| |
| - std::unique_ptr<RTPFragmentationHeader> header(new RTPFragmentationHeader()); |
| - header->VerifyAndAllocateFragmentationHeader(frag_offsets.size()); |
| - RTC_DCHECK_EQ(frag_lengths.size(), frag_offsets.size()); |
| - for (size_t i = 0; i < frag_offsets.size(); ++i) { |
| - header->fragmentationOffset[i] = frag_offsets[i]; |
| - header->fragmentationLength[i] = frag_lengths[i]; |
| - } |
| - *out_header = std::move(header); |
| CFRelease(contiguous_buffer); |
| + |
| return true; |
| } |
| |
| @@ -384,7 +350,7 @@ bool H265AnnexBBufferToCMSampleBuffer(const uint8_t* annexb_buffer, |
| RTC_DCHECK(video_format); |
| *out_sample_buffer = nullptr; |
| |
| - AnnexBBufferReader reader(annexb_buffer, annexb_buffer_size); |
| + AnnexBBufferReader reader(annexb_buffer, annexb_buffer_size, false); |
| if (reader.SeekToNextNaluOfType(H265::kVps)) { |
| // Buffer contains an SPS NALU - skip it and the following PPS |
| const uint8_t* data; |
| @@ -507,7 +473,7 @@ CMVideoFormatDescriptionRef CreateH265VideoFormatDescription( |
| size_t annexb_buffer_size) { |
| const uint8_t* param_set_ptrs[3] = {}; |
| size_t param_set_sizes[3] = {}; |
| - AnnexBBufferReader reader(annexb_buffer, annexb_buffer_size); |
| + AnnexBBufferReader reader(annexb_buffer, annexb_buffer_size, false); |
| // Skip everyting before the VPS, then read the VPS, SPS and PPS |
| if (!reader.SeekToNextNaluOfType(H265::kVps)) { |
| return nullptr; |
| @@ -539,10 +505,11 @@ CMVideoFormatDescriptionRef CreateH265VideoFormatDescription( |
| #endif |
| |
| AnnexBBufferReader::AnnexBBufferReader(const uint8_t* annexb_buffer, |
| - size_t length) |
| + size_t length, bool isH264) |
| : start_(annexb_buffer), length_(length) { |
| RTC_DCHECK(annexb_buffer); |
| - offsets_ = H264::FindNaluIndices(annexb_buffer, length); |
| + |
| + offsets_ = isH264 ? H264::FindNaluIndices(annexb_buffer, length) : H265::FindNaluIndices(annexb_buffer, length); |
| offset_ = offsets_.begin(); |
| } |
| |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/nalu_rewriter.h b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/nalu_rewriter.h |
| index 4da1cc57c7d1..2ed560f98615 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/nalu_rewriter.h |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/nalu_rewriter.h |
| @@ -18,10 +18,7 @@ |
| #include <vector> |
| |
| #include "common_video/h264/h264_common.h" |
| -#ifndef DISABLE_H265 |
| #include "common_video/h265/h265_common.h" |
| -#endif |
| -#include "modules/include/module_common_types.h" |
| #include "rtc_base/buffer.h" |
| |
| using webrtc::H264::NaluIndex; |
| @@ -30,13 +27,10 @@ namespace webrtc { |
| |
| // Converts a sample buffer emitted from the VideoToolbox encoder into a buffer |
| // suitable for RTP. The sample buffer is in avcc format whereas the rtp buffer |
| -// needs to be in Annex B format. Data is written directly to |annexb_buffer| |
| -// and a new RTPFragmentationHeader is returned in |out_header|. |
| -bool H264CMSampleBufferToAnnexBBuffer( |
| - CMSampleBufferRef avcc_sample_buffer, |
| - bool is_keyframe, |
| - rtc::Buffer* annexb_buffer, |
| - std::unique_ptr<RTPFragmentationHeader>* out_header); |
| +// needs to be in Annex B format. Data is written directly to |annexb_buffer|. |
| +bool H264CMSampleBufferToAnnexBBuffer(CMSampleBufferRef avcc_sample_buffer, |
| + bool is_keyframe, |
| + rtc::Buffer* annexb_buffer); |
| |
| // Converts a buffer received from RTP into a sample buffer suitable for the |
| // VideoToolbox decoder. The RTP buffer is in annex b format whereas the sample |
| @@ -52,17 +46,13 @@ bool H264AnnexBBufferToCMSampleBuffer(const uint8_t* annexb_buffer, |
| |
| #ifndef DISABLE_H265 |
| // Converts a sample buffer emitted from the VideoToolbox encoder into a buffer |
| -// suitable for RTP. The sample buffer is in hvcc format whereas the rtp buffer |
| -// needs to be in Annex B format. Data is written directly to |annexb_buffer| |
| -// and a new RTPFragmentationHeader is returned in |out_header|. |
| -bool H265CMSampleBufferToAnnexBBuffer( |
| - CMSampleBufferRef hvcc_sample_buffer, |
| - bool is_keyframe, |
| - rtc::Buffer* annexb_buffer, |
| - std::unique_ptr<RTPFragmentationHeader> *out_header) |
| - __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_11_0); |
| +// suitable for RTP. The sample buffer is in avcc format whereas the rtp buffer |
| +// needs to be in Annex B format. Data is written directly to |annexb_buffer|. |
| +bool H265CMSampleBufferToAnnexBBuffer(CMSampleBufferRef avcc_sample_buffer, |
| + bool is_keyframe, |
| + rtc::Buffer* annexb_buffer); |
| |
| - // Converts a buffer received from RTP into a sample buffer suitable for the |
| +// Converts a buffer received from RTP into a sample buffer suitable for the |
| // VideoToolbox decoder. The RTP buffer is in annex b format whereas the sample |
| // buffer is in hvcc format. |
| // If |is_keyframe| is true then |video_format| is ignored since the format will |
| @@ -73,6 +63,10 @@ bool H265AnnexBBufferToCMSampleBuffer(const uint8_t* annexb_buffer, |
| CMVideoFormatDescriptionRef video_format, |
| CMSampleBufferRef* out_sample_buffer) |
| __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_11_0); |
| + |
| +CMVideoFormatDescriptionRef CreateH265VideoFormatDescription( |
| + const uint8_t* annexb_buffer, |
| + size_t annexb_buffer_size); |
| #endif |
| |
| // Returns a video format description created from the sps/pps information in |
| @@ -82,17 +76,10 @@ CMVideoFormatDescriptionRef CreateVideoFormatDescription( |
| const uint8_t* annexb_buffer, |
| size_t annexb_buffer_size); |
| |
| -#ifndef DISABLE_H265 |
| -CMVideoFormatDescriptionRef CreateH265VideoFormatDescription( |
| - const uint8_t* annexb_buffer, |
| - size_t annexb_buffer_size) |
| - __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_11_0); |
| -#endif |
| - |
| // Helper class for reading NALUs from an RTP Annex B buffer. |
| class AnnexBBufferReader final { |
| public: |
| - AnnexBBufferReader(const uint8_t* annexb_buffer, size_t length); |
| + AnnexBBufferReader(const uint8_t* annexb_buffer, size_t length, bool isH264 = true); |
| ~AnnexBBufferReader(); |
| AnnexBBufferReader(const AnnexBBufferReader& other) = delete; |
| void operator=(const AnnexBBufferReader& other) = delete; |
| @@ -113,9 +100,7 @@ class AnnexBBufferReader final { |
| // Return true if a NALU of the desired type is found, false if we |
| // reached the end instead |
| bool SeekToNextNaluOfType(H264::NaluType type); |
| -#ifndef DISABLE_H265 |
| bool SeekToNextNaluOfType(H265::NaluType type); |
| -#endif |
| |
| private: |
| // Returns the the next offset that contains NALU data. |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/native/src/objc_video_encoder_factory.mm b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/native/src/objc_video_encoder_factory.mm |
| index 33469813af34..fef97f1fca28 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/native/src/objc_video_encoder_factory.mm |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/native/src/objc_video_encoder_factory.mm |
| @@ -19,7 +19,6 @@ |
| #import "components/video_codec/RTCCodecSpecificInfoH265+Private.h" |
| #endif |
| #import "sdk/objc/api/peerconnection/RTCEncodedImage+Private.h" |
| -#import "sdk/objc/api/peerconnection/RTCRtpFragmentationHeader+Private.h" |
| #import "sdk/objc/api/peerconnection/RTCVideoCodecInfo+Private.h" |
| #import "sdk/objc/api/peerconnection/RTCVideoEncoderSettings+Private.h" |
| #import "sdk/objc/api/video_codec/RTCVideoCodecConstants.h" |
| @@ -80,10 +79,8 @@ class ObjCVideoEncoder : public VideoEncoder { |
| #endif |
| } |
| |
| - std::unique_ptr<RTPFragmentationHeader> fragmentationHeader = |
| - [header createNativeFragmentationHeader]; |
| EncodedImageCallback::Result res = |
| - callback->OnEncodedImage(encodedImage, &codecSpecificInfo, fragmentationHeader.get()); |
| + callback->OnEncodedImage(encodedImage, &codecSpecificInfo); |
| return res.error == EncodedImageCallback::Result::OK; |
| }]; |
| |
| @@ -163,13 +160,8 @@ std::vector<SdpVideoFormat> ObjCVideoEncoderFactory::GetImplementations() const |
| |
| VideoEncoderFactory::CodecInfo ObjCVideoEncoderFactory::QueryVideoEncoder( |
| const SdpVideoFormat &format) const { |
| - // TODO(andersc): This is a hack until we figure out how this should be done properly. |
| - NSString *formatName = [NSString stringForStdString:format.name]; |
| - NSSet *wrappedSoftwareFormats = |
| - [NSSet setWithObjects:kRTCVideoCodecVp8Name, kRTCVideoCodecVp9Name, nil]; |
| |
| - CodecInfo codec_info; |
| - codec_info.is_hardware_accelerated = ![wrappedSoftwareFormats containsObject:formatName]; |
| + VideoEncoderFactory::CodecInfo codec_info; |
| codec_info.has_internal_source = false; |
| return codec_info; |
| } |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/video/rtp_video_stream_receiver.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/video/rtp_video_stream_receiver.cc |
| index 1b8828be2cee..935a61bf4c4e 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/video/rtp_video_stream_receiver.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/video/rtp_video_stream_receiver.cc |
| @@ -628,7 +628,24 @@ void RtpVideoStreamReceiver::OnReceivedPayloadData( |
| packet->video_payload = std::move(fixed.bitstream); |
| break; |
| } |
| - |
| +#ifndef DISABLE_H265 |
| + } else if (packet->codec() == kVideoCodecH265) { |
| + video_coding::H265VpsSpsPpsTracker::FixedBitstream fixed = |
| + h265_tracker_.CopyAndFixBitstream( |
| + rtc::MakeArrayView(codec_payload.cdata(), codec_payload.size()), |
| + &packet->video_header); |
| + switch (fixed.action) { |
| + case video_coding::H265VpsSpsPpsTracker::kRequestKeyframe: |
| + rtcp_feedback_buffer_.RequestKeyFrame(); |
| + rtcp_feedback_buffer_.SendBufferedRtcpFeedback(); |
| + ABSL_FALLTHROUGH_INTENDED; |
| + case video_coding::H265VpsSpsPpsTracker::kDrop: |
| + return; |
| + case video_coding::H265VpsSpsPpsTracker::kInsert: |
| + packet->video_payload = std::move(fixed.bitstream); |
| + break; |
| + } |
| +#endif |
| } else { |
| packet->video_payload = std::move(codec_payload); |
| } |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/video/rtp_video_stream_receiver.h b/Source/ThirdParty/libwebrtc/Source/webrtc/video/rtp_video_stream_receiver.h |
| index 40958c48ecfb..67e69962de5c 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/video/rtp_video_stream_receiver.h |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/video/rtp_video_stream_receiver.h |
| @@ -37,6 +37,9 @@ |
| #include "modules/rtp_rtcp/source/rtp_video_header.h" |
| #include "modules/rtp_rtcp/source/video_rtp_depacketizer.h" |
| #include "modules/video_coding/h264_sps_pps_tracker.h" |
| +#ifndef DISABLE_H265 |
| +#include "modules/video_coding/h265_vps_sps_pps_tracker.h" |
| +#endif |
| #include "modules/video_coding/loss_notification_controller.h" |
| #include "modules/video_coding/packet_buffer.h" |
| #include "modules/video_coding/rtp_frame_reference_finder.h" |
| @@ -366,6 +369,10 @@ class RtpVideoStreamReceiver : public LossNotificationSender, |
| // Maps payload id to the depacketizer. |
| std::map<uint8_t, std::unique_ptr<VideoRtpDepacketizer>> payload_type_map_; |
| |
| +#ifndef DISABLE_H265 |
| + video_coding::H265VpsSpsPpsTracker h265_tracker_; |
| +#endif |
| + |
| // TODO(johan): Remove pt_codec_params_ once |
| // https://bugs.chromium.org/p/webrtc/issues/detail?id=6883 is resolved. |
| // Maps a payload type to a map of out-of-band supplied codec parameters. |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/video/rtp_video_stream_receiver2.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/video/rtp_video_stream_receiver2.cc |
| index f3345597ea2d..281dbde1a2e1 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/video/rtp_video_stream_receiver2.cc |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/video/rtp_video_stream_receiver2.cc |
| @@ -596,7 +596,24 @@ void RtpVideoStreamReceiver2::OnReceivedPayloadData( |
| packet->video_payload = std::move(fixed.bitstream); |
| break; |
| } |
| - |
| +#ifndef DISABLE_H265 |
| + } else if (packet->codec() == kVideoCodecH265) { |
| + video_coding::H265VpsSpsPpsTracker::FixedBitstream fixed = |
| + h265_tracker_.CopyAndFixBitstream( |
| + rtc::MakeArrayView(codec_payload.cdata(), codec_payload.size()), |
| + &packet->video_header); |
| + switch (fixed.action) { |
| + case video_coding::H265VpsSpsPpsTracker::kRequestKeyframe: |
| + rtcp_feedback_buffer_.RequestKeyFrame(); |
| + rtcp_feedback_buffer_.SendBufferedRtcpFeedback(); |
| + ABSL_FALLTHROUGH_INTENDED; |
| + case video_coding::H265VpsSpsPpsTracker::kDrop: |
| + return; |
| + case video_coding::H265VpsSpsPpsTracker::kInsert: |
| + packet->video_payload = std::move(fixed.bitstream); |
| + break; |
| + } |
| +#endif |
| } else { |
| packet->video_payload = std::move(codec_payload); |
| } |
| diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/video/rtp_video_stream_receiver2.h b/Source/ThirdParty/libwebrtc/Source/webrtc/video/rtp_video_stream_receiver2.h |
| index 40e7ef6f1b53..f36293ad44b2 100644 |
| --- a/Source/ThirdParty/libwebrtc/Source/webrtc/video/rtp_video_stream_receiver2.h |
| +++ b/Source/ThirdParty/libwebrtc/Source/webrtc/video/rtp_video_stream_receiver2.h |
| @@ -35,6 +35,9 @@ |
| #include "modules/rtp_rtcp/source/rtp_video_header.h" |
| #include "modules/rtp_rtcp/source/video_rtp_depacketizer.h" |
| #include "modules/video_coding/h264_sps_pps_tracker.h" |
| +#ifndef DISABLE_H265 |
| +#include "modules/video_coding/h265_vps_sps_pps_tracker.h" |
| +#endif |
| #include "modules/video_coding/loss_notification_controller.h" |
| #include "modules/video_coding/packet_buffer.h" |
| #include "modules/video_coding/rtp_frame_reference_finder.h" |
| @@ -330,6 +333,10 @@ class RtpVideoStreamReceiver2 : public LossNotificationSender, |
| std::map<uint8_t, std::unique_ptr<VideoRtpDepacketizer>> payload_type_map_ |
| RTC_GUARDED_BY(worker_task_checker_); |
| |
| +#ifndef DISABLE_H265 |
| + video_coding::H265VpsSpsPpsTracker h265_tracker_; |
| +#endif |
| + |
| // TODO(johan): Remove pt_codec_params_ once |
| // https://bugs.chromium.org/p/webrtc/issues/detail?id=6883 is resolved. |
| // Maps a payload type to a map of out-of-band supplied codec parameters. |