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