Commit 7a3ceab0 authored by Angie Chiang's avatar Angie Chiang

Add bitstream debug tool

This is a debug tool used to detect bitstream error. On encoder side, it
pushes each bit and probability into a queue before the bit is written into
the Arithmetic coder. On decoder side, whenever a bit is read out from the
Arithmetic coder, it pops out the reference bit and probability from the
queue as well. If the two results do not match, this debug tool will report
an error.  This tool can be used to pin down the bitstream error precisely.
By combining gdb's backtrace method, we can detect which module causes the
bitstream error.

This tool is moved from following two CLs of nextgenv2
https://chromium-review.googlesource.com/#/c/366432/
https://chromium-review.googlesource.com/#/c/380300/

Change-Id: Iec6d4c2e3851b8ac1db35776fd7a216a9230a983
parent fd08f495
......@@ -16,6 +16,13 @@
#include <limits.h>
#include "./aom_config.h"
#if CONFIG_BITSTREAM_DEBUG
#include <assert.h>
#include <stdio.h>
#include "aom_util/debug_util.h"
#endif // CONFIG_BITSTREAM_DEBUG
#include "aom/aomdx.h"
#include "aom/aom_integer.h"
#if CONFIG_ANS
......@@ -152,6 +159,28 @@ static INLINE int aom_read_(aom_reader *r, int prob ACCT_STR_PARAM) {
#if CONFIG_ACCOUNTING
if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
#endif
#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 (ret != ref_bit) {
fprintf(stderr, "\n *** bit error, frame_idx_r %d bit %d ref_bit %d\n",
frame_idx, ret, ref_bit);
assert(0);
}
}
#endif // CONFIG_BITSTREAM_DEBUG
return ret;
}
......
......@@ -14,6 +14,12 @@
#include <assert.h>
#include "./aom_config.h"
#if CONFIG_BITSTREAM_DEBUG
#include <stdio.h>
#include "aom_util/debug_util.h"
#endif // CONFIG_BITSTREAM_DEBUG
#if CONFIG_ANS
#include "aom_dsp/buf_ans.h"
#elif CONFIG_DAALA_EC
......@@ -22,7 +28,6 @@
#include "aom_dsp/dkboolwriter.h"
#endif
#include "aom_dsp/prob.h"
#ifdef __cplusplus
extern "C" {
#endif
......@@ -66,6 +71,18 @@ static INLINE void aom_write(aom_writer *br, int bit, int probability) {
#else
aom_dk_write(br, bit, probability);
#endif
#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
}
static INLINE void aom_write_bit(aom_writer *w, int bit) {
......
......@@ -13,4 +13,6 @@
UTIL_SRCS-yes += aom_util.mk
UTIL_SRCS-yes += aom_thread.c
UTIL_SRCS-yes += aom_thread.h
UTIL_SRCS-$(CONFIG_BITSTREAM_DEBUG) += debug_util.c
UTIL_SRCS-$(CONFIG_BITSTREAM_DEBUG) += debug_util.h
UTIL_SRCS-yes += endian_inl.h
/*
* 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.
*/
#include <assert.h>
#include <stdio.h>
#include "aom_util/debug_util.h"
#define QUEUE_MAX_SIZE 2000000
static int result_queue[QUEUE_MAX_SIZE];
static int prob_queue[QUEUE_MAX_SIZE];
static int queue_r = 0;
static int queue_w = 0;
static int queue_prev_w = -1;
static int skip_r = 0;
static int skip_w = 0;
static int frame_idx_w = 0;
static int frame_idx_r = 0;
void bitstream_queue_set_frame_write(int frame_idx) { frame_idx_w = frame_idx; }
int bitstream_queue_get_frame_write(void) { return frame_idx_w; }
void bitstream_queue_set_frame_read(int frame_idx) { frame_idx_r = frame_idx; }
int bitstream_queue_get_frame_read(void) { return frame_idx_r; }
void bitstream_queue_set_skip_write(int skip) { skip_w = skip; }
void bitstream_queue_set_skip_read(int skip) { skip_r = skip; }
void bitstream_queue_record_write(void) { queue_prev_w = queue_w; }
void bitstream_queue_reset_write(void) { queue_w = queue_prev_w; }
int bitstream_queue_get_write(void) { return queue_w; }
int bitstream_queue_get_read(void) { return queue_r; }
void bitstream_queue_pop(int *result, int *prob) {
if (!skip_r) {
if (queue_w == queue_r) {
printf("buffer underflow queue_w %d queue_r %d\n", queue_w, queue_r);
assert(0);
}
*result = result_queue[queue_r];
*prob = prob_queue[queue_r];
queue_r = (queue_r + 1) % QUEUE_MAX_SIZE;
}
}
void bitstream_queue_push(int result, int prob) {
if (!skip_w) {
result_queue[queue_w] = result;
prob_queue[queue_w] = prob;
queue_w = (queue_w + 1) % QUEUE_MAX_SIZE;
if (queue_w == queue_r) {
printf("buffer overflow queue_w %d queue_r %d\n", queue_w, queue_r);
assert(0);
}
}
}
/*
* 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_UTIL_DEBUG_UTIL_H_
#define AOM_UTIL_DEBUG_UTIL_H_
#include "./aom_config.h"
#ifdef __cplusplus
extern "C" {
#endif
/* This is a debug tool used to detect bitstream error. On encoder side, it
* pushes each bit and probability into a queue before the bit is written into
* the Arithmetic coder. On decoder side, whenever a bit is read out from the
* Arithmetic coder, it pops out the reference bit and probability from the
* queue as well. If the two results do not match, this debug tool will report
* an error. This tool can be used to pin down the bitstream error precisely.
* By combining gdb's backtrace method, we can detect which module causes the
* bitstream error. */
int bitstream_queue_get_write(void);
int bitstream_queue_get_read(void);
void bitstream_queue_record_write(void);
void bitstream_queue_reset_write(void);
void bitstream_queue_pop(int *result, int *prob);
void bitstream_queue_push(int result, int prob);
void bitstream_queue_set_skip_write(int skip);
void bitstream_queue_set_skip_read(int skip);
void bitstream_queue_set_frame_write(int frame_idx);
int bitstream_queue_get_frame_write(void);
void bitstream_queue_set_frame_read(int frame_idx);
int bitstream_queue_get_frame_read(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // AOM_UTIL_DEBUG_UTIL_H_
......@@ -26,6 +26,9 @@
#include "aom_ports/mem_ops.h"
#include "aom_scale/aom_scale.h"
#include "aom_util/aom_thread.h"
#if CONFIG_BITSTREAM_DEBUG
#include "aom_util/debug_util.h"
#endif // CONFIG_BITSTREAM_DEBUG
#include "av1/common/alloccommon.h"
#if CONFIG_CLPF
......@@ -2246,13 +2249,19 @@ void av1_decode_frame(AV1Decoder *pbi, const uint8_t *data,
struct aom_read_bit_buffer rb;
int context_updated = 0;
uint8_t clear_data[MAX_AV1_HEADER_SIZE];
const size_t first_partition_size = read_uncompressed_header(
pbi, init_read_bit_buffer(pbi, &rb, data, data_end, clear_data));
size_t first_partition_size;
const int tile_rows = 1 << cm->log2_tile_rows;
const int tile_cols = 1 << cm->log2_tile_cols;
YV12_BUFFER_CONFIG *const new_fb = get_frame_new_buffer(cm);
xd->cur_buf = new_fb;
#if CONFIG_BITSTREAM_DEBUG
bitstream_queue_set_frame_read(cm->current_video_frame * 2 + cm->show_frame);
#endif
first_partition_size = read_uncompressed_header(
pbi, init_read_bit_buffer(pbi, &rb, data, data_end, clear_data));
if (!first_partition_size) {
// showing a frame directly
#if CONFIG_EXT_REFS
......
......@@ -19,6 +19,9 @@
#include "aom_mem/aom_mem.h"
#include "aom_ports/mem_ops.h"
#include "aom_ports/system_state.h"
#if CONFIG_BITSTREAM_DEBUG
#include "aom_util/debug_util.h"
#endif // CONFIG_BITSTREAM_DEBUG
#if CONFIG_CLPF
#include "av1/common/clpf.h"
......@@ -2308,6 +2311,10 @@ void av1_pack_bitstream(AV1_COMP *const cpi, uint8_t *dest, size_t *size) {
// tile size marker in the header
#endif
#if CONFIG_BITSTREAM_DEBUG
bitstream_queue_reset_write();
#endif
write_uncompressed_header(cpi, &wb);
#if CONFIG_EXT_REFS
......
......@@ -65,6 +65,9 @@
#include "aom_ports/mem.h"
#include "aom_ports/system_state.h"
#include "aom_scale/aom_scale.h"
#if CONFIG_BITSTREAM_DEBUG
#include "aom_util/debug_util.h"
#endif // CONFIG_BITSTREAM_DEBUG
#define AM_SEGMENT_ID_INACTIVE 7
#define AM_SEGMENT_ID_ACTIVE 0
......@@ -4251,6 +4254,13 @@ int av1_get_compressed_data(AV1_COMP *cpi, unsigned int *frame_flags,
#endif // CONFIG_EXT_REFS
int i;
#if CONFIG_BITSTREAM_DEBUG
assert(cpi->oxcf.max_threads == 0 &&
"bitstream debug tool does not support multithreading");
bitstream_queue_record_write();
bitstream_queue_set_frame_write(cm->current_video_frame * 2 + cm->show_frame);
#endif
aom_usec_timer_start(&cmptimer);
av1_set_high_precision_mv(cpi, ALTREF_HIGH_PRECISION_MV);
......
......@@ -272,6 +272,7 @@ EXPERIMENT_LIST="
filter_7bit
delta_q
adapt_scan
bitstream_debug
"
CONFIG_LIST="
dependency_tracking
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment