449 lines
17 KiB
C++
449 lines
17 KiB
C++
/* The copyright in this software is being made available under the BSD
|
|
* License, included below. This software may be subject to other third party
|
|
* and contributor rights, including patent rights, and no such rights are
|
|
* granted under this license.
|
|
*
|
|
* Copyright (c) 2010-2014, ITU/ISO/IEC
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
* * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
|
|
* be used to endorse or promote products derived from this software without
|
|
* specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
/** \file Debug.cpp
|
|
\brief Defines types and objects for environment-variable-based debugging and feature control
|
|
*/
|
|
|
|
#include "Debug.h"
|
|
#include <algorithm>
|
|
#include <math.h>
|
|
#include "TComDataCU.h"
|
|
#include "TComPic.h"
|
|
#include "TComYuv.h"
|
|
|
|
static const UInt settingNameWidth = 66;
|
|
static const UInt settingHelpWidth = 84;
|
|
static const UInt settingValueWidth = 3;
|
|
|
|
#ifdef DEBUG_STRING
|
|
// these strings are used to reorder the debug output so that the encoder and decoder match.
|
|
const Char *debug_reorder_data_inter_token[MAX_NUM_COMPONENT+1]
|
|
= {"Start of channel 0 inter debug\n", "Start of channel 1 inter debug\n", "Start of channel 2 inter debug\n", "End of inter residual debug\n"} ;
|
|
const Char *partSizeToString[NUMBER_OF_PART_SIZES]={"2Nx2N(0)", "2NxN(1)", "Nx2N(2)", "NxN(3)", "2Nx(N/2+3N/2)(4)", "2Nx(3N/2+N/2)(5)", "(N/2+3N/2)x2N(6)", "(3N/2+N/2)x2N(7)"};
|
|
#endif
|
|
|
|
// --------------------------------------------------------------------------------------------------------------------- //
|
|
|
|
//EnvVar definition
|
|
|
|
std::list<std::pair<std::string, std::string> > &EnvVar::getEnvVarList()
|
|
{
|
|
static std::list<std::pair<std::string, std::string> > varInfoList;
|
|
return varInfoList;
|
|
}
|
|
|
|
std::list<EnvVar*> &EnvVar::getEnvVarInUse()
|
|
{
|
|
static std::list<EnvVar*> varInUseList;
|
|
return varInUseList;
|
|
}
|
|
|
|
static inline Void printPair(const std::pair<std::string, std::string> &p)
|
|
{
|
|
if (p.second=="")
|
|
{
|
|
std::cout << "\n" << std::setw(settingNameWidth) << p.first << "\n" << std::endl;
|
|
}
|
|
else
|
|
{
|
|
std::cout << std::setw(settingNameWidth) << p.first << ": " << p.second << "\n" << std::endl;
|
|
}
|
|
}
|
|
|
|
static inline Void printVal(const EnvVar* env)
|
|
{
|
|
std::cout << std::setw(settingNameWidth) << env->getName() << " = " << std::setw(settingValueWidth) << env->getInt() << " (string = " << std::setw(15) << env->getString() << ")" << std::endl;
|
|
}
|
|
|
|
//static inline Bool sameEnvName( const std::pair<std::string, std::string> &a,
|
|
// const std::pair<std::string, std::string> &b )
|
|
//{
|
|
// // only check env name
|
|
// return (a.first==b.first);
|
|
//}
|
|
|
|
Void EnvVar::printEnvVar()
|
|
{
|
|
// getEnvVarList().unique(sameEnvName);
|
|
if (getEnvVarList().size()!=0)
|
|
{
|
|
std::cout << "--- Environment variables:\n" << std::endl;
|
|
for_each(getEnvVarList().begin(), getEnvVarList().end(), printPair);
|
|
}
|
|
std::cout << std::endl;
|
|
}
|
|
|
|
Void EnvVar::printEnvVarInUse()
|
|
{
|
|
if (getEnvVarInUse().size()!=0)
|
|
{
|
|
std::cout << "RExt Environment variables set as follows: \n" << std::endl;
|
|
for_each(getEnvVarInUse().begin(), getEnvVarInUse().end(), printVal);
|
|
}
|
|
std::cout << std::endl;
|
|
}
|
|
|
|
EnvVar::EnvVar(const std::string &sName, const std::string &sDefault, const std::string &sHelp) :
|
|
m_sName(sName),
|
|
m_sHelp(sHelp),
|
|
m_sVal(),
|
|
m_dVal(0),
|
|
m_iVal(0),
|
|
m_bSet(false)
|
|
{
|
|
if (getenv(m_sName.c_str()))
|
|
{
|
|
m_sVal = getenv(m_sName.c_str());
|
|
m_bSet = true;
|
|
getEnvVarInUse().push_back(this);
|
|
}
|
|
else m_sVal = sDefault;
|
|
|
|
m_dVal = strtod(m_sVal.c_str(), 0);
|
|
m_iVal = Int(m_dVal);
|
|
|
|
getEnvVarList().push_back( std::pair<std::string, std::string>(m_sName, indentNewLines(lineWrap(splitOnSettings(m_sHelp), settingHelpWidth), (settingNameWidth + 4))) );
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------------------------------------------------- //
|
|
|
|
// Debug environment variables:
|
|
|
|
EnvVar Debug("-- Debugging","","");
|
|
|
|
EnvVar DebugOptionList::DebugSBAC ("DEBUG_SBAC", "0", "Output debug data from SBAC entropy coder (coefficient data etc.)" );
|
|
EnvVar DebugOptionList::DebugRQT ("DEBUG_RQT", "0", "Output RQT debug data from entropy coder" );
|
|
EnvVar DebugOptionList::DebugPred ("DEBUG_PRED", "0", "Output prediction debug" );
|
|
EnvVar DebugOptionList::ForceLumaMode ("FORCE_LUMA_MODE", "0", "Force a particular intra direction for Luma (0-34)" );
|
|
EnvVar DebugOptionList::ForceChromaMode ("FORCE_CHROMA_MODE", "0", "Force a particular intra direction for chroma (0-5)" );
|
|
|
|
#ifdef DEBUG_STRING
|
|
EnvVar DebugOptionList::DebugString_Structure ("DEBUG_STRUCTURE", "0", "Produce output on chosen structure bit0=intra, bit1=inter");
|
|
EnvVar DebugOptionList::DebugString_Pred ("DEBUG_PRED", "0", "Produce output on prediction data. bit0=intra, bit1=inter");
|
|
EnvVar DebugOptionList::DebugString_Resi ("DEBUG_RESI", "0", "Produce output on residual data. bit0=intra, bit1=inter");
|
|
EnvVar DebugOptionList::DebugString_Reco ("DEBUG_RECO", "0", "Produce output on reconstructed data. bit0=intra, bit1=inter");
|
|
EnvVar DebugOptionList::DebugString_InvTran ("DEBUG_INV_QT", "0", "Produce output on inverse-quantiser and transform stages. bit0=intra, bit1=inter");
|
|
#endif
|
|
|
|
// --------------------------------------------------------------------------------------------------------------------- //
|
|
|
|
//macro value printing function
|
|
|
|
Void printMacroSettings()
|
|
{
|
|
std::cout << "Non-environment-variable-controlled macros set as follows: \n" << std::endl;
|
|
|
|
//------------------------------------------------
|
|
|
|
//setting macros
|
|
|
|
PRINT_CONSTANT(RExt__DECODER_DEBUG_BIT_STATISTICS, settingNameWidth, settingValueWidth);
|
|
PRINT_CONSTANT(RExt__HIGH_BIT_DEPTH_SUPPORT, settingNameWidth, settingValueWidth);
|
|
PRINT_CONSTANT(RExt__HIGH_PRECISION_FORWARD_TRANSFORM, settingNameWidth, settingValueWidth);
|
|
|
|
PRINT_CONSTANT(O0043_BEST_EFFORT_DECODING, settingNameWidth, settingValueWidth);
|
|
|
|
PRINT_CONSTANT(RD_TEST_SAO_DISABLE_AT_PICTURE_LEVEL, settingNameWidth, settingValueWidth);
|
|
|
|
//------------------------------------------------
|
|
|
|
std::cout << std::endl;
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------------------------------------------------- //
|
|
|
|
//Debugging
|
|
|
|
UInt g_debugCounter = 0;
|
|
Bool g_printDebug = false;
|
|
Void* g_debugAddr = NULL;
|
|
|
|
#ifdef DEBUG_ENCODER_SEARCH_BINS
|
|
const UInt debugEncoderSearchBinTargetLine = 0;
|
|
const UInt debugEncoderSearchBinWindow = 1000000;
|
|
#endif
|
|
|
|
#ifdef DEBUG_CABAC_BINS
|
|
const UInt debugCabacBinTargetLine = 0;
|
|
const UInt debugCabacBinWindow = 1000000;
|
|
#endif
|
|
|
|
Void printSBACCoeffData( const UInt lastX,
|
|
const UInt lastY,
|
|
const UInt width,
|
|
const UInt height,
|
|
const UInt chan,
|
|
const UInt absPart,
|
|
const UInt scanIdx,
|
|
const TCoeff *const pCoeff,
|
|
const Bool finalEncode
|
|
)
|
|
{
|
|
if (DebugOptionList::DebugSBAC.getInt()!=0 && finalEncode)
|
|
{
|
|
std::cout << "Size: " << width << "x" << height << ", Last X/Y: (" << lastX << ", " << lastY << "), absPartIdx: " << absPart << ", scanIdx: " << scanIdx << ", chan: " << chan << std::endl;
|
|
for (Int i=0; i<width*height; i++)
|
|
{
|
|
std::cout << std::setw(3) << pCoeff[i];// + dcVal;
|
|
if (i%width == width-1) std::cout << std::endl;
|
|
else std::cout << ",";
|
|
}
|
|
std::cout << std::endl;
|
|
}
|
|
}
|
|
|
|
Void printCbfArray( TComDataCU* pcCU )
|
|
{
|
|
const UInt CUSizeInParts = pcCU->getWidth(0)/4;
|
|
const UInt numValidComp=pcCU->getPic()->getNumberValidComponents();
|
|
for (UInt ch=0; ch<numValidComp; ch++)
|
|
{
|
|
const ComponentID compID=ComponentID(ch);
|
|
printf("channel: %d\n", ch);
|
|
for (Int y=0; y<CUSizeInParts; y++)
|
|
{
|
|
for (Int x=0; x<CUSizeInParts; x++)
|
|
{
|
|
printf(x+1==CUSizeInParts?"%3d\n":"%3d, ", pcCU->getCbf(compID)[g_auiRasterToZscan[y*CUSizeInParts + x]]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
UInt getDecimalWidth(const Double value)
|
|
{
|
|
return (value == 0) ? 1 : (UInt(floor(log10(fabs(value)))) + ((value < 0) ? 2 : 1));
|
|
//for the minus sign
|
|
}
|
|
|
|
UInt getZScanIndex(const UInt x, const UInt y)
|
|
{
|
|
UInt remainingX = x;
|
|
UInt remainingY = y;
|
|
UInt offset = 0;
|
|
UInt result = 0;
|
|
|
|
while ((remainingX != 0) || (remainingY != 0))
|
|
{
|
|
result |= ((remainingX & 0x1) << offset) | ((remainingY & 0x1) << (offset + 1));
|
|
|
|
remainingX >>= 1;
|
|
remainingY >>= 1;
|
|
offset += 2;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------------------------------------------------- //
|
|
|
|
//String manipulation functions for aligning and wrapping printed text
|
|
|
|
|
|
std::string splitOnSettings(const std::string &input)
|
|
{
|
|
std::string result = input;
|
|
|
|
std::string::size_type searchFromPosition = 0;
|
|
|
|
while (searchFromPosition < result.length())
|
|
{
|
|
//find the " = " that is used to define each setting
|
|
std::string::size_type equalsPosition = result.find(" = ", searchFromPosition);
|
|
|
|
if (equalsPosition == std::string::npos) break;
|
|
|
|
//then find the end of the numeric characters
|
|
std::string::size_type splitPosition = result.find_last_of("1234567890", equalsPosition);
|
|
|
|
//then find the last space before the first numeric character...
|
|
if (splitPosition != std::string::npos) splitPosition = result.find_last_of(' ', splitPosition);
|
|
|
|
//...and replace it with a new line
|
|
if (splitPosition != std::string::npos) result.replace(splitPosition, 1, 1, '\n');
|
|
|
|
//start the next search from the end of the " = " string
|
|
searchFromPosition = (equalsPosition + 3);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
std::string lineWrap(const std::string &input, const UInt maximumLineLength)
|
|
{
|
|
if (maximumLineLength == 0) return input;
|
|
std::string result = input;
|
|
|
|
std::string::size_type lineStartPosition = result.find_first_not_of(' '); //don't wrap any leading spaces in the string
|
|
|
|
while (lineStartPosition != std::string::npos)
|
|
{
|
|
//------------------------------------------------
|
|
|
|
const std::string::size_type searchFromPosition = lineStartPosition + maximumLineLength;
|
|
|
|
if (searchFromPosition >= result.length()) break;
|
|
|
|
//------------------------------------------------
|
|
|
|
//first check to see if there is another new line character before the maximum line length
|
|
//we can't use find for this unfortunately because it doesn't take both a beginning and an end for its search range
|
|
std::string::size_type nextLineStartPosition = std::string::npos;
|
|
for (std::string::size_type currentPosition = lineStartPosition; currentPosition <= searchFromPosition; currentPosition++)
|
|
{
|
|
if (result[currentPosition] == '\n') { nextLineStartPosition = currentPosition + 1; break; }
|
|
}
|
|
|
|
//------------------------------------------------
|
|
|
|
//if there ia another new line character before the maximum line length, we need to start this loop again from that position
|
|
if (nextLineStartPosition != std::string::npos) lineStartPosition = nextLineStartPosition;
|
|
else
|
|
{
|
|
std::string::size_type spacePosition = std::string::npos;
|
|
|
|
//search backwards for the last space character (must use signed Int because lineStartPosition can be 0)
|
|
for (Int currentPosition = Int(searchFromPosition); currentPosition >= Int(lineStartPosition); currentPosition--)
|
|
{
|
|
if (result[currentPosition] == ' ') { spacePosition = currentPosition; break; }
|
|
}
|
|
|
|
//if we didn't find a space searching backwards, we must hyphenate
|
|
if (spacePosition == std::string::npos)
|
|
{
|
|
result.insert(searchFromPosition, "-\n");
|
|
lineStartPosition = searchFromPosition + 2; //make sure the next search ignores the hyphen
|
|
}
|
|
else //if we found a space to split on, replace it with a new line character
|
|
{
|
|
result.replace(spacePosition, 1, 1, '\n');
|
|
lineStartPosition = spacePosition + 1;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
std::string indentNewLines(const std::string &input, const UInt indentBy)
|
|
{
|
|
std::string result = input;
|
|
|
|
const std::string indentString(indentBy, ' ');
|
|
std::string::size_type offset = 0;
|
|
|
|
while ((offset = result.find('\n', offset)) != std::string::npos)
|
|
{
|
|
if ((++offset) >= result.length()) break; //increment offset so we don't find the same \n again and do no indentation at the end
|
|
result.insert(offset, indentString);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------------------------------------------------- //
|
|
|
|
|
|
Void printBlockToStream( std::ostream &ss, const Char *pLinePrefix, TComYuv &src, const UInt numSubBlocksAcross, const UInt numSubBlocksUp, const UInt defWidth )
|
|
{
|
|
const UInt numValidComp=src.getNumberValidComponents();
|
|
|
|
for (UInt ch=0; ch<numValidComp ; ch++)
|
|
{
|
|
const ComponentID compID = ComponentID(ch);
|
|
const UInt width = src.getWidth(compID);
|
|
const UInt height = src.getHeight(compID);
|
|
const UInt stride = src.getStride(compID);
|
|
const Pel* blkSrc = src.getAddr(compID);
|
|
const UInt subBlockWidth=width/numSubBlocksAcross;
|
|
const UInt subBlockHeight=height/numSubBlocksUp;
|
|
|
|
ss << pLinePrefix << " compID: " << compID << "\n";
|
|
for (UInt y=0; y<height; y++)
|
|
{
|
|
if ((y%subBlockHeight)==0 && y!=0)
|
|
ss << pLinePrefix << '\n';
|
|
|
|
ss << pLinePrefix;
|
|
for (UInt x=0; x<width; x++)
|
|
{
|
|
if ((x%subBlockWidth)==0 && x!=0)
|
|
ss << std::setw(defWidth+2) << "";
|
|
|
|
ss << std::setw(defWidth) << blkSrc[y*stride + x] << ' ';
|
|
}
|
|
ss << '\n';
|
|
}
|
|
ss << pLinePrefix << " --- \n";
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG_STRING
|
|
Int DebugStringGetPredModeMask(PredMode mode)
|
|
{
|
|
return (mode==MODE_INTRA)?1:2;
|
|
}
|
|
|
|
Void DebugInterPredResiReco(std::string &sDebug, TComYuv &pred, TComYuv &resi, TComYuv &reco, Int predmode_mask)
|
|
{
|
|
if (DebugOptionList::DebugString_Pred.getInt()&predmode_mask)
|
|
{
|
|
std::stringstream ss(std::stringstream::out);
|
|
printBlockToStream(ss, "###inter-pred: ", pred);
|
|
std::string debugTmp;
|
|
debugTmp=ss.str();
|
|
sDebug=debugTmp+sDebug;
|
|
}
|
|
if (DebugOptionList::DebugString_Resi.getInt()&predmode_mask)
|
|
{
|
|
std::stringstream ss(std::stringstream::out);
|
|
printBlockToStream(ss, "###inter-resi: ", resi);
|
|
sDebug+=ss.str();
|
|
}
|
|
if (DebugOptionList::DebugString_Reco.getInt()&predmode_mask)
|
|
{
|
|
std::stringstream ss(std::stringstream::out);
|
|
printBlockToStream(ss, "###inter-reco: ", reco);
|
|
sDebug+=ss.str();
|
|
}
|
|
}
|
|
#endif
|