Index: webrtc/modules/rtp_rtcp/source/rtp_header_extensions.cc |
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.cc b/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.cc |
index 28685b4640a9e123c55ecb5a2003dd018ddf9c89..70796eac7b0d022ea812406ad9e9d845271825ab 100644 |
--- a/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.cc |
+++ b/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.cc |
@@ -380,4 +380,106 @@ constexpr const char RepairedRtpStreamId::kUri[]; |
constexpr RTPExtensionType RtpMid::kId; |
constexpr const char RtpMid::kUri[]; |
+// For Frame Marking RTP Header Extension: |
+// |
+// https://tools.ietf.org/html/draft-ietf-avtext-framemarking-04#page-4 |
+// This extensions provides meta-information about the RTP streams outside the |
+// encrypted media payload, an RTP switch can do codec-agnostic |
+// selective forwarding without decrypting the payload. |
+// |
+// for Non-Scalable Streams: |
+// |
+// 0 1 |
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
+// | ID=? | L=0 |S|E|I|D|0 0 0 0| |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
+// |
+// for Scalable Streams: |
+// |
+// 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 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
+// | ID=? | L=2 |S|E|I|D|B| TID | LID | TL0PICIDX | |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
+// |
+constexpr RTPExtensionType FrameMarking::kId; |
+constexpr const char* FrameMarking::kUri; |
+ |
+bool FrameMarking::Parse(rtc::ArrayView<const uint8_t> data, |
+ FrameMarks* frame_marks) { |
+ RTC_DCHECK(frame_marks); |
+ |
+ if (data.empty()) |
+ return false; |
+ |
+ // Set frame marking data |
+ frame_marks->start_of_frame = (data[0] & 0x80) != 0; |
+ frame_marks->end_of_frame = (data[0] & 0x40) != 0; |
+ frame_marks->independent = (data[0] & 0x20) != 0; |
+ frame_marks->discardable = (data[0] & 0x10) != 0; |
+ |
+ // Check variable length. |
+ if (data.size() == 1) { |
+ // We are non-scalable. |
+ frame_marks->base_layer_sync = false; |
+ frame_marks->temporal_layer_id = 0; |
+ frame_marks->layer_id = 0; |
+ frame_marks->tl0_pic_idx = 0; |
+ } else if (data.size() == 3) { |
+ // Set scalable parts |
+ frame_marks->base_layer_sync = (data[0] & 0x08) != 0; |
+ frame_marks->temporal_layer_id = data[0] & 0x07; |
+ frame_marks->layer_id = data[1]; |
+ frame_marks->tl0_pic_idx = data[2]; |
+ } else { |
+ // Incorrect length. |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+bool FrameMarking::IsScalable(const FrameMarks& frame_marks) { |
+ return (frame_marks.base_layer_sync || |
+ (frame_marks.temporal_layer_id && |
+ frame_marks.temporal_layer_id != kNoTemporalIdx) || |
+ (frame_marks.layer_id && frame_marks.layer_id != kNoSpatialIdx) || |
+ (frame_marks.tl0_pic_idx && frame_marks.tl0_pic_idx != kNoTl0PicIdx)); |
+} |
+ |
+size_t FrameMarking::ValueSize(const FrameMarks& frame_marks) { |
+ return IsScalable(frame_marks) ? 3 : 1; |
+} |
+ |
+bool FrameMarking::Write(uint8_t* data, const FrameMarks& frame_marks) { |
+ data[0] = frame_marks.start_of_frame ? 0x80 : 0x00; |
+ data[0] |= frame_marks.end_of_frame ? 0x40 : 0x00; |
+ data[0] |= frame_marks.independent ? 0x20 : 0x00; |
+ data[0] |= frame_marks.discardable ? 0x10 : 0x00; |
+ |
+ // Check if it is scalable. |
+ if (IsScalable(frame_marks)) { |
+ data[0] |= frame_marks.base_layer_sync ? 0x08 : 0x00; |
+ data[0] |= (frame_marks.temporal_layer_id & 0x07); |
+ data[1] = frame_marks.layer_id; |
+ data[2] = static_cast<uint8_t>(frame_marks.tl0_pic_idx); |
+ } |
+ return true; |
+} |
+ |
+uint8_t FrameMarking::CreateLayerId(const RTPVideoHeaderVP9& vp9) { |
+ // The following shows VP9 Layer encoding information (3 bits for |
+ // spatial and temporal layer) mapped to the generic LID and TID fields. |
+ // The P and U bits MUST match the corresponding bits in the VP9 Payload |
+ // Description. |
+ // 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 |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
+ // | ID=2 | L=2 |S|E|I|D|B| TID |0|0|0|P|U| SID | TL0PICIDX | |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
+ return (vp9.spatial_idx != kNoSpatialIdx ? vp9.spatial_idx & 0x07 : 0x00) | |
+ (vp9.temporal_up_switch ? 0x08 : 0x00) | |
+ (vp9.inter_pic_predicted ? 0x10 : 0x00); |
+} |
+ |
} // namespace webrtc |