layer_filtering_transport.cc revision 91d6edef35e7275879c30ce16ecb8b6dc73c6e4a
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 11#include "webrtc/base/checks.h" 12#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" 13#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" 14#include "webrtc/modules/rtp_rtcp/source/byte_io.h" 15#include "webrtc/modules/rtp_rtcp/source/rtp_format.h" 16#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" 17#include "webrtc/test/layer_filtering_transport.h" 18 19namespace webrtc { 20namespace test { 21 22LayerFilteringTransport::LayerFilteringTransport( 23 const FakeNetworkPipe::Config& config, 24 uint8_t vp8_video_payload_type, 25 uint8_t vp9_video_payload_type, 26 uint8_t tl_discard_threshold, 27 uint8_t sl_discard_threshold) 28 : test::DirectTransport(config), 29 vp8_video_payload_type_(vp8_video_payload_type), 30 vp9_video_payload_type_(vp9_video_payload_type), 31 tl_discard_threshold_(tl_discard_threshold), 32 sl_discard_threshold_(sl_discard_threshold), 33 current_seq_num_(10000) { 34} // TODO(ivica): random seq num? 35 36bool LayerFilteringTransport::SendRtp(const uint8_t* packet, size_t length) { 37 if (tl_discard_threshold_ == 0 && sl_discard_threshold_ == 0) { 38 // Nothing to change, forward the packet immediately. 39 return test::DirectTransport::SendRtp(packet, length); 40 } 41 42 bool set_marker_bit = false; 43 rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create()); 44 RTPHeader header; 45 parser->Parse(packet, length, &header); 46 47 if (header.payloadType == vp8_video_payload_type_ || 48 header.payloadType == vp9_video_payload_type_) { 49 const uint8_t* payload = packet + header.headerLength; 50 RTC_DCHECK_GT(length, header.headerLength); 51 const size_t payload_length = length - header.headerLength; 52 RTC_DCHECK_GT(payload_length, header.paddingLength); 53 const size_t payload_data_length = payload_length - header.paddingLength; 54 55 const bool is_vp8 = header.payloadType == vp8_video_payload_type_; 56 rtc::scoped_ptr<RtpDepacketizer> depacketizer( 57 RtpDepacketizer::Create(is_vp8 ? kRtpVideoVp8 : kRtpVideoVp9)); 58 RtpDepacketizer::ParsedPayload parsed_payload; 59 if (depacketizer->Parse(&parsed_payload, payload, payload_data_length)) { 60 const uint8_t temporalIdx = 61 is_vp8 ? parsed_payload.type.Video.codecHeader.VP8.temporalIdx 62 : parsed_payload.type.Video.codecHeader.VP9.temporal_idx; 63 const uint8_t spatialIdx = 64 is_vp8 ? kNoSpatialIdx 65 : parsed_payload.type.Video.codecHeader.VP9.spatial_idx; 66 if (sl_discard_threshold_ > 0 && 67 spatialIdx == sl_discard_threshold_ - 1 && 68 parsed_payload.type.Video.codecHeader.VP9.end_of_frame) { 69 // This layer is now the last in the superframe. 70 set_marker_bit = true; 71 } 72 if ((tl_discard_threshold_ > 0 && temporalIdx != kNoTemporalIdx && 73 temporalIdx >= tl_discard_threshold_) || 74 (sl_discard_threshold_ > 0 && spatialIdx != kNoSpatialIdx && 75 spatialIdx >= sl_discard_threshold_)) { 76 return true; // Discard the packet. 77 } 78 } else { 79 RTC_NOTREACHED() << "Parse error"; 80 } 81 } 82 83 uint8_t temp_buffer[IP_PACKET_SIZE]; 84 memcpy(temp_buffer, packet, length); 85 86 // We are discarding some of the packets (specifically, whole layers), so 87 // make sure the marker bit is set properly, and that sequence numbers are 88 // continuous. 89 if (set_marker_bit) { 90 temp_buffer[1] |= kRtpMarkerBitMask; 91 } 92 ByteWriter<uint16_t>::WriteBigEndian(&temp_buffer[2], current_seq_num_); 93 94 ++current_seq_num_; // Increase only if packet not discarded. 95 96 return test::DirectTransport::SendRtp(temp_buffer, length); 97} 98 99} // namespace test 100} // namespace webrtc 101