tor-browser

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

frame_buffer.cc (8783B)


      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/frame_buffer.h"
     12 
     13 #include <cstdint>
     14 #include <cstring>
     15 #include <vector>
     16 
     17 #include "api/video/encoded_image.h"
     18 #include "api/video/video_frame_type.h"
     19 #include "api/video/video_timing.h"
     20 #include "modules/video_coding/codecs/h264/include/h264_globals.h"
     21 #include "modules/video_coding/codecs/vp9/include/vp9_globals.h"
     22 #include "modules/video_coding/deprecated/jitter_buffer_common.h"
     23 #include "modules/video_coding/deprecated/packet.h"
     24 #include "modules/video_coding/deprecated/session_info.h"
     25 #include "modules/video_coding/encoded_frame.h"
     26 #include "rtc_base/checks.h"
     27 #include "rtc_base/logging.h"
     28 #include "rtc_base/trace_event.h"
     29 
     30 namespace webrtc {
     31 
     32 VCMFrameBuffer::VCMFrameBuffer()
     33    : _state(kStateEmpty), _nackCount(0), _latestPacketTimeMs(-1) {}
     34 
     35 VCMFrameBuffer::~VCMFrameBuffer() {}
     36 
     37 VideoFrameType VCMFrameBuffer::FrameType() const {
     38  return _sessionInfo.FrameType();
     39 }
     40 
     41 int32_t VCMFrameBuffer::GetLowSeqNum() const {
     42  return _sessionInfo.LowSequenceNumber();
     43 }
     44 
     45 int32_t VCMFrameBuffer::GetHighSeqNum() const {
     46  return _sessionInfo.HighSequenceNumber();
     47 }
     48 
     49 int VCMFrameBuffer::PictureId() const {
     50  return _sessionInfo.PictureId();
     51 }
     52 
     53 int VCMFrameBuffer::TemporalId() const {
     54  return _sessionInfo.TemporalId();
     55 }
     56 
     57 bool VCMFrameBuffer::LayerSync() const {
     58  return _sessionInfo.LayerSync();
     59 }
     60 
     61 int VCMFrameBuffer::Tl0PicId() const {
     62  return _sessionInfo.Tl0PicId();
     63 }
     64 
     65 std::vector<NaluInfo> VCMFrameBuffer::GetNaluInfos() const {
     66  return _sessionInfo.GetNaluInfos();
     67 }
     68 
     69 void VCMFrameBuffer::SetGofInfo(const GofInfoVP9& gof_info, size_t idx) {
     70  TRACE_EVENT0("webrtc", "VCMFrameBuffer::SetGofInfo");
     71  _sessionInfo.SetGofInfo(gof_info, idx);
     72  // TODO(asapersson): Consider adding hdr->VP9.ref_picture_id for testing.
     73  _codecSpecificInfo.codecSpecific.VP9.temporal_idx =
     74      gof_info.temporal_idx[idx];
     75  _codecSpecificInfo.codecSpecific.VP9.temporal_up_switch =
     76      gof_info.temporal_up_switch[idx];
     77 }
     78 
     79 // Insert packet
     80 VCMFrameBufferEnum VCMFrameBuffer::InsertPacket(const VCMPacket& packet,
     81                                                int64_t timeInMs,
     82                                                const FrameData& frame_data) {
     83  TRACE_EVENT0("webrtc", "VCMFrameBuffer::InsertPacket");
     84  RTC_DCHECK(!(nullptr == packet.dataPtr && packet.sizeBytes > 0));
     85  if (packet.dataPtr != nullptr) {
     86    _payloadType = packet.payloadType;
     87  }
     88 
     89  if (kStateEmpty == _state) {
     90    // First packet (empty and/or media) inserted into this frame.
     91    // store some info and set some initial values.
     92    SetRtpTimestamp(packet.timestamp);
     93    // We only take the ntp timestamp of the first packet of a frame.
     94    ntp_time_ms_ = packet.ntp_time_ms_;
     95    _codec = packet.codec();
     96    if (packet.video_header.frame_type != VideoFrameType::kEmptyFrame) {
     97      // first media packet
     98      SetState(kStateIncomplete);
     99    }
    100  }
    101 
    102  size_t oldSize = encoded_image_buffer_ ? encoded_image_buffer_->size() : 0;
    103  uint32_t requiredSizeBytes =
    104      size() + packet.sizeBytes +
    105      (packet.insertStartCode ? kH264StartCodeLengthBytes : 0);
    106  if (requiredSizeBytes > oldSize) {
    107    const uint8_t* prevBuffer = data();
    108    const uint32_t increments =
    109        requiredSizeBytes / kBufferIncStepSizeBytes +
    110        (requiredSizeBytes % kBufferIncStepSizeBytes > 0);
    111    const uint32_t newSize = oldSize + increments * kBufferIncStepSizeBytes;
    112    if (newSize > kMaxJBFrameSizeBytes) {
    113      RTC_LOG(LS_ERROR) << "Failed to insert packet due to frame being too "
    114                           "big.";
    115      return kSizeError;
    116    }
    117    if (data() == nullptr) {
    118      encoded_image_buffer_ = EncodedImageBuffer::Create(newSize);
    119      SetEncodedData(encoded_image_buffer_);
    120      set_size(0);
    121    } else {
    122      RTC_CHECK(encoded_image_buffer_ != nullptr);
    123      RTC_DCHECK_EQ(encoded_image_buffer_->data(), data());
    124      encoded_image_buffer_->Realloc(newSize);
    125    }
    126    _sessionInfo.UpdateDataPointers(prevBuffer, data());
    127  }
    128 
    129  if (packet.width() > 0 && packet.height() > 0) {
    130    _encodedWidth = packet.width();
    131    _encodedHeight = packet.height();
    132  }
    133 
    134  // Don't copy payload specific data for empty packets (e.g padding packets).
    135  if (packet.sizeBytes > 0)
    136    CopyCodecSpecific(&packet.video_header);
    137 
    138  int retVal = _sessionInfo.InsertPacket(
    139      packet, encoded_image_buffer_ ? encoded_image_buffer_->data() : nullptr,
    140      frame_data);
    141  if (retVal == -1) {
    142    return kSizeError;
    143  } else if (retVal == -2) {
    144    return kDuplicatePacket;
    145  } else if (retVal == -3) {
    146    return kOutOfBoundsPacket;
    147  }
    148  // update size
    149  set_size(size() + static_cast<uint32_t>(retVal));
    150 
    151  _latestPacketTimeMs = timeInMs;
    152 
    153  // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/
    154  // ts_126114v120700p.pdf Section 7.4.5.
    155  // The MTSI client shall add the payload bytes as defined in this clause
    156  // onto the last RTP packet in each group of packets which make up a key
    157  // frame (I-frame or IDR frame in H.264 (AVC), or an IRAP picture in H.265
    158  // (HEVC)).
    159  if (packet.markerBit) {
    160    rotation_ = packet.video_header.rotation;
    161    content_type_ = packet.video_header.content_type;
    162    if (packet.video_header.video_timing.flags != VideoSendTiming::kInvalid) {
    163      timing_.encode_start_ms =
    164          ntp_time_ms_ + packet.video_header.video_timing.encode_start_delta_ms;
    165      timing_.encode_finish_ms =
    166          ntp_time_ms_ +
    167          packet.video_header.video_timing.encode_finish_delta_ms;
    168      timing_.packetization_finish_ms =
    169          ntp_time_ms_ +
    170          packet.video_header.video_timing.packetization_finish_delta_ms;
    171      timing_.pacer_exit_ms =
    172          ntp_time_ms_ + packet.video_header.video_timing.pacer_exit_delta_ms;
    173      timing_.network_timestamp_ms =
    174          ntp_time_ms_ +
    175          packet.video_header.video_timing.network_timestamp_delta_ms;
    176      timing_.network2_timestamp_ms =
    177          ntp_time_ms_ +
    178          packet.video_header.video_timing.network2_timestamp_delta_ms;
    179    }
    180    timing_.flags = packet.video_header.video_timing.flags;
    181  }
    182 
    183  if (packet.is_first_packet_in_frame()) {
    184    SetPlayoutDelay(packet.video_header.playout_delay);
    185  }
    186 
    187  if (_sessionInfo.complete()) {
    188    SetState(kStateComplete);
    189    return kCompleteSession;
    190  }
    191  return kIncomplete;
    192 }
    193 
    194 int64_t VCMFrameBuffer::LatestPacketTimeMs() const {
    195  TRACE_EVENT0("webrtc", "VCMFrameBuffer::LatestPacketTimeMs");
    196  return _latestPacketTimeMs;
    197 }
    198 
    199 void VCMFrameBuffer::IncrementNackCount() {
    200  TRACE_EVENT0("webrtc", "VCMFrameBuffer::IncrementNackCount");
    201  _nackCount++;
    202 }
    203 
    204 int16_t VCMFrameBuffer::GetNackCount() const {
    205  TRACE_EVENT0("webrtc", "VCMFrameBuffer::GetNackCount");
    206  return _nackCount;
    207 }
    208 
    209 bool VCMFrameBuffer::HaveFirstPacket() const {
    210  TRACE_EVENT0("webrtc", "VCMFrameBuffer::HaveFirstPacket");
    211  return _sessionInfo.HaveFirstPacket();
    212 }
    213 
    214 int VCMFrameBuffer::NumPackets() const {
    215  TRACE_EVENT0("webrtc", "VCMFrameBuffer::NumPackets");
    216  return _sessionInfo.NumPackets();
    217 }
    218 
    219 void VCMFrameBuffer::Reset() {
    220  TRACE_EVENT0("webrtc", "VCMFrameBuffer::Reset");
    221  set_size(0);
    222  _sessionInfo.Reset();
    223  _payloadType = 0;
    224  _nackCount = 0;
    225  _latestPacketTimeMs = -1;
    226  _state = kStateEmpty;
    227  VCMEncodedFrame::Reset();
    228 }
    229 
    230 // Set state of frame
    231 void VCMFrameBuffer::SetState(VCMFrameBufferStateEnum state) {
    232  TRACE_EVENT0("webrtc", "VCMFrameBuffer::SetState");
    233  if (_state == state) {
    234    return;
    235  }
    236  switch (state) {
    237    case kStateIncomplete:
    238      // we can go to this state from state kStateEmpty
    239      RTC_DCHECK_EQ(_state, kStateEmpty);
    240 
    241      // Do nothing, we received a packet
    242      break;
    243 
    244    case kStateComplete:
    245      RTC_DCHECK(_state == kStateEmpty || _state == kStateIncomplete);
    246 
    247      break;
    248 
    249    case kStateEmpty:
    250      // Should only be set to empty through Reset().
    251      RTC_DCHECK_NOTREACHED();
    252      break;
    253  }
    254  _state = state;
    255 }
    256 
    257 // Get current state of frame
    258 VCMFrameBufferStateEnum VCMFrameBuffer::GetState() const {
    259  return _state;
    260 }
    261 
    262 void VCMFrameBuffer::PrepareForDecode(bool continuous) {
    263  TRACE_EVENT0("webrtc", "VCMFrameBuffer::PrepareForDecode");
    264  size_t bytes_removed = _sessionInfo.MakeDecodable();
    265  set_size(size() - bytes_removed);
    266  // Transfer frame information to EncodedFrame and create any codec
    267  // specific information.
    268  _frameType = _sessionInfo.FrameType();
    269  _missingFrame = !continuous;
    270 }
    271 
    272 }  // namespace webrtc