dboolhuff.h 4.26 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
1
/*
2
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar's avatar
John Koleszar committed
3
 *
4
 *  Use of this source code is governed by a BSD-style license
5 6
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
7
 *  in the file PATENTS.  All contributing project authors may
8
 *  be found in the AUTHORS file in the root of the source tree.
John Koleszar's avatar
John Koleszar committed
9 10 11 12 13
 */


#ifndef DBOOLHUFF_H
#define DBOOLHUFF_H
14 15
#include <stddef.h>
#include <limits.h>
John Koleszar's avatar
John Koleszar committed
16 17
#include "vpx_ports/config.h"
#include "vpx_ports/mem.h"
18
#include "vpx/vpx_integer.h"
John Koleszar's avatar
John Koleszar committed
19

20 21 22 23 24 25 26 27
typedef size_t VP8_BD_VALUE;

# define VP8_BD_VALUE_SIZE ((int)sizeof(VP8_BD_VALUE)*CHAR_BIT)
/*This is meant to be a large, positive constant that can still be efficiently
   loaded as an immediate (on platforms like ARM, for example).
  Even relatively modest values like 100 would work fine.*/
# define VP8_LOTS_OF_BITS (0x40000000)

John Koleszar's avatar
John Koleszar committed
28 29 30 31 32 33
typedef struct {
  const unsigned char *user_buffer_end;
  const unsigned char *user_buffer;
  VP8_BD_VALUE         value;
  int                  count;
  unsigned int         range;
John Koleszar's avatar
John Koleszar committed
34 35
} BOOL_DECODER;

36
DECLARE_ALIGNED(16, extern const unsigned char, vp8_norm[256]);
John Koleszar's avatar
John Koleszar committed
37

38
int vp9dx_start_decode(BOOL_DECODER *br,
Johann's avatar
Johann committed
39 40 41
                       const unsigned char *source,
                       unsigned int source_sz);

42
void vp9dx_bool_decoder_fill(BOOL_DECODER *br);
43

44 45
int vp9_decode_uniform(BOOL_DECODER *br, int n);
int vp9_decode_term_subexp(BOOL_DECODER *br, int k, int num_syms);
46
int vp9_inv_recenter_nonneg(int v, int m);
47

48 49 50 51 52 53 54
/*The refill loop is used in several places, so define it in a macro to make
   sure they're all consistent.
  An inline function would be cleaner, but has a significant penalty, because
   multiple BOOL_DECODER fields must be modified, and the compiler is not smart
   enough to eliminate the stores to those fields and the subsequent reloads
   from them when inlining the function.*/
#define VP8DX_BOOL_DECODER_FILL(_count,_value,_bufptr,_bufend) \
John Koleszar's avatar
John Koleszar committed
55 56 57 58 59 60 61 62 63
  do \
  { \
    int shift = VP8_BD_VALUE_SIZE - 8 - ((_count) + 8); \
    int loop_end, x; \
    size_t bits_left = ((_bufend)-(_bufptr))*CHAR_BIT; \
    \
    x = shift + CHAR_BIT - bits_left; \
    loop_end = 0; \
    if(x >= 0) \
64
    { \
John Koleszar's avatar
John Koleszar committed
65 66 67
      (_count) += VP8_LOTS_OF_BITS; \
      loop_end = x; \
      if(!bits_left) break; \
68
    } \
John Koleszar's avatar
John Koleszar committed
69 70 71 72 73 74 75 76
    while(shift >= loop_end) \
    { \
      (_count) += CHAR_BIT; \
      (_value) |= (VP8_BD_VALUE)*(_bufptr)++ << shift; \
      shift -= CHAR_BIT; \
    } \
  } \
  while(0) \
77 78


John Koleszar's avatar
John Koleszar committed
79
static int vp8dx_decode_bool(BOOL_DECODER *br, int probability) {
John Koleszar's avatar
John Koleszar committed
80 81 82 83 84 85 86 87 88 89
  unsigned int bit = 0;
  VP8_BD_VALUE value;
  unsigned int split;
  VP8_BD_VALUE bigsplit;
  int count;
  unsigned int range;

  split = 1 + (((br->range - 1) * probability) >> 8);

  if (br->count < 0)
90
    vp9dx_bool_decoder_fill(br);
John Koleszar's avatar
John Koleszar committed
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115

  value = br->value;
  count = br->count;

  bigsplit = (VP8_BD_VALUE)split << (VP8_BD_VALUE_SIZE - 8);

  range = split;

  if (value >= bigsplit) {
    range = br->range - split;
    value = value - bigsplit;
    bit = 1;
  }

  {
    register unsigned int shift = vp8_norm[range];
    range <<= shift;
    value <<= shift;
    count -= shift;
  }
  br->value = value;
  br->count = count;
  br->range = range;

  return bit;
John Koleszar's avatar
John Koleszar committed
116 117
}

John Koleszar's avatar
John Koleszar committed
118 119 120
static int vp8_decode_value(BOOL_DECODER *br, int bits) {
  int z = 0;
  int bit;
John Koleszar's avatar
John Koleszar committed
121

John Koleszar's avatar
John Koleszar committed
122 123 124
  for (bit = bits - 1; bit >= 0; bit--) {
    z |= (vp8dx_decode_bool(br, 0x80) << bit);
  }
John Koleszar's avatar
John Koleszar committed
125

John Koleszar's avatar
John Koleszar committed
126
  return z;
John Koleszar's avatar
John Koleszar committed
127
}
128

John Koleszar's avatar
John Koleszar committed
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
static int vp8dx_bool_error(BOOL_DECODER *br) {
  /* Check if we have reached the end of the buffer.
   *
   * Variable 'count' stores the number of bits in the 'value' buffer, minus
   * 8. The top byte is part of the algorithm, and the remainder is buffered
   * to be shifted into it. So if count == 8, the top 16 bits of 'value' are
   * occupied, 8 for the algorithm and 8 in the buffer.
   *
   * When reading a byte from the user's buffer, count is filled with 8 and
   * one byte is filled into the value buffer. When we reach the end of the
   * data, count is additionally filled with VP8_LOTS_OF_BITS. So when
   * count == VP8_LOTS_OF_BITS - 1, the user's data has been exhausted.
   */
  if ((br->count > VP8_BD_VALUE_SIZE) && (br->count < VP8_LOTS_OF_BITS)) {
    /* We have tried to decode bits after the end of
     * stream was encountered.
145
     */
John Koleszar's avatar
John Koleszar committed
146 147 148 149 150
    return 1;
  }

  /* No error. */
  return 0;
151
}
152

John Koleszar's avatar
John Koleszar committed
153
#endif