首页 > 代码库 > HEVC 调试技巧

HEVC 调试技巧

这两天在写HEVC中读CTU的部分,包括PartMode,partSize,PredInfo

还有特别重要的扫描表和残差系数的几个函数,经过调试已经没有问题,但是在调试过程中因为涉及到码字等相关问题,调试的复杂度比较大,

后来根据写TRACE文件的方法,调试基本就是流程性的工作了,不再会出现没有头绪的情况


在HM代码模型中,在

/** \file     TComRom.h
    \brief    global variables & functions (header)
*/

当中有一个宏 

#ifndef ENC_DEC_TRACE
#define ENC_DEC_TRACE 1

这个宏是控制在HM中调试信息的,主要将一些解出来的信息输出到文件中,之后可以通过在新程序中输出相同的信息,利用文件对比工具,比如我用的Beyond Compare

在主程序中的输出宏:

#define DTRACE_CABAC_F(x)     if ( ( g_nSymbolCounter >= COUNTER_START && g_nSymbolCounter <= COUNTER_END )|| g_bJustDoIt ) fprintf( g_hTrace, "%f", x );
#define DTRACE_CABAC_V(x)     if ( ( g_nSymbolCounter >= COUNTER_START && g_nSymbolCounter <= COUNTER_END )|| g_bJustDoIt ) fprintf( g_hTrace, "%d", x );
#define DTRACE_CABAC_VL(x)    if ( ( g_nSymbolCounter >= COUNTER_START && g_nSymbolCounter <= COUNTER_END )|| g_bJustDoIt ) fprintf( g_hTrace, "%lld", x );
#define DTRACE_CABAC_T(x)     if ( ( g_nSymbolCounter >= COUNTER_START && g_nSymbolCounter <= COUNTER_END )|| g_bJustDoIt ) fprintf( g_hTrace, "%s", x );
#define DTRACE_CABAC_X(x)     if ( ( g_nSymbolCounter >= COUNTER_START && g_nSymbolCounter <= COUNTER_END )|| g_bJustDoIt ) fprintf( g_hTrace, "%x", x );
#define DTRACE_CABAC_R( x,y ) if ( ( g_nSymbolCounter >= COUNTER_START && g_nSymbolCounter <= COUNTER_END )|| g_bJustDoIt ) fprintf( g_hTrace, x,    y );
#define DTRACE_CABAC_N        if ( ( g_nSymbolCounter >= COUNTER_START && g_nSymbolCounter <= COUNTER_END )|| g_bJustDoIt ) fprintf( g_hTrace, "\n"    );
g_nSymbolCounter  全局变量,标示当前元素的系数,这样匹配到不同点位置的时候可以根据他打条件断点进行调试

除了一些常规的信息跟踪以外,在HEVC中很重要的就是对底层熵解码的码流进行跟踪,因此再开一个文件,用于存储底层的码流信息,至于为什么要单开一个文件,因为项目是协同合作,你负责熵解码部分,那么这部分调试输出文件自己拥有就可以了,不用放到主调试文件中上传到版本库

#if XT_DEBUG
#define TRACE_BIN_VL(x)       if ( ( g_nSymbolCounter >= COUNTER_START && g_nSymbolCounter <= COUNTER_END )|| g_bJustDoIt ) fprintf( g_binTrace, "%lld", x );
#define TRACE_BIN_V(x)        if ( ( g_nSymbolCounter >= COUNTER_START && g_nSymbolCounter <= COUNTER_END )|| g_bJustDoIt )fprintf( g_binTrace, "%d", x );
#define TRACE_BIN_T(x)        if ( ( g_nSymbolCounter >= COUNTER_START && g_nSymbolCounter <= COUNTER_END )|| g_bJustDoIt )fprintf( g_binTrace, "%s", x );
#define TRACE_BIN_N           if ( ( g_nSymbolCounter >= COUNTER_START && g_nSymbolCounter <= COUNTER_END )|| g_bJustDoIt )fprintf( g_binTrace, "\n"    );
#endif

在代码的合适位置加入相应的代码进行调试。比如在解出CBF后:

      DTRACE_CABAC_VL( g_nSymbolCounter++ )
      DTRACE_CABAC_T( "\tparseQtCbf()" )
      DTRACE_CABAC_T( "\tsub-TU=" )
      DTRACE_CABAC_V( subTU )
      DTRACE_CABAC_T( "\tsymbol=" )
      DTRACE_CABAC_V( uiCbf )
      DTRACE_CABAC_T( "\tctx=" )
      DTRACE_CABAC_V( uiCtx )
      DTRACE_CABAC_T( "\tetype=" )
      DTRACE_CABAC_V( compID )
      DTRACE_CABAC_T( "\tuiAbsPartIdx=" )
      DTRACE_CABAC_V( subTUAbsPartIdx )
      DTRACE_CABAC_T( "\n" )

在底层熵解码解码之后加入: 小技巧,最好加上调试对应的函数名字,这样方便定位

#if XT_DEBUG
  TRACE_BIN_VL( g_binTraceCounter++ )
	  TRACE_BIN_T( "  Value=http://www.mamicode.com/" )>
在调试过程中,首先根据主调试文件输出信息进行对比,获取不同处的g_nSymbolCounter,根据这个变量做条件断点,之后运行到对应位置,因为HEVC中最有可能出错的就是底层熵解码,在对比g_binTrace文件找到码流错误的上一位置,同样,条件断点进行单步调试。注意代码中最好加入fflush函数,这样可以动态的观察变化

一般这个过程找出问题是很简单的,调试就变得容易了,如果码流没有出错,一般就是逻辑出问题,小心一点就问题不大

技术分享


技术分享



HEVC 调试技巧