blob: ad6e117131fd1c7836399c9117d8843a39e15692 [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"
Danil Chapovalova3ecb7a2019-12-09 10:24:47 +010021#include "modules/rtp_rtcp/source/create_video_rtp_depacketizer.h"
Yves Gerey3e707812018-11-28 16:47:49 +010022#include "modules/rtp_rtcp/source/rtp_video_header.h"
Danil Chapovalova3ecb7a2019-12-09 10:24:47 +010023#include "modules/rtp_rtcp/source/video_rtp_depacketizer.h"
Yves Gerey3e707812018-11-28 16:47:49 +010024#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(
Danil Chapovalov85a10002019-10-21 15:00:53 +020033 TaskQueueBase* 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),
Danil Chapovalova3ecb7a2019-12-09 10:24:47 +010046 vp8_depacketizer_(CreateVideoRtpDepacketizer(kVideoCodecVP8)),
47 vp9_depacketizer_(CreateVideoRtpDepacketizer(kVideoCodecVP9)),
Ilya Nikolaevskiy255d1cd2017-12-21 18:02:59 +010048 selected_tl_(selected_tl),
49 selected_sl_(selected_sl),
50 discarded_last_packet_(false),
51 ssrc_to_filter_min_(ssrc_to_filter_min),
52 ssrc_to_filter_max_(ssrc_to_filter_max) {}
53
54LayerFilteringTransport::LayerFilteringTransport(
Danil Chapovalov85a10002019-10-21 15:00:53 +020055 TaskQueueBase* task_queue,
Artem Titov46c4e602018-08-17 14:26:54 +020056 std::unique_ptr<SimulatedPacketReceiverInterface> pipe,
Christoffer Rodbrob4bb4eb2017-11-13 13:03:52 +010057 Call* send_call,
58 uint8_t vp8_video_payload_type,
59 uint8_t vp9_video_payload_type,
60 int selected_tl,
Sebastian Jansson09408112018-04-24 14:41:22 +020061 int selected_sl,
62 const std::map<uint8_t, MediaType>& payload_type_map)
Danil Chapovalova3ecb7a2019-12-09 10:24:47 +010063 : LayerFilteringTransport(task_queue,
64 std::move(pipe),
65 send_call,
66 vp8_video_payload_type,
67 vp9_video_payload_type,
68 selected_tl,
69 selected_sl,
70 payload_type_map,
71 /*ssrc_to_filter_min=*/0,
72 /*ssrc_to_filter_max=*/0xFFFFFFFF) {}
Christoffer Rodbrob4bb4eb2017-11-13 13:03:52 +010073
sprangce4aef12015-11-02 07:23:20 -080074bool LayerFilteringTransport::DiscardedLastPacket() const {
75 return discarded_last_packet_;
ivicae78e2c72015-10-07 23:44:29 -070076}
ivica7f6a6fc2015-09-08 02:40:29 -070077
stefan1d8a5062015-10-02 03:39:33 -070078bool LayerFilteringTransport::SendRtp(const uint8_t* packet,
79 size_t length,
80 const PacketOptions& options) {
sprangce4aef12015-11-02 07:23:20 -080081 if (selected_tl_ == -1 && selected_sl_ == -1) {
ivica7f6a6fc2015-09-08 02:40:29 -070082 // Nothing to change, forward the packet immediately.
stefan1d8a5062015-10-02 03:39:33 -070083 return test::DirectTransport::SendRtp(packet, length, options);
ivica7f6a6fc2015-09-08 02:40:29 -070084 }
85
Danil Chapovalova3ecb7a2019-12-09 10:24:47 +010086 RtpPacket rtp_packet;
87 rtp_packet.Parse(packet, length);
sprangce4aef12015-11-02 07:23:20 -080088
Danil Chapovalova3ecb7a2019-12-09 10:24:47 +010089 if (rtp_packet.Ssrc() < ssrc_to_filter_min_ ||
90 rtp_packet.Ssrc() > ssrc_to_filter_max_) {
Ilya Nikolaevskiy255d1cd2017-12-21 18:02:59 +010091 // Nothing to change, forward the packet immediately.
92 return test::DirectTransport::SendRtp(packet, length, options);
93 }
94
Danil Chapovalova3ecb7a2019-12-09 10:24:47 +010095 if (rtp_packet.PayloadType() == vp8_video_payload_type_ ||
96 rtp_packet.PayloadType() == vp9_video_payload_type_) {
97 const bool is_vp8 = rtp_packet.PayloadType() == vp8_video_payload_type_;
98 VideoRtpDepacketizer& depacketizer =
99 is_vp8 ? *vp8_depacketizer_ : *vp9_depacketizer_;
100 if (auto parsed_payload = depacketizer.Parse(rtp_packet.PayloadBuffer())) {
philipel29d88462018-08-08 14:26:00 +0200101 int temporal_idx;
102 int spatial_idx;
103 bool non_ref_for_inter_layer_pred;
104 bool end_of_frame;
105
106 if (is_vp8) {
Philip Eliassond52a1a62018-09-07 13:03:55 +0000107 temporal_idx = absl::get<RTPVideoHeaderVP8>(
Danil Chapovalova3ecb7a2019-12-09 10:24:47 +0100108 parsed_payload->video_header.video_type_header)
Philip Eliassond52a1a62018-09-07 13:03:55 +0000109 .temporalIdx;
philipel29d88462018-08-08 14:26:00 +0200110 spatial_idx = kNoSpatialIdx;
“Michael23c5a992018-06-21 11:07:21 -0500111 num_active_spatial_layers_ = 1;
philipel29d88462018-08-08 14:26:00 +0200112 non_ref_for_inter_layer_pred = false;
113 end_of_frame = true;
114 } else {
115 const auto& vp9_header = absl::get<RTPVideoHeaderVP9>(
Danil Chapovalova3ecb7a2019-12-09 10:24:47 +0100116 parsed_payload->video_header.video_type_header);
philipel29d88462018-08-08 14:26:00 +0200117 temporal_idx = vp9_header.temporal_idx;
118 spatial_idx = vp9_header.spatial_idx;
119 non_ref_for_inter_layer_pred = vp9_header.non_ref_for_inter_layer_pred;
120 end_of_frame = vp9_header.end_of_frame;
Sergey Silkin941fd432018-12-20 10:19:51 +0100121 if (vp9_header.ss_data_available) {
122 RTC_DCHECK(vp9_header.temporal_idx == kNoTemporalIdx ||
123 vp9_header.temporal_idx == 0);
124 RTC_DCHECK(vp9_header.spatial_idx == kNoSpatialIdx ||
125 vp9_header.spatial_idx == 0);
philipel29d88462018-08-08 14:26:00 +0200126 num_active_spatial_layers_ = vp9_header.num_spatial_layers;
127 }
128 }
129
130 if (spatial_idx == kNoSpatialIdx)
131 num_active_spatial_layers_ = 1;
132
“Michael23c5a992018-06-21 11:07:21 -0500133 RTC_CHECK_GT(num_active_spatial_layers_, 0);
134
135 if (selected_sl_ >= 0 &&
136 spatial_idx ==
137 std::min(num_active_spatial_layers_ - 1, selected_sl_) &&
philipel29d88462018-08-08 14:26:00 +0200138 end_of_frame) {
ivica7f6a6fc2015-09-08 02:40:29 -0700139 // This layer is now the last in the superframe.
Danil Chapovalova3ecb7a2019-12-09 10:24:47 +0100140 rtp_packet.SetMarker(true);
Sergey Silkin57027362018-05-15 09:12:05 +0200141 } else {
142 const bool higher_temporal_layer =
143 (selected_tl_ >= 0 && temporal_idx != kNoTemporalIdx &&
144 temporal_idx > selected_tl_);
145
146 const bool higher_spatial_layer =
147 (selected_sl_ >= 0 && spatial_idx != kNoSpatialIdx &&
148 spatial_idx > selected_sl_);
149
150 // Filter out non-reference lower spatial layers since they are not
151 // needed for decoding of target spatial layer.
152 const bool lower_non_ref_spatial_layer =
153 (selected_sl_ >= 0 && spatial_idx != kNoSpatialIdx &&
“Michael23c5a992018-06-21 11:07:21 -0500154 spatial_idx <
155 std::min(num_active_spatial_layers_ - 1, selected_sl_) &&
156 non_ref_for_inter_layer_pred);
Sergey Silkin57027362018-05-15 09:12:05 +0200157
158 if (higher_temporal_layer || higher_spatial_layer ||
159 lower_non_ref_spatial_layer) {
160 // Truncate packet to a padding packet.
Danil Chapovalova3ecb7a2019-12-09 10:24:47 +0100161 rtp_packet.SetPayloadSize(0);
162 rtp_packet.SetPadding(1);
163 rtp_packet.SetMarker(false);
Sergey Silkin57027362018-05-15 09:12:05 +0200164 discarded_last_packet_ = true;
Sergey Silkin57027362018-05-15 09:12:05 +0200165 }
ivica7f6a6fc2015-09-08 02:40:29 -0700166 }
167 } else {
168 RTC_NOTREACHED() << "Parse error";
169 }
170 }
171
Danil Chapovalova3ecb7a2019-12-09 10:24:47 +0100172 return test::DirectTransport::SendRtp(rtp_packet.data(), rtp_packet.size(),
173 options);
ivica7f6a6fc2015-09-08 02:40:29 -0700174}
175
176} // namespace test
177} // namespace webrtc