1c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin// Copyright 2014 The Chromium Authors. All rights reserved.
2c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin// Use of this source code is governed by a BSD-style license that can be
3c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin// found in the LICENSE file.
4c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
5c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin#include "bit_reader_core.h"
6c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
7c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin#include <stdint.h>
8c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
9c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin#include "base/sys_byteorder.h"
10c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
11c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Linnamespace {
12c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Linconst int kRegWidthInBits = sizeof(uint64_t) * 8;
13c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin}
14c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
15c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Linnamespace media {
16c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
17c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih LinBitReaderCore::ByteStreamProvider::ByteStreamProvider() {
18c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin}
19c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
20c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih LinBitReaderCore::ByteStreamProvider::~ByteStreamProvider() {
21c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin}
22c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
23c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih LinBitReaderCore::BitReaderCore(ByteStreamProvider* byte_stream_provider)
24c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    : byte_stream_provider_(byte_stream_provider),
25c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin      bits_read_(0),
26c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin      nbits_(0),
27c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin      reg_(0),
28c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin      nbits_next_(0),
29c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin      reg_next_(0) {
30c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin}
31c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
32c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih LinBitReaderCore::~BitReaderCore() {
33c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin}
34c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
35c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Linbool BitReaderCore::ReadFlag(bool* flag) {
36c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  if (nbits_ == 0 && !Refill(1))
37c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    return false;
38c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
39c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  *flag = (reg_ & (UINT64_C(1) << (kRegWidthInBits - 1))) != 0;
40c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  reg_ <<= 1;
41c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  nbits_--;
42c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  bits_read_++;
43c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  return true;
44c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin}
45c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
46c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Linint BitReaderCore::PeekBitsMsbAligned(int num_bits, uint64_t* out) {
47c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  // Try to have at least |num_bits| in the bit register.
48c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  if (nbits_ < num_bits)
49c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    Refill(num_bits);
50c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
51c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  *out = reg_;
52c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  return nbits_;
53c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin}
54c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
55c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Linbool BitReaderCore::SkipBitsSmall(int num_bits) {
56c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  DCHECK_GE(num_bits, 0);
57c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  uint64_t dummy;
58c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  while (num_bits >= kRegWidthInBits) {
59c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    if (!ReadBitsInternal(kRegWidthInBits, &dummy))
60c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin      return false;
61c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    num_bits -= kRegWidthInBits;
62c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  }
63c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  return ReadBitsInternal(num_bits, &dummy);
64c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin}
65c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
66c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Linbool BitReaderCore::SkipBits(int num_bits) {
67c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  DCHECK_GE(num_bits, 0);
68c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
69c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  const int remaining_bits = nbits_ + nbits_next_;
70c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  if (remaining_bits >= num_bits)
71c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    return SkipBitsSmall(num_bits);
72c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
73c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  // Skip first the remaining available bits.
74c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  num_bits -= remaining_bits;
75c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  bits_read_ += remaining_bits;
76c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  nbits_ = 0;
77c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  reg_ = 0;
78c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  nbits_next_ = 0;
79c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  reg_next_ = 0;
80c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
81c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  // Next, skip an integer number of bytes.
82c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  const int nbytes = num_bits / 8;
83c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  if (nbytes > 0) {
84c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    const uint8_t* byte_stream_window;
85c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    const int window_size =
86c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin        byte_stream_provider_->GetBytes(nbytes, &byte_stream_window);
87c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    DCHECK_GE(window_size, 0);
88c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    DCHECK_LE(window_size, nbytes);
89c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    if (window_size < nbytes) {
90c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin      // Note that some bytes were consumed.
91c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin      bits_read_ += 8 * window_size;
92c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin      return false;
93c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    }
94c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    num_bits -= 8 * nbytes;
95c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    bits_read_ += 8 * nbytes;
96c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  }
97c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
98c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  // Skip the remaining bits.
99c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  return SkipBitsSmall(num_bits);
100c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin}
101c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
102c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Linint BitReaderCore::bits_read() const {
103c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  return bits_read_;
104c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin}
105c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
106c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Linbool BitReaderCore::ReadBitsInternal(int num_bits, uint64_t* out) {
107c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  DCHECK_GE(num_bits, 0);
108c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
109c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  if (num_bits == 0) {
110c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    *out = 0;
111c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    return true;
112c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  }
113c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
114c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  if (num_bits > nbits_ && !Refill(num_bits)) {
115c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    // Any subsequent ReadBits should fail:
116c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    // empty the current bit register for that purpose.
117c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    nbits_ = 0;
118c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    reg_ = 0;
119c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    return false;
120c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  }
121c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
122c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  bits_read_ += num_bits;
123c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
124c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  if (num_bits == kRegWidthInBits) {
125c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    // Special case needed since for example for a 64 bit integer "a"
126c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    // "a << 64" is not defined by the C/C++ standard.
127c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    *out = reg_;
128c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    reg_ = 0;
129c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    nbits_ = 0;
130c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    return true;
131c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  }
132c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
133c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  *out = reg_ >> (kRegWidthInBits - num_bits);
134c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  reg_ <<= num_bits;
135c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  nbits_ -= num_bits;
136c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  return true;
137c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin}
138c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
139c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Linbool BitReaderCore::Refill(int min_nbits) {
140c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  DCHECK_LE(min_nbits, kRegWidthInBits);
141c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
142c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  // Transfer from the next to the current register.
143c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  RefillCurrentRegister();
144c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  if (min_nbits <= nbits_)
145c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    return true;
146c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  DCHECK_EQ(nbits_next_, 0);
147c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  DCHECK_EQ(reg_next_, 0u);
148c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
149c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  // Max number of bytes to refill.
150c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  int max_nbytes = sizeof(reg_next_);
151c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
152c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  // Refill.
153c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  const uint8_t* byte_stream_window;
154c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  int window_size =
155c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin      byte_stream_provider_->GetBytes(max_nbytes, &byte_stream_window);
156c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  DCHECK_GE(window_size, 0);
157c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  DCHECK_LE(window_size, max_nbytes);
158c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  if (window_size == 0)
159c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    return false;
160c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
161c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  reg_next_ = 0;
162c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  memcpy(&reg_next_, byte_stream_window, window_size);
163c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  reg_next_ = base::NetToHost64(reg_next_);
164c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  nbits_next_ = window_size * 8;
165c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
166c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  // Transfer from the next to the current register.
167c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  RefillCurrentRegister();
168c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
169c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  return (nbits_ >= min_nbits);
170c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin}
171c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
172c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Linvoid BitReaderCore::RefillCurrentRegister() {
173c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  // No refill possible if the destination register is full
174c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  // or the source register is empty.
175c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  if (nbits_ == kRegWidthInBits || nbits_next_ == 0)
176c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    return;
177c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
178c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  reg_ |= (reg_next_ >> nbits_);
179c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
180c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  int free_nbits = kRegWidthInBits - nbits_;
181c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  if (free_nbits >= nbits_next_) {
182c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    nbits_ += nbits_next_;
183c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    reg_next_ = 0;
184c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    nbits_next_ = 0;
185c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    return;
186c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  }
187c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
188c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  nbits_ += free_nbits;
189c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  reg_next_ <<= free_nbits;
190c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  nbits_next_ -= free_nbits;
191c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin}
192c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
193c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin}  // namespace media
194