aboutsummaryrefslogtreecommitdiff
path: root/webrtc/test/layer_filtering_transport.cc
diff options
context:
space:
mode:
Diffstat (limited to 'webrtc/test/layer_filtering_transport.cc')
-rw-r--r--webrtc/test/layer_filtering_transport.cc106
1 files changed, 106 insertions, 0 deletions
diff --git a/webrtc/test/layer_filtering_transport.cc b/webrtc/test/layer_filtering_transport.cc
new file mode 100644
index 0000000000..a4ebf47f93
--- /dev/null
+++ b/webrtc/test/layer_filtering_transport.cc
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/base/checks.h"
+#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
+#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
+#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
+#include "webrtc/modules/rtp_rtcp/source/rtp_format.h"
+#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
+#include "webrtc/test/layer_filtering_transport.h"
+
+namespace webrtc {
+namespace test {
+
+LayerFilteringTransport::LayerFilteringTransport(
+ const FakeNetworkPipe::Config& config,
+ Call* send_call,
+ uint8_t vp8_video_payload_type,
+ uint8_t vp9_video_payload_type,
+ uint8_t tl_discard_threshold,
+ uint8_t sl_discard_threshold)
+ : test::DirectTransport(config, send_call),
+ vp8_video_payload_type_(vp8_video_payload_type),
+ vp9_video_payload_type_(vp9_video_payload_type),
+ tl_discard_threshold_(tl_discard_threshold),
+ sl_discard_threshold_(sl_discard_threshold) {}
+
+uint16_t LayerFilteringTransport::NextSequenceNumber(uint32_t ssrc) {
+ auto it = current_seq_nums_.find(ssrc);
+ if (it == current_seq_nums_.end())
+ return current_seq_nums_[ssrc] = 10000;
+ return ++it->second;
+}
+
+bool LayerFilteringTransport::SendRtp(const uint8_t* packet,
+ size_t length,
+ const PacketOptions& options) {
+ if (tl_discard_threshold_ == 0 && sl_discard_threshold_ == 0) {
+ // Nothing to change, forward the packet immediately.
+ return test::DirectTransport::SendRtp(packet, length, options);
+ }
+
+ bool set_marker_bit = false;
+ rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
+ RTPHeader header;
+ parser->Parse(packet, length, &header);
+
+ if (header.payloadType == vp8_video_payload_type_ ||
+ header.payloadType == vp9_video_payload_type_) {
+ const uint8_t* payload = packet + header.headerLength;
+ RTC_DCHECK_GT(length, header.headerLength);
+ const size_t payload_length = length - header.headerLength;
+ RTC_DCHECK_GT(payload_length, header.paddingLength);
+ const size_t payload_data_length = payload_length - header.paddingLength;
+
+ const bool is_vp8 = header.payloadType == vp8_video_payload_type_;
+ rtc::scoped_ptr<RtpDepacketizer> depacketizer(
+ RtpDepacketizer::Create(is_vp8 ? kRtpVideoVp8 : kRtpVideoVp9));
+ RtpDepacketizer::ParsedPayload parsed_payload;
+ if (depacketizer->Parse(&parsed_payload, payload, payload_data_length)) {
+ const uint8_t temporalIdx =
+ is_vp8 ? parsed_payload.type.Video.codecHeader.VP8.temporalIdx
+ : parsed_payload.type.Video.codecHeader.VP9.temporal_idx;
+ const uint8_t spatialIdx =
+ is_vp8 ? kNoSpatialIdx
+ : parsed_payload.type.Video.codecHeader.VP9.spatial_idx;
+ if (sl_discard_threshold_ > 0 &&
+ spatialIdx == sl_discard_threshold_ - 1 &&
+ parsed_payload.type.Video.codecHeader.VP9.end_of_frame) {
+ // This layer is now the last in the superframe.
+ set_marker_bit = true;
+ }
+ if ((tl_discard_threshold_ > 0 && temporalIdx != kNoTemporalIdx &&
+ temporalIdx >= tl_discard_threshold_) ||
+ (sl_discard_threshold_ > 0 && spatialIdx != kNoSpatialIdx &&
+ spatialIdx >= sl_discard_threshold_)) {
+ return true; // Discard the packet.
+ }
+ } else {
+ RTC_NOTREACHED() << "Parse error";
+ }
+ }
+
+ uint8_t temp_buffer[IP_PACKET_SIZE];
+ memcpy(temp_buffer, packet, length);
+
+ // We are discarding some of the packets (specifically, whole layers), so
+ // make sure the marker bit is set properly, and that sequence numbers are
+ // continuous.
+ if (set_marker_bit)
+ temp_buffer[1] |= kRtpMarkerBitMask;
+
+ uint16_t seq_num = NextSequenceNumber(header.ssrc);
+ ByteWriter<uint16_t>::WriteBigEndian(&temp_buffer[2], seq_num);
+ return test::DirectTransport::SendRtp(temp_buffer, length, options);
+}
+
+} // namespace test
+} // namespace webrtc