blob: 3a2a97ef5aedddcf2867b8f6ae846e75a4d69ddb [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
kwibergbfefb032016-05-01 14:53:46 -070011#include <memory>
12
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
14#include "modules/rtp_rtcp/source/byte_io.h"
15#include "modules/rtp_rtcp/source/rtp_format.h"
16#include "modules/rtp_rtcp/source/rtp_utility.h"
17#include "rtc_base/checks.h"
18#include "test/layer_filtering_transport.h"
ivica7f6a6fc2015-09-08 02:40:29 -070019
20namespace webrtc {
21namespace test {
22
23LayerFilteringTransport::LayerFilteringTransport(
eladalon413ee9a2017-08-22 04:02:52 -070024 SingleThreadedTaskQueueForTesting* task_queue,
ivica7f6a6fc2015-09-08 02:40:29 -070025 const FakeNetworkPipe::Config& config,
stefanf116bd02015-10-27 08:29:42 -070026 Call* send_call,
ivica7f6a6fc2015-09-08 02:40:29 -070027 uint8_t vp8_video_payload_type,
28 uint8_t vp9_video_payload_type,
sprangce4aef12015-11-02 07:23:20 -080029 int selected_tl,
minyue20c84cc2017-04-10 16:57:57 -070030 int selected_sl,
31 const std::map<uint8_t, MediaType>& payload_type_map)
eladalon413ee9a2017-08-22 04:02:52 -070032 : DirectTransport(task_queue, config, send_call, payload_type_map),
ivica7f6a6fc2015-09-08 02:40:29 -070033 vp8_video_payload_type_(vp8_video_payload_type),
34 vp9_video_payload_type_(vp9_video_payload_type),
sprangce4aef12015-11-02 07:23:20 -080035 selected_tl_(selected_tl),
36 selected_sl_(selected_sl),
37 discarded_last_packet_(false) {}
ivicae78e2c72015-10-07 23:44:29 -070038
sprangce4aef12015-11-02 07:23:20 -080039bool LayerFilteringTransport::DiscardedLastPacket() const {
40 return discarded_last_packet_;
ivicae78e2c72015-10-07 23:44:29 -070041}
ivica7f6a6fc2015-09-08 02:40:29 -070042
stefan1d8a5062015-10-02 03:39:33 -070043bool LayerFilteringTransport::SendRtp(const uint8_t* packet,
44 size_t length,
45 const PacketOptions& options) {
sprangce4aef12015-11-02 07:23:20 -080046 if (selected_tl_ == -1 && selected_sl_ == -1) {
ivica7f6a6fc2015-09-08 02:40:29 -070047 // Nothing to change, forward the packet immediately.
stefan1d8a5062015-10-02 03:39:33 -070048 return test::DirectTransport::SendRtp(packet, length, options);
ivica7f6a6fc2015-09-08 02:40:29 -070049 }
50
51 bool set_marker_bit = false;
sprangce4aef12015-11-02 07:23:20 -080052 RtpUtility::RtpHeaderParser parser(packet, length);
ivica7f6a6fc2015-09-08 02:40:29 -070053 RTPHeader header;
danilchapf6975f42015-12-28 10:18:46 -080054 parser.Parse(&header);
sprangce4aef12015-11-02 07:23:20 -080055
kwiberg352444f2016-11-28 15:58:53 -080056 RTC_DCHECK_LE(length, IP_PACKET_SIZE);
sprangce4aef12015-11-02 07:23:20 -080057 uint8_t temp_buffer[IP_PACKET_SIZE];
58 memcpy(temp_buffer, packet, length);
ivica7f6a6fc2015-09-08 02:40:29 -070059
60 if (header.payloadType == vp8_video_payload_type_ ||
61 header.payloadType == vp9_video_payload_type_) {
62 const uint8_t* payload = packet + header.headerLength;
henrikg91d6ede2015-09-17 00:24:34 -070063 RTC_DCHECK_GT(length, header.headerLength);
ivica7f6a6fc2015-09-08 02:40:29 -070064 const size_t payload_length = length - header.headerLength;
henrikg91d6ede2015-09-17 00:24:34 -070065 RTC_DCHECK_GT(payload_length, header.paddingLength);
ivica7f6a6fc2015-09-08 02:40:29 -070066 const size_t payload_data_length = payload_length - header.paddingLength;
67
68 const bool is_vp8 = header.payloadType == vp8_video_payload_type_;
kwibergbfefb032016-05-01 14:53:46 -070069 std::unique_ptr<RtpDepacketizer> depacketizer(
ivica7f6a6fc2015-09-08 02:40:29 -070070 RtpDepacketizer::Create(is_vp8 ? kRtpVideoVp8 : kRtpVideoVp9));
71 RtpDepacketizer::ParsedPayload parsed_payload;
72 if (depacketizer->Parse(&parsed_payload, payload, payload_data_length)) {
sprangce4aef12015-11-02 07:23:20 -080073 const int temporal_idx = static_cast<int>(
ivica7f6a6fc2015-09-08 02:40:29 -070074 is_vp8 ? parsed_payload.type.Video.codecHeader.VP8.temporalIdx
sprangce4aef12015-11-02 07:23:20 -080075 : parsed_payload.type.Video.codecHeader.VP9.temporal_idx);
76 const int spatial_idx = static_cast<int>(
ivica7f6a6fc2015-09-08 02:40:29 -070077 is_vp8 ? kNoSpatialIdx
sprangce4aef12015-11-02 07:23:20 -080078 : parsed_payload.type.Video.codecHeader.VP9.spatial_idx);
79 if (selected_sl_ >= 0 && spatial_idx == selected_sl_ &&
ivica7f6a6fc2015-09-08 02:40:29 -070080 parsed_payload.type.Video.codecHeader.VP9.end_of_frame) {
81 // This layer is now the last in the superframe.
82 set_marker_bit = true;
sprangce4aef12015-11-02 07:23:20 -080083 } else if ((selected_tl_ >= 0 && temporal_idx != kNoTemporalIdx &&
84 temporal_idx > selected_tl_) ||
85 (selected_sl_ >= 0 && spatial_idx != kNoSpatialIdx &&
ilnik68af10d2017-03-02 04:59:33 -080086 spatial_idx > selected_sl_)) {
sprangce4aef12015-11-02 07:23:20 -080087 // Truncate packet to a padding packet.
88 length = header.headerLength + 1;
89 temp_buffer[0] |= (1 << 5); // P = 1.
90 temp_buffer[1] &= 0x7F; // M = 0.
91 discarded_last_packet_ = true;
92 temp_buffer[header.headerLength] = 1; // One byte of padding.
ivica7f6a6fc2015-09-08 02:40:29 -070093 }
94 } else {
95 RTC_NOTREACHED() << "Parse error";
96 }
97 }
98
ivica7f6a6fc2015-09-08 02:40:29 -070099 // We are discarding some of the packets (specifically, whole layers), so
100 // make sure the marker bit is set properly, and that sequence numbers are
101 // continuous.
ivicae78e2c72015-10-07 23:44:29 -0700102 if (set_marker_bit)
ivica7f6a6fc2015-09-08 02:40:29 -0700103 temp_buffer[1] |= kRtpMarkerBitMask;
ivica7f6a6fc2015-09-08 02:40:29 -0700104
stefan1d8a5062015-10-02 03:39:33 -0700105 return test::DirectTransport::SendRtp(temp_buffer, length, options);
ivica7f6a6fc2015-09-08 02:40:29 -0700106}
107
108} // namespace test
109} // namespace webrtc