Home | History | Annotate | Download | only in base
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "media/base/bit_reader_core.h"
      6 
      7 #include <base/port.h>
      8 #include <base/sys_byteorder.h>
      9 
     10 namespace {
     11 const int kRegWidthInBits = sizeof(uint64) * 8;
     12 }
     13 
     14 namespace media {
     15 
     16 BitReaderCore::ByteStreamProvider::ByteStreamProvider() {
     17 }
     18 
     19 BitReaderCore::ByteStreamProvider::~ByteStreamProvider() {
     20 }
     21 
     22 BitReaderCore::BitReaderCore(ByteStreamProvider* byte_stream_provider)
     23     : byte_stream_provider_(byte_stream_provider),
     24       bits_read_(0),
     25       nbits_(0),
     26       reg_(0),
     27       nbits_next_(0),
     28       reg_next_(0) {
     29 }
     30 
     31 BitReaderCore::~BitReaderCore() {
     32 }
     33 
     34 bool BitReaderCore::ReadFlag(bool* flag) {
     35   if (nbits_ == 0 && !Refill(1))
     36     return false;
     37 
     38   *flag = (reg_ & (GG_UINT64_C(1) << (kRegWidthInBits - 1))) != 0;
     39   reg_ <<= 1;
     40   nbits_--;
     41   bits_read_++;
     42   return true;
     43 }
     44 
     45 int BitReaderCore::PeekBitsMsbAligned(int num_bits, uint64* out) {
     46   // Try to have at least |num_bits| in the bit register.
     47   if (nbits_ < num_bits)
     48     Refill(num_bits);
     49 
     50   *out = reg_;
     51   return nbits_;
     52 }
     53 
     54 bool BitReaderCore::SkipBits(int num_bits) {
     55   DCHECK_GE(num_bits, 0);
     56   DVLOG_IF(0, num_bits > 100)
     57       << "BitReader::SkipBits inefficient for large skips";
     58 
     59   uint64 dummy;
     60   while (num_bits >= kRegWidthInBits) {
     61     if (!ReadBitsInternal(kRegWidthInBits, &dummy))
     62       return false;
     63     num_bits -= kRegWidthInBits;
     64   }
     65   return ReadBitsInternal(num_bits, &dummy);
     66 }
     67 
     68 int BitReaderCore::bits_read() const {
     69   return bits_read_;
     70 }
     71 
     72 bool BitReaderCore::ReadBitsInternal(int num_bits, uint64* out) {
     73   DCHECK_GE(num_bits, 0);
     74 
     75   if (num_bits == 0) {
     76     *out = 0;
     77     return true;
     78   }
     79 
     80   if (num_bits > nbits_ && !Refill(num_bits)) {
     81     // Any subsequent ReadBits should fail:
     82     // empty the current bit register for that purpose.
     83     nbits_ = 0;
     84     reg_ = 0;
     85     return false;
     86   }
     87 
     88   bits_read_ += num_bits;
     89 
     90   if (num_bits == kRegWidthInBits) {
     91     // Special case needed since for example for a 64 bit integer "a"
     92     // "a << 64" is not defined by the C/C++ standard.
     93     *out = reg_;
     94     reg_ = 0;
     95     nbits_ = 0;
     96     return true;
     97   }
     98 
     99   *out = reg_ >> (kRegWidthInBits - num_bits);
    100   reg_ <<= num_bits;
    101   nbits_ -= num_bits;
    102   return true;
    103 }
    104 
    105 bool BitReaderCore::Refill(int min_nbits) {
    106   DCHECK_LE(min_nbits, kRegWidthInBits);
    107 
    108   // Transfer from the next to the current register.
    109   RefillCurrentRegister();
    110   if (min_nbits <= nbits_)
    111     return true;
    112   DCHECK_EQ(nbits_next_, 0);
    113   DCHECK_EQ(reg_next_, 0u);
    114 
    115   // Max number of bytes to refill.
    116   int max_nbytes = sizeof(reg_next_);
    117 
    118   // Refill.
    119   const uint8* byte_stream_window;
    120   int window_size =
    121       byte_stream_provider_->GetBytes(max_nbytes, &byte_stream_window);
    122   DCHECK_GE(window_size, 0);
    123   DCHECK_LE(window_size, max_nbytes);
    124   if (window_size == 0)
    125     return false;
    126 
    127   reg_next_ = 0;
    128   memcpy(&reg_next_, byte_stream_window, window_size);
    129   reg_next_ = base::NetToHost64(reg_next_);
    130   nbits_next_ = window_size * 8;
    131 
    132   // Transfer from the next to the current register.
    133   RefillCurrentRegister();
    134 
    135   return (nbits_ >= min_nbits);
    136 }
    137 
    138 void BitReaderCore::RefillCurrentRegister() {
    139   // No refill possible if the destination register is full
    140   // or the source register is empty.
    141   if (nbits_ == kRegWidthInBits || nbits_next_ == 0)
    142     return;
    143 
    144   reg_ |= (reg_next_ >> nbits_);
    145 
    146   int free_nbits = kRegWidthInBits - nbits_;
    147   if (free_nbits >= nbits_next_) {
    148     nbits_ += nbits_next_;
    149     reg_next_ = 0;
    150     nbits_next_ = 0;
    151     return;
    152   }
    153 
    154   nbits_ += free_nbits;
    155   reg_next_ <<= free_nbits;
    156   nbits_next_ -= free_nbits;
    157 }
    158 
    159 }  // namespace media
    160