blob: 6edf3b2358b777e9832eca56cb81c6942b1e8554 [file] [log] [blame]
ivica7f6a6fc2015-09-08 02:40:29 -07001/*
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 Olssona4d87372019-07-05 19:08:33 +020011#include "test/layer_filtering_transport.h"
12
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <string.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
Yves Gerey3e707812018-11-28 16:47:49 +010015#include <algorithm>
kwibergbfefb032016-05-01 14:53:46 -070016#include <memory>
Yves Gerey3e707812018-11-28 16:47:49 +010017#include <utility>
kwibergbfefb032016-05-01 14:53:46 -070018
Yves Gerey3e707812018-11-28 16:47:49 +010019#include "api/rtp_headers.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "modules/rtp_rtcp/source/rtp_format.h"
22#include "modules/rtp_rtcp/source/rtp_utility.h"
Yves Gerey3e707812018-11-28 16:47:49 +010023#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 Bonadei92ea95e2017-09-15 06:47:31 +020027#include "rtc_base/checks.h"
ivica7f6a6fc2015-09-08 02:40:29 -070028
29namespace webrtc {
30namespace test {
31
32LayerFilteringTransport::LayerFilteringTransport(
Yves Gerey6516f762019-08-29 11:50:23 +020033 DEPRECATED_SingleThreadedTaskQueueForTesting* task_queue,
Artem Titov46c4e602018-08-17 14:26:54 +020034 std::unique_ptr<SimulatedPacketReceiverInterface> pipe,
Ilya Nikolaevskiy255d1cd2017-12-21 18:02:59 +010035 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 Jansson09408112018-04-24 14:41:22 +020040 const std::map<uint8_t, MediaType>& payload_type_map,
Ilya Nikolaevskiy255d1cd2017-12-21 18:02:59 +010041 uint32_t ssrc_to_filter_min,
42 uint32_t ssrc_to_filter_max)
Sebastian Jansson09408112018-04-24 14:41:22 +020043 : DirectTransport(task_queue, std::move(pipe), send_call, payload_type_map),
Ilya Nikolaevskiy255d1cd2017-12-21 18:02:59 +010044 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
52LayerFilteringTransport::LayerFilteringTransport(
Yves Gerey6516f762019-08-29 11:50:23 +020053 DEPRECATED_SingleThreadedTaskQueueForTesting* task_queue,
Artem Titov46c4e602018-08-17 14:26:54 +020054 std::unique_ptr<SimulatedPacketReceiverInterface> pipe,
Christoffer Rodbrob4bb4eb2017-11-13 13:03:52 +010055 Call* send_call,
56 uint8_t vp8_video_payload_type,
57 uint8_t vp9_video_payload_type,
58 int selected_tl,
Sebastian Jansson09408112018-04-24 14:41:22 +020059 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 Rodbrob4bb4eb2017-11-13 13:03:52 +010062 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 Nikolaevskiy255d1cd2017-12-21 18:02:59 +010066 discarded_last_packet_(false),
67 ssrc_to_filter_min_(0),
68 ssrc_to_filter_max_(0xFFFFFFFF) {}
Christoffer Rodbrob4bb4eb2017-11-13 13:03:52 +010069
sprangce4aef12015-11-02 07:23:20 -080070bool LayerFilteringTransport::DiscardedLastPacket() const {
71 return discarded_last_packet_;
ivicae78e2c72015-10-07 23:44:29 -070072}
ivica7f6a6fc2015-09-08 02:40:29 -070073
stefan1d8a5062015-10-02 03:39:33 -070074bool LayerFilteringTransport::SendRtp(const uint8_t* packet,
75 size_t length,
76 const PacketOptions& options) {
sprangce4aef12015-11-02 07:23:20 -080077 if (selected_tl_ == -1 && selected_sl_ == -1) {
ivica7f6a6fc2015-09-08 02:40:29 -070078 // Nothing to change, forward the packet immediately.
stefan1d8a5062015-10-02 03:39:33 -070079 return test::DirectTransport::SendRtp(packet, length, options);
ivica7f6a6fc2015-09-08 02:40:29 -070080 }
81
82 bool set_marker_bit = false;
sprangce4aef12015-11-02 07:23:20 -080083 RtpUtility::RtpHeaderParser parser(packet, length);
ivica7f6a6fc2015-09-08 02:40:29 -070084 RTPHeader header;
danilchapf6975f42015-12-28 10:18:46 -080085 parser.Parse(&header);
sprangce4aef12015-11-02 07:23:20 -080086
Ilya Nikolaevskiy255d1cd2017-12-21 18:02:59 +010087 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
kwiberg352444f2016-11-28 15:58:53 -080092 RTC_DCHECK_LE(length, IP_PACKET_SIZE);
sprangce4aef12015-11-02 07:23:20 -080093 uint8_t temp_buffer[IP_PACKET_SIZE];
94 memcpy(temp_buffer, packet, length);
ivica7f6a6fc2015-09-08 02:40:29 -070095
96 if (header.payloadType == vp8_video_payload_type_ ||
97 header.payloadType == vp9_video_payload_type_) {
98 const uint8_t* payload = packet + header.headerLength;
henrikg91d6ede2015-09-17 00:24:34 -070099 RTC_DCHECK_GT(length, header.headerLength);
ivica7f6a6fc2015-09-08 02:40:29 -0700100 const size_t payload_length = length - header.headerLength;
henrikg91d6ede2015-09-17 00:24:34 -0700101 RTC_DCHECK_GT(payload_length, header.paddingLength);
ivica7f6a6fc2015-09-08 02:40:29 -0700102 const size_t payload_data_length = payload_length - header.paddingLength;
103
104 const bool is_vp8 = header.payloadType == vp8_video_payload_type_;
kwibergbfefb032016-05-01 14:53:46 -0700105 std::unique_ptr<RtpDepacketizer> depacketizer(
Niels Möller520ca4e2018-06-04 11:14:38 +0200106 RtpDepacketizer::Create(is_vp8 ? kVideoCodecVP8 : kVideoCodecVP9));
ivica7f6a6fc2015-09-08 02:40:29 -0700107 RtpDepacketizer::ParsedPayload parsed_payload;
108 if (depacketizer->Parse(&parsed_payload, payload, payload_data_length)) {
philipel29d88462018-08-08 14:26:00 +0200109 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 Eliassond52a1a62018-09-07 13:03:55 +0000115 temporal_idx = absl::get<RTPVideoHeaderVP8>(
116 parsed_payload.video_header().video_type_header)
117 .temporalIdx;
philipel29d88462018-08-08 14:26:00 +0200118 spatial_idx = kNoSpatialIdx;
“Michael23c5a992018-06-21 11:07:21 -0500119 num_active_spatial_layers_ = 1;
philipel29d88462018-08-08 14:26:00 +0200120 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 Silkin941fd432018-12-20 10:19:51 +0100129 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);
philipel29d88462018-08-08 14:26:00 +0200134 num_active_spatial_layers_ = vp9_header.num_spatial_layers;
135 }
136 }
137
138 if (spatial_idx == kNoSpatialIdx)
139 num_active_spatial_layers_ = 1;
140
“Michael23c5a992018-06-21 11:07:21 -0500141 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_) &&
philipel29d88462018-08-08 14:26:00 +0200146 end_of_frame) {
ivica7f6a6fc2015-09-08 02:40:29 -0700147 // This layer is now the last in the superframe.
148 set_marker_bit = true;
Sergey Silkin57027362018-05-15 09:12:05 +0200149 } 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 &&
“Michael23c5a992018-06-21 11:07:21 -0500162 spatial_idx <
163 std::min(num_active_spatial_layers_ - 1, selected_sl_) &&
164 non_ref_for_inter_layer_pred);
Sergey Silkin57027362018-05-15 09:12:05 +0200165
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 }
ivica7f6a6fc2015-09-08 02:40:29 -0700175 }
176 } else {
177 RTC_NOTREACHED() << "Parse error";
178 }
179 }
180
ivica7f6a6fc2015-09-08 02:40:29 -0700181 // 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.
ivicae78e2c72015-10-07 23:44:29 -0700184 if (set_marker_bit)
ivica7f6a6fc2015-09-08 02:40:29 -0700185 temp_buffer[1] |= kRtpMarkerBitMask;
ivica7f6a6fc2015-09-08 02:40:29 -0700186
stefan1d8a5062015-10-02 03:39:33 -0700187 return test::DirectTransport::SendRtp(temp_buffer, length, options);
ivica7f6a6fc2015-09-08 02:40:29 -0700188}
189
190} // namespace test
191} // namespace webrtc