1c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin// Copyright 2016 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.
4a21d5d577bdc284457867409e2a9c3b4a665d152Johny Lin// Note: ported from Chromium commit head: 1323b9c
5c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
6c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin#include "vp9_bool_decoder.h"
7c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
8c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin#include <algorithm>
9c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
10c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin#include "base/logging.h"
11c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin#include "bit_reader.h"
12c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
13c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Linnamespace media {
14c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
15c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Linnamespace {
16c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
17c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin// This is an optimization lookup table for the loop in spec 9.2.2.
18c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin//     while BoolRange <= 128:
19c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin//       read 1 bit
20c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin//       BoolRange *= 2
21c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin// This table indicates how many iterations to run for a given BoolRange. So
22c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin// the loop could be reduced to
23c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin//     read (kCountToShiftTo128[BoolRange]) bits
24c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Linconst int kCountToShiftTo128[256] = {
25c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
26c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
27c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
28c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
29c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
30c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
31c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
32c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
33c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
34c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
35c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
36c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin};
37c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin}  // namespace
38c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
39a21d5d577bdc284457867409e2a9c3b4a665d152Johny LinVp9BoolDecoder::Vp9BoolDecoder() = default;
40c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
41a21d5d577bdc284457867409e2a9c3b4a665d152Johny LinVp9BoolDecoder::~Vp9BoolDecoder() = default;
42c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
43c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin// 9.2.1 Initialization process for Boolean decoder
44c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Linbool Vp9BoolDecoder::Initialize(const uint8_t* data, size_t size) {
45c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  DCHECK(data);
46c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  if (size < 1) {
47c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    DVLOG(1) << "input size of bool decoder shall be at least 1";
48c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    valid_ = false;
49c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    return false;
50c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  }
51c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
52c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  reader_.reset(new BitReader(data, size));
53c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  valid_ = true;
54c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
55c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  bool_value_ = 0;
56c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  count_to_fill_ = 8;
57c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  bool_range_ = 255;
58c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  if (ReadLiteral(1) != 0) {
59c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    DVLOG(1) << "marker bit should be 0";
60c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    valid_ = false;
61c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    return false;
62c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  }
63c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  return true;
64c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin}
65c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
66c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin// Fill at least |count_to_fill_| bits and prefill remain bits of |bool_value_|
67c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin// if data is enough.
68c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Linbool Vp9BoolDecoder::Fill() {
69c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  DCHECK_GE(count_to_fill_, 0);
70c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
71c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  int bits_left = reader_->bits_available();
72c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  if (bits_left < count_to_fill_) {
73c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    valid_ = false;
74c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    DVLOG(1) << "Vp9BoolDecoder reads beyond the end of stream";
75c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    return false;
76c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  }
77c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
78c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  DCHECK_LE(count_to_fill_, kBoolSize);
79c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  int max_bits_to_read = kBigBoolBitSize - kBoolSize + count_to_fill_;
80c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  int bits_to_read = std::min(max_bits_to_read, bits_left);
81c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
82c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  BigBool data;
83c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  reader_->ReadBits(bits_to_read, &data);
84c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  bool_value_ |= data << (max_bits_to_read - bits_to_read);
85c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  count_to_fill_ -= bits_to_read;
86c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
87c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  return true;
88c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin}
89c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
90c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin// 9.2.2 Boolean decoding process
91c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Linbool Vp9BoolDecoder::ReadBool(int prob) {
92c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  DCHECK(reader_);
93c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
94c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  if (count_to_fill_ > 0) {
95c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    if (!Fill())
96c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin      return false;
97c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  }
98c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
99c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  unsigned int split = (bool_range_ * prob + (256 - prob)) >> kBoolSize;
100c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  BigBool big_split = static_cast<BigBool>(split)
101c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin                      << (kBigBoolBitSize - kBoolSize);
102c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
103c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  bool bit;
104c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  if (bool_value_ < big_split) {
105c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    bool_range_ = split;
106c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    bit = false;
107c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  } else {
108c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    bool_range_ -= split;
109c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    bool_value_ -= big_split;
110c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    bit = true;
111c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  }
112c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
113c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  // Need to fill |count| bits next time in order to make |bool_range_| >=
114c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  // 128.
115c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  DCHECK_LT(bool_range_, arraysize(kCountToShiftTo128));
116c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  DCHECK_GT(bool_range_, 0u);
117c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  int count = kCountToShiftTo128[bool_range_];
118c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  bool_range_ <<= count;
119c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  bool_value_ <<= count;
120c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  count_to_fill_ += count;
121c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
122c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  return bit;
123c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin}
124c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
125c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin// 9.2.4 Parsing process for read_literal
126c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Linuint8_t Vp9BoolDecoder::ReadLiteral(int bits) {
127c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  DCHECK_LT(static_cast<size_t>(bits), sizeof(uint8_t) * 8);
128c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  DCHECK(reader_);
129c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
130c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  uint8_t x = 0;
131c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  for (int i = 0; i < bits; i++)
132c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    x = 2 * x + ReadBool(128);
133c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
134c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  return x;
135c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin}
136c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
137c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Linbool Vp9BoolDecoder::ConsumePaddingBits() {
138c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  DCHECK(reader_);
139c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
140c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  if (count_to_fill_ > reader_->bits_available()) {
141c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    // 9.2.2 Boolean decoding process
142c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    // Although we actually don't used the value, spec says the bitstream
143c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    // should have enough bits to fill bool range, this should never happen.
144c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    DVLOG(2) << "not enough bits in bitstream to fill bool range";
145c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    return false;
146c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  }
147c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
148c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  if (bool_value_ != 0) {
149c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    DVLOG(1) << "prefilled padding bits are not zero";
150c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    return false;
151c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  }
152c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  while (reader_->bits_available() > 0) {
153c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    int data;
154c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    int size_to_read =
155c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin        std::min(reader_->bits_available(), static_cast<int>(sizeof(data) * 8));
156c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    reader_->ReadBits(size_to_read, &data);
157c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    if (data != 0) {
158c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin      DVLOG(1) << "padding bits are not zero";
159c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin      return false;
160c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin    }
161c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  }
162c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin  return true;
163c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin}
164c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin
165c8ab179e7518f2da789ff936d8ee4def58e2160aPin-chih Lin}  // namespace media
166