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"
12ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
13ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
147f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica#include "webrtc/modules/rtp_rtcp/source/rtp_format.h"
157f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
167f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica#include "webrtc/test/layer_filtering_transport.h"
177f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica
187f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivicanamespace webrtc {
197f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivicanamespace test {
207f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica
217f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivicaLayerFilteringTransport::LayerFilteringTransport(
227f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    const FakeNetworkPipe::Config& config,
23f116bd0d7a3cdad20bb638d5a87427bd920c8904stefan    Call* send_call,
247f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    uint8_t vp8_video_payload_type,
257f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    uint8_t vp9_video_payload_type,
26ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang    int selected_tl,
27ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang    int selected_sl)
28f116bd0d7a3cdad20bb638d5a87427bd920c8904stefan    : test::DirectTransport(config, send_call),
297f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica      vp8_video_payload_type_(vp8_video_payload_type),
307f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica      vp9_video_payload_type_(vp9_video_payload_type),
31ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang      selected_tl_(selected_tl),
32ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang      selected_sl_(selected_sl),
33ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang      discarded_last_packet_(false) {}
34e78e2c714bdbecb910526746d9e3678a245a8f8bivica
35ce4aef16eec96862199e89b6d3ffe059558ac2c0sprangbool LayerFilteringTransport::DiscardedLastPacket() const {
36ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang  return discarded_last_packet_;
37e78e2c714bdbecb910526746d9e3678a245a8f8bivica}
387f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica
391d8a506405734d0cef9653704b036ca4f1388960stefanbool LayerFilteringTransport::SendRtp(const uint8_t* packet,
401d8a506405734d0cef9653704b036ca4f1388960stefan                                      size_t length,
411d8a506405734d0cef9653704b036ca4f1388960stefan                                      const PacketOptions& options) {
42ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang  if (selected_tl_ == -1 && selected_sl_ == -1) {
437f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    // Nothing to change, forward the packet immediately.
441d8a506405734d0cef9653704b036ca4f1388960stefan    return test::DirectTransport::SendRtp(packet, length, options);
457f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica  }
467f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica
477f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica  bool set_marker_bit = false;
48ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang  RtpUtility::RtpHeaderParser parser(packet, length);
497f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica  RTPHeader header;
50f6975f46131981f83e0c88d276dee6b6c5753180danilchap  parser.Parse(&header);
51ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang
52ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang  RTC_DCHECK_LE(length, static_cast<size_t>(IP_PACKET_SIZE));
53ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang  uint8_t temp_buffer[IP_PACKET_SIZE];
54ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang  memcpy(temp_buffer, packet, length);
557f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica
567f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica  if (header.payloadType == vp8_video_payload_type_ ||
577f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica      header.payloadType == vp9_video_payload_type_) {
587f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    const uint8_t* payload = packet + header.headerLength;
5991d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_DCHECK_GT(length, header.headerLength);
607f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    const size_t payload_length = length - header.headerLength;
6191d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_DCHECK_GT(payload_length, header.paddingLength);
627f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    const size_t payload_data_length = payload_length - header.paddingLength;
637f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica
647f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    const bool is_vp8 = header.payloadType == vp8_video_payload_type_;
657f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    rtc::scoped_ptr<RtpDepacketizer> depacketizer(
667f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica        RtpDepacketizer::Create(is_vp8 ? kRtpVideoVp8 : kRtpVideoVp9));
677f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    RtpDepacketizer::ParsedPayload parsed_payload;
687f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    if (depacketizer->Parse(&parsed_payload, payload, payload_data_length)) {
69ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang      const int temporal_idx = static_cast<int>(
707f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica          is_vp8 ? parsed_payload.type.Video.codecHeader.VP8.temporalIdx
71ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang                 : parsed_payload.type.Video.codecHeader.VP9.temporal_idx);
72ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang      const int spatial_idx = static_cast<int>(
737f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica          is_vp8 ? kNoSpatialIdx
74ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang                 : parsed_payload.type.Video.codecHeader.VP9.spatial_idx);
75ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang      if (selected_sl_ >= 0 && spatial_idx == selected_sl_ &&
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;
79ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang      } else if ((selected_tl_ >= 0 && temporal_idx != kNoTemporalIdx &&
80ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang                  temporal_idx > selected_tl_) ||
81ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang                 (selected_sl_ >= 0 && spatial_idx != kNoSpatialIdx &&
82ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang                  spatial_idx > selected_sl_)) {
83ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang        // Truncate packet to a padding packet.
84ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang        length = header.headerLength + 1;
85ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang        temp_buffer[0] |= (1 << 5);  // P = 1.
86ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang        temp_buffer[1] &= 0x7F;      // M = 0.
87ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang        discarded_last_packet_ = true;
88ce4aef16eec96862199e89b6d3ffe059558ac2c0sprang        temp_buffer[header.headerLength] = 1;  // One byte of padding.
897f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica      }
907f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    } else {
917f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica      RTC_NOTREACHED() << "Parse error";
927f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    }
937f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica  }
947f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica
957f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica  // We are discarding some of the packets (specifically, whole layers), so
967f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica  // make sure the marker bit is set properly, and that sequence numbers are
977f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica  // continuous.
98e78e2c714bdbecb910526746d9e3678a245a8f8bivica  if (set_marker_bit)
997f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica    temp_buffer[1] |= kRtpMarkerBitMask;
1007f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica
1011d8a506405734d0cef9653704b036ca4f1388960stefan  return test::DirectTransport::SendRtp(temp_buffer, length, options);
1027f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica}
1037f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica
1047f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica}  // namespace test
1057f6a6fc0b23795cd4f0aacbf707618c1f3d0a878ivica}  // namespace webrtc
106