dboolhuff.h 4.28 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

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

void vp8dx_bool_decoder_fill(BOOL_DECODER *br);
43

44 45 46 47 48 49
#if CONFIG_NEWUPDATE
int vp8_decode_uniform(BOOL_DECODER *br, int n);
int vp8_decode_term_subexp(BOOL_DECODER *br, int k, int num_syms);
int inv_recenter_nonneg(int v, int m);
#endif

50 51 52 53 54 55 56
/*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
57 58 59 60 61 62 63 64 65
  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) \
66
    { \
John Koleszar's avatar
John Koleszar committed
67 68 69
      (_count) += VP8_LOTS_OF_BITS; \
      loop_end = x; \
      if(!bits_left) break; \
70
    } \
John Koleszar's avatar
John Koleszar committed
71 72 73 74 75 76 77 78
    while(shift >= loop_end) \
    { \
      (_count) += CHAR_BIT; \
      (_value) |= (VP8_BD_VALUE)*(_bufptr)++ << shift; \
      shift -= CHAR_BIT; \
    } \
  } \
  while(0) \
79 80


John Koleszar's avatar
John Koleszar committed
81
static int vp8dx_decode_bool(BOOL_DECODER *br, int probability) {
John Koleszar's avatar
John Koleszar committed
82 83 84 85 86 87 88 89 90 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 116 117
  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)
    vp8dx_bool_decoder_fill(br);

  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
118 119
}

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

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

John Koleszar's avatar
John Koleszar committed
128
  return z;
John Koleszar's avatar
John Koleszar committed
129
}
130

John Koleszar's avatar
John Koleszar committed
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
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.
147
     */
John Koleszar's avatar
John Koleszar committed
148 149 150 151 152
    return 1;
  }

  /* No error. */
  return 0;
153
}
154

John Koleszar's avatar
John Koleszar committed
155
#endif