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/include/rtp_rtcp_defines.h"
13 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
14 #include "webrtc/modules/rtp_rtcp/source/rtp_format.h"
15 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
16 #include "webrtc/test/layer_filtering_transport.h"
17
18 namespace webrtc {
19 namespace test {
20
LayerFilteringTransport(const FakeNetworkPipe::Config & config,Call * send_call,uint8_t vp8_video_payload_type,uint8_t vp9_video_payload_type,int selected_tl,int selected_sl)21 LayerFilteringTransport::LayerFilteringTransport(
22 const FakeNetworkPipe::Config& config,
23 Call* send_call,
24 uint8_t vp8_video_payload_type,
25 uint8_t vp9_video_payload_type,
26 int selected_tl,
27 int selected_sl)
28 : test::DirectTransport(config, send_call),
29 vp8_video_payload_type_(vp8_video_payload_type),
30 vp9_video_payload_type_(vp9_video_payload_type),
31 selected_tl_(selected_tl),
32 selected_sl_(selected_sl),
33 discarded_last_packet_(false) {}
34
DiscardedLastPacket() const35 bool LayerFilteringTransport::DiscardedLastPacket() const {
36 return discarded_last_packet_;
37 }
38
SendRtp(const uint8_t * packet,size_t length,const PacketOptions & options)39 bool LayerFilteringTransport::SendRtp(const uint8_t* packet,
40 size_t length,
41 const PacketOptions& options) {
42 if (selected_tl_ == -1 && selected_sl_ == -1) {
43 // Nothing to change, forward the packet immediately.
44 return test::DirectTransport::SendRtp(packet, length, options);
45 }
46
47 bool set_marker_bit = false;
48 RtpUtility::RtpHeaderParser parser(packet, length);
49 RTPHeader header;
50 parser.Parse(&header);
51
52 RTC_DCHECK_LE(length, static_cast<size_t>(IP_PACKET_SIZE));
53 uint8_t temp_buffer[IP_PACKET_SIZE];
54 memcpy(temp_buffer, packet, length);
55
56 if (header.payloadType == vp8_video_payload_type_ ||
57 header.payloadType == vp9_video_payload_type_) {
58 const uint8_t* payload = packet + header.headerLength;
59 RTC_DCHECK_GT(length, header.headerLength);
60 const size_t payload_length = length - header.headerLength;
61 RTC_DCHECK_GT(payload_length, header.paddingLength);
62 const size_t payload_data_length = payload_length - header.paddingLength;
63
64 const bool is_vp8 = header.payloadType == vp8_video_payload_type_;
65 rtc::scoped_ptr<RtpDepacketizer> depacketizer(
66 RtpDepacketizer::Create(is_vp8 ? kRtpVideoVp8 : kRtpVideoVp9));
67 RtpDepacketizer::ParsedPayload parsed_payload;
68 if (depacketizer->Parse(&parsed_payload, payload, payload_data_length)) {
69 const int temporal_idx = static_cast<int>(
70 is_vp8 ? parsed_payload.type.Video.codecHeader.VP8.temporalIdx
71 : parsed_payload.type.Video.codecHeader.VP9.temporal_idx);
72 const int spatial_idx = static_cast<int>(
73 is_vp8 ? kNoSpatialIdx
74 : parsed_payload.type.Video.codecHeader.VP9.spatial_idx);
75 if (selected_sl_ >= 0 && spatial_idx == selected_sl_ &&
76 parsed_payload.type.Video.codecHeader.VP9.end_of_frame) {
77 // This layer is now the last in the superframe.
78 set_marker_bit = true;
79 } else if ((selected_tl_ >= 0 && temporal_idx != kNoTemporalIdx &&
80 temporal_idx > selected_tl_) ||
81 (selected_sl_ >= 0 && spatial_idx != kNoSpatialIdx &&
82 spatial_idx > selected_sl_)) {
83 // Truncate packet to a padding packet.
84 length = header.headerLength + 1;
85 temp_buffer[0] |= (1 << 5); // P = 1.
86 temp_buffer[1] &= 0x7F; // M = 0.
87 discarded_last_packet_ = true;
88 temp_buffer[header.headerLength] = 1; // One byte of padding.
89 }
90 } else {
91 RTC_NOTREACHED() << "Parse error";
92 }
93 }
94
95 // We are discarding some of the packets (specifically, whole layers), so
96 // make sure the marker bit is set properly, and that sequence numbers are
97 // continuous.
98 if (set_marker_bit)
99 temp_buffer[1] |= kRtpMarkerBitMask;
100
101 return test::DirectTransport::SendRtp(temp_buffer, length, options);
102 }
103
104 } // namespace test
105 } // namespace webrtc
106