layer_filtering_transport.cc revision f116bd0d7a3cdad20bb638d5a87427bd920c8904
17f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica/*
27f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
37f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica *
47f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica *  Use of this source code is governed by a BSD-style license
57f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica *  that can be found in the LICENSE file in the root of the source
67f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica *  tree. An additional intellectual property rights grant can be found
77f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica *  in the file PATENTS.  All contributing project authors may
87f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica *  be found in the AUTHORS file in the root of the source tree.
97f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica */
107f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica
117f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica#include "webrtc/base/checks.h"
127f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
137f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
147f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
157f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica#include "webrtc/modules/rtp_rtcp/source/rtp_format.h"
167f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
177f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica#include "webrtc/test/layer_filtering_transport.h"
187f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica
197f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivicanamespace webrtc {
207f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivicanamespace test {
217f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica
227f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivicaLayerFilteringTransport::LayerFilteringTransport(
237f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    const FakeNetworkPipe::Config& config,
24f116bd0d7a3cdad20bb638d5a87427bd920c8904stefan    Call* send_call,
257f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    uint8_t vp8_video_payload_type,
267f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    uint8_t vp9_video_payload_type,
277a975f75e7fa7a9335411ef22b6687f78f7b297fsprang    uint8_t tl_discard_threshold,
287a975f75e7fa7a9335411ef22b6687f78f7b297fsprang    uint8_t sl_discard_threshold)
29f116bd0d7a3cdad20bb638d5a87427bd920c8904stefan    : test::DirectTransport(config, send_call),
307f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica      vp8_video_payload_type_(vp8_video_payload_type),
317f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica      vp9_video_payload_type_(vp9_video_payload_type),
327a975f75e7fa7a9335411ef22b6687f78f7b297fsprang      tl_discard_threshold_(tl_discard_threshold),
33f116bd0d7a3cdad20bb638d5a87427bd920c8904stefan      sl_discard_threshold_(sl_discard_threshold) {}
34e78e2c714bdbecb910526746d9e3678a245a8f8bivica
35e78e2c714bdbecb910526746d9e3678a245a8f8bivicauint16_t LayerFilteringTransport::NextSequenceNumber(uint32_t ssrc) {
36e78e2c714bdbecb910526746d9e3678a245a8f8bivica  auto it = current_seq_nums_.find(ssrc);
37e78e2c714bdbecb910526746d9e3678a245a8f8bivica  if (it == current_seq_nums_.end())
38e78e2c714bdbecb910526746d9e3678a245a8f8bivica    return current_seq_nums_[ssrc] = 10000;
39e78e2c714bdbecb910526746d9e3678a245a8f8bivica  return ++it->second;
40e78e2c714bdbecb910526746d9e3678a245a8f8bivica}
417f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica
421d8a506405734d0cef9653704b036ca4f1388960stefanbool LayerFilteringTransport::SendRtp(const uint8_t* packet,
431d8a506405734d0cef9653704b036ca4f1388960stefan                                      size_t length,
441d8a506405734d0cef9653704b036ca4f1388960stefan                                      const PacketOptions& options) {
457a975f75e7fa7a9335411ef22b6687f78f7b297fsprang  if (tl_discard_threshold_ == 0 && sl_discard_threshold_ == 0) {
467f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    // Nothing to change, forward the packet immediately.
471d8a506405734d0cef9653704b036ca4f1388960stefan    return test::DirectTransport::SendRtp(packet, length, options);
487f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica  }
497f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica
507f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica  bool set_marker_bit = false;
517f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica  rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
527f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica  RTPHeader header;
537f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica  parser->Parse(packet, length, &header);
547f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica
557f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica  if (header.payloadType == vp8_video_payload_type_ ||
567f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica      header.payloadType == vp9_video_payload_type_) {
577f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    const uint8_t* payload = packet + header.headerLength;
5891d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_DCHECK_GT(length, header.headerLength);
597f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    const size_t payload_length = length - header.headerLength;
6091d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_DCHECK_GT(payload_length, header.paddingLength);
617f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    const size_t payload_data_length = payload_length - header.paddingLength;
627f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica
637f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    const bool is_vp8 = header.payloadType == vp8_video_payload_type_;
647f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    rtc::scoped_ptr<RtpDepacketizer> depacketizer(
657f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica        RtpDepacketizer::Create(is_vp8 ? kRtpVideoVp8 : kRtpVideoVp9));
667f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    RtpDepacketizer::ParsedPayload parsed_payload;
677f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    if (depacketizer->Parse(&parsed_payload, payload, payload_data_length)) {
687a975f75e7fa7a9335411ef22b6687f78f7b297fsprang      const uint8_t temporalIdx =
697f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica          is_vp8 ? parsed_payload.type.Video.codecHeader.VP8.temporalIdx
707a975f75e7fa7a9335411ef22b6687f78f7b297fsprang                 : parsed_payload.type.Video.codecHeader.VP9.temporal_idx;
717a975f75e7fa7a9335411ef22b6687f78f7b297fsprang      const uint8_t spatialIdx =
727f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica          is_vp8 ? kNoSpatialIdx
737a975f75e7fa7a9335411ef22b6687f78f7b297fsprang                 : parsed_payload.type.Video.codecHeader.VP9.spatial_idx;
747a975f75e7fa7a9335411ef22b6687f78f7b297fsprang      if (sl_discard_threshold_ > 0 &&
757a975f75e7fa7a9335411ef22b6687f78f7b297fsprang          spatialIdx == sl_discard_threshold_ - 1 &&
767f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica          parsed_payload.type.Video.codecHeader.VP9.end_of_frame) {
777f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica        // This layer is now the last in the superframe.
787f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica        set_marker_bit = true;
797f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica      }
807a975f75e7fa7a9335411ef22b6687f78f7b297fsprang      if ((tl_discard_threshold_ > 0 && temporalIdx != kNoTemporalIdx &&
817a975f75e7fa7a9335411ef22b6687f78f7b297fsprang           temporalIdx >= tl_discard_threshold_) ||
827a975f75e7fa7a9335411ef22b6687f78f7b297fsprang          (sl_discard_threshold_ > 0 && spatialIdx != kNoSpatialIdx &&
837a975f75e7fa7a9335411ef22b6687f78f7b297fsprang           spatialIdx >= sl_discard_threshold_)) {
847a975f75e7fa7a9335411ef22b6687f78f7b297fsprang        return true;  // Discard the packet.
857f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica      }
867f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    } else {
877f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica      RTC_NOTREACHED() << "Parse error";
887f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    }
897f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica  }
907f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica
917f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica  uint8_t temp_buffer[IP_PACKET_SIZE];
927f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica  memcpy(temp_buffer, packet, length);
937f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica
947f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica  // We are discarding some of the packets (specifically, whole layers), so
957f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica  // make sure the marker bit is set properly, and that sequence numbers are
967f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica  // continuous.
97e78e2c714bdbecb910526746d9e3678a245a8f8bivica  if (set_marker_bit)
987f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    temp_buffer[1] |= kRtpMarkerBitMask;
997f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica
100e78e2c714bdbecb910526746d9e3678a245a8f8bivica  uint16_t seq_num = NextSequenceNumber(header.ssrc);
101e78e2c714bdbecb910526746d9e3678a245a8f8bivica  ByteWriter<uint16_t>::WriteBigEndian(&temp_buffer[2], seq_num);
1021d8a506405734d0cef9653704b036ca4f1388960stefan  return test::DirectTransport::SendRtp(temp_buffer, length, options);
1037f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica}
1047f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica
1057f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica}  // namespace test
1067f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica}  // namespace webrtc
107