ivica | 7f6a6fc | 2015-09-08 02:40:29 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license |
| 5 | * that can be found in the LICENSE file in the root of the source |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 11 | #include "test/layer_filtering_transport.h" |
| 12 | |
Yves Gerey | 3e70781 | 2018-11-28 16:47:49 +0100 | [diff] [blame] | 13 | #include <string.h> |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 14 | |
Yves Gerey | 3e70781 | 2018-11-28 16:47:49 +0100 | [diff] [blame] | 15 | #include <algorithm> |
kwiberg | bfefb03 | 2016-05-01 14:53:46 -0700 | [diff] [blame] | 16 | #include <memory> |
Yves Gerey | 3e70781 | 2018-11-28 16:47:49 +0100 | [diff] [blame] | 17 | #include <utility> |
kwiberg | bfefb03 | 2016-05-01 14:53:46 -0700 | [diff] [blame] | 18 | |
Yves Gerey | 3e70781 | 2018-11-28 16:47:49 +0100 | [diff] [blame] | 19 | #include "api/rtp_headers.h" |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 20 | #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 21 | #include "modules/rtp_rtcp/source/rtp_format.h" |
| 22 | #include "modules/rtp_rtcp/source/rtp_utility.h" |
Yves Gerey | 3e70781 | 2018-11-28 16:47:49 +0100 | [diff] [blame] | 23 | #include "modules/rtp_rtcp/source/rtp_video_header.h" |
| 24 | #include "modules/video_coding/codecs/interface/common_constants.h" |
| 25 | #include "modules/video_coding/codecs/vp8/include/vp8_globals.h" |
| 26 | #include "modules/video_coding/codecs/vp9/include/vp9_globals.h" |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 27 | #include "rtc_base/checks.h" |
ivica | 7f6a6fc | 2015-09-08 02:40:29 -0700 | [diff] [blame] | 28 | |
| 29 | namespace webrtc { |
| 30 | namespace test { |
| 31 | |
| 32 | LayerFilteringTransport::LayerFilteringTransport( |
Yves Gerey | 6516f76 | 2019-08-29 11:50:23 +0200 | [diff] [blame] | 33 | DEPRECATED_SingleThreadedTaskQueueForTesting* task_queue, |
Artem Titov | 46c4e60 | 2018-08-17 14:26:54 +0200 | [diff] [blame] | 34 | std::unique_ptr<SimulatedPacketReceiverInterface> pipe, |
Ilya Nikolaevskiy | 255d1cd | 2017-12-21 18:02:59 +0100 | [diff] [blame] | 35 | Call* send_call, |
| 36 | uint8_t vp8_video_payload_type, |
| 37 | uint8_t vp9_video_payload_type, |
| 38 | int selected_tl, |
| 39 | int selected_sl, |
Sebastian Jansson | 0940811 | 2018-04-24 14:41:22 +0200 | [diff] [blame] | 40 | const std::map<uint8_t, MediaType>& payload_type_map, |
Ilya Nikolaevskiy | 255d1cd | 2017-12-21 18:02:59 +0100 | [diff] [blame] | 41 | uint32_t ssrc_to_filter_min, |
| 42 | uint32_t ssrc_to_filter_max) |
Sebastian Jansson | 0940811 | 2018-04-24 14:41:22 +0200 | [diff] [blame] | 43 | : DirectTransport(task_queue, std::move(pipe), send_call, payload_type_map), |
Ilya Nikolaevskiy | 255d1cd | 2017-12-21 18:02:59 +0100 | [diff] [blame] | 44 | vp8_video_payload_type_(vp8_video_payload_type), |
| 45 | vp9_video_payload_type_(vp9_video_payload_type), |
| 46 | selected_tl_(selected_tl), |
| 47 | selected_sl_(selected_sl), |
| 48 | discarded_last_packet_(false), |
| 49 | ssrc_to_filter_min_(ssrc_to_filter_min), |
| 50 | ssrc_to_filter_max_(ssrc_to_filter_max) {} |
| 51 | |
| 52 | LayerFilteringTransport::LayerFilteringTransport( |
Yves Gerey | 6516f76 | 2019-08-29 11:50:23 +0200 | [diff] [blame] | 53 | DEPRECATED_SingleThreadedTaskQueueForTesting* task_queue, |
Artem Titov | 46c4e60 | 2018-08-17 14:26:54 +0200 | [diff] [blame] | 54 | std::unique_ptr<SimulatedPacketReceiverInterface> pipe, |
Christoffer Rodbro | b4bb4eb | 2017-11-13 13:03:52 +0100 | [diff] [blame] | 55 | Call* send_call, |
| 56 | uint8_t vp8_video_payload_type, |
| 57 | uint8_t vp9_video_payload_type, |
| 58 | int selected_tl, |
Sebastian Jansson | 0940811 | 2018-04-24 14:41:22 +0200 | [diff] [blame] | 59 | int selected_sl, |
| 60 | const std::map<uint8_t, MediaType>& payload_type_map) |
| 61 | : DirectTransport(task_queue, std::move(pipe), send_call, payload_type_map), |
Christoffer Rodbro | b4bb4eb | 2017-11-13 13:03:52 +0100 | [diff] [blame] | 62 | vp8_video_payload_type_(vp8_video_payload_type), |
| 63 | vp9_video_payload_type_(vp9_video_payload_type), |
| 64 | selected_tl_(selected_tl), |
| 65 | selected_sl_(selected_sl), |
Ilya Nikolaevskiy | 255d1cd | 2017-12-21 18:02:59 +0100 | [diff] [blame] | 66 | discarded_last_packet_(false), |
| 67 | ssrc_to_filter_min_(0), |
| 68 | ssrc_to_filter_max_(0xFFFFFFFF) {} |
Christoffer Rodbro | b4bb4eb | 2017-11-13 13:03:52 +0100 | [diff] [blame] | 69 | |
sprang | ce4aef1 | 2015-11-02 07:23:20 -0800 | [diff] [blame] | 70 | bool LayerFilteringTransport::DiscardedLastPacket() const { |
| 71 | return discarded_last_packet_; |
ivica | e78e2c7 | 2015-10-07 23:44:29 -0700 | [diff] [blame] | 72 | } |
ivica | 7f6a6fc | 2015-09-08 02:40:29 -0700 | [diff] [blame] | 73 | |
stefan | 1d8a506 | 2015-10-02 03:39:33 -0700 | [diff] [blame] | 74 | bool LayerFilteringTransport::SendRtp(const uint8_t* packet, |
| 75 | size_t length, |
| 76 | const PacketOptions& options) { |
sprang | ce4aef1 | 2015-11-02 07:23:20 -0800 | [diff] [blame] | 77 | if (selected_tl_ == -1 && selected_sl_ == -1) { |
ivica | 7f6a6fc | 2015-09-08 02:40:29 -0700 | [diff] [blame] | 78 | // Nothing to change, forward the packet immediately. |
stefan | 1d8a506 | 2015-10-02 03:39:33 -0700 | [diff] [blame] | 79 | return test::DirectTransport::SendRtp(packet, length, options); |
ivica | 7f6a6fc | 2015-09-08 02:40:29 -0700 | [diff] [blame] | 80 | } |
| 81 | |
| 82 | bool set_marker_bit = false; |
sprang | ce4aef1 | 2015-11-02 07:23:20 -0800 | [diff] [blame] | 83 | RtpUtility::RtpHeaderParser parser(packet, length); |
ivica | 7f6a6fc | 2015-09-08 02:40:29 -0700 | [diff] [blame] | 84 | RTPHeader header; |
danilchap | f6975f4 | 2015-12-28 10:18:46 -0800 | [diff] [blame] | 85 | parser.Parse(&header); |
sprang | ce4aef1 | 2015-11-02 07:23:20 -0800 | [diff] [blame] | 86 | |
Ilya Nikolaevskiy | 255d1cd | 2017-12-21 18:02:59 +0100 | [diff] [blame] | 87 | if (header.ssrc < ssrc_to_filter_min_ || header.ssrc > ssrc_to_filter_max_) { |
| 88 | // Nothing to change, forward the packet immediately. |
| 89 | return test::DirectTransport::SendRtp(packet, length, options); |
| 90 | } |
| 91 | |
kwiberg | 352444f | 2016-11-28 15:58:53 -0800 | [diff] [blame] | 92 | RTC_DCHECK_LE(length, IP_PACKET_SIZE); |
sprang | ce4aef1 | 2015-11-02 07:23:20 -0800 | [diff] [blame] | 93 | uint8_t temp_buffer[IP_PACKET_SIZE]; |
| 94 | memcpy(temp_buffer, packet, length); |
ivica | 7f6a6fc | 2015-09-08 02:40:29 -0700 | [diff] [blame] | 95 | |
| 96 | if (header.payloadType == vp8_video_payload_type_ || |
| 97 | header.payloadType == vp9_video_payload_type_) { |
| 98 | const uint8_t* payload = packet + header.headerLength; |
henrikg | 91d6ede | 2015-09-17 00:24:34 -0700 | [diff] [blame] | 99 | RTC_DCHECK_GT(length, header.headerLength); |
ivica | 7f6a6fc | 2015-09-08 02:40:29 -0700 | [diff] [blame] | 100 | const size_t payload_length = length - header.headerLength; |
henrikg | 91d6ede | 2015-09-17 00:24:34 -0700 | [diff] [blame] | 101 | RTC_DCHECK_GT(payload_length, header.paddingLength); |
ivica | 7f6a6fc | 2015-09-08 02:40:29 -0700 | [diff] [blame] | 102 | const size_t payload_data_length = payload_length - header.paddingLength; |
| 103 | |
| 104 | const bool is_vp8 = header.payloadType == vp8_video_payload_type_; |
kwiberg | bfefb03 | 2016-05-01 14:53:46 -0700 | [diff] [blame] | 105 | std::unique_ptr<RtpDepacketizer> depacketizer( |
Niels Möller | 520ca4e | 2018-06-04 11:14:38 +0200 | [diff] [blame] | 106 | RtpDepacketizer::Create(is_vp8 ? kVideoCodecVP8 : kVideoCodecVP9)); |
ivica | 7f6a6fc | 2015-09-08 02:40:29 -0700 | [diff] [blame] | 107 | RtpDepacketizer::ParsedPayload parsed_payload; |
| 108 | if (depacketizer->Parse(&parsed_payload, payload, payload_data_length)) { |
philipel | 29d8846 | 2018-08-08 14:26:00 +0200 | [diff] [blame] | 109 | int temporal_idx; |
| 110 | int spatial_idx; |
| 111 | bool non_ref_for_inter_layer_pred; |
| 112 | bool end_of_frame; |
| 113 | |
| 114 | if (is_vp8) { |
Philip Eliasson | d52a1a6 | 2018-09-07 13:03:55 +0000 | [diff] [blame] | 115 | temporal_idx = absl::get<RTPVideoHeaderVP8>( |
| 116 | parsed_payload.video_header().video_type_header) |
| 117 | .temporalIdx; |
philipel | 29d8846 | 2018-08-08 14:26:00 +0200 | [diff] [blame] | 118 | spatial_idx = kNoSpatialIdx; |
“Michael | 23c5a99 | 2018-06-21 11:07:21 -0500 | [diff] [blame] | 119 | num_active_spatial_layers_ = 1; |
philipel | 29d8846 | 2018-08-08 14:26:00 +0200 | [diff] [blame] | 120 | non_ref_for_inter_layer_pred = false; |
| 121 | end_of_frame = true; |
| 122 | } else { |
| 123 | const auto& vp9_header = absl::get<RTPVideoHeaderVP9>( |
| 124 | parsed_payload.video_header().video_type_header); |
| 125 | temporal_idx = vp9_header.temporal_idx; |
| 126 | spatial_idx = vp9_header.spatial_idx; |
| 127 | non_ref_for_inter_layer_pred = vp9_header.non_ref_for_inter_layer_pred; |
| 128 | end_of_frame = vp9_header.end_of_frame; |
Sergey Silkin | 941fd43 | 2018-12-20 10:19:51 +0100 | [diff] [blame] | 129 | if (vp9_header.ss_data_available) { |
| 130 | RTC_DCHECK(vp9_header.temporal_idx == kNoTemporalIdx || |
| 131 | vp9_header.temporal_idx == 0); |
| 132 | RTC_DCHECK(vp9_header.spatial_idx == kNoSpatialIdx || |
| 133 | vp9_header.spatial_idx == 0); |
philipel | 29d8846 | 2018-08-08 14:26:00 +0200 | [diff] [blame] | 134 | num_active_spatial_layers_ = vp9_header.num_spatial_layers; |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | if (spatial_idx == kNoSpatialIdx) |
| 139 | num_active_spatial_layers_ = 1; |
| 140 | |
“Michael | 23c5a99 | 2018-06-21 11:07:21 -0500 | [diff] [blame] | 141 | RTC_CHECK_GT(num_active_spatial_layers_, 0); |
| 142 | |
| 143 | if (selected_sl_ >= 0 && |
| 144 | spatial_idx == |
| 145 | std::min(num_active_spatial_layers_ - 1, selected_sl_) && |
philipel | 29d8846 | 2018-08-08 14:26:00 +0200 | [diff] [blame] | 146 | end_of_frame) { |
ivica | 7f6a6fc | 2015-09-08 02:40:29 -0700 | [diff] [blame] | 147 | // This layer is now the last in the superframe. |
| 148 | set_marker_bit = true; |
Sergey Silkin | 5702736 | 2018-05-15 09:12:05 +0200 | [diff] [blame] | 149 | } else { |
| 150 | const bool higher_temporal_layer = |
| 151 | (selected_tl_ >= 0 && temporal_idx != kNoTemporalIdx && |
| 152 | temporal_idx > selected_tl_); |
| 153 | |
| 154 | const bool higher_spatial_layer = |
| 155 | (selected_sl_ >= 0 && spatial_idx != kNoSpatialIdx && |
| 156 | spatial_idx > selected_sl_); |
| 157 | |
| 158 | // Filter out non-reference lower spatial layers since they are not |
| 159 | // needed for decoding of target spatial layer. |
| 160 | const bool lower_non_ref_spatial_layer = |
| 161 | (selected_sl_ >= 0 && spatial_idx != kNoSpatialIdx && |
“Michael | 23c5a99 | 2018-06-21 11:07:21 -0500 | [diff] [blame] | 162 | spatial_idx < |
| 163 | std::min(num_active_spatial_layers_ - 1, selected_sl_) && |
| 164 | non_ref_for_inter_layer_pred); |
Sergey Silkin | 5702736 | 2018-05-15 09:12:05 +0200 | [diff] [blame] | 165 | |
| 166 | if (higher_temporal_layer || higher_spatial_layer || |
| 167 | lower_non_ref_spatial_layer) { |
| 168 | // Truncate packet to a padding packet. |
| 169 | length = header.headerLength + 1; |
| 170 | temp_buffer[0] |= (1 << 5); // P = 1. |
| 171 | temp_buffer[1] &= 0x7F; // M = 0. |
| 172 | discarded_last_packet_ = true; |
| 173 | temp_buffer[header.headerLength] = 1; // One byte of padding. |
| 174 | } |
ivica | 7f6a6fc | 2015-09-08 02:40:29 -0700 | [diff] [blame] | 175 | } |
| 176 | } else { |
| 177 | RTC_NOTREACHED() << "Parse error"; |
| 178 | } |
| 179 | } |
| 180 | |
ivica | 7f6a6fc | 2015-09-08 02:40:29 -0700 | [diff] [blame] | 181 | // We are discarding some of the packets (specifically, whole layers), so |
| 182 | // make sure the marker bit is set properly, and that sequence numbers are |
| 183 | // continuous. |
ivica | e78e2c7 | 2015-10-07 23:44:29 -0700 | [diff] [blame] | 184 | if (set_marker_bit) |
ivica | 7f6a6fc | 2015-09-08 02:40:29 -0700 | [diff] [blame] | 185 | temp_buffer[1] |= kRtpMarkerBitMask; |
ivica | 7f6a6fc | 2015-09-08 02:40:29 -0700 | [diff] [blame] | 186 | |
stefan | 1d8a506 | 2015-10-02 03:39:33 -0700 | [diff] [blame] | 187 | return test::DirectTransport::SendRtp(temp_buffer, length, options); |
ivica | 7f6a6fc | 2015-09-08 02:40:29 -0700 | [diff] [blame] | 188 | } |
| 189 | |
| 190 | } // namespace test |
| 191 | } // namespace webrtc |