/* 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-2015, 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 #include #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 > &EnvVar::getEnvVarList() { static std::list > varInfoList; return varInfoList; } std::list &EnvVar::getEnvVarInUse() { static std::list varInUseList; return varInUseList; } static inline Void printPair(const std::pair &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 &a, // const std::pair &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(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; #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 << "\n"; for (Int i=0; igetWidth(0)/4; const UInt numValidComp=pcCU->getPic()->getNumberValidComponents(); for (UInt ch=0; chgetCbf(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