tor-browser

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

h264_common.cc (3837B)


      1 /*
      2 *  Copyright (c) 2016 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 "common_video/h264/h264_common.h"
     12 
     13 #include <cstddef>
     14 #include <cstdint>
     15 #include <vector>
     16 
     17 #include "api/array_view.h"
     18 #include "rtc_base/buffer.h"
     19 
     20 namespace webrtc {
     21 namespace H264 {
     22 
     23 const uint8_t kNaluTypeMask = 0x1F;
     24 
     25 std::vector<NaluIndex> FindNaluIndices(ArrayView<const uint8_t> buffer) {
     26  // This is sorta like Boyer-Moore, but with only the first optimization step:
     27  // given a 3-byte sequence we're looking at, if the 3rd byte isn't 1 or 0,
     28  // skip ahead to the next 3-byte sequence. 0s and 1s are relatively rare, so
     29  // this will skip the majority of reads/checks.
     30  std::vector<NaluIndex> sequences;
     31  if (buffer.size() < kNaluShortStartSequenceSize)
     32    return sequences;
     33 
     34  static_assert(kNaluShortStartSequenceSize >= 2,
     35                "kNaluShortStartSequenceSize must be larger or equals to 2");
     36  const size_t end = buffer.size() - kNaluShortStartSequenceSize;
     37  for (size_t i = 0; i < end;) {
     38    if (buffer[i + 2] > 1) {
     39      i += 3;
     40    } else if (buffer[i + 2] == 1) {
     41      if (buffer[i + 1] == 0 && buffer[i] == 0) {
     42        // We found a start sequence, now check if it was a 3 of 4 byte one.
     43        NaluIndex index = {.start_offset = i,
     44                           .payload_start_offset = i + 3,
     45                           .payload_size = 0};
     46        if (index.start_offset > 0 && buffer[index.start_offset - 1] == 0)
     47          --index.start_offset;
     48 
     49        // Update length of previous entry.
     50        auto it = sequences.rbegin();
     51        if (it != sequences.rend())
     52          it->payload_size = index.start_offset - it->payload_start_offset;
     53 
     54        sequences.push_back(index);
     55      }
     56 
     57      i += 3;
     58    } else {
     59      ++i;
     60    }
     61  }
     62 
     63  // Update length of last entry, if any.
     64  auto it = sequences.rbegin();
     65  if (it != sequences.rend())
     66    it->payload_size = buffer.size() - it->payload_start_offset;
     67 
     68  return sequences;
     69 }
     70 
     71 NaluType ParseNaluType(uint8_t data) {
     72  return static_cast<NaluType>(data & kNaluTypeMask);
     73 }
     74 
     75 std::vector<uint8_t> ParseRbsp(ArrayView<const uint8_t> data) {
     76  std::vector<uint8_t> out;
     77  out.reserve(data.size());
     78 
     79  for (size_t i = 0; i < data.size();) {
     80    // Be careful about over/underflow here. byte_length_ - 3 can underflow, and
     81    // i + 3 can overflow, but byte_length_ - i can't, because i < byte_length_
     82    // above, and that expression will produce the number of bytes left in
     83    // the stream including the byte at i.
     84    if (data.size() - i >= 3 && !data[i] && !data[i + 1] && data[i + 2] == 3) {
     85      // Two rbsp bytes.
     86      out.push_back(data[i++]);
     87      out.push_back(data[i++]);
     88      // Skip the emulation byte.
     89      i++;
     90    } else {
     91      // Single rbsp byte.
     92      out.push_back(data[i++]);
     93    }
     94  }
     95  return out;
     96 }
     97 
     98 void WriteRbsp(ArrayView<const uint8_t> bytes, Buffer* destination) {
     99  static const uint8_t kZerosInStartSequence = 2;
    100  static const uint8_t kEmulationByte = 0x03u;
    101  size_t num_consecutive_zeros = 0;
    102  destination->EnsureCapacity(destination->size() + bytes.size());
    103 
    104  for (uint8_t byte : bytes) {
    105    if (byte <= kEmulationByte &&
    106        num_consecutive_zeros >= kZerosInStartSequence) {
    107      // Need to escape.
    108      destination->AppendData(kEmulationByte);
    109      num_consecutive_zeros = 0;
    110    }
    111    destination->AppendData(byte);
    112    if (byte == 0) {
    113      ++num_consecutive_zeros;
    114    } else {
    115      num_consecutive_zeros = 0;
    116    }
    117  }
    118 }
    119 
    120 }  // namespace H264
    121 }  // namespace webrtc