/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
#include <stdint.h>
#include <stdio.h>

#include "webrtc/modules/video_coding/utility/include/vp8_header_parser.h"

#include "webrtc/system_wrappers/include/logging.h"

namespace webrtc {

namespace vp8 {
namespace {
const size_t kCommonPayloadHeaderLength = 3;
const size_t kKeyPayloadHeaderLength = 10;
}  // namespace

static uint32_t BSwap32(uint32_t x) {
  return (x >> 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | (x << 24);
}

static void VP8LoadFinalBytes(VP8BitReader* const br) {
  // Only read 8bits at a time.
  if (br->buf_ < br->buf_end_) {
    br->bits_ += 8;
    br->value_ = static_cast<uint32_t>(*br->buf_++) | (br->value_ << 8);
  } else if (!br->eof_) {
    br->value_ <<= 8;
    br->bits_ += 8;
    br->eof_ = 1;
  }
}

static void VP8LoadNewBytes(VP8BitReader* const br) {
  int BITS = 24;
  // Read 'BITS' bits at a time.
  if (br->buf_ + sizeof(uint32_t) <= br->buf_end_) {
    uint32_t bits;
    const uint32_t in_bits = *(const uint32_t*)(br->buf_);
    br->buf_ += BITS >> 3;
#if defined(WEBRTC_ARCH_BIG_ENDIAN)
      bits = static_cast<uint32_t>(in_bits);
      if (BITS != 8 * sizeof(uint32_t))
        bits >>= (8 * sizeof(uint32_t) - BITS);
#else
      bits = BSwap32(in_bits);
      bits >>= 32 - BITS;
#endif
    br->value_ = bits | (br->value_ << BITS);
    br->bits_ += BITS;
  } else {
    VP8LoadFinalBytes(br);
  }
}

static void VP8InitBitReader(VP8BitReader* const br,
                             const uint8_t* const start,
                             const uint8_t* const end) {
  br->range_   = 255 - 1;
  br->buf_     = start;
  br->buf_end_ = end;
  br->value_   = 0;
  br->bits_    = -8;   // To load the very first 8bits.
  br->eof_     = 0;
  VP8LoadNewBytes(br);
}

// Read a bit with proba 'prob'.
static int VP8GetBit(VP8BitReader* const br, int prob) {
  uint8_t range = br->range_;
  if (br->bits_ < 0) {
    VP8LoadNewBytes(br);
  }

  const int pos = br->bits_;
  const uint8_t split = (range * prob) >> 8;
  const uint8_t value = static_cast<uint8_t>(br->value_ >> pos);
  int bit;
  if (value > split) {
    range -= split + 1;
    br->value_ -= static_cast<uint32_t>(split + 1) << pos;
    bit = 1;
  } else {
    range = split;
    bit = 0;
  }
  if (range <= static_cast<uint8_t>(0x7e)) {
    const int shift = kVP8Log2Range[range];
    range = kVP8NewRange[range];
    br->bits_ -= shift;
  }
  br->range_ = range;
  return bit;
}

static uint32_t VP8GetValue(VP8BitReader* const br, int bits) {
  uint32_t v = 0;
  while (bits-- > 0) {
    v |= VP8GetBit(br, 0x80) << bits;
  }
  return v;
}

static uint32_t VP8Get(VP8BitReader* const br) {
  return VP8GetValue(br, 1);
}

static int32_t VP8GetSignedValue(VP8BitReader* const br, int bits) {
  const int value = VP8GetValue(br, bits);
  return VP8Get(br) ? -value : value;
}

static void ParseSegmentHeader(VP8BitReader* br) {
  int use_segment = VP8Get(br);
  if (use_segment) {
    int update_map = VP8Get(br);
    if (VP8Get(br)) {
      int s;
      VP8Get(br);
      for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
       VP8Get(br) ? VP8GetSignedValue(br, 7) : 0;
      }
      for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
        VP8Get(br) ? VP8GetSignedValue(br, 6) : 0;
      }
    }
    if (update_map) {
      int s;
      for (s = 0; s < MB_FEATURE_TREE_PROBS; ++s) {
        VP8Get(br) ? VP8GetValue(br, 8) : 255;
      }
    }
  }
}

static void ParseFilterHeader(VP8BitReader* br) {
  VP8Get(br);
  VP8GetValue(br, 6);
  VP8GetValue(br, 3);
  int use_lf_delta = VP8Get(br);
  if (use_lf_delta) {
    if (VP8Get(br)) {
      int i;
      for (i = 0; i < NUM_REF_LF_DELTAS; ++i) {
        if (VP8Get(br)) {
          VP8GetSignedValue(br, 6);
        }
      }
      for (i = 0; i < NUM_MODE_LF_DELTAS; ++i) {
        if (VP8Get(br)) {
          VP8GetSignedValue(br, 6);
        }
      }
    }
  }
}

bool GetQp(const uint8_t* buf, size_t length, int* qp) {
  if (length < kCommonPayloadHeaderLength) {
    LOG(LS_WARNING) << "Failed to get QP, invalid length.";
    return false;
  }
  VP8BitReader br;
  const uint32_t bits = buf[0] | (buf[1] << 8) | (buf[2] << 16);
  int key_frame = !(bits & 1);
  // Size of first partition in bytes.
  uint32_t partition_length = (bits >> 5);
  size_t header_length = kCommonPayloadHeaderLength;
  if (key_frame) {
    header_length = kKeyPayloadHeaderLength;
  }
  if (header_length + partition_length > length) {
    LOG(LS_WARNING) << "Failed to get QP, invalid length: " << length;
    return false;
  }
  buf += header_length;

  VP8InitBitReader(&br, buf, buf + partition_length);
  if (key_frame) {
    // Color space and pixel type.
    VP8Get(&br);
    VP8Get(&br);
  }
  ParseSegmentHeader(&br);
  ParseFilterHeader(&br);
  // Number of coefficient data partitions.
  VP8GetValue(&br, 2);
  // Base QP.
  const int base_q0 = VP8GetValue(&br, 7);
  if (br.eof_ == 1) {
    LOG(LS_WARNING) << "Failed to get QP, end of file reached.";
    return false;
  }
  *qp = base_q0;
  return true;
}

}  // namespace vp8

}  // namespace webrtc
