// Copyright 2012 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/media/filters/shell_rbsp_stream.h"

#include "base/logging.h"

namespace cobalt {
namespace media {

ShellRBSPStream::ShellRBSPStream(const uint8* nalu_buffer,
                                 size_t nalu_buffer_size)
    : nalu_buffer_(nalu_buffer),
      nalu_buffer_size_(nalu_buffer_size),
      nalu_buffer_byte_offset_(0),
      current_nalu_byte_(0),
      number_consecutive_zeros_(0),
      rbsp_bit_offset_(0) {}

// read unsigned Exp-Golomb coded integer, ISO 14496-10 Section 9.1
bool ShellRBSPStream::ReadUEV(uint32* uev_out) {
  DCHECK(uev_out);
  int leading_zero_bits = -1;
  for (uint8 b = 0; b == 0; leading_zero_bits++) {
    if (!ReadRBSPBit(&b)) {
      return false;
    }
  }
  // we can only fit 31 bits of Exp-Golomb coded data into a 32-bit number
  if (leading_zero_bits >= 32) {
    return false;
  }
  uint32 result = (1 << leading_zero_bits) - 1;
  uint32 remainder = 0;
  if (!ReadBits(leading_zero_bits, &remainder)) {
    return false;
  }
  result += remainder;
  *uev_out = result;
  return true;
}

// read signed Exp-Golomb coded integer, ISO 14496-10 Section 9.1
bool ShellRBSPStream::ReadSEV(int32* sev_out) {
  DCHECK(sev_out);
  // we start off by reading an unsigned Exp-Golomb coded number
  uint32 uev = 0;
  if (!ReadUEV(&uev)) {
    return false;
  }
  // the LSb in this number is treated as the inverted sign bit
  bool is_negative = !(uev & 1);
  int32 result = static_cast<int32>((uev + 1) >> 1);
  if (is_negative) {
    result *= -1;
  }
  *sev_out = result;
  return true;
}

// read and return up to 32 bits, filling from the right, meaning that
// ReadBits(17) on a stream of all 1s would return 0x01ffff
bool ShellRBSPStream::ReadBits(size_t bits, uint32* bits_out) {
  DCHECK(bits_out);
  if (bits > 32) {
    return false;
  }
  if (bits == 0) {
    return true;
  }
  uint32 result = 0;
  size_t bytes = bits >> 3;
  // read bytes first
  for (int i = 0; i < bytes; i++) {
    uint8 new_byte = 0;
    if (!ReadRBSPByte(&new_byte)) {
      return false;
    }
    result = result << 8;
    result = result | static_cast<uint32>(new_byte);
  }
  // scoot any leftover bits in
  bits = bits % 8;
  for (int i = 0; i < bits; i++) {
    uint8 new_bit = 0;
    if (!ReadRBSPBit(&new_bit)) {
      return false;
    }
    result = result << 1;
    result = result | static_cast<uint32>(new_bit);
  }
  *bits_out = result;
  return true;
}

// jump over bytes in the RBSP stream
bool ShellRBSPStream::SkipBytes(size_t bytes) {
  for (int i = 0; i < bytes; ++i) {
    if (!ConsumeNALUByte()) {
      return false;
    }
  }
  return true;
}

// jump over bits in the RBSP stream
bool ShellRBSPStream::SkipBits(size_t bits) {
  // skip bytes first
  size_t bytes = bits >> 3;
  if (bytes > 0) {
    if (!SkipBytes(bytes)) {
      return false;
    }
  }
  // mask off byte skips
  bits = bits & 7;
  // if no bits left to skip just return
  if (bits == 0) {
    return true;
  }
  // obey the convention that if our bit offset is 0 we haven't loaded the
  // current byte, extract it from NALU stream as we are going to advance
  // the bit cursor in to it (or potentially past it)
  if (rbsp_bit_offset_ == 0) {
    if (!ConsumeNALUByte()) {
      return false;
    }
  }
  // add to our bit offset
  rbsp_bit_offset_ += bits;
  // if we jumped in to the next byte advance the NALU stream, respecting the
  // convention that if we're at 8 bits stay on the current byte
  if (rbsp_bit_offset_ >= 9) {
    if (!ConsumeNALUByte()) {
      return false;
    }
  }
  rbsp_bit_offset_ = rbsp_bit_offset_ % 8;
  return true;
}

// advance by one byte through the NALU buffer, respecting the encoding of
// 00 00 03 => 00 00. Updates the state of current_nalu_byte_ to the new value.
bool ShellRBSPStream::ConsumeNALUByte() {
  if (nalu_buffer_byte_offset_ >= nalu_buffer_size_) {
    return false;
  }
  current_nalu_byte_ = nalu_buffer_[nalu_buffer_byte_offset_];
  if (current_nalu_byte_ == 0x03 && number_consecutive_zeros_ >= 2) {
    ++nalu_buffer_byte_offset_;
    current_nalu_byte_ = nalu_buffer_[nalu_buffer_byte_offset_];
    number_consecutive_zeros_ = 0;
  }

  if (current_nalu_byte_ == 0) {
    ++number_consecutive_zeros_;
  } else {
    number_consecutive_zeros_ = 0;
  }
  ++nalu_buffer_byte_offset_;
  return true;
}

// return single bit in the LSb from the RBSP stream. Bits are read from MSb
// to LSb in the stream.
bool ShellRBSPStream::ReadRBSPBit(uint8* bit_out) {
  DCHECK(bit_out);
  // check to see if we need to consume a fresh byte
  if (rbsp_bit_offset_ == 0) {
    if (!ConsumeNALUByte()) {
      return false;
    }
  }
  // since we read from MSb to LSb in stream we shift right
  uint8 bit = (current_nalu_byte_ >> (7 - rbsp_bit_offset_)) & 1;
  // increment bit offset
  rbsp_bit_offset_ = (rbsp_bit_offset_ + 1) % 8;
  *bit_out = bit;
  return true;
}

bool ShellRBSPStream::ReadRBSPByte(uint8* byte_out) {
  DCHECK(byte_out);
  // fast path for byte-aligned access
  if (rbsp_bit_offset_ == 0) {
    if (!ConsumeNALUByte()) {
      return false;
    }
    *byte_out = current_nalu_byte_;
    return true;
  }
  // at least some of the bits in the current byte will be included in this
  // next byte, absorb them
  uint8 upper_part = current_nalu_byte_;
  // read next byte from stream
  if (!ConsumeNALUByte()) {
    return false;
  }
  // form the byte from the two bytes
  *byte_out = (upper_part << rbsp_bit_offset_) |
              (current_nalu_byte_ >> (8 - rbsp_bit_offset_));
  return true;
}

}  // namespace media
}  // namespace cobalt
