Shaka Player Embedded
buffer_reader.cc
Go to the documentation of this file.
1 // Copyright 2017 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/util/buffer_reader.h"
16 
17 #include <glog/logging.h>
18 
19 #include <algorithm>
20 #include <cmath>
21 #include <cstring>
22 
23 namespace shaka {
24 namespace util {
25 
26 BufferReader::BufferReader() : data_(nullptr), size_(0), bit_offset_(0) {}
27 BufferReader::BufferReader(const uint8_t* data, size_t data_size)
28  : data_(data), size_(data_size), bit_offset_(0) {}
29 
30 void BufferReader::SetBuffer(const uint8_t* data, size_t data_size) {
31  data_ = data;
32  size_ = data_size;
33  bit_offset_ = 0;
34 }
35 
36 size_t BufferReader::Read(uint8_t* dest, size_t dest_size) {
37  if (bit_offset_ == 0) {
38  const uint8_t* src = data_;
39  const size_t to_read = Skip(dest_size);
40  std::memcpy(dest, src, to_read);
41  return to_read;
42  } else {
43  size_t i = 0;
44  while (!empty()) {
45  dest[i] = static_cast<uint8_t>(ReadBits(8));
46  i++;
47  }
48  return i;
49  }
50 }
51 
52 size_t BufferReader::SkipBits(size_t count) {
53  const size_t capacity = size_ * 8 - bit_offset_;
54  const size_t to_read = std::min(count, capacity);
55  const size_t to_read_bytes = (bit_offset_ + to_read) / 8;
56  DCHECK_LE(to_read_bytes, size_);
57  data_ += to_read_bytes;
58  size_ -= to_read_bytes;
59  bit_offset_ = (bit_offset_ + to_read) % 8;
60  return to_read;
61 }
62 
63 uint64_t BufferReader::ReadBits(size_t count, Endianness endianness) {
64  DCHECK_LE(count, 64);
65  DCHECK(endianness == kBigEndian || (bit_offset_ == 0 && count % 8 == 0));
66  uint64_t ret = 0;
67 
68  for (size_t i = 0; i < count && size_ > 0;) {
69  // Read a single byte, only keeping a part of it for sub-byte reads.
70  // Sub-byte reads are always big-endian.
71  // 0 1 1 0 1 1 0 1
72  // |bit_offset_| c | c=count
73  // |
74  // result=0b10
75  const size_t bits_remain = 8 - bit_offset_;
76  const size_t to_read = std::min(count - i, bits_remain);
77  const size_t shift = bits_remain - to_read;
78  const size_t mask = ((1 << to_read) - 1);
79  const uint8_t part = (data_[0] >> shift) & mask;
80  if (endianness == kBigEndian)
81  ret |= part << (count - i - to_read);
82  else
83  ret |= part << i;
84 
85  if (bit_offset_ + to_read == 8) {
86  data_++;
87  size_--;
88  bit_offset_ = 0;
89  } else {
90  DCHECK_LT(bit_offset_ + to_read, 8);
91  bit_offset_ += to_read;
92  }
93  i += to_read;
94  }
95 
96  return ret;
97 }
98 
100  // See https://en.wikipedia.org/wiki/Exponential-Golomb_coding
101  size_t count = 0;
102  while (!empty() && ReadBits(1) == 0)
103  count++;
104  return (1 << count) - 1 + ReadBits(count);
105 }
106 
107 } // namespace util
108 } // namespace shaka
const char * dest
Definition: media_utils.cc:31
size_t Skip(size_t count)
Definition: buffer_reader.h:75
size_t SkipBits(size_t count)
uint64_t ReadBits(size_t count, Endianness endianness=kBigEndian)
const uint8_t * data() const
Definition: buffer_reader.h:47
void SetBuffer(const uint8_t *data, size_t data_size)
size_t Read(uint8_t *dest, size_t dest_size)