16fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org/*
26fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
36fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org *
46fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org *  Use of this source code is governed by a BSD-style license
56fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org *  that can be found in the LICENSE file in the root of the source
66fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org *  tree. An additional intellectual property rights grant can be found
76fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org *  in the file PATENTS.  All contributing project authors may
86fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org *  be found in the AUTHORS file in the root of the source tree.
96fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org */
106fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
110e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org#ifndef VP9_ENCODER_VP9_WRITER_H_
120e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org#define VP9_ENCODER_VP9_WRITER_H_
136fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
146fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#include "vpx_ports/mem.h"
156fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
160e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org#include "vp9/common/vp9_prob.h"
170e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org
18dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org#ifdef __cplusplus
19dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.orgextern "C" {
20dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org#endif
21dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org
226fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgtypedef struct {
236fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  unsigned int lowvalue;
246fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  unsigned int range;
256fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  int count;
266fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  unsigned int pos;
2710a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org  uint8_t *buffer;
2810a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org} vp9_writer;
296fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
3010a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.orgvoid vp9_start_encode(vp9_writer *bc, uint8_t *buffer);
3110a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.orgvoid vp9_stop_encode(vp9_writer *bc);
326fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
3341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.orgstatic INLINE void vp9_write(vp9_writer *br, int bit, int probability) {
346fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  unsigned int split;
356fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  int count = br->count;
366fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  unsigned int range = br->range;
376fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  unsigned int lowvalue = br->lowvalue;
386fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  register unsigned int shift;
396fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
406fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  split = 1 + (((range - 1) * probability) >> 8);
416fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
426fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  range = split;
436fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
446fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  if (bit) {
456fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    lowvalue += split;
466fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    range = br->range - split;
476fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  }
486fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
496fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  shift = vp9_norm[range];
506fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
516fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  range <<= shift;
526fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  count += shift;
536fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
546fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  if (count >= 0) {
556fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    int offset = shift - count;
566fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
576fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    if ((lowvalue << (offset - 1)) & 0x80000000) {
586fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      int x = br->pos - 1;
596fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
606fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      while (x >= 0 && br->buffer[x] == 0xff) {
6110a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org        br->buffer[x] = 0;
626fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org        x--;
636fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      }
646fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
656fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      br->buffer[x] += 1;
666fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    }
676fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
686fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    br->buffer[br->pos++] = (lowvalue >> (24 - offset));
696fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    lowvalue <<= offset;
706fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    shift = count;
716fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    lowvalue &= 0xffffff;
726fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    count -= 8;
736fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  }
746fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
756fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  lowvalue <<= shift;
766fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  br->count = count;
776fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  br->lowvalue = lowvalue;
786fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  br->range = range;
796fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org}
806fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
8141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.orgstatic INLINE void vp9_write_bit(vp9_writer *w, int bit) {
8210a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org  vp9_write(w, bit, 128);  // vp9_prob_half
8310a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org}
8410a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org
8541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.orgstatic INLINE void vp9_write_literal(vp9_writer *w, int data, int bits) {
8610a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org  int bit;
8710a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org
8810a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org  for (bit = bits - 1; bit >= 0; bit--)
8910a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org    vp9_write_bit(w, 1 & (data >> bit));
9010a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org}
9110a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org
92d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org#define vp9_write_prob(w, v) vp9_write_literal((w), (v), 8)
9310a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org
94dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org#ifdef __cplusplus
95dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org}  // extern "C"
96dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org#endif
97dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org
980e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org#endif  // VP9_ENCODER_VP9_WRITER_H_
99