From 4f88a9d1c3668d69aa853bf47b173d17d0967c76 Mon Sep 17 00:00:00 2001 From: Jeremy Leconte Date: Wed, 17 Mar 2021 17:01:31 +0100 Subject: [PATCH] Create a VideoFrameTrackingId RTP header extension. Bug: webrtc:12594 Change-Id: I518b549b18143f4711728b4637a4689772474c45 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/212084 Reviewed-by: Artem Titov Reviewed-by: Danil Chapovalov Commit-Queue: Jeremy Leconte Cr-Commit-Position: refs/heads/master@{#33567} --- .../video-frame-tracking-id/README.md | 27 ++++++++++++++++++ modules/rtp_rtcp/include/rtp_rtcp_defines.h | 1 + .../source/rtp_header_extension_map.cc | 1 + .../rtp_rtcp/source/rtp_header_extensions.cc | 28 +++++++++++++++++++ .../rtp_rtcp/source/rtp_header_extensions.h | 16 +++++++++++ modules/rtp_rtcp/source/rtp_packet.cc | 3 +- modules/rtp_rtcp/source/rtp_sender.cc | 1 + modules/rtp_rtcp/source/rtp_utility.cc | 4 +++ test/fuzzers/rtp_packet_fuzzer.cc | 5 ++++ 9 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 docs/native-code/rtp-hdrext/video-frame-tracking-id/README.md diff --git a/docs/native-code/rtp-hdrext/video-frame-tracking-id/README.md b/docs/native-code/rtp-hdrext/video-frame-tracking-id/README.md new file mode 100644 index 0000000000..d1c609744e --- /dev/null +++ b/docs/native-code/rtp-hdrext/video-frame-tracking-id/README.md @@ -0,0 +1,27 @@ +# Video Frame Tracking Id + +The Video Frame Tracking Id extension is meant for media quality testing +purpose and shouldn't be used in production. It tracks webrtc::VideoFrame id +field from the sender to the receiver to gather referenced base media quality +metrics such as PSNR or SSIM. +Contact for more info. + +**Name:** "Video Frame Tracking Id" + +**Formal name:** + + +**Status:** This extension is defined to allow for media quality testing. It is +enabled by using a field trial and should only be used in a testing environment. + +### Data layout overview + 1-byte header + 2 bytes of data: + + 0              1 2 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | ID   | L=1 | video-frame-tracking-id | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +Notes: The extension shoud be present only in the first packet of each frame. +If attached to other packets it can be ignored. \ No newline at end of file diff --git a/modules/rtp_rtcp/include/rtp_rtcp_defines.h b/modules/rtp_rtcp/include/rtp_rtcp_defines.h index cbc2d92111..2e460e45c1 100644 --- a/modules/rtp_rtcp/include/rtp_rtcp_defines.h +++ b/modules/rtp_rtcp/include/rtp_rtcp_defines.h @@ -74,6 +74,7 @@ enum RTPExtensionType : int { kRtpExtensionGenericFrameDescriptor = kRtpExtensionGenericFrameDescriptor00, kRtpExtensionGenericFrameDescriptor02, kRtpExtensionColorSpace, + kRtpExtensionVideoFrameTrackingId, kRtpExtensionNumberOfExtensions // Must be the last entity in the enum. }; diff --git a/modules/rtp_rtcp/source/rtp_header_extension_map.cc b/modules/rtp_rtcp/source/rtp_header_extension_map.cc index c16dcaf6f7..aebe884c0f 100644 --- a/modules/rtp_rtcp/source/rtp_header_extension_map.cc +++ b/modules/rtp_rtcp/source/rtp_header_extension_map.cc @@ -50,6 +50,7 @@ constexpr ExtensionInfo kExtensions[] = { CreateExtensionInfo(), CreateExtensionInfo(), CreateExtensionInfo(), + CreateExtensionInfo(), }; // Because of kRtpExtensionNone, NumberOfExtension is 1 bigger than the actual diff --git a/modules/rtp_rtcp/source/rtp_header_extensions.cc b/modules/rtp_rtcp/source/rtp_header_extensions.cc index b540e4b22e..1c3073e90d 100644 --- a/modules/rtp_rtcp/source/rtp_header_extensions.cc +++ b/modules/rtp_rtcp/source/rtp_header_extensions.cc @@ -823,4 +823,32 @@ bool InbandComfortNoiseExtension::Write(rtc::ArrayView data, return true; } +// VideoFrameTrackingIdExtension +// +// 0 1 2 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | ID | L=1 | video-frame-tracking-id | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +constexpr RTPExtensionType VideoFrameTrackingIdExtension::kId; +constexpr uint8_t VideoFrameTrackingIdExtension::kValueSizeBytes; +constexpr const char VideoFrameTrackingIdExtension::kUri[]; + +bool VideoFrameTrackingIdExtension::Parse(rtc::ArrayView data, + uint16_t* video_frame_tracking_id) { + if (data.size() != kValueSizeBytes) { + return false; + } + *video_frame_tracking_id = ByteReader::ReadBigEndian(data.data()); + return true; +} + +bool VideoFrameTrackingIdExtension::Write(rtc::ArrayView data, + uint16_t video_frame_tracking_id) { + RTC_DCHECK_EQ(data.size(), kValueSizeBytes); + ByteWriter::WriteBigEndian(data.data(), video_frame_tracking_id); + return true; +} + } // namespace webrtc diff --git a/modules/rtp_rtcp/source/rtp_header_extensions.h b/modules/rtp_rtcp/source/rtp_header_extensions.h index 1352611fb1..f6e7a579ab 100644 --- a/modules/rtp_rtcp/source/rtp_header_extensions.h +++ b/modules/rtp_rtcp/source/rtp_header_extensions.h @@ -307,5 +307,21 @@ class InbandComfortNoiseExtension { absl::optional level); }; +class VideoFrameTrackingIdExtension { + public: + using value_type = uint16_t; + static constexpr RTPExtensionType kId = kRtpExtensionVideoFrameTrackingId; + static constexpr uint8_t kValueSizeBytes = 2; + static constexpr const char kUri[] = + "http://www.webrtc.org/experiments/rtp-hdrext/video-frame-tracking-id"; + static bool Parse(rtc::ArrayView data, + uint16_t* video_frame_tracking_id); + static size_t ValueSize(uint16_t /*video_frame_tracking_id*/) { + return kValueSizeBytes; + } + static bool Write(rtc::ArrayView data, + uint16_t video_frame_tracking_id); +}; + } // namespace webrtc #endif // MODULES_RTP_RTCP_SOURCE_RTP_HEADER_EXTENSIONS_H_ diff --git a/modules/rtp_rtcp/source/rtp_packet.cc b/modules/rtp_rtcp/source/rtp_packet.cc index 38d29cc2b4..84769d0f4b 100644 --- a/modules/rtp_rtcp/source/rtp_packet.cc +++ b/modules/rtp_rtcp/source/rtp_packet.cc @@ -198,7 +198,8 @@ void RtpPacket::ZeroMutableExtensions() { case RTPExtensionType::kRtpExtensionVideoContentType: case RTPExtensionType::kRtpExtensionVideoLayersAllocation: case RTPExtensionType::kRtpExtensionVideoRotation: - case RTPExtensionType::kRtpExtensionInbandComfortNoise: { + case RTPExtensionType::kRtpExtensionInbandComfortNoise: + case RTPExtensionType::kRtpExtensionVideoFrameTrackingId: { // Non-mutable extension. Don't change it. break; } diff --git a/modules/rtp_rtcp/source/rtp_sender.cc b/modules/rtp_rtcp/source/rtp_sender.cc index c8ea999e95..8435e5f33d 100644 --- a/modules/rtp_rtcp/source/rtp_sender.cc +++ b/modules/rtp_rtcp/source/rtp_sender.cc @@ -121,6 +121,7 @@ bool IsNonVolatile(RTPExtensionType type) { case kRtpExtensionVideoTiming: case kRtpExtensionRepairedRtpStreamId: case kRtpExtensionColorSpace: + case kRtpExtensionVideoFrameTrackingId: return false; case kRtpExtensionNone: case kRtpExtensionNumberOfExtensions: diff --git a/modules/rtp_rtcp/source/rtp_utility.cc b/modules/rtp_rtcp/source/rtp_utility.cc index a3d6d6f7f1..a22785faca 100644 --- a/modules/rtp_rtcp/source/rtp_utility.cc +++ b/modules/rtp_rtcp/source/rtp_utility.cc @@ -536,6 +536,10 @@ void RtpHeaderParser::ParseOneByteExtensionHeader( RTC_LOG(WARNING) << "Inband comfort noise extension unsupported by " "rtp header parser."; break; + case kRtpExtensionVideoFrameTrackingId: + RTC_LOG(WARNING) + << "VideoFrameTrackingId unsupported by rtp header parser."; + break; case kRtpExtensionNone: case kRtpExtensionNumberOfExtensions: { RTC_NOTREACHED() << "Invalid extension type: " << type; diff --git a/test/fuzzers/rtp_packet_fuzzer.cc b/test/fuzzers/rtp_packet_fuzzer.cc index 3f03114a33..9e8fd6f4c1 100644 --- a/test/fuzzers/rtp_packet_fuzzer.cc +++ b/test/fuzzers/rtp_packet_fuzzer.cc @@ -148,6 +148,11 @@ void FuzzOneInput(const uint8_t* data, size_t size) { packet.GetExtension(&allocation); break; } + case kRtpExtensionVideoFrameTrackingId: { + uint16_t tracking_id; + packet.GetExtension(&tracking_id); + break; + } case kRtpExtensionGenericFrameDescriptor02: // This extension requires state to read and so complicated that // deserves own fuzzer.