Move and wrap the old vpx boolcoder.

This should make room for compile time pluggable replacements.

Change-Id: Ib7afcffa93bf664b89a49da21a20138127443292
(cherry picked from commit 9dd0b89824)
This commit is contained in:
Alex Converse 2016-06-06 15:12:06 -07:00
Родитель e54fd03c5a
Коммит eb00cb289b
7 изменённых файлов: 320 добавлений и 211 удалений

Просмотреть файл

@ -22,7 +22,8 @@ DSP_SRCS-yes += prob.c
ifeq ($(CONFIG_ENCODERS),yes) ifeq ($(CONFIG_ENCODERS),yes)
DSP_SRCS-yes += bitwriter.h DSP_SRCS-yes += bitwriter.h
DSP_SRCS-yes += bitwriter.c DSP_SRCS-yes += dkboolwriter.h
DSP_SRCS-yes += dkboolwriter.c
DSP_SRCS-yes += bitwriter_buffer.c DSP_SRCS-yes += bitwriter_buffer.c
DSP_SRCS-yes += bitwriter_buffer.h DSP_SRCS-yes += bitwriter_buffer.h
DSP_SRCS-yes += psnr.c DSP_SRCS-yes += psnr.c
@ -35,7 +36,8 @@ endif
ifeq ($(CONFIG_DECODERS),yes) ifeq ($(CONFIG_DECODERS),yes)
DSP_SRCS-yes += bitreader.h DSP_SRCS-yes += bitreader.h
DSP_SRCS-yes += bitreader.c DSP_SRCS-yes += dkboolreader.h
DSP_SRCS-yes += dkboolreader.c
DSP_SRCS-yes += bitreader_buffer.c DSP_SRCS-yes += bitreader_buffer.c
DSP_SRCS-yes += bitreader_buffer.h DSP_SRCS-yes += bitreader_buffer.h
endif endif

Просмотреть файл

@ -12,147 +12,45 @@
#ifndef AOM_DSP_BITREADER_H_ #ifndef AOM_DSP_BITREADER_H_
#define AOM_DSP_BITREADER_H_ #define AOM_DSP_BITREADER_H_
#include <limits.h>
#include <stddef.h>
#include "./aom_config.h" #include "./aom_config.h"
#if CONFIG_BITSTREAM_DEBUG
#include <assert.h>
#include <stdio.h>
#endif // CONFIG_BITSTREAM_DEBUG
#include "aom_ports/mem.h"
#include "aom/aomdx.h" #include "aom/aomdx.h"
#include "aom/aom_integer.h" #include "aom/aom_integer.h"
#include "aom_dsp/dkboolreader.h"
#include "aom_dsp/prob.h" #include "aom_dsp/prob.h"
#include "aom_util/debug_util.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
typedef size_t BD_VALUE; typedef struct aom_dk_reader aom_reader;
#define BD_VALUE_SIZE ((int)sizeof(BD_VALUE) * CHAR_BIT) static INLINE int aom_reader_init(aom_reader *r, const uint8_t *buffer,
size_t size, aom_decrypt_cb decrypt_cb,
void *decrypt_state) {
return aom_dk_reader_init(r, buffer, size, decrypt_cb, decrypt_state);
}
// This is meant to be a large, positive constant that can still be efficiently static INLINE const uint8_t *aom_reader_find_end(aom_reader *r) {
// loaded as an immediate (on platforms like ARM, for example). return aom_dk_reader_find_end(r);
// Even relatively modest values like 100 would work fine. }
#define LOTS_OF_BITS 0x40000000
typedef struct {
// Be careful when reordering this struct, it may impact the cache negatively.
BD_VALUE value;
unsigned int range;
int count;
const uint8_t *buffer_end;
const uint8_t *buffer;
aom_decrypt_cb decrypt_cb;
void *decrypt_state;
uint8_t clear_buffer[sizeof(BD_VALUE) + 1];
} aom_reader;
int aom_reader_init(aom_reader *r, const uint8_t *buffer, size_t size,
aom_decrypt_cb decrypt_cb, void *decrypt_state);
void aom_reader_fill(aom_reader *r);
const uint8_t *aom_reader_find_end(aom_reader *r);
static INLINE int aom_reader_has_error(aom_reader *r) { static INLINE int aom_reader_has_error(aom_reader *r) {
// Check if we have reached the end of the buffer. return aom_dk_reader_has_error(r);
//
// 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 LOTS_OF_BITS. So when
// count == LOTS_OF_BITS - 1, the user's data has been exhausted.
//
// 1 if we have tried to decode bits after the end of stream was encountered.
// 0 No error.
return r->count > BD_VALUE_SIZE && r->count < LOTS_OF_BITS;
} }
static INLINE int aom_read(aom_reader *r, int prob) { static INLINE int aom_read(aom_reader *r, int prob) {
unsigned int bit = 0; return aom_dk_read(r, prob);
BD_VALUE value;
BD_VALUE bigsplit;
int count;
unsigned int range;
unsigned int split = (r->range * prob + (256 - prob)) >> CHAR_BIT;
if (r->count < 0) aom_reader_fill(r);
value = r->value;
count = r->count;
bigsplit = (BD_VALUE)split << (BD_VALUE_SIZE - CHAR_BIT);
range = split;
if (value >= bigsplit) {
range = r->range - split;
value = value - bigsplit;
bit = 1;
}
{
register int shift = aom_norm[range];
range <<= shift;
value <<= shift;
count -= shift;
}
r->value = value;
r->count = count;
r->range = range;
#if CONFIG_BITSTREAM_DEBUG
{
int ref_bit, ref_prob;
const int queue_r = bitstream_queue_get_read();
const int frame_idx = bitstream_queue_get_frame_read();
bitstream_queue_pop(&ref_bit, &ref_prob);
if (prob != ref_prob) {
fprintf(
stderr,
"\n *** prob error, frame_idx_r %d prob %d ref_prob %d queue_r %d\n",
frame_idx, prob, ref_prob, queue_r);
assert(0);
}
if ((int)bit != ref_bit) {
fprintf(stderr, "\n *** bit error, frame_idx_r %d bit %d ref_bit %d\n",
frame_idx, bit, ref_bit);
assert(0);
}
}
#endif // CONFIG_BITSTREAM_DEBUG
return bit;
} }
static INLINE int aom_read_bit(aom_reader *r) { static INLINE int aom_read_bit(aom_reader *r) { return aom_dk_read_bit(r); }
return aom_read(r, 128); // aom_prob_half
}
static INLINE int aom_read_literal(aom_reader *r, int bits) { static INLINE int aom_read_literal(aom_reader *r, int bits) {
int literal = 0, bit; return aom_dk_read_literal(r, bits);
for (bit = bits - 1; bit >= 0; bit--) literal |= aom_read_bit(r) << bit;
return literal;
} }
static INLINE int aom_read_tree(aom_reader *r, const aom_tree_index *tree, static INLINE int aom_read_tree(aom_reader *r, const aom_tree_index *tree,
const aom_prob *probs) { const aom_prob *probs) {
aom_tree_index i = 0; return aom_dk_read_tree(r, tree, probs);
while ((i = tree[i + aom_read(r, probs[i >> 1])]) > 0) continue;
return -i;
} }
#ifdef __cplusplus #ifdef __cplusplus

Просмотреть файл

@ -12,103 +12,33 @@
#ifndef AOM_DSP_BITWRITER_H_ #ifndef AOM_DSP_BITWRITER_H_
#define AOM_DSP_BITWRITER_H_ #define AOM_DSP_BITWRITER_H_
#include "./aom_config.h" #include "aom_dsp/dkboolwriter.h"
#if CONFIG_BITSTREAM_DEBUG
#include <stdio.h>
#endif
#include "aom_ports/mem.h"
#include "aom_dsp/prob.h" #include "aom_dsp/prob.h"
#include "aom_util/debug_util.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
typedef struct aom_writer { typedef struct aom_dk_writer aom_writer;
unsigned int lowvalue;
unsigned int range;
int count;
unsigned int pos;
uint8_t *buffer;
} aom_writer;
void aom_start_encode(aom_writer *bc, uint8_t *buffer); static INLINE void aom_start_encode(aom_writer *bc, uint8_t *buffer) {
void aom_stop_encode(aom_writer *bc); aom_dk_start_encode(bc, buffer);
}
static INLINE void aom_stop_encode(aom_writer *bc) { aom_dk_stop_encode(bc); }
static INLINE void aom_write(aom_writer *br, int bit, int probability) { static INLINE void aom_write(aom_writer *br, int bit, int probability) {
unsigned int split; aom_dk_write(br, bit, probability);
int count = br->count;
unsigned int range = br->range;
unsigned int lowvalue = br->lowvalue;
register int shift;
#if CONFIG_BITSTREAM_DEBUG
// int queue_r = 0;
// int frame_idx_r = 0;
// int queue_w = bitstream_queue_get_write();
// int frame_idx_w = bitstream_queue_get_frame_write();
// if (frame_idx_w == frame_idx_r && queue_w == queue_r) {
// fprintf(stderr, "\n *** bitstream queue at frame_idx_w %d queue_w %d\n",
// frame_idx_w, queue_w);
// }
bitstream_queue_push(bit, probability);
#endif // CONFIG_BITSTREAM_DEBUG
split = 1 + (((range - 1) * probability) >> 8);
range = split;
if (bit) {
lowvalue += split;
range = br->range - split;
}
shift = aom_norm[range];
range <<= shift;
count += shift;
if (count >= 0) {
int offset = shift - count;
if ((lowvalue << (offset - 1)) & 0x80000000) {
int x = br->pos - 1;
while (x >= 0 && br->buffer[x] == 0xff) {
br->buffer[x] = 0;
x--;
}
br->buffer[x] += 1;
}
br->buffer[br->pos++] = (lowvalue >> (24 - offset));
lowvalue <<= offset;
shift = count;
lowvalue &= 0xffffff;
count -= 8;
}
lowvalue <<= shift;
br->count = count;
br->lowvalue = lowvalue;
br->range = range;
} }
static INLINE void aom_write_bit(aom_writer *w, int bit) { static INLINE void aom_write_bit(aom_writer *w, int bit) {
aom_write(w, bit, 128); // aom_prob_half aom_dk_write_bit(w, bit);
} }
static INLINE void aom_write_literal(aom_writer *w, int data, int bits) { static INLINE void aom_write_literal(aom_writer *w, int data, int bits) {
int bit; aom_dk_write_literal(w, data, bits);
for (bit = bits - 1; bit >= 0; bit--) aom_write_bit(w, 1 & (data >> bit));
} }
#define aom_write_prob(w, v) aom_write_literal((w), (v), 8)
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif

Просмотреть файл

@ -11,15 +11,16 @@
#include "./aom_config.h" #include "./aom_config.h"
#include "aom_dsp/bitreader.h" #include "aom_dsp/dkboolreader.h"
#include "aom_dsp/prob.h" #include "aom_dsp/prob.h"
#include "aom_dsp/aom_dsp_common.h" #include "aom_dsp/aom_dsp_common.h"
#include "aom_ports/mem.h" #include "aom_ports/mem.h"
#include "aom_mem/aom_mem.h" #include "aom_mem/aom_mem.h"
#include "aom_util/endian_inl.h" #include "aom_util/endian_inl.h"
int aom_reader_init(aom_reader *r, const uint8_t *buffer, size_t size, int aom_dk_reader_init(struct aom_dk_reader *r, const uint8_t *buffer,
aom_decrypt_cb decrypt_cb, void *decrypt_state) { size_t size, aom_decrypt_cb decrypt_cb,
void *decrypt_state) {
if (size && !buffer) { if (size && !buffer) {
return 1; return 1;
} else { } else {
@ -30,12 +31,12 @@ int aom_reader_init(aom_reader *r, const uint8_t *buffer, size_t size,
r->range = 255; r->range = 255;
r->decrypt_cb = decrypt_cb; r->decrypt_cb = decrypt_cb;
r->decrypt_state = decrypt_state; r->decrypt_state = decrypt_state;
aom_reader_fill(r); aom_dk_reader_fill(r);
return aom_read_bit(r) != 0; // marker bit return aom_dk_read_bit(r) != 0; // marker bit
} }
} }
void aom_reader_fill(aom_reader *r) { void aom_dk_reader_fill(struct aom_dk_reader *r) {
const uint8_t *const buffer_end = r->buffer_end; const uint8_t *const buffer_end = r->buffer_end;
const uint8_t *buffer = r->buffer; const uint8_t *buffer = r->buffer;
const uint8_t *buffer_start = buffer; const uint8_t *buffer_start = buffer;
@ -90,7 +91,7 @@ void aom_reader_fill(aom_reader *r) {
r->count = count; r->count = count;
} }
const uint8_t *aom_reader_find_end(aom_reader *r) { const uint8_t *aom_dk_reader_find_end(struct aom_dk_reader *r) {
// Find the end of the coded buffer // Find the end of the coded buffer
while (r->count > CHAR_BIT && r->count < BD_VALUE_SIZE) { while (r->count > CHAR_BIT && r->count < BD_VALUE_SIZE) {
r->count -= CHAR_BIT; r->count -= CHAR_BIT;

164
aom_dsp/dkboolreader.h Normal file
Просмотреть файл

@ -0,0 +1,164 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#ifndef AOM_DSP_DKBOOLREADER_H_
#define AOM_DSP_DKBOOLREADER_H_
#include <stddef.h>
#include <limits.h>
#include "./aom_config.h"
#if CONFIG_BITSTREAM_DEBUG
#include <assert.h>
#include <stdio.h>
#endif // CONFIG_BITSTREAM_DEBUG
#include "aom_ports/mem.h"
#include "aom/aomdx.h"
#include "aom/aom_integer.h"
#include "aom_dsp/prob.h"
#include "aom_util/debug_util.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef size_t BD_VALUE;
#define BD_VALUE_SIZE ((int)sizeof(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 LOTS_OF_BITS 0x40000000
struct aom_dk_reader {
// Be careful when reordering this struct, it may impact the cache negatively.
BD_VALUE value;
unsigned int range;
int count;
const uint8_t *buffer_end;
const uint8_t *buffer;
aom_decrypt_cb decrypt_cb;
void *decrypt_state;
uint8_t clear_buffer[sizeof(BD_VALUE) + 1];
};
int aom_dk_reader_init(struct aom_dk_reader *r, const uint8_t *buffer,
size_t size, aom_decrypt_cb decrypt_cb,
void *decrypt_state);
void aom_dk_reader_fill(struct aom_dk_reader *r);
const uint8_t *aom_dk_reader_find_end(struct aom_dk_reader *r);
static INLINE int aom_dk_reader_has_error(struct aom_dk_reader *r) {
// 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 LOTS_OF_BITS. So when
// count == LOTS_OF_BITS - 1, the user's data has been exhausted.
//
// 1 if we have tried to decode bits after the end of stream was encountered.
// 0 No error.
return r->count > BD_VALUE_SIZE && r->count < LOTS_OF_BITS;
}
static INLINE int aom_dk_read(struct aom_dk_reader *r, int prob) {
unsigned int bit = 0;
BD_VALUE value;
BD_VALUE bigsplit;
int count;
unsigned int range;
unsigned int split = (r->range * prob + (256 - prob)) >> CHAR_BIT;
if (r->count < 0) aom_dk_reader_fill(r);
value = r->value;
count = r->count;
bigsplit = (BD_VALUE)split << (BD_VALUE_SIZE - CHAR_BIT);
range = split;
if (value >= bigsplit) {
range = r->range - split;
value = value - bigsplit;
bit = 1;
}
{
register int shift = aom_norm[range];
range <<= shift;
value <<= shift;
count -= shift;
}
r->value = value;
r->count = count;
r->range = range;
#if CONFIG_BITSTREAM_DEBUG
{
int ref_bit, ref_prob;
const int queue_r = bitstream_queue_get_read();
const int frame_idx = bitstream_queue_get_frame_read();
bitstream_queue_pop(&ref_bit, &ref_prob);
if (prob != ref_prob) {
fprintf(
stderr,
"\n *** prob error, frame_idx_r %d prob %d ref_prob %d queue_r %d\n",
frame_idx, prob, ref_prob, queue_r);
assert(0);
}
if ((int)bit != ref_bit) {
fprintf(stderr, "\n *** bit error, frame_idx_r %d bit %d ref_bit %d\n",
frame_idx, bit, ref_bit);
assert(0);
}
}
#endif // CONFIG_BITSTREAM_DEBUG
return bit;
}
static INLINE int aom_dk_read_bit(struct aom_dk_reader *r) {
return aom_dk_read(r, 128); // aom_prob_half
}
static INLINE int aom_dk_read_literal(struct aom_dk_reader *r, int bits) {
int literal = 0, bit;
for (bit = bits - 1; bit >= 0; bit--) literal |= aom_dk_read_bit(r) << bit;
return literal;
}
static INLINE int aom_dk_read_tree(struct aom_dk_reader *r,
const aom_tree_index *tree,
const aom_prob *probs) {
aom_tree_index i = 0;
while ((i = tree[i + aom_dk_read(r, probs[i >> 1])]) > 0) continue;
return -i;
}
#ifdef __cplusplus
} // extern "C"
#endif
#endif // AOM_DSP_DKBOOLREADER_H_

Просмотреть файл

@ -10,25 +10,25 @@
#include <assert.h> #include <assert.h>
#include "./bitwriter.h" #include "./dkboolwriter.h"
void aom_start_encode(aom_writer *br, uint8_t *source) { void aom_dk_start_encode(aom_dk_writer *br, uint8_t *source) {
br->lowvalue = 0; br->lowvalue = 0;
br->range = 255; br->range = 255;
br->count = -24; br->count = -24;
br->buffer = source; br->buffer = source;
br->pos = 0; br->pos = 0;
aom_write_bit(br, 0); aom_dk_write_bit(br, 0);
} }
void aom_stop_encode(aom_writer *br) { void aom_dk_stop_encode(aom_dk_writer *br) {
int i; int i;
#if CONFIG_BITSTREAM_DEBUG #if CONFIG_BITSTREAM_DEBUG
bitstream_queue_set_skip_write(1); bitstream_queue_set_skip_write(1);
#endif // CONFIG_BITSTREAM_DEBUG #endif // CONFIG_BITSTREAM_DEBUG
for (i = 0; i < 32; i++) aom_write_bit(br, 0); for (i = 0; i < 32; i++) aom_dk_write_bit(br, 0);
#if CONFIG_BITSTREAM_DEBUG #if CONFIG_BITSTREAM_DEBUG
bitstream_queue_set_skip_write(0); bitstream_queue_set_skip_write(0);

114
aom_dsp/dkboolwriter.h Normal file
Просмотреть файл

@ -0,0 +1,114 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#ifndef AOM_DSP_DKBOOLWRITER_H_
#define AOM_DSP_DKBOOLWRITER_H_
#include "./aom_config.h"
#if CONFIG_BITSTREAM_DEBUG
#include <stdio.h>
#endif
#include "aom_dsp/prob.h"
#include "aom_ports/mem.h"
#include "aom_util/debug_util.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct aom_dk_writer {
unsigned int lowvalue;
unsigned int range;
int count;
unsigned int pos;
uint8_t *buffer;
} aom_dk_writer;
void aom_dk_start_encode(aom_dk_writer *bc, uint8_t *buffer);
void aom_dk_stop_encode(aom_dk_writer *bc);
static INLINE void aom_dk_write(aom_dk_writer *br, int bit, int probability) {
unsigned int split;
int count = br->count;
unsigned int range = br->range;
unsigned int lowvalue = br->lowvalue;
register int shift;
#if CONFIG_BITSTREAM_DEBUG
// int queue_r = 0;
// int frame_idx_r = 0;
// int queue_w = bitstream_queue_get_write();
// int frame_idx_w = bitstream_queue_get_frame_write();
// if (frame_idx_w == frame_idx_r && queue_w == queue_r) {
// fprintf(stderr, "\n *** bitstream queue at frame_idx_w %d queue_w %d\n",
// frame_idx_w, queue_w);
// }
bitstream_queue_push(bit, probability);
#endif // CONFIG_BITSTREAM_DEBUG
split = 1 + (((range - 1) * probability) >> 8);
range = split;
if (bit) {
lowvalue += split;
range = br->range - split;
}
shift = aom_norm[range];
range <<= shift;
count += shift;
if (count >= 0) {
int offset = shift - count;
if ((lowvalue << (offset - 1)) & 0x80000000) {
int x = br->pos - 1;
while (x >= 0 && br->buffer[x] == 0xff) {
br->buffer[x] = 0;
x--;
}
br->buffer[x] += 1;
}
br->buffer[br->pos++] = (lowvalue >> (24 - offset));
lowvalue <<= offset;
shift = count;
lowvalue &= 0xffffff;
count -= 8;
}
lowvalue <<= shift;
br->count = count;
br->lowvalue = lowvalue;
br->range = range;
}
static INLINE void aom_dk_write_bit(aom_dk_writer *w, int bit) {
aom_dk_write(w, bit, 128); // aom_prob_half
}
static INLINE void aom_dk_write_literal(aom_dk_writer *w, int data, int bits) {
int bit;
for (bit = bits - 1; bit >= 0; bit--) aom_dk_write_bit(w, 1 & (data >> bit));
}
#ifdef __cplusplus
} // extern "C"
#endif
#endif // AOM_DSP_DKBOOLWRITER_H_