Home | History | Annotate | Download | only in test
      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 
     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 
     35 bool LayerFilteringTransport::DiscardedLastPacket() const {
     36   return discarded_last_packet_;
     37 }
     38 
     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