Chromium Code Reviews| 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 2f3feb34cd3851f53da1bbda45d5f90a9f575bd8..71bbd3254cc45bbc2ccc5fbb3090c9c7e49049aa 100644 |
| --- a/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.cc |
| +++ b/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.cc |
| @@ -313,4 +313,112 @@ bool RepairedRtpStreamId::Write(uint8_t* data, const std::string& rsid) { |
| return RtpStreamId::Write(data, rsid); |
| } |
| +// 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; |
| +} |
| + |
| +size_t FrameMarking::ValueSize(const FrameMarks& frame_marks) { |
| + // Check if it is scalable. |
| + if (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 != static_cast<uint8_t>(kNoTl0PicIdx))) |
|
danilchap
2017/06/30 12:53:25
does it make 0xff picture id invalid?
may be inste
sergio.garcia.murillo
2017/06/30 13:42:00
Agree, changing it to int so it matches the other
|
| + return 3; |
| + else |
| + return 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 (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 != static_cast<uint8_t>(kNoTl0PicIdx))) { |
|
danilchap
2017/06/30 12:53:25
same here (since this check is large and non-trivi
sergio.garcia.murillo
2017/06/30 13:42:00
Done.
|
| + 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] = frame_marks.tl0_pic_idx; |
| + } |
| + return true; |
| +} |
| + |
| +uint8_t FrameMarking::CreateLayerId(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 | |
|
danilchap
2017/06/30 12:53:25
linked spec has different format for VP9 LID Mappi
sergio.garcia.murillo
2017/06/30 13:42:00
Current draft has invalid format for LID. Spatial
|
| + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| + return (vp9.spatial_idx != kNoSpatialIdx ? vp9.spatial_idx & 0x07 : 0x00) | |
| + (vp9.temporal_up_switch ? 0x08 : 0x00) | |
| + (vp9.inter_pic_predicted ? 0x10 : 0x00); |
| +} |
| + |
| } // namespace webrtc |