ref: 483b71e8e78dbd8759bf506b532b062aa5b2d713
parent: d2d5174440c65938f9e46a1aa4a717d6914d8a40
author: Angie Chiang <angiebird@google.com>
date: Tue Apr 23 14:19:30 EDT 2019
Add bistream_debug tool Change-Id: I339899cff65c7ef563f9411f2d7af9a32a08a705
--- a/configure
+++ b/configure
@@ -328,6 +328,7 @@
experimental
size_limit
always_adjust_bpm
+ bitstream_debug
${EXPERIMENT_LIST}
"
CMDLINE_SELECT="
@@ -389,6 +390,7 @@
vp9_highbitdepth
experimental
always_adjust_bpm
+ bitstream_debug
"
process_cmdline() {
--- a/vp9/decoder/vp9_decodeframe.c
+++ b/vp9/decoder/vp9_decodeframe.c
@@ -23,6 +23,9 @@
#include "vpx_ports/mem_ops.h"
#include "vpx_scale/vpx_scale.h"
#include "vpx_util/vpx_thread.h"
+#if CONFIG_BITSTREAM_DEBUG
+#include "vpx_util/vpx_debug_util.h"
+#endif // CONFIG_BITSTREAM_DEBUG
#include "vp9/common/vp9_alloccommon.h"
#include "vp9/common/vp9_common.h"
@@ -2920,6 +2923,10 @@
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);
+#if CONFIG_BITSTREAM_DEBUG
+ bitstream_queue_set_frame_read(cm->current_video_frame * 2 + cm->show_frame);
+#endif
+
xd->cur_buf = new_fb;
if (!first_partition_size) {
--- a/vp9/decoder/vp9_detokenize.c
+++ b/vp9/decoder/vp9_detokenize.c
@@ -33,7 +33,21 @@
int *count, unsigned int *range) {
const unsigned int split = (*range * prob + (256 - prob)) >> CHAR_BIT;
const BD_VALUE bigsplit = (BD_VALUE)split << (BD_VALUE_SIZE - CHAR_BIT);
+#if CONFIG_BITSTREAM_DEBUG
+ const int queue_r = bitstream_queue_get_read();
+ const int frame_idx = bitstream_queue_get_frame_read();
+ int ref_result, ref_prob;
+ bitstream_queue_pop(&ref_result, &ref_prob);
+ if (prob != ref_prob) {
+ fprintf(stderr,
+ "\n *** [bit] prob error, frame_idx_r %d prob %d ref_prob %d "
+ "queue_r %d\n",
+ frame_idx, prob, ref_prob, queue_r);
+ assert(0);
+ }
+#endif
+
if (*count < 0) {
r->value = *value;
r->count = *count;
@@ -51,6 +65,20 @@
*value <<= shift;
*count -= shift;
}
+#if CONFIG_BITSTREAM_DEBUG
+ {
+ const int bit = 1;
+ if (bit != ref_result) {
+ fprintf(
+ stderr,
+ "\n *** [bit] result error, frame_idx_r %d bit %d ref_result %d "
+ "queue_r %d\n",
+ frame_idx, bit, ref_result, queue_r);
+
+ assert(0);
+ }
+ }
+#endif
return 1;
}
*range = split;
@@ -60,6 +88,19 @@
*value <<= shift;
*count -= shift;
}
+#if CONFIG_BITSTREAM_DEBUG
+ {
+ const int bit = 0;
+ if (bit != ref_result) {
+ fprintf(stderr,
+ "\n *** [bit] result error, frame_idx_r %d bit %d ref_result %d "
+ "queue_r %d\n",
+ frame_idx, bit, ref_result, queue_r);
+
+ assert(0);
+ }
+ }
+#endif
return 0;
}
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -18,6 +18,9 @@
#include "vpx_mem/vpx_mem.h"
#include "vpx_ports/mem_ops.h"
#include "vpx_ports/system_state.h"
+#if CONFIG_BITSTREAM_DEBUG
+#include "vpx_util/vpx_debug_util.h"
+#endif // CONFIG_BITSTREAM_DEBUG
#include "vp9/common/vp9_entropy.h"
#include "vp9/common/vp9_entropymode.h"
@@ -1352,6 +1355,10 @@
size_t first_part_size, uncompressed_hdr_size;
struct vpx_write_bit_buffer wb = { data, 0 };
struct vpx_write_bit_buffer saved_wb;
+
+#if CONFIG_BITSTREAM_DEBUG
+ bitstream_queue_reset_write();
+#endif
write_uncompressed_header(cpi, &wb);
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -26,6 +26,9 @@
#include "vpx_ports/mem.h"
#include "vpx_ports/system_state.h"
#include "vpx_ports/vpx_timer.h"
+#if CONFIG_BITSTREAM_DEBUG
+#include "vpx_util/vpx_debug_util.h"
+#endif // CONFIG_BITSTREAM_DEBUG
#include "vp9/common/vp9_alloccommon.h"
#include "vp9/common/vp9_filter.h"
@@ -7355,6 +7358,13 @@
vp9_estimate_qp_gop(cpi);
setup_tpl_stats(cpi);
}
+
+#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
cpi->td.mb.fp_src_pred = 0;
#if CONFIG_REALTIME_ONLY
--- a/vpx_dsp/bitreader.h
+++ b/vpx_dsp/bitreader.h
@@ -12,6 +12,7 @@
#define VPX_VPX_DSP_BITREADER_H_
#include <stddef.h>
+#include <stdio.h>
#include <limits.h>
#include "./vpx_config.h"
@@ -19,6 +20,9 @@
#include "vpx/vp8dx.h"
#include "vpx/vpx_integer.h"
#include "vpx_dsp/prob.h"
+#if CONFIG_BITSTREAM_DEBUG
+#include "vpx_util/vpx_debug_util.h"
+#endif // CONFIG_BITSTREAM_DEBUG
#ifdef __cplusplus
extern "C" {
@@ -102,6 +106,31 @@
r->value = value;
r->count = count;
r->range = range;
+
+#if CONFIG_BITSTREAM_DEBUG
+ {
+ const int queue_r = bitstream_queue_get_read();
+ const int frame_idx = bitstream_queue_get_frame_read();
+ int ref_result, ref_prob;
+ bitstream_queue_pop(&ref_result, &ref_prob);
+ if ((int)bit != ref_result) {
+ fprintf(stderr,
+ "\n *** [bit] result error, frame_idx_r %d bit %d ref_result %d "
+ "queue_r %d\n",
+ frame_idx, bit, ref_result, queue_r);
+
+ assert(0);
+ }
+ if (prob != ref_prob) {
+ fprintf(stderr,
+ "\n *** [bit] prob error, frame_idx_r %d prob %d ref_prob %d "
+ "queue_r %d\n",
+ frame_idx, prob, ref_prob, queue_r);
+
+ assert(0);
+ }
+ }
+#endif
return bit;
}
--- a/vpx_dsp/bitwriter.c
+++ b/vpx_dsp/bitwriter.c
@@ -12,6 +12,10 @@
#include "./bitwriter.h"
+#if CONFIG_BITSTREAM_DEBUG
+#include "vpx_util/vpx_debug_util.h"
+#endif
+
void vpx_start_encode(vpx_writer *br, uint8_t *source) {
br->lowvalue = 0;
br->range = 255;
@@ -24,8 +28,15 @@
void vpx_stop_encode(vpx_writer *br) {
int i;
+#if CONFIG_BITSTREAM_DEBUG
+ bitstream_queue_set_skip_write(1);
+#endif
for (i = 0; i < 32; i++) vpx_write_bit(br, 0);
// Ensure there's no ambigous collision with any index marker bytes
if ((br->buffer[br->pos - 1] & 0xe0) == 0xc0) br->buffer[br->pos++] = 0;
+
+#if CONFIG_BITSTREAM_DEBUG
+ bitstream_queue_set_skip_write(0);
+#endif
}
--- a/vpx_dsp/bitwriter.h
+++ b/vpx_dsp/bitwriter.h
@@ -11,9 +11,14 @@
#ifndef VPX_VPX_DSP_BITWRITER_H_
#define VPX_VPX_DSP_BITWRITER_H_
+#include <stdio.h>
+
#include "vpx_ports/mem.h"
#include "vpx_dsp/prob.h"
+#if CONFIG_BITSTREAM_DEBUG
+#include "vpx_util/vpx_debug_util.h"
+#endif // CONFIG_BITSTREAM_DEBUG
#ifdef __cplusplus
extern "C" {
@@ -36,6 +41,21 @@
unsigned int range = br->range;
unsigned int lowvalue = br->lowvalue;
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);
+ assert(0);
+ }
+ */
+ bitstream_queue_push(bit, probability);
+#endif
split = 1 + (((range - 1) * probability) >> 8);
--- /dev/null
+++ b/vpx_util/vpx_debug_util.c
@@ -1,0 +1,72 @@
+/*
+ * Copyright (c) 2019 The WebM project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include "vpx_util/vpx_debug_util.h"
+
+#if CONFIG_BITSTREAM_DEBUG
+#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, const 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);
+ }
+ }
+}
+#endif // CONFIG_BITSTREAM_DEBUG
--- /dev/null
+++ b/vpx_util/vpx_debug_util.h
@@ -1,0 +1,49 @@
+/*
+ * Copyright (c) 2019 The WebM project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef VPX_VPX_UTIL_VPX_DEBUG_UTIL_H_
+#define VPX_VPX_UTIL_VPX_DEBUG_UTIL_H_
+
+#include "./vpx_config.h"
+
+#include "vpx_dsp/prob.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if CONFIG_BITSTREAM_DEBUG
+/* 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. */
+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);
+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, const int prob);
+void bitstream_queue_set_skip_write(int skip);
+void bitstream_queue_set_skip_read(int skip);
+#endif // CONFIG_BITSTREAM_DEBUG
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // VPX_VPX_UTIL_VPX_DEBUG_UTIL_H_
--- a/vpx_util/vpx_util.mk
+++ b/vpx_util/vpx_util.mk
@@ -15,3 +15,5 @@
UTIL_SRCS-yes += endian_inl.h
UTIL_SRCS-yes += vpx_write_yuv_frame.h
UTIL_SRCS-yes += vpx_write_yuv_frame.c
+UTIL_SRCS-yes += vpx_debug_util.h
+UTIL_SRCS-yes += vpx_debug_util.c