From 58e975a681f06c06593e01e461b761f12709457f Mon Sep 17 00:00:00 2001 From: Joao Carreira Date: Tue, 24 Jul 2018 19:48:50 +0100 Subject: [PATCH] Implement an initial approach for all directional intra modes --- modules/HEVCIntraPrediction.cpp | 151 ++++++++++++++++++++++++++++---- modules/HEVCIntraPrediction.h | 2 + 2 files changed, 138 insertions(+), 15 deletions(-) diff --git a/modules/HEVCIntraPrediction.cpp b/modules/HEVCIntraPrediction.cpp index 0120803..1073547 100644 --- a/modules/HEVCIntraPrediction.cpp +++ b/modules/HEVCIntraPrediction.cpp @@ -23,6 +23,8 @@ */ #include "HEVCIntraPrediction.h" +#include +#include "lib/LibMemory.h" HEVCIntraPrediction::HEVCIntraPrediction() { @@ -34,43 +36,162 @@ HEVCIntraPrediction::HEVCIntraPrediction() m_pchModuleName = "HEVCIntraPrediction"; m_pchModuleTooltip = "Apply intra-frame prediction"; m_uiNumberOfFrames = 1; - m_uiModuleRequirements = CLP_MODULE_REQUIRES_OPTIONS; + m_uiModuleRequirements = CLP_MODULE_REQUIRES_NEW_WINDOW | + CLP_MODULE_USES_KEYS | + CLP_MODULE_REQUIRES_OPTIONS; - m_cModuleOptions.addOptions() /**/ -// ( "mode", m_uiMode, "Intra mode [0-34]" ) -// ( "block_size", m_uiBlockSize, "Block size" ) - ( "x_pel", m_uiXpel, "X coordinate [0]" ) - ( "y_pel", m_uiXpel, "Y coordinate [0]" ) - ; + m_cModuleOptions.addOptions() /**/ + ( "mode", m_uiMode, "Intra mode (26-34) [26]" ) /**/ + ( "block_size", m_uiBlockSize, "Block size [4]" ) /**/ + ( "x_pel", m_uiXpel, "X coordinate [1]" ) /**/ ( "y_pel", m_uiXpel, "Y coordinate [1]" ); m_pcPredBlock = NULL; - m_uiMode = 31; + m_referenceMem = NULL; + + m_uiMode = 26; m_uiBlockSize = 4; - m_uiXpel = 0; - m_uiYpel = 0; + m_uiXpel = 1; + m_uiYpel = 1; } bool HEVCIntraPrediction::create( std::vector apcFrameList ) { m_pcPredBlock = NULL; - m_pcPredBlock = new CalypFrame( m_uiBlockSize, m_uiBlockSize, CLP_GRAY, apcFrameList[0]->getBitsPel() ); + m_pcPredBlock = new CalypFrame( m_uiBlockSize * 2 + 1, m_uiBlockSize * 2 + 1, CLP_GRAY, apcFrameList[0]->getBitsPel() ); + + getMem1D( &m_referenceMem, m_uiBlockSize * 4 ); return true; } +static const int g_AngularParamLookUp[] = {32, 26, 21, 17, 13, 9, 5, 2, 0, -2, -5, -9, -13, -17, -21, -26, // Horizontal + -32, -26, -21, -17, -13, -9, -5, -2, 0, 2, 5, 9, 13, 17, 21, 26, 32}; // Vertical + +static const int g_InverAngularParamLookup[2][8] = {{-32, -26, -21, -17, -13, -9, -5, -2}, + {-256, -315, -390, -482, -630, -910, -1638, -4096}}; + +int getAngularParam( int mode ) +{ + return g_AngularParamLookUp[mode - 2]; +} + +int getInverseAngularParam( int angular_param ) +{ + for( int i = 0; i < 8; i++ ) + { + if( g_InverAngularParamLookup[0][i] == angular_param ) + return g_InverAngularParamLookup[1][i]; + } + assert( 0 ); +} + +ClpPel getNegativeReferenceSample( int ref_pos ) +{ +} + CalypFrame* HEVCIntraPrediction::process( std::vector apcFrameList ) { - // Vertical modes - if( m_uiMode >= 18 && m_uiMode <=34 ) + if( m_uiMode < 2 ) { - - + m_uiMode = 2; } + else if( m_uiMode > 34 ) + { + m_uiMode = 34; + } + + int y, x; + int *main_coordinate, *sub_cordinate; + + ClpPel** predBlock = m_pcPredBlock->getPelBufferYUV()[0]; + ClpPel** refFrame = apcFrameList[0]->getPelBufferYUV()[0]; + + // Reset block + for( y = 0; y < m_uiBlockSize * 2 + 1; y++ ) + { + for( x = 0; x < m_uiBlockSize * 2 + 1; x++ ) + { + predBlock[y][x] = refFrame[m_uiYpel + y - 1][m_uiXpel + x - 1]; + } + } + + ClpPel* refArray = &( m_referenceMem[m_uiBlockSize * 2] ); + int angular_param = getAngularParam( m_uiMode ); + + if( m_uiMode >= 2 && m_uiMode <= 17 ) + { // Horizontal modes + main_coordinate = &y; + sub_cordinate = &x; + } + else + { // Vertical modes + main_coordinate = &x; + sub_cordinate = &y; + } + + *main_coordinate = 0; + *sub_cordinate = 0; + for( unsigned int i = 0; i < m_uiBlockSize * 2 + 1; i++ ) + { + *main_coordinate = i; + refArray[i] = predBlock[y][x]; + } + if( angular_param < 0 ) + { + int inverse_angular_param = getInverseAngularParam( angular_param ); + *main_coordinate = 0; + *sub_cordinate = 0; + for( int i = -1; i > -int( 2 * m_uiBlockSize ); i-- ) + { + *sub_cordinate = ( ( i * inverse_angular_param + 128 ) >> 8 ); + if( *sub_cordinate >= 2 * m_uiBlockSize ) + break; + refArray[i] = predBlock[y][x]; + } + } + + for( y = 0; y < m_uiBlockSize; y++ ) + { + for( x = 0; x < m_uiBlockSize; x++ ) + { + int ref_pos = *main_coordinate + 1 + ( ( ( *sub_cordinate + 1 ) * angular_param ) >> 5 ); + int fract = ( ( *sub_cordinate + 1 ) * angular_param ) & 31; + predBlock[y + 1][x + 1] = ( ( 32 - fract ) * refArray[ref_pos] + fract * refArray[ref_pos + 1] + 16 ) >> 5; + } + } + return m_pcPredBlock; } +bool HEVCIntraPrediction::keyPressed( enum Module_Key_Supported value ) +{ + if( value == MODULE_KEY_LEFT ) + { + m_uiMode -= 1; + return true; + } + if( value == MODULE_KEY_RIGHT ) + { + m_uiMode += 1; + return true; + } + if( value == MODULE_KEY_UP ) + { + m_uiMode += 1; + return true; + } + if( value == MODULE_KEY_DOWN ) + { + m_uiMode -= 1; + return true; + } + return false; +} + void HEVCIntraPrediction::destroy() { if( m_pcPredBlock ) delete m_pcPredBlock; + if( m_referenceMem ) + freeMem1D( m_referenceMem ); m_pcPredBlock = NULL; } diff --git a/modules/HEVCIntraPrediction.h b/modules/HEVCIntraPrediction.h index 8920f10..913f23e 100644 --- a/modules/HEVCIntraPrediction.h +++ b/modules/HEVCIntraPrediction.h @@ -38,12 +38,14 @@ private: unsigned int m_uiBlockSize; unsigned int m_uiXpel; unsigned int m_uiYpel; + ClpPel* m_referenceMem; public: HEVCIntraPrediction(); virtual ~HEVCIntraPrediction() {} bool create( std::vector apcFrameList ); CalypFrame* process( std::vector apcFrameList ); + bool keyPressed( enum Module_Key_Supported value ); void destroy(); };