tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

session_info.cc (18374B)


      1 /*
      2 *  Copyright (c) 2012 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 "modules/video_coding/deprecated/session_info.h"
     12 
     13 #include <cstdint>
     14 #include <cstring>
     15 #include <iterator>
     16 #include <variant>
     17 #include <vector>
     18 
     19 #include "absl/algorithm/container.h"
     20 #include "api/video/video_codec_type.h"
     21 #include "api/video/video_frame_type.h"
     22 #include "modules/include/module_common_types_public.h"
     23 #include "modules/video_coding/codecs/h264/include/h264_globals.h"
     24 #include "modules/video_coding/codecs/interface/common_constants.h"
     25 #include "modules/video_coding/codecs/vp8/include/vp8_globals.h"
     26 #include "modules/video_coding/codecs/vp9/include/vp9_globals.h"
     27 #include "modules/video_coding/deprecated/jitter_buffer_common.h"
     28 #include "modules/video_coding/deprecated/packet.h"
     29 #include "rtc_base/checks.h"
     30 #include "rtc_base/logging.h"
     31 
     32 namespace webrtc {
     33 
     34 namespace {
     35 
     36 uint16_t BufferToUWord16(const uint8_t* dataBuffer) {
     37  return (dataBuffer[0] << 8) | dataBuffer[1];
     38 }
     39 
     40 }  // namespace
     41 
     42 VCMSessionInfo::VCMSessionInfo()
     43    : complete_(false),
     44      frame_type_(VideoFrameType::kVideoFrameDelta),
     45      packets_(),
     46      empty_seq_num_low_(-1),
     47      empty_seq_num_high_(-1),
     48      first_packet_seq_num_(-1),
     49      last_packet_seq_num_(-1) {}
     50 
     51 VCMSessionInfo::~VCMSessionInfo() {}
     52 
     53 void VCMSessionInfo::UpdateDataPointers(const uint8_t* old_base_ptr,
     54                                        const uint8_t* new_base_ptr) {
     55  for (PacketIterator it = packets_.begin(); it != packets_.end(); ++it)
     56    if ((*it).dataPtr != nullptr) {
     57      RTC_DCHECK(old_base_ptr != nullptr && new_base_ptr != nullptr);
     58      (*it).dataPtr = new_base_ptr + ((*it).dataPtr - old_base_ptr);
     59    }
     60 }
     61 
     62 int VCMSessionInfo::LowSequenceNumber() const {
     63  if (packets_.empty())
     64    return empty_seq_num_low_;
     65  return packets_.front().seqNum;
     66 }
     67 
     68 int VCMSessionInfo::HighSequenceNumber() const {
     69  if (packets_.empty())
     70    return empty_seq_num_high_;
     71  if (empty_seq_num_high_ == -1)
     72    return packets_.back().seqNum;
     73  return LatestSequenceNumber(packets_.back().seqNum, empty_seq_num_high_);
     74 }
     75 
     76 int VCMSessionInfo::PictureId() const {
     77  if (packets_.empty())
     78    return kNoPictureId;
     79  if (packets_.front().video_header.codec == kVideoCodecVP8) {
     80    return std::get<RTPVideoHeaderVP8>(
     81               packets_.front().video_header.video_type_header)
     82        .pictureId;
     83  } else if (packets_.front().video_header.codec == kVideoCodecVP9) {
     84    return std::get<RTPVideoHeaderVP9>(
     85               packets_.front().video_header.video_type_header)
     86        .picture_id;
     87  } else {
     88    return kNoPictureId;
     89  }
     90 }
     91 
     92 int VCMSessionInfo::TemporalId() const {
     93  if (packets_.empty())
     94    return kNoTemporalIdx;
     95  if (packets_.front().video_header.codec == kVideoCodecVP8) {
     96    return std::get<RTPVideoHeaderVP8>(
     97               packets_.front().video_header.video_type_header)
     98        .temporalIdx;
     99  } else if (packets_.front().video_header.codec == kVideoCodecVP9) {
    100    return std::get<RTPVideoHeaderVP9>(
    101               packets_.front().video_header.video_type_header)
    102        .temporal_idx;
    103  } else {
    104    return kNoTemporalIdx;
    105  }
    106 }
    107 
    108 bool VCMSessionInfo::LayerSync() const {
    109  if (packets_.empty())
    110    return false;
    111  if (packets_.front().video_header.codec == kVideoCodecVP8) {
    112    return std::get<RTPVideoHeaderVP8>(
    113               packets_.front().video_header.video_type_header)
    114        .layerSync;
    115  } else if (packets_.front().video_header.codec == kVideoCodecVP9) {
    116    return std::get<RTPVideoHeaderVP9>(
    117               packets_.front().video_header.video_type_header)
    118        .temporal_up_switch;
    119  } else {
    120    return false;
    121  }
    122 }
    123 
    124 int VCMSessionInfo::Tl0PicId() const {
    125  if (packets_.empty())
    126    return kNoTl0PicIdx;
    127  if (packets_.front().video_header.codec == kVideoCodecVP8) {
    128    return std::get<RTPVideoHeaderVP8>(
    129               packets_.front().video_header.video_type_header)
    130        .tl0PicIdx;
    131  } else if (packets_.front().video_header.codec == kVideoCodecVP9) {
    132    return std::get<RTPVideoHeaderVP9>(
    133               packets_.front().video_header.video_type_header)
    134        .tl0_pic_idx;
    135  } else {
    136    return kNoTl0PicIdx;
    137  }
    138 }
    139 
    140 std::vector<NaluInfo> VCMSessionInfo::GetNaluInfos() const {
    141  if (packets_.empty() ||
    142      packets_.front().video_header.codec != kVideoCodecH264)
    143    return std::vector<NaluInfo>();
    144  std::vector<NaluInfo> nalu_infos;
    145  for (const VCMPacket& packet : packets_) {
    146    const auto& h264 =
    147        std::get<RTPVideoHeaderH264>(packet.video_header.video_type_header);
    148    absl::c_copy(h264.nalus, std::back_inserter(nalu_infos));
    149  }
    150  return nalu_infos;
    151 }
    152 
    153 void VCMSessionInfo::SetGofInfo(const GofInfoVP9& gof_info, size_t idx) {
    154  if (packets_.empty())
    155    return;
    156 
    157  auto* vp9_header = std::get_if<RTPVideoHeaderVP9>(
    158      &packets_.front().video_header.video_type_header);
    159  if (!vp9_header || vp9_header->flexible_mode)
    160    return;
    161 
    162  vp9_header->temporal_idx = gof_info.temporal_idx[idx];
    163  vp9_header->temporal_up_switch = gof_info.temporal_up_switch[idx];
    164  vp9_header->num_ref_pics = gof_info.num_ref_pics[idx];
    165  for (uint8_t i = 0; i < gof_info.num_ref_pics[idx]; ++i) {
    166    vp9_header->pid_diff[i] = gof_info.pid_diff[idx][i];
    167  }
    168 }
    169 
    170 void VCMSessionInfo::Reset() {
    171  complete_ = false;
    172  frame_type_ = VideoFrameType::kVideoFrameDelta;
    173  packets_.clear();
    174  empty_seq_num_low_ = -1;
    175  empty_seq_num_high_ = -1;
    176  first_packet_seq_num_ = -1;
    177  last_packet_seq_num_ = -1;
    178 }
    179 
    180 size_t VCMSessionInfo::SessionLength() const {
    181  size_t length = 0;
    182  for (PacketIteratorConst it = packets_.begin(); it != packets_.end(); ++it)
    183    length += (*it).sizeBytes;
    184  return length;
    185 }
    186 
    187 int VCMSessionInfo::NumPackets() const {
    188  return packets_.size();
    189 }
    190 
    191 size_t VCMSessionInfo::InsertBuffer(uint8_t* frame_buffer,
    192                                    PacketIterator packet_it) {
    193  VCMPacket& packet = *packet_it;
    194  PacketIterator it;
    195 
    196  // Calculate the offset into the frame buffer for this packet.
    197  size_t offset = 0;
    198  for (it = packets_.begin(); it != packet_it; ++it)
    199    offset += (*it).sizeBytes;
    200 
    201  // Set the data pointer to pointing to the start of this packet in the
    202  // frame buffer.
    203  const uint8_t* packet_buffer = packet.dataPtr;
    204  packet.dataPtr = frame_buffer + offset;
    205 
    206  // We handle H.264 STAP-A packets in a special way as we need to remove the
    207  // two length bytes between each NAL unit, and potentially add start codes.
    208  // TODO(pbos): Remove H264 parsing from this step and use a fragmentation
    209  // header supplied by the H264 depacketizer.
    210  const size_t kH264NALHeaderLengthInBytes = 1;
    211  const size_t kLengthFieldLength = 2;
    212  const auto* h264 =
    213      std::get_if<RTPVideoHeaderH264>(&packet.video_header.video_type_header);
    214  if (h264 && h264->packetization_type == kH264StapA) {
    215    size_t required_length = 0;
    216    const uint8_t* nalu_ptr = packet_buffer + kH264NALHeaderLengthInBytes;
    217    while (nalu_ptr < packet_buffer + packet.sizeBytes) {
    218      size_t length = BufferToUWord16(nalu_ptr);
    219      required_length +=
    220          length + (packet.insertStartCode ? kH264StartCodeLengthBytes : 0);
    221      nalu_ptr += kLengthFieldLength + length;
    222    }
    223    ShiftSubsequentPackets(packet_it, required_length);
    224    nalu_ptr = packet_buffer + kH264NALHeaderLengthInBytes;
    225    uint8_t* frame_buffer_ptr = frame_buffer + offset;
    226    while (nalu_ptr < packet_buffer + packet.sizeBytes) {
    227      size_t length = BufferToUWord16(nalu_ptr);
    228      nalu_ptr += kLengthFieldLength;
    229      frame_buffer_ptr += Insert(nalu_ptr, length, packet.insertStartCode,
    230                                 const_cast<uint8_t*>(frame_buffer_ptr));
    231      nalu_ptr += length;
    232    }
    233    packet.sizeBytes = required_length;
    234    return packet.sizeBytes;
    235  }
    236  ShiftSubsequentPackets(
    237      packet_it, packet.sizeBytes +
    238                     (packet.insertStartCode ? kH264StartCodeLengthBytes : 0));
    239 
    240  packet.sizeBytes =
    241      Insert(packet_buffer, packet.sizeBytes, packet.insertStartCode,
    242             const_cast<uint8_t*>(packet.dataPtr));
    243  return packet.sizeBytes;
    244 }
    245 
    246 size_t VCMSessionInfo::Insert(const uint8_t* buffer,
    247                              size_t length,
    248                              bool insert_start_code,
    249                              uint8_t* frame_buffer) {
    250  if (!buffer || !frame_buffer) {
    251    return 0;
    252  }
    253  if (insert_start_code) {
    254    const unsigned char startCode[] = {0, 0, 0, 1};
    255    memcpy(frame_buffer, startCode, kH264StartCodeLengthBytes);
    256  }
    257  memcpy(frame_buffer + (insert_start_code ? kH264StartCodeLengthBytes : 0),
    258         buffer, length);
    259  length += (insert_start_code ? kH264StartCodeLengthBytes : 0);
    260 
    261  return length;
    262 }
    263 
    264 void VCMSessionInfo::ShiftSubsequentPackets(PacketIterator it,
    265                                            int steps_to_shift) {
    266  ++it;
    267  if (it == packets_.end())
    268    return;
    269  uint8_t* first_packet_ptr = const_cast<uint8_t*>((*it).dataPtr);
    270  int shift_length = 0;
    271  // Calculate the total move length and move the data pointers in advance.
    272  for (; it != packets_.end(); ++it) {
    273    shift_length += (*it).sizeBytes;
    274    if ((*it).dataPtr != nullptr)
    275      (*it).dataPtr += steps_to_shift;
    276  }
    277  memmove(first_packet_ptr + steps_to_shift, first_packet_ptr, shift_length);
    278 }
    279 
    280 void VCMSessionInfo::UpdateCompleteSession() {
    281  if (HaveFirstPacket() && HaveLastPacket()) {
    282    // Do we have all the packets in this session?
    283    bool complete_session = true;
    284    PacketIterator it = packets_.begin();
    285    PacketIterator prev_it = it;
    286    ++it;
    287    for (; it != packets_.end(); ++it) {
    288      if (!InSequence(it, prev_it)) {
    289        complete_session = false;
    290        break;
    291      }
    292      prev_it = it;
    293    }
    294    complete_ = complete_session;
    295  }
    296 }
    297 
    298 bool VCMSessionInfo::complete() const {
    299  return complete_;
    300 }
    301 
    302 // Find the end of the NAL unit which the packet pointed to by `packet_it`
    303 // belongs to. Returns an iterator to the last packet of the frame if the end
    304 // of the NAL unit wasn't found.
    305 VCMSessionInfo::PacketIterator VCMSessionInfo::FindNaluEnd(
    306    PacketIterator packet_it) const {
    307  if ((*packet_it).completeNALU == kNaluEnd ||
    308      (*packet_it).completeNALU == kNaluComplete) {
    309    return packet_it;
    310  }
    311  // Find the end of the NAL unit.
    312  for (; packet_it != packets_.end(); ++packet_it) {
    313    if (((*packet_it).completeNALU == kNaluComplete &&
    314         (*packet_it).sizeBytes > 0) ||
    315        // Found next NALU.
    316        (*packet_it).completeNALU == kNaluStart)
    317      return --packet_it;
    318    if ((*packet_it).completeNALU == kNaluEnd)
    319      return packet_it;
    320  }
    321  // The end wasn't found.
    322  return --packet_it;
    323 }
    324 
    325 size_t VCMSessionInfo::DeletePacketData(PacketIterator start,
    326                                        PacketIterator end) {
    327  size_t bytes_to_delete = 0;  // The number of bytes to delete.
    328  PacketIterator packet_after_end = end;
    329  ++packet_after_end;
    330 
    331  // Get the number of bytes to delete.
    332  // Clear the size of these packets.
    333  for (PacketIterator it = start; it != packet_after_end; ++it) {
    334    bytes_to_delete += (*it).sizeBytes;
    335    (*it).sizeBytes = 0;
    336    (*it).dataPtr = nullptr;
    337  }
    338  if (bytes_to_delete > 0)
    339    ShiftSubsequentPackets(end, -static_cast<int>(bytes_to_delete));
    340  return bytes_to_delete;
    341 }
    342 
    343 VCMSessionInfo::PacketIterator VCMSessionInfo::FindNextPartitionBeginning(
    344    PacketIterator it) const {
    345  while (it != packets_.end()) {
    346    if (std::get<RTPVideoHeaderVP8>((*it).video_header.video_type_header)
    347            .beginningOfPartition) {
    348      return it;
    349    }
    350    ++it;
    351  }
    352  return it;
    353 }
    354 
    355 VCMSessionInfo::PacketIterator VCMSessionInfo::FindPartitionEnd(
    356    PacketIterator it) const {
    357  RTC_DCHECK_EQ((*it).codec(), kVideoCodecVP8);
    358  PacketIterator prev_it = it;
    359  const int partition_id =
    360      std::get<RTPVideoHeaderVP8>((*it).video_header.video_type_header)
    361          .partitionId;
    362  while (it != packets_.end()) {
    363    bool beginning =
    364        std::get<RTPVideoHeaderVP8>((*it).video_header.video_type_header)
    365            .beginningOfPartition;
    366    int current_partition_id =
    367        std::get<RTPVideoHeaderVP8>((*it).video_header.video_type_header)
    368            .partitionId;
    369    bool packet_loss_found = (!beginning && !InSequence(it, prev_it));
    370    if (packet_loss_found ||
    371        (beginning && current_partition_id != partition_id)) {
    372      // Missing packet, the previous packet was the last in sequence.
    373      return prev_it;
    374    }
    375    prev_it = it;
    376    ++it;
    377  }
    378  return prev_it;
    379 }
    380 
    381 bool VCMSessionInfo::InSequence(const PacketIterator& packet_it,
    382                                const PacketIterator& prev_packet_it) {
    383  // If the two iterators are pointing to the same packet they are considered
    384  // to be in sequence.
    385  return (packet_it == prev_packet_it ||
    386          (static_cast<uint16_t>((*prev_packet_it).seqNum + 1) ==
    387           (*packet_it).seqNum));
    388 }
    389 
    390 size_t VCMSessionInfo::MakeDecodable() {
    391  size_t return_length = 0;
    392  if (packets_.empty()) {
    393    return 0;
    394  }
    395  PacketIterator it = packets_.begin();
    396  // Make sure we remove the first NAL unit if it's not decodable.
    397  if ((*it).completeNALU == kNaluIncomplete || (*it).completeNALU == kNaluEnd) {
    398    PacketIterator nalu_end = FindNaluEnd(it);
    399    return_length += DeletePacketData(it, nalu_end);
    400    it = nalu_end;
    401  }
    402  PacketIterator prev_it = it;
    403  // Take care of the rest of the NAL units.
    404  for (; it != packets_.end(); ++it) {
    405    bool start_of_nalu = ((*it).completeNALU == kNaluStart ||
    406                          (*it).completeNALU == kNaluComplete);
    407    if (!start_of_nalu && !InSequence(it, prev_it)) {
    408      // Found a sequence number gap due to packet loss.
    409      PacketIterator nalu_end = FindNaluEnd(it);
    410      return_length += DeletePacketData(it, nalu_end);
    411      it = nalu_end;
    412    }
    413    prev_it = it;
    414  }
    415  return return_length;
    416 }
    417 
    418 bool VCMSessionInfo::HaveFirstPacket() const {
    419  return !packets_.empty() && (first_packet_seq_num_ != -1);
    420 }
    421 
    422 bool VCMSessionInfo::HaveLastPacket() const {
    423  return !packets_.empty() && (last_packet_seq_num_ != -1);
    424 }
    425 
    426 int VCMSessionInfo::InsertPacket(const VCMPacket& packet,
    427                                 uint8_t* frame_buffer,
    428                                 const FrameData& /* frame_data */) {
    429  if (packet.video_header.frame_type == VideoFrameType::kEmptyFrame) {
    430    // Update sequence number of an empty packet.
    431    // Only media packets are inserted into the packet list.
    432    InformOfEmptyPacket(packet.seqNum);
    433    return 0;
    434  }
    435 
    436  if (packets_.size() == kMaxPacketsInSession) {
    437    RTC_LOG(LS_ERROR) << "Max number of packets per frame has been reached.";
    438    return -1;
    439  }
    440 
    441  // Find the position of this packet in the packet list in sequence number
    442  // order and insert it. Loop over the list in reverse order.
    443  ReversePacketIterator rit = packets_.rbegin();
    444  for (; rit != packets_.rend(); ++rit)
    445    if (LatestSequenceNumber(packet.seqNum, (*rit).seqNum) == packet.seqNum)
    446      break;
    447 
    448  // Check for duplicate packets.
    449  if (rit != packets_.rend() && (*rit).seqNum == packet.seqNum &&
    450      (*rit).sizeBytes > 0)
    451    return -2;
    452 
    453  if (packet.codec() == kVideoCodecH264) {
    454    frame_type_ = packet.video_header.frame_type;
    455    if (packet.is_first_packet_in_frame() &&
    456        (first_packet_seq_num_ == -1 ||
    457         IsNewerSequenceNumber(first_packet_seq_num_, packet.seqNum))) {
    458      first_packet_seq_num_ = packet.seqNum;
    459    }
    460    if (packet.markerBit &&
    461        (last_packet_seq_num_ == -1 ||
    462         IsNewerSequenceNumber(packet.seqNum, last_packet_seq_num_))) {
    463      last_packet_seq_num_ = packet.seqNum;
    464    }
    465  } else {
    466    // Only insert media packets between first and last packets (when
    467    // available).
    468    // Placing check here, as to properly account for duplicate packets.
    469    // Check if this is first packet (only valid for some codecs)
    470    // Should only be set for one packet per session.
    471    if (packet.is_first_packet_in_frame() && first_packet_seq_num_ == -1) {
    472      // The first packet in a frame signals the frame type.
    473      frame_type_ = packet.video_header.frame_type;
    474      // Store the sequence number for the first packet.
    475      first_packet_seq_num_ = static_cast<int>(packet.seqNum);
    476    } else if (first_packet_seq_num_ != -1 &&
    477               IsNewerSequenceNumber(first_packet_seq_num_, packet.seqNum)) {
    478      RTC_LOG(LS_WARNING)
    479          << "Received packet with a sequence number which is out "
    480             "of frame boundaries";
    481      return -3;
    482    } else if (frame_type_ == VideoFrameType::kEmptyFrame &&
    483               packet.video_header.frame_type != VideoFrameType::kEmptyFrame) {
    484      // Update the frame type with the type of the first media packet.
    485      // TODO(mikhal): Can this trigger?
    486      frame_type_ = packet.video_header.frame_type;
    487    }
    488 
    489    // Track the marker bit, should only be set for one packet per session.
    490    if (packet.markerBit && last_packet_seq_num_ == -1) {
    491      last_packet_seq_num_ = static_cast<int>(packet.seqNum);
    492    } else if (last_packet_seq_num_ != -1 &&
    493               IsNewerSequenceNumber(packet.seqNum, last_packet_seq_num_)) {
    494      RTC_LOG(LS_WARNING)
    495          << "Received packet with a sequence number which is out "
    496             "of frame boundaries";
    497      return -3;
    498    }
    499  }
    500 
    501  // The insert operation invalidates the iterator `rit`.
    502  PacketIterator packet_list_it = packets_.insert(rit.base(), packet);
    503 
    504  size_t returnLength = InsertBuffer(frame_buffer, packet_list_it);
    505  UpdateCompleteSession();
    506 
    507  return static_cast<int>(returnLength);
    508 }
    509 
    510 void VCMSessionInfo::InformOfEmptyPacket(uint16_t seq_num) {
    511  // Empty packets may be FEC or filler packets. They are sequential and
    512  // follow the data packets, therefore, we should only keep track of the high
    513  // and low sequence numbers and may assume that the packets in between are
    514  // empty packets belonging to the same frame (timestamp).
    515  if (empty_seq_num_high_ == -1)
    516    empty_seq_num_high_ = seq_num;
    517  else
    518    empty_seq_num_high_ = LatestSequenceNumber(seq_num, empty_seq_num_high_);
    519  if (empty_seq_num_low_ == -1 ||
    520      IsNewerSequenceNumber(empty_seq_num_low_, seq_num))
    521    empty_seq_num_low_ = seq_num;
    522 }
    523 
    524 }  // namespace webrtc