/* 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 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. */ #include "TRenImage.h" #include "TRenFilter.h" #include "TRenSingleModel.h" #if H_3D_VSO ////////////// TRENSINGLE MODEL /////////////// template TRenSingleModelC::TRenSingleModelC() : m_iDistShift ( ( g_bitDepthY - 8) << 1 ) { m_iWidth = -1; m_iHeight = -1; m_iStride = -1; m_iUsedHeight = -1; m_iHorOffset = -1; m_iMode = -1; m_iPad = PICYUV_PAD; m_iGapTolerance = -1; m_bUseOrgRef = false; m_pcPicYuvRef = NULL; m_pcOutputSamples = NULL; m_pcOutputSamplesRow = NULL; m_iOutputSamplesStride = -1; m_ppiCurLUT = NULL; m_piInvZLUTLeft = NULL; m_piInvZLUTRight = NULL; m_aapiRefVideoPel[0] = NULL; m_aapiRefVideoPel[1] = NULL; m_aapiRefVideoPel[2] = NULL; m_aiRefVideoStrides[0] = -1; m_aiRefVideoStrides[1] = -1; m_aiRefVideoStrides[2] = -1; for (UInt uiViewNum = 0 ; uiViewNum < 2; uiViewNum++) { // LUT m_appiShiftLut[uiViewNum] = NULL; m_pcInputSamples[uiViewNum] = NULL; m_iInputSamplesStride = -1; m_ppiCurLUT = NULL; m_piInvZLUTLeft = NULL; m_piInvZLUTRight = NULL; } #if H_3D_VSO_EARLY_SKIP m_pbHorSkip = NULL; #endif } template TRenSingleModelC::~TRenSingleModelC() { #if H_3D_VSO_EARLY_SKIP if ( m_pbHorSkip ) { delete[] m_pbHorSkip; m_pbHorSkip = NULL; } #endif if ( m_pcInputSamples [0] ) delete[] m_pcInputSamples [0]; if ( m_pcInputSamples [1] ) delete[] m_pcInputSamples [1]; if ( m_pcOutputSamples ) delete[] m_pcOutputSamples ; if ( m_piInvZLUTLeft ) delete[] m_piInvZLUTLeft ; if ( m_piInvZLUTRight ) delete[] m_piInvZLUTRight; if ( m_aapiRefVideoPel[0] ) delete[] ( m_aapiRefVideoPel[0] - ( m_aiRefVideoStrides[0] * m_iPad + m_iPad ) ); if ( m_aapiRefVideoPel[1] ) delete[] ( m_aapiRefVideoPel[1] - ( m_aiRefVideoStrides[1] * m_iPad + m_iPad ) ); if ( m_aapiRefVideoPel[2] ) delete[] ( m_aapiRefVideoPel[2] - ( m_aiRefVideoStrides[2] * m_iPad + m_iPad ) ); } template Void #if H_3D_VSO_EARLY_SKIP TRenSingleModelC::create( Int iMode, Int iWidth, Int iHeight, Int iShiftPrec, Int*** aaaiSubPelShiftTable, Int iHoleMargin, Bool bUseOrgRef, Int iBlendMode, Bool bEarlySkip ) #else TRenSingleModelC::create( Int iMode, Int iWidth, Int iHeight, Int iShiftPrec, Int*** aaaiSubPelShiftTable, Int iHoleMargin, Bool bUseOrgRef, Int iBlendMode ) #endif { #if H_3D_VSO_EARLY_SKIP m_pbHorSkip = new Bool [MAX_CU_SIZE]; m_bEarlySkip = bEarlySkip; #endif AOF( iBlendMode == iBM ); m_iMode = iMode; m_iWidth = iWidth; m_iHeight = iHeight; m_iStride = iWidth; m_iSampledWidth = m_iWidth << iShiftPrec; m_iSampledStride = m_iStride << iShiftPrec; m_iShiftPrec = iShiftPrec; m_aaiSubPelShiftL = aaaiSubPelShiftTable[0]; m_aaiSubPelShiftR = aaaiSubPelShiftTable[1]; if (m_iMode == 2) { m_piInvZLUTLeft = new Int[257]; m_piInvZLUTRight = new Int[257]; } m_iGapTolerance = ( 2 << iShiftPrec ); m_iHoleMargin = iHoleMargin; m_bUseOrgRef = bUseOrgRef; m_aiRefVideoStrides[0] = m_iStride + (m_iPad << 1); m_aiRefVideoStrides[1] = m_iStride + (m_iPad << 1); m_aiRefVideoStrides[2] = m_iStride + (m_iPad << 1); m_aapiRefVideoPel [0] = new Pel[ m_aiRefVideoStrides[0] * (m_iHeight + (m_iPad << 1))]; m_aapiRefVideoPel [1] = new Pel[ m_aiRefVideoStrides[1] * (m_iHeight + (m_iPad << 1))]; m_aapiRefVideoPel [2] = new Pel[ m_aiRefVideoStrides[2] * (m_iHeight + (m_iPad << 1))]; m_aapiRefVideoPel [0] += m_aiRefVideoStrides[0] * m_iPad + m_iPad; m_aapiRefVideoPel [1] += m_aiRefVideoStrides[1] * m_iPad + m_iPad; m_aapiRefVideoPel [2] += m_aiRefVideoStrides[2] * m_iPad + m_iPad; m_iInputSamplesStride = m_iWidth+1; m_iOutputSamplesStride = m_iWidth; m_pcInputSamples[0] = new RenModelInPels[m_iInputSamplesStride*m_iHeight]; m_pcInputSamples[1] = new RenModelInPels[m_iInputSamplesStride*m_iHeight]; m_pcOutputSamples = new RenModelOutPels[m_iOutputSamplesStride*m_iHeight]; } template Void TRenSingleModelC::setLRView( Int iViewPos, Pel** apiCurVideoPel, Int* aiCurVideoStride, Pel* piCurDepthPel, Int iCurDepthStride ) { AOF(( iViewPos == 0) || (iViewPos == 1) ); RenModelInPels* pcCurInputSampleRow = m_pcInputSamples[iViewPos]; Pel* piDRow = piCurDepthPel; Pel* piYRow = apiCurVideoPel[0]; #if H_3D_VSO_COLOR_PLANES Pel* piURow = apiCurVideoPel[1]; Pel* piVRow = apiCurVideoPel[2]; #endif Int iOffsetX = ( iViewPos == VIEWPOS_RIGHT ) ? 1 : 0; for ( Int iPosY = 0; iPosY < m_iUsedHeight; iPosY++ ) { if ( iViewPos == VIEWPOS_RIGHT ) { Int iSubPosX = (1 << m_iShiftPrec); pcCurInputSampleRow[0].aiY[iSubPosX] = piYRow[0]; #if H_3D_VSO_COLOR_PLANES pcCurInputSampleRow[0].aiU[iSubPosX] = piURow[0]; pcCurInputSampleRow[0].aiV[iSubPosX] = piVRow[0]; #endif } for ( Int iPosX = 0; iPosX < m_iWidth; iPosX++ ) { pcCurInputSampleRow[iPosX].iD = piDRow[iPosX]; for (Int iSubPosX = 0; iSubPosX < (1 << m_iShiftPrec)+1; iSubPosX++ ) { Int iShift = (iPosX << m_iShiftPrec) + iSubPosX; pcCurInputSampleRow[iPosX+iOffsetX].aiY[iSubPosX] = piYRow[iShift]; #if H_3D_VSO_COLOR_PLANES pcCurInputSampleRow[iPosX+iOffsetX].aiU[iSubPosX] = piURow[iShift]; pcCurInputSampleRow[iPosX+iOffsetX].aiV[iSubPosX] = piVRow[iShift]; #endif } } pcCurInputSampleRow += m_iInputSamplesStride; piDRow += iCurDepthStride; piYRow += aiCurVideoStride[0]; #if H_3D_VSO_COLOR_PLANES piURow += aiCurVideoStride[1]; piVRow += aiCurVideoStride[2]; #endif } m_aapiBaseVideoPel [iViewPos] = apiCurVideoPel; m_aaiBaseVideoStrides [iViewPos] = aiCurVideoStride; m_apiBaseDepthPel [iViewPos] = piCurDepthPel; m_aiBaseDepthStrides [iViewPos] = iCurDepthStride; } template Void TRenSingleModelC::setupPart ( UInt uiHorOffset, Int iUsedHeight ) { AOT( iUsedHeight > m_iHeight ); m_iUsedHeight = iUsedHeight; m_iHorOffset = (Int) uiHorOffset; } template Void TRenSingleModelC::setup( TComPicYuv* pcOrgVideo, Int** ppiShiftLutLeft, Int** ppiBaseShiftLutLeft, Int** ppiShiftLutRight, Int** ppiBaseShiftLutRight, Int iDistToLeft, Bool bKeepReference ) { AOT( !m_bUseOrgRef && pcOrgVideo ); AOT( (ppiShiftLutLeft == NULL) && (m_iMode == 0 || m_iMode == 2) ); AOT( (ppiShiftLutRight == NULL) && (m_iMode == 1 || m_iMode == 2) ); m_appiShiftLut[0] = ppiShiftLutLeft; m_appiShiftLut[1] = ppiShiftLutRight; // Copy Reference m_pcPicYuvRef = pcOrgVideo; if ( pcOrgVideo && !bKeepReference ) { TRenFilter::copy( pcOrgVideo->getLumaAddr() + m_iHorOffset * pcOrgVideo->getStride() , pcOrgVideo->getStride() , m_iWidth, m_iUsedHeight, m_aapiRefVideoPel[0], m_aiRefVideoStrides[0]); TRenFilter::sampleCUpHorUp(0, pcOrgVideo->getCbAddr() + (m_iHorOffset >> 1) * pcOrgVideo->getCStride(), pcOrgVideo->getCStride(), m_iWidth >> 1, m_iUsedHeight >> 1, m_aapiRefVideoPel[1], m_aiRefVideoStrides[1]); TRenFilter::sampleCUpHorUp(0, pcOrgVideo->getCrAddr() + (m_iHorOffset >> 1) * pcOrgVideo->getCStride(), pcOrgVideo->getCStride(), m_iWidth >> 1, m_iUsedHeight >> 1, m_aapiRefVideoPel[2], m_aiRefVideoStrides[2]); xSetStructRefView(); } // Initial Rendering xResetStructError(); xInitSampleStructs(); switch ( m_iMode ) { case 0: #if H_3D_VSO_EARLY_SKIP xRenderL( 0, 0, m_iWidth, m_iUsedHeight, m_aiBaseDepthStrides[0], m_apiBaseDepthPel[0],false ); #else xRenderL( 0, 0, m_iWidth, m_iUsedHeight, m_aiBaseDepthStrides[0], m_apiBaseDepthPel[0] ); #endif break; case 1: #if H_3D_VSO_EARLY_SKIP xRenderR( 0, 0, m_iWidth, m_iUsedHeight, m_aiBaseDepthStrides[1], m_apiBaseDepthPel[1],false); #else xRenderR( 0, 0, m_iWidth, m_iUsedHeight, m_aiBaseDepthStrides[1], m_apiBaseDepthPel[1] ); #endif break; case 2: TRenFilter::setupZLUT( true, 30, iDistToLeft, ppiBaseShiftLutLeft, ppiBaseShiftLutRight, m_iBlendZThres, m_iBlendDistWeight, m_piInvZLUTLeft, m_piInvZLUTRight ); #if H_3D_VSO_EARLY_SKIP xRenderL( 0, 0, m_iWidth, m_iUsedHeight, m_aiBaseDepthStrides[0], m_apiBaseDepthPel[0],false); xRenderR( 0, 0, m_iWidth, m_iUsedHeight, m_aiBaseDepthStrides[1], m_apiBaseDepthPel[1],false); #else xRenderL( 0, 0, m_iWidth, m_iUsedHeight, m_aiBaseDepthStrides[0], m_apiBaseDepthPel[0] ); xRenderR( 0, 0, m_iWidth, m_iUsedHeight, m_aiBaseDepthStrides[1], m_apiBaseDepthPel[1] ); #endif break; default: AOT(true); } // Get Rendered View as Reference if ( !pcOrgVideo && !bKeepReference ) { xResetStructError(); xSetStructSynthViewAsRefView(); } } template Void #if H_3D_VSO_COLOR_PLANES TRenSingleModelC::xGetSampleStrTextPtrs( Int iViewNum, Pel RenModelOutPels::*& rpiSrcY, Pel RenModelOutPels::*& rpiSrcU, Pel RenModelOutPels::*& rpiSrcV ) #else TRenSingleModelC::xGetSampleStrTextPtrs( Int iViewNum, Pel RenModelOutPels::*& rpiSrcY ) #endif { switch ( iViewNum ) { case 0: rpiSrcY = &RenModelOutPels::iYLeft; #if H_3D_VSO_COLOR_PLANES rpiSrcU = &RenModelOutPels::iULeft; rpiSrcV = &RenModelOutPels::iVLeft; #endif break; case 1: rpiSrcY = &RenModelOutPels::iYRight; #if H_3D_VSO_COLOR_PLANES rpiSrcU = &RenModelOutPels::iURight; rpiSrcV = &RenModelOutPels::iVRight; #endif break; case 2: rpiSrcY = &RenModelOutPels::iYBlended; #if H_3D_VSO_COLOR_PLANES rpiSrcU = &RenModelOutPels::iUBlended; rpiSrcV = &RenModelOutPels::iVBlended; #endif break; } } template Void TRenSingleModelC::xGetSampleStrDepthPtrs( Int iViewNum, Pel RenModelOutPels::*& rpiSrcD ) { AOT(iViewNum != 0 && iViewNum != 1); rpiSrcD = (iViewNum == 1) ? &RenModelOutPels::iDRight : &RenModelOutPels::iDLeft; } template Void TRenSingleModelC::xSetStructRefView( ) { RenModelOutPels* pcCurOutSampleRow = m_pcOutputSamples; Pel* piYRow = m_aapiRefVideoPel[0]; #if H_3D_VSO_COLOR_PLANES Pel* piURow = m_aapiRefVideoPel[1]; Pel* piVRow = m_aapiRefVideoPel[2]; #endif for ( Int iPosY = 0; iPosY < m_iUsedHeight; iPosY++ ) { for ( Int iPosX = 0; iPosX < m_iWidth; iPosX++ ) { pcCurOutSampleRow[iPosX].iYRef = piYRow[iPosX]; #if H_3D_VSO_COLOR_PLANES pcCurOutSampleRow[iPosX].iURef = piURow[iPosX]; pcCurOutSampleRow[iPosX].iVRef = piVRow[iPosX]; #endif } pcCurOutSampleRow += m_iOutputSamplesStride; piYRow += m_aiRefVideoStrides[0]; #if H_3D_VSO_COLOR_PLANES piURow += m_aiRefVideoStrides[1]; piVRow += m_aiRefVideoStrides[2]; #endif } } template Void TRenSingleModelC::xResetStructError( ) { RenModelOutPels* pcCurOutSampleRow = m_pcOutputSamples; for ( Int iPosY = 0; iPosY < m_iHeight; iPosY++ ) { for ( Int iPosX = 0; iPosX < m_iWidth; iPosX++ ) { pcCurOutSampleRow[iPosX].iError = 0; } pcCurOutSampleRow += m_iOutputSamplesStride; } } template Void TRenSingleModelC::xSetStructSynthViewAsRefView( ) { AOT( m_iMode < 0 || m_iMode > 2); RenModelOutPels* pcCurOutSampleRow = m_pcOutputSamples; Pel RenModelOutPels::* piSrcY = NULL; #if H_3D_VSO_COLOR_PLANES Pel RenModelOutPels::* piSrcU = NULL; Pel RenModelOutPels::* piSrcV = NULL; xGetSampleStrTextPtrs( m_iMode, piSrcY, piSrcU, piSrcV ); #else xGetSampleStrTextPtrs( m_iMode, piSrcY ); #endif for ( Int iPosY = 0; iPosY < m_iUsedHeight; iPosY++ ) { for ( Int iPosX = 0; iPosX < m_iWidth; iPosX++ ) { pcCurOutSampleRow[iPosX].iYRef = pcCurOutSampleRow[iPosX].*piSrcY; #if H_3D_VSO_COLOR_PLANES pcCurOutSampleRow[iPosX].iURef = pcCurOutSampleRow[iPosX].*piSrcU; pcCurOutSampleRow[iPosX].iVRef = pcCurOutSampleRow[iPosX].*piSrcV; #endif } pcCurOutSampleRow += m_iOutputSamplesStride; } } template Void TRenSingleModelC::xInitSampleStructs() { RenModelOutPels* pcOutSampleRow = m_pcOutputSamples; RenModelInPels * pcLeftInSampleRow = m_pcInputSamples[0]; RenModelInPels * pcRightInSampleRow = m_pcInputSamples[1]; for (Int iPosY = 0; iPosY < m_iHeight; iPosY++) { for (Int iPosX = 0; iPosX < m_iWidth; iPosX++) { //// Output Samples pcOutSampleRow[iPosX].iFilledLeft = REN_IS_HOLE; pcOutSampleRow[iPosX].iFilledRight = REN_IS_HOLE; pcOutSampleRow[iPosX].iDLeft = 0; pcOutSampleRow[iPosX].iDRight = 0; pcOutSampleRow[iPosX].iDBlended = 0; // Y Planes pcOutSampleRow[iPosX].iYLeft = 0; pcOutSampleRow[iPosX].iYRight = 0; pcOutSampleRow[iPosX].iYBlended = 0; #if H_3D_VSO_COLOR_PLANES // U Planes pcOutSampleRow[iPosX].iULeft = 1 << (g_bitDepthC - 1); pcOutSampleRow[iPosX].iURight = 1 << (g_bitDepthC - 1); pcOutSampleRow[iPosX].iUBlended = 1 << (g_bitDepthC - 1); // V Planes pcOutSampleRow[iPosX].iVLeft = 1 << (g_bitDepthC - 1); pcOutSampleRow[iPosX].iVRight = 1 << (g_bitDepthC - 1); pcOutSampleRow[iPosX].iVBlended = 1 << (g_bitDepthC - 1); #endif //// Input Samples pcLeftInSampleRow [iPosX].bOccluded = false; pcRightInSampleRow[iPosX].bOccluded = false; } pcOutSampleRow += m_iOutputSamplesStride; pcLeftInSampleRow += m_iInputSamplesStride; pcRightInSampleRow += m_iInputSamplesStride; } } #if H_3D_VSO_EARLY_SKIP template RMDist TRenSingleModelC::getDistDepth( Int iViewPos, Int iStartPosX, Int iStartPosY, Int iWidth, Int iHeight, Int iStride, Pel* piNewData , Pel * piOrgData, Int iOrgStride ) #else template RMDist TRenSingleModelC::getDistDepth( Int iViewPos, Int iStartPosX, Int iStartPosY, Int iWidth, Int iHeight, Int iStride, Pel* piNewData ) #endif { RMDist iSSE = 0; #if H_3D_VSO_EARLY_SKIP Bool bEarlySkip; #endif switch ( iViewPos ) { case 0: #if H_3D_VSO_EARLY_SKIP bEarlySkip = m_bEarlySkip ? xDetectEarlySkipL(iStartPosX, iStartPosY, iWidth, iHeight, iStride, piNewData, piOrgData, iOrgStride) : false; if( !bEarlySkip ) { iSSE = xRenderL( iStartPosX, iStartPosY, iWidth, iHeight, iStride, piNewData,true ); } #else iSSE = xRenderL( iStartPosX, iStartPosY, iWidth, iHeight, iStride, piNewData ); #endif break; case 1: #if H_3D_VSO_EARLY_SKIP bEarlySkip = m_bEarlySkip ? xDetectEarlySkipR(iStartPosX, iStartPosY, iWidth, iHeight, iStride, piNewData, piOrgData, iOrgStride) : false; if( !bEarlySkip ) { iSSE = xRenderR( iStartPosX, iStartPosY, iWidth, iHeight, iStride, piNewData,true ); } #else iSSE = xRenderR( iStartPosX, iStartPosY, iWidth, iHeight, iStride, piNewData ); #endif break; default: assert(0); } return iSSE; } #if H_3D_VSO_EARLY_SKIP template Void TRenSingleModelC::setDepth( Int iViewPos, Int iStartPosX, Int iStartPosY, Int iWidth, Int iHeight, Int iStride, Pel* piNewData, Pel* piOrgData, Int iOrgStride ) #else template Void TRenSingleModelC::setDepth( Int iViewPos, Int iStartPosX, Int iStartPosY, Int iWidth, Int iHeight, Int iStride, Pel* piNewData ) #endif { #ifdef H_3D_VSO_EARLY_SKIP Bool bEarlySkip; #endif switch ( iViewPos ) { case 0: #if H_3D_VSO_EARLY_SKIP bEarlySkip = m_bEarlySkip ? xDetectEarlySkipL(iStartPosX, iStartPosY, iWidth, iHeight, iStride, piNewData, piOrgData,iOrgStride) : false; if( !bEarlySkip ) { xRenderL( iStartPosX, iStartPosY, iWidth, iHeight, iStride, piNewData,true ); } #else xRenderL( iStartPosX, iStartPosY, iWidth, iHeight, iStride, piNewData ); #endif break; case 1: #if H_3D_VSO_EARLY_SKIP bEarlySkip = m_bEarlySkip ? xDetectEarlySkipR(iStartPosX, iStartPosY, iWidth, iHeight, iStride, piNewData, piOrgData,iOrgStride) : false; if( !bEarlySkip ) { xRenderR( iStartPosX, iStartPosY, iWidth, iHeight, iStride, piNewData,true ); } #else xRenderR( iStartPosX, iStartPosY, iWidth, iHeight, iStride, piNewData ); #endif break; default: assert(0); } } template Void TRenSingleModelC::getSynthVideo( Int iViewPos, TComPicYuv* pcPicYuv ) { AOT( pcPicYuv->getWidth() != m_iWidth ); AOT( pcPicYuv->getHeight() < m_iUsedHeight + m_iHorOffset ); #if H_3D_VSO_COLOR_PLANES Pel RenModelOutPels::* piText[3] = { NULL, NULL, NULL }; xGetSampleStrTextPtrs(iViewPos, piText[0], piText[1], piText[2]); // Temp image for chroma down sampling PelImage cTempImage( m_iWidth, m_iUsedHeight, 3, 0); Int aiStrides[3]; Pel* apiData [3]; cTempImage.getDataAndStrides( apiData, aiStrides ); for (UInt uiCurPlane = 0; uiCurPlane < 3; uiCurPlane++ ) { xCopyFromSampleStruct( m_pcOutputSamples, m_iOutputSamplesStride, piText[uiCurPlane], apiData[uiCurPlane], aiStrides[uiCurPlane] , m_iWidth, m_iUsedHeight); } xCopy2PicYuv( apiData, aiStrides, pcPicYuv ); #else Pel RenModelOutPels::* piY; xGetSampleStrTextPtrs(iViewPos, piY); xCopyFromSampleStruct( m_pcOutputSamples, m_iOutputSamplesStride, piY, pcPicYuv->getLumaAddr() + m_iHorOffset * pcPicYuv->getStride(), pcPicYuv->getStride(), m_iWidth, m_iUsedHeight ); pcPicYuv->setChromaTo( 1 << (g_bitDepthC - 1) ); #endif } template Void TRenSingleModelC::getSynthDepth( Int iViewPos, TComPicYuv* pcPicYuv ) { AOT( iViewPos != 0 && iViewPos != 1); AOT( pcPicYuv->getWidth() != m_iWidth ); AOT( pcPicYuv->getHeight() < m_iUsedHeight + m_iHorOffset ); Pel RenModelOutPels::* piD = 0; xGetSampleStrDepthPtrs(iViewPos, piD); xCopyFromSampleStruct( m_pcOutputSamples, m_iOutputSamplesStride, piD, pcPicYuv->getLumaAddr() + pcPicYuv->getStride() * m_iHorOffset, pcPicYuv->getStride(), m_iWidth, m_iUsedHeight ); pcPicYuv->setChromaTo( 1 << (g_bitDepthC - 1) ); } template Void TRenSingleModelC::getRefVideo ( Int iViewPos, TComPicYuv* pcPicYuv ) { AOT( pcPicYuv->getWidth() != m_iWidth ); AOT( pcPicYuv->getHeight() < m_iUsedHeight + m_iHorOffset); #if H_3D_VSO_COLOR_PLANES Pel RenModelOutPels::* piText[3]; piText[0] = &RenModelOutPels::iYRef; piText[1] = &RenModelOutPels::iURef; piText[2] = &RenModelOutPels::iVRef; // Temp image for chroma down sampling PelImage cTempImage( m_iWidth, m_iUsedHeight, 3, 0); Int aiStrides[3]; Pel* apiData [3]; cTempImage.getDataAndStrides( apiData, aiStrides ); for (UInt uiCurPlane = 0; uiCurPlane < 3; uiCurPlane++ ) { xCopyFromSampleStruct( m_pcOutputSamples, m_iOutputSamplesStride, piText[uiCurPlane], apiData[uiCurPlane], aiStrides[uiCurPlane] , m_iWidth, m_iUsedHeight); } xCopy2PicYuv( apiData, aiStrides, pcPicYuv ); #else xCopyFromSampleStruct( m_pcOutputSamples, m_iOutputSamplesStride, &RenModelOutPels::iYRef, pcPicYuv->getLumaAddr() * pcPicYuv->getStride() + m_iHorOffset, pcPicYuv->getStride(), m_iWidth, m_iUsedHeight ); pcPicYuv->setChromaTo( 1 << ( g_bitDepthC - 1 ) ); #endif } template RMDist TRenSingleModelC::getDistVideo( Int iViewPos, Int iPlane, Int iStartPosX, Int iStartPosY, Int iWidth, Int iHeight, Int iStride, Pel* piNewData ) { AOF(false); return 0; } template Void TRenSingleModelC::setVideo( Int iViewPos, Int iPlane, Int iStartPosX, Int iStartPosY, Int iWidth, Int iHeight, Int iStride, Pel* piNewData ) { AOF(false); } template __inline Void TRenSingleModelC::xSetViewRow( Int iPosY ) { m_pcInputSamplesRow[0] = m_pcInputSamples[0] + m_iInputSamplesStride * iPosY; m_pcInputSamplesRow[1] = m_pcInputSamples[1] + m_iInputSamplesStride * iPosY; m_pcOutputSamplesRow = m_pcOutputSamples + m_iOutputSamplesStride * iPosY; } template __inline Void TRenSingleModelC::xIncViewRow( ) { m_pcInputSamplesRow[0] += m_iInputSamplesStride ; m_pcInputSamplesRow[1] += m_iInputSamplesStride ; m_pcOutputSamplesRow += m_iOutputSamplesStride; } #if H_3D_VSO_EARLY_SKIP template template __inline RMDist TRenSingleModelC::xRenderL( Int iStartPosX, Int iStartPosY, Int iWidth, Int iHeight, Int iStride, Pel* piNewData, Bool bFast) #else template template __inline RMDist TRenSingleModelC::xRenderL( Int iStartPosX, Int iStartPosY, Int iWidth, Int iHeight, Int iStride, Pel* piNewData) #endif { const Int iCurViewPos = 0; const Int iOtherViewPos = 1; m_iCurViewPos = iCurViewPos ; m_iOtherViewPos = iOtherViewPos; m_piNewDepthData = piNewData; m_iNewDataWidth = iWidth; m_iStartChangePosX = iStartPosX; if ((iWidth == 0) || (iHeight == 0)) return 0; // Get Data m_ppiCurLUT = m_appiShiftLut [iCurViewPos]; xSetViewRow ( iStartPosY); // Init Start RMDist iError = 0; Int iStartChangePos; iStartChangePos = m_iStartChangePosX; for (Int iPosY = iStartPosY; iPosY < iStartPosY + iHeight; iPosY++ ) { #if H_3D_VSO_EARLY_SKIP if( m_bEarlySkip && bFast ) { if ( m_pbHorSkip[iPosY-iStartPosY] ) { xIncViewRow(); m_piNewDepthData += iStride; continue; } } #endif m_bInOcclusion = false; Int iLastSPos; Int iEndChangePos = m_iStartChangePosX + iWidth - 1; Int iPosXinNewData = iWidth - 1; Int iMinChangedSPos = m_iSampledWidth; if ( iEndChangePos == ( m_iWidth -1 )) // Special processing for rightmost depth sample { m_iCurDepth = m_piNewDepthData[iPosXinNewData]; Int iCurSPos = xShiftNewData(iEndChangePos, iPosXinNewData); m_iLastOccludedSPos = iCurSPos + 1; m_iLastOccludedSPosFP = xRangeLeftL( m_iLastOccludedSPos ); xExtrapolateMarginL ( iCurSPos, iEndChangePos, iError ); iMinChangedSPos = std::min( iMinChangedSPos, (iEndChangePos << m_iShiftPrec) - m_ppiCurLUT[0][ RenModRemoveBitInc( std::max(m_pcInputSamplesRow[iCurViewPos][iEndChangePos].iD, m_piNewDepthData[iPosXinNewData] )) ]); iLastSPos = iCurSPos; m_iLastDepth = m_iCurDepth; if ( bSet ) { m_pcInputSamplesRow[iCurViewPos][iEndChangePos].iD = m_piNewDepthData[iPosXinNewData]; } iPosXinNewData--; iEndChangePos--; } else { iLastSPos = xShift(iEndChangePos+1); m_iLastDepth = m_pcInputSamplesRow [iCurViewPos][iEndChangePos+1].iD; xInitRenderPartL( iEndChangePos, iLastSPos ); } //// RENDER NEW DATA Int iCurPosX; for ( iCurPosX = iEndChangePos; iCurPosX >= iStartChangePos; iCurPosX-- ) { // Get minimal changed sample position iMinChangedSPos = std::min( iMinChangedSPos, (iCurPosX << m_iShiftPrec) - m_ppiCurLUT[0][ RenModRemoveBitInc( std::max(m_pcInputSamplesRow[iCurViewPos][iCurPosX].iD, m_piNewDepthData[iPosXinNewData] )) ]); Int iCurSPos = xShiftNewData(iCurPosX,iPosXinNewData); m_iCurDepth = m_piNewDepthData[iPosXinNewData]; xRenderRangeL(iCurSPos, iLastSPos, iCurPosX, iError ); iLastSPos = iCurSPos; m_iLastDepth = m_iCurDepth; if ( bSet ) { m_pcInputSamplesRow[iCurViewPos][iCurPosX].iD = m_piNewDepthData[iPosXinNewData]; } iPosXinNewData--; } //// RE-RENDER DATA LEFT TO NEW DATA while ( iCurPosX >= 0 ) { Int iCurSPos = xShift(iCurPosX); m_iCurDepth = m_pcInputSamplesRow[iCurViewPos][iCurPosX].iD; xRenderRangeL( iCurSPos, iLastSPos, iCurPosX, iError ); if ( iCurSPos < iMinChangedSPos ) { break; } iCurPosX--; iLastSPos = iCurSPos; m_iLastDepth = m_iCurDepth; } xIncViewRow(); m_piNewDepthData += iStride; } return iError; } #ifdef H_3D_VSO_EARLY_SKIP template template __inline RMDist TRenSingleModelC::xRenderR( Int iStartPosX, Int iStartPosY, Int iWidth, Int iHeight, Int iStride, Pel* piNewData , Bool bFast) #else template template __inline RMDist TRenSingleModelC::xRenderR( Int iStartPosX, Int iStartPosY, Int iWidth, Int iHeight, Int iStride, Pel* piNewData ) #endif { const Int iCurViewPos = 1; const Int iOtherViewPos = 0; m_iCurViewPos = iCurViewPos; m_iOtherViewPos = iOtherViewPos; m_piNewDepthData = piNewData; m_iNewDataWidth = iWidth; m_iStartChangePosX = iStartPosX; if ((iWidth == 0) || (iHeight == 0)) return 0; // Get Data m_ppiCurLUT = m_appiShiftLut [iCurViewPos]; xSetViewRow ( iStartPosY); // Init Start RMDist iError = 0; Int iEndChangePos; iEndChangePos = m_iStartChangePosX + iWidth - 1; for (Int iPosY = iStartPosY; iPosY < iStartPosY + iHeight; iPosY++ ) { #if H_3D_VSO_EARLY_SKIP if( m_bEarlySkip && bFast ) { if ( m_pbHorSkip[iPosY-iStartPosY] ) { xIncViewRow(); m_piNewDepthData += iStride; continue; } } #endif m_bInOcclusion = false; Int iLastSPos; Int iStartChangePos = m_iStartChangePosX; Int iPosXinNewData = 0; Int iMaxChangedSPos = -1; if ( iStartChangePos == 0 ) // Special processing for leftmost depth sample { m_iCurDepth = m_piNewDepthData[iPosXinNewData]; Int iCurSPos = xShiftNewData(iStartChangePos, iPosXinNewData); m_iLastOccludedSPos = iCurSPos - 1; m_iLastOccludedSPosFP = xRangeRightR( m_iLastOccludedSPos ); xExtrapolateMarginR ( iCurSPos, iStartChangePos, iError ); iMaxChangedSPos = std::max( iMaxChangedSPos, (iStartChangePos << m_iShiftPrec) - m_ppiCurLUT[0][ RenModRemoveBitInc( std::max(m_pcInputSamplesRow[iCurViewPos][iStartChangePos].iD, m_piNewDepthData[iPosXinNewData] )) ]); iLastSPos = iCurSPos; m_iLastDepth = m_iCurDepth; if ( bSet ) { m_pcInputSamplesRow[iCurViewPos][iStartChangePos].iD = m_piNewDepthData[iPosXinNewData]; } iPosXinNewData++; iStartChangePos++; } else { iLastSPos = xShift(iStartChangePos-1); m_iLastDepth = m_pcInputSamplesRow[iCurViewPos][iStartChangePos-1].iD; xInitRenderPartR( iStartChangePos, iLastSPos ); } //// RENDER NEW DATA Int iCurPosX; for ( iCurPosX = iStartChangePos; iCurPosX <= iEndChangePos; iCurPosX++ ) { // Get minimal changed sample position iMaxChangedSPos = std::max( iMaxChangedSPos, (iCurPosX << m_iShiftPrec) - m_ppiCurLUT[0][ RenModRemoveBitInc( std::max(m_pcInputSamplesRow[iCurViewPos][iCurPosX].iD, m_piNewDepthData[iPosXinNewData] )) ]); Int iCurSPos = xShiftNewData(iCurPosX,iPosXinNewData); m_iCurDepth = m_piNewDepthData[iPosXinNewData]; xRenderRangeR(iCurSPos, iLastSPos, iCurPosX, iError ); iLastSPos = iCurSPos; m_iLastDepth = m_iCurDepth; if ( bSet ) { m_pcInputSamplesRow[iCurViewPos][iCurPosX].iD = m_piNewDepthData[iPosXinNewData]; } iPosXinNewData++; } //// RE-RENDER DATA LEFT TO NEW DATA while ( iCurPosX < m_iWidth ) { Int iCurSPos = xShift(iCurPosX); m_iCurDepth = m_pcInputSamplesRow[iCurViewPos][iCurPosX].iD; xRenderRangeR( iCurSPos, iLastSPos, iCurPosX, iError ); if ( iCurSPos > iMaxChangedSPos ) { break; } iCurPosX++; iLastSPos = iCurSPos; m_iLastDepth = m_iCurDepth; } xIncViewRow(); m_piNewDepthData += iStride; } return iError; } template __inline Void TRenSingleModelC::xInitRenderPartL( Int iEndChangePos, Int iLastSPos ) { const Int iCurViewPos = 0; // GET MINIMAL OCCLUDED SAMPLE POSITION Int iCurPosX = iEndChangePos; if ( ( iCurPosX + 1 < m_iWidth ) && (m_pcInputSamplesRow[iCurViewPos][ iCurPosX + 1].bOccluded ) ) { iCurPosX++; while ( (iCurPosX + 1 < m_iWidth) && (m_pcInputSamplesRow[iCurViewPos][ iCurPosX + 1].bOccluded ) ) iCurPosX++; if ( iCurPosX + 1 < m_iWidth ) { iCurPosX++; m_iLastOccludedSPos = xShift(iCurPosX); } else { m_iLastOccludedSPos = xShift(iCurPosX) + 1; } m_iLastOccludedSPosFP = xRoundL( m_iLastOccludedSPos ); } else { m_iLastOccludedSPos = iLastSPos+1; m_iLastOccludedSPosFP = xRangeLeftL( m_iLastOccludedSPos ); } m_bInOcclusion = iLastSPos >= m_iLastOccludedSPos; }; template __inline Void TRenSingleModelC::xInitRenderPartR( Int iStartChangePos, Int iLastSPos ) { const Int iCurViewPos = 1; // GET MINIMAL OCCLUDED SAMPLE POSITION Int iCurPosX = iStartChangePos; if ( ( iCurPosX - 1 > -1 ) && (m_pcInputSamplesRow[iCurViewPos][ iCurPosX - 1].bOccluded ) ) { iCurPosX--; while ( (iCurPosX - 1 > -1 ) && (m_pcInputSamplesRow[iCurViewPos][ iCurPosX - 1].bOccluded ) ) iCurPosX--; if ( iCurPosX - 1 > -1 ) { iCurPosX--; m_iLastOccludedSPos = xShift(iCurPosX); } else { m_iLastOccludedSPos = xShift(iCurPosX) - 1; } m_iLastOccludedSPosFP = xRoundR( m_iLastOccludedSPos ); } else { m_iLastOccludedSPos = iLastSPos-1; m_iLastOccludedSPosFP = xRangeRightR( m_iLastOccludedSPos ); } m_bInOcclusion = iLastSPos <= m_iLastOccludedSPos; }; template template __inline Void TRenSingleModelC::xRenderShiftedRangeL(Int iCurSPos, Int iLastSPos, Int iCurPos, RMDist& riError ) { assert( iCurSPos <= iLastSPos ); //assert( iRightSPos < m_iWidth ); Int iDeltaSPos = iLastSPos - iCurSPos; if ( iDeltaSPos > m_iGapTolerance ) { xFillHoleL( iCurSPos, iLastSPos, iCurPos, riError ); } else { if (iLastSPos < 0 ) return; RM_AOT( iDeltaSPos > m_iGapTolerance ); m_iThisDepth = m_iCurDepth; for (Int iFillSPos = std::max(0, xRangeLeftL(iCurSPos) ); iFillSPos <= min(xRangeRightL( iLastSPos ) ,m_iLastOccludedSPosFP-1); iFillSPos++ ) { Int iDeltaCurSPos = (iFillSPos << m_iShiftPrec) - iCurSPos; RM_AOT( iDeltaCurSPos > iDeltaSPos ); RM_AOT( iDeltaCurSPos < 0 ); RM_AOT( m_aaiSubPelShiftL[iDeltaSPos][iDeltaCurSPos] == 0xdeaddead); xSetShiftedPelL( iCurPos, m_aaiSubPelShiftL[iDeltaSPos][iDeltaCurSPos], iFillSPos, REN_IS_FILLED, riError ); } }; } template template __inline Void TRenSingleModelC::xRenderShiftedRangeR(Int iCurSPos, Int iLastSPos, Int iCurPos, RMDist& riError ) { assert( iCurSPos >= iLastSPos ); Int iDeltaSPos = iCurSPos - iLastSPos; if ( iDeltaSPos > m_iGapTolerance ) { xFillHoleR( iCurSPos, iLastSPos, iCurPos, riError ); } else { if (iLastSPos > m_iSampledWidth - 1 ) return; m_iThisDepth = m_iCurDepth; RM_AOT( iDeltaSPos > m_iGapTolerance ); for (Int iFillSPos = max(m_iLastOccludedSPosFP+1, xRangeLeftR(iLastSPos) ); iFillSPos <= min(xRangeRightR( iCurSPos ) ,m_iWidth -1); iFillSPos++ ) { Int iDeltaCurSPos = (iFillSPos << m_iShiftPrec) - iLastSPos; RM_AOT( iDeltaCurSPos > iDeltaSPos ); RM_AOT( iDeltaCurSPos < 0 ); RM_AOT( m_aaiSubPelShiftR[iDeltaSPos][iDeltaCurSPos] == 0xdeaddead); xSetShiftedPelR( iCurPos, m_aaiSubPelShiftR[iDeltaSPos][iDeltaCurSPos], iFillSPos, REN_IS_FILLED, riError ); } }; } template template __inline Void TRenSingleModelC::xRenderRangeL(Int iCurSPos, Int iLastSPos, Int iCurPos, RMDist& riError ) { const Int iCurViewPos = 0; if ( !m_bInOcclusion ) { if ( iCurSPos >= iLastSPos ) { m_iLastOccludedSPos = iLastSPos; Int iRightSPosFP = xRoundL( iLastSPos ); if ( ( iRightSPosFP == xRangeRightL(iLastSPos)) && (iRightSPosFP >= 0) ) { m_iThisDepth = m_iLastDepth; xSetShiftedPelL( iCurPos+1, 0, iRightSPosFP, REN_IS_FILLED, riError ); } m_iLastOccludedSPosFP = iRightSPosFP; m_bInOcclusion = true; if ( bSet ) { m_pcInputSamplesRow[iCurViewPos][ iCurPos ].bOccluded = true; } } else { if ( bSet ) { m_pcInputSamplesRow[iCurViewPos][ iCurPos ].bOccluded = false; } xRenderShiftedRangeL(iCurSPos, iLastSPos, iCurPos, riError ); } } else { if ( iCurSPos < m_iLastOccludedSPos ) { m_bInOcclusion = false; if ( bSet ) { m_pcInputSamplesRow[iCurViewPos][ iCurPos ].bOccluded = false; } xRenderShiftedRangeL(iCurSPos, iLastSPos, iCurPos, riError ); } else { if ( bSet ) { m_pcInputSamplesRow[iCurViewPos][ iCurPos ].bOccluded = true; } } } } template template __inline Void TRenSingleModelC::xRenderRangeR(Int iCurSPos, Int iLastSPos, Int iCurPos, RMDist& riError ) { const Int iCurViewPos = 1; // Find out if current sample is occluded if ( !m_bInOcclusion ) { if ( iCurSPos <= iLastSPos ) { m_iLastOccludedSPos = iLastSPos; Int iLeftSPosFP = xRoundR( iLastSPos ); if ( ( iLeftSPosFP == xRangeLeftR(iLastSPos)) && (iLeftSPosFP <= m_iWidth - 1) ) { m_iThisDepth = m_iLastDepth; xSetShiftedPelR( iCurPos-1,1 << m_iShiftPrec , iLeftSPosFP, REN_IS_FILLED, riError ); } m_iLastOccludedSPosFP = iLeftSPosFP; m_bInOcclusion = true; if ( bSet ) { m_pcInputSamplesRow[iCurViewPos][ iCurPos ].bOccluded = true; } } else { if ( bSet ) { m_pcInputSamplesRow[iCurViewPos][ iCurPos ].bOccluded = false; } xRenderShiftedRangeR(iCurSPos, iLastSPos, iCurPos, riError ); } } else { if ( iCurSPos > m_iLastOccludedSPos ) { m_bInOcclusion = false; if ( bSet ) { m_pcInputSamplesRow[iCurViewPos][ iCurPos ].bOccluded = false; } xRenderShiftedRangeR(iCurSPos, iLastSPos, iCurPos, riError ); } else { if ( bSet ) { m_pcInputSamplesRow[iCurViewPos][ iCurPos ].bOccluded = true; } } } } template template __inline Void TRenSingleModelC::xFillHoleL( Int iCurSPos, Int iLastSPos, Int iCurPos, RMDist& riError ) { if (iLastSPos < 0) return; Int iStartFillSPos = iCurSPos; Int iStartFillPos = iCurPos; Int iLastPos = iCurPos + 1; Int iStartFillSPosFP = xRangeLeftL(iStartFillSPos); if (iStartFillSPosFP == xRoundL(iStartFillSPos)) { if ((iStartFillSPosFP >= 0) && (iStartFillSPosFP < m_iLastOccludedSPosFP) ) { m_iThisDepth = m_iCurDepth; xSetShiftedPelL ( iStartFillPos, 0, iStartFillSPosFP, REN_IS_FILLED, riError ); } } else { iStartFillSPosFP--; } m_iThisDepth = m_iLastDepth; for (Int iFillSPos = std::max(iStartFillSPosFP+1,0); iFillSPos <= min(xRangeRightL( iLastSPos ), m_iLastOccludedSPosFP-1 ); iFillSPos++ ) { xSetShiftedPelL( iLastPos, 0, iFillSPos, REN_IS_HOLE, riError ); } } template template __inline Void TRenSingleModelC::xFillHoleR( Int iCurSPos, Int iLastSPos, Int iCurPos, RMDist& riError ) { if (iLastSPos < 0) return; Int iStartFillSPos = iCurSPos; Int iEndFillPos = iCurPos; Int iLastPos = iCurPos - 1; Int iStartFillSPosFP = xRangeRightR(iStartFillSPos); if (iStartFillSPosFP == xRoundR(iStartFillSPos)) { if ((iStartFillSPosFP < m_iWidth) && (iStartFillSPosFP > m_iLastOccludedSPosFP) ) { m_iThisDepth = m_iCurDepth; xSetShiftedPelR( iEndFillPos, 1 << m_iShiftPrec , iStartFillSPosFP, REN_IS_FILLED, riError ); } } else { iStartFillSPosFP++; } m_iThisDepth = m_iLastDepth; for (Int iFillSPos = max(xRangeLeftR( iLastSPos ), m_iLastOccludedSPosFP+1); iFillSPos <= min(iStartFillSPosFP,m_iWidth)-1 ; iFillSPos++ ) { xSetShiftedPelR( iLastPos, 1 << m_iShiftPrec, iFillSPos, REN_IS_HOLE, riError ); } } template template __inline Void TRenSingleModelC::xExtrapolateMarginL(Int iCurSPos, Int iCurPos, RMDist& riError ) { // if (iLeftSPos < 0 ) // return; Int iSPosFullPel = std::max(0,xRangeLeftL(iCurSPos)); m_iThisDepth = m_iCurDepth; if (iSPosFullPel < m_iWidth) { xSetShiftedPelL( iCurPos, 0, iSPosFullPel, REN_IS_FILLED, riError ); } for (Int iFillSPos = iSPosFullPel +1; iFillSPos < m_iWidth; iFillSPos++ ) { xSetShiftedPelL( iCurPos, 0, iFillSPos, REN_IS_HOLE, riError ); } } template template __inline Void TRenSingleModelC::xExtrapolateMarginR(Int iCurSPos, Int iCurPos, RMDist& riError ) { // if (iLeftSPos < 0 ) // return; Int iSPosFullPel = std::min(m_iWidth-1,xRangeRightR(iCurSPos)); m_iThisDepth = m_iCurDepth; if (iSPosFullPel > -1) { xSetShiftedPelR( iCurPos, 1 << m_iShiftPrec, iSPosFullPel, REN_IS_FILLED, riError ); } for (Int iFillSPos = iSPosFullPel -1; iFillSPos > -1; iFillSPos-- ) { xSetShiftedPelR( iCurPos , 1 << m_iShiftPrec, iFillSPos, REN_IS_HOLE, riError ); } } template __inline Int TRenSingleModelC::xShiftNewData( Int iPosX, Int iPosInNewData ) { RM_AOT( iPosInNewData < 0 ); RM_AOF( iPosInNewData < m_iNewDataWidth ); return (iPosX << m_iShiftPrec) - m_ppiCurLUT[0][ RenModRemoveBitInc( m_piNewDepthData[iPosInNewData] )]; } template __inline Int TRenSingleModelC::xShift( Int iPosX ) { RM_AOT( iPosX < 0); RM_AOF( iPosX < m_iWidth); return (iPosX << m_iShiftPrec) - m_ppiCurLUT[0][ RenModRemoveBitInc( m_pcInputSamplesRow[m_iCurViewPos][iPosX].iD )]; } template __inline Int TRenSingleModelC::xShift( Int iPos, Int iPosInNewData ) { if ( (iPosInNewData >= 0) && (iPosInNewData < m_iNewDataWidth) ) { return xShiftNewData(iPos ,iPosInNewData ); } else { return xShift(iPos); } } template __inline Int TRenSingleModelC::xRangeLeftL( Int iPos ) { return ( iPos + (1 << m_iShiftPrec) - 1) >> m_iShiftPrec; } template __inline Int TRenSingleModelC::xRangeLeftR( Int iPos ) { return xRangeRightR( iPos ) + 1; } template __inline Int TRenSingleModelC::xRangeRightL( Int iPos ) { return xRangeLeftL(iPos) - 1; } template __inline Int TRenSingleModelC::xRangeRightR( Int iPos ) { return iPos >> m_iShiftPrec; } template __inline Int TRenSingleModelC::xRoundL( Int iPos ) { return (iPos + (( 1 << m_iShiftPrec ) >> 1 )) >> m_iShiftPrec; } template __inline Int TRenSingleModelC::xRoundR( Int iPos ) { return (m_iShiftPrec == 0) ? iPos : xRoundL(iPos - 1); } template Void TRenSingleModelC::xSetPels( Pel* piPelSource , Int iSourceStride, Int iWidth, Int iHeight, Pel iVal ) { for (Int iYPos = 0; iYPos < iHeight; iYPos++) { for (Int iXPos = 0; iXPos < iWidth; iXPos++) { piPelSource[iXPos] = iVal; } piPelSource += iSourceStride; } } template Void TRenSingleModelC::xSetInts( Int* piPelSource , Int iSourceStride, Int iWidth, Int iHeight, Int iVal ) { for (Int iYPos = 0; iYPos < iHeight; iYPos++) { for (Int iXPos = 0; iXPos < iWidth; iXPos++) { piPelSource[iXPos] = iVal; } piPelSource += iSourceStride; } } template Void TRenSingleModelC::xSetBools( Bool* pbPelSource , Int iSourceStride, Int iWidth, Int iHeight, Bool bVal ) { for (Int iYPos = 0; iYPos < iHeight; iYPos++) { for (Int iXPos = 0; iXPos < iWidth; iXPos++) { pbPelSource[iXPos] = bVal; } pbPelSource += iSourceStride; } } template template __inline Void TRenSingleModelC::xSetShiftedPelL(Int iSourcePos, Int iSubSourcePos, Int iTargetSPos, Pel iFilled, RMDist& riError ) { RM_AOT( iSourcePos < 0 ); RM_AOT( iSourcePos >= m_iWidth ); RM_AOT( iSubSourcePos < 0 ); RM_AOT( iSubSourcePos > (1 << m_iShiftPrec) ); RM_AOT( iTargetSPos < 0 ); RM_AOT( iTargetSPos >= m_iWidth ); RenModelOutPels* pcOutSample = m_pcOutputSamplesRow + iTargetSPos; RenModelInPels * pcInSample = m_pcInputSamplesRow[VIEWPOS_LEFT] + iSourcePos ; if ( iBM != BLEND_NONE ) { xSetShiftedPelBlendL (pcInSample, iSubSourcePos, pcOutSample, iFilled, riError); } else { xSetShiftedPelNoBlendL(pcInSample, iSubSourcePos, pcOutSample, iFilled, riError); } } template template __inline Void TRenSingleModelC::xSetShiftedPelNoBlendL(RenModelInPels* pcInSample, Int iSubSourcePos, RenModelOutPels* pcOutSample, Pel iFilled, RMDist& riError ) { if ( bSet ) { // Filled pcOutSample->iFilledLeft = iFilled; // Yuv pcOutSample->iYLeft = pcInSample->aiY[iSubSourcePos]; #if H_3D_VSO_COLOR_PLANES pcOutSample->iULeft = pcInSample->aiU[iSubSourcePos]; pcOutSample->iVLeft = pcInSample->aiV[iSubSourcePos]; pcOutSample->iError = xGetDist( pcOutSample->iYLeft - pcOutSample->iYRef, pcOutSample->iULeft - pcOutSample->iURef, pcOutSample->iVLeft - pcOutSample->iVRef ); #else pcOutSample->iError = xGetDist( pcOutSample->iYLeft - pcOutSample->iYRef ); #endif } else { #if H_3D_VSO_COLOR_PLANES riError += xGetDist( pcInSample->aiY[iSubSourcePos] - pcOutSample->iYRef, pcInSample->aiU[iSubSourcePos] - pcOutSample->iURef, pcInSample->aiV[iSubSourcePos] - pcOutSample->iVRef ); #else riError += xGetDist( pcInSample->aiY[iSubSourcePos] - pcOutSample->iYRef ); #endif riError -= pcOutSample->iError; } } template template __inline Void TRenSingleModelC::xSetShiftedPelBlendL(RenModelInPels* pcInSample, Int iSubSourcePos, RenModelOutPels* pcOutSample, Pel iFilled, RMDist& riError ) { Pel piBlendedValueY; #if H_3D_VSO_COLOR_PLANES Pel piBlendedValueU; Pel piBlendedValueV; #endif xGetBlendedValue ( pcInSample ->aiY[iSubSourcePos], pcOutSample->iYRight, #if H_3D_VSO_COLOR_PLANES pcInSample ->aiU[iSubSourcePos], pcOutSample->iURight, pcInSample ->aiV[iSubSourcePos], pcOutSample->iVRight, #endif m_piInvZLUTLeft [RenModRemoveBitInc(m_iThisDepth) ], m_piInvZLUTRight[RenModRemoveBitInc(pcOutSample->iDRight)], iFilled, pcOutSample->iFilledRight , piBlendedValueY #if H_3D_VSO_COLOR_PLANES , piBlendedValueU, piBlendedValueV #endif ); if ( bSet ) { // Set values pcOutSample->iDLeft = m_iThisDepth; pcOutSample->iYLeft = pcInSample ->aiY[iSubSourcePos]; pcOutSample->iYBlended = piBlendedValueY; #if H_3D_VSO_COLOR_PLANES pcOutSample->iULeft = pcInSample ->aiU[iSubSourcePos]; pcOutSample->iUBlended = piBlendedValueU; pcOutSample->iVLeft = pcInSample ->aiV[iSubSourcePos]; pcOutSample->iVBlended = piBlendedValueV; #endif pcOutSample->iFilledLeft = iFilled; // Get Error Int iDiffY = pcOutSample->iYRef - piBlendedValueY; #if H_3D_VSO_COLOR_PLANES Int iDiffU = pcOutSample->iURef - piBlendedValueU; Int iDiffV = pcOutSample->iVRef - piBlendedValueV; pcOutSample->iError = xGetDist(iDiffY, iDiffU, iDiffV ); #else pcOutSample->iError = xGetDist(iDiffY ); #endif } else { Int iDiffY = pcOutSample->iYRef - piBlendedValueY; #if H_3D_VSO_COLOR_PLANES Int iDiffU = pcOutSample->iURef - piBlendedValueU; Int iDiffV = pcOutSample->iVRef - piBlendedValueV; riError += ( xGetDist( iDiffY, iDiffU, iDiffV ) - pcOutSample->iError ); #else riError += ( xGetDist( iDiffY ) - pcOutSample->iError ); #endif } } template template __inline Void TRenSingleModelC::xSetShiftedPelR(Int iSourcePos, Int iSubSourcePos, Int iTargetSPos, Pel iFilled, RMDist& riError ) { RM_AOT( iSourcePos < 0 ); RM_AOT( iSourcePos >= m_iWidth ); RM_AOT( iSubSourcePos < 0 ); RM_AOT( iSubSourcePos >= (1 << m_iShiftPrec)+1 ); RM_AOT( iTargetSPos < 0 ); RM_AOT( iTargetSPos >= m_iWidth ); RenModelOutPels* pcOutSample = m_pcOutputSamplesRow + iTargetSPos; RenModelInPels * pcInSample = m_pcInputSamplesRow[VIEWPOS_RIGHT] + iSourcePos ; if ( iBM != BLEND_NONE ) { xSetShiftedPelBlendR (pcInSample, iSubSourcePos, pcOutSample, iFilled, riError); } else { xSetShiftedPelNoBlendR (pcInSample, iSubSourcePos, pcOutSample, iFilled, riError); } } template template __inline Void TRenSingleModelC::xSetShiftedPelNoBlendR(RenModelInPels* pcInSample, Int iSubSourcePos, RenModelOutPels* pcOutSample, Pel iFilled, RMDist& riError ) { if ( bSet ) { // Filled pcOutSample->iFilledRight = iFilled; // Yuv pcOutSample->iYRight = pcInSample->aiY[iSubSourcePos]; #if H_3D_VSO_COLOR_PLANES pcOutSample->iURight = pcInSample->aiU[iSubSourcePos]; pcOutSample->iVRight = pcInSample->aiV[iSubSourcePos]; pcOutSample->iError = xGetDist( pcOutSample->iYRight - pcOutSample->iYRef, pcOutSample->iURight - pcOutSample->iURef, pcOutSample->iVRight - pcOutSample->iVRef ); #else pcOutSample->iError = xGetDist( pcOutSample->iYRight - pcOutSample->iYRef ); #endif } else { #if H_3D_VSO_COLOR_PLANES riError += xGetDist( pcInSample->aiY[iSubSourcePos] - pcOutSample->iYRef, pcInSample->aiU[iSubSourcePos] - pcOutSample->iURef, pcInSample->aiV[iSubSourcePos] - pcOutSample->iVRef ); #else riError += xGetDist( pcInSample->aiY[iSubSourcePos] - pcOutSample->iYRef ); #endif riError -= pcOutSample->iError; } } template template __inline Void TRenSingleModelC::xSetShiftedPelBlendR(RenModelInPels* pcInSample, Int iSubSourcePos, RenModelOutPels* pcOutSample, Pel iFilled, RMDist& riError ) { Pel piBlendedValueY; #if H_3D_VSO_COLOR_PLANES Pel piBlendedValueU; Pel piBlendedValueV; #endif xGetBlendedValue ( pcOutSample->iYLeft, pcInSample ->aiY[iSubSourcePos], #if H_3D_VSO_COLOR_PLANES pcOutSample->iULeft, pcInSample ->aiU[iSubSourcePos], pcOutSample->iVLeft, pcInSample ->aiV[iSubSourcePos], #endif m_piInvZLUTLeft [RenModRemoveBitInc(pcOutSample->iDLeft)], m_piInvZLUTRight [RenModRemoveBitInc(m_iThisDepth) ], pcOutSample->iFilledLeft, iFilled, piBlendedValueY #if H_3D_VSO_COLOR_PLANES , piBlendedValueU, piBlendedValueV #endif ); if ( bSet ) { // Set values pcOutSample->iDRight = m_iThisDepth; pcOutSample->iYRight = pcInSample ->aiY[iSubSourcePos]; pcOutSample->iYBlended = piBlendedValueY; #if H_3D_VSO_COLOR_PLANES pcOutSample->iURight = pcInSample ->aiU[iSubSourcePos]; pcOutSample->iUBlended = piBlendedValueU; pcOutSample->iVRight = pcInSample ->aiV[iSubSourcePos]; pcOutSample->iVBlended = piBlendedValueV; #endif pcOutSample->iFilledRight = iFilled; // Get Error Int iDiffY = pcOutSample->iYRef - piBlendedValueY; #if H_3D_VSO_COLOR_PLANES Int iDiffU = pcOutSample->iURef - piBlendedValueU; Int iDiffV = pcOutSample->iVRef - piBlendedValueV; pcOutSample->iError = xGetDist(iDiffY, iDiffU, iDiffV ); #else pcOutSample->iError = xGetDist(iDiffY ); #endif } else { Int iDiffY = pcOutSample->iYRef - piBlendedValueY; #if H_3D_VSO_COLOR_PLANES Int iDiffU = pcOutSample->iURef - piBlendedValueU; Int iDiffV = pcOutSample->iVRef - piBlendedValueV; riError += ( xGetDist( iDiffY, iDiffU, iDiffV ) - pcOutSample->iError ); #else riError += ( xGetDist( iDiffY ) - pcOutSample->iError ); #endif } } template __inline Int TRenSingleModelC::xGetDist( Int iDiffY, Int iDiffU, Int iDiffV ) { if ( !bBitInc ) { return ( (iDiffY * iDiffY ) + ((( (iDiffU * iDiffU ) +(iDiffV * iDiffV ) ) ) >> 2 ) ); } else { return ( ((iDiffY * iDiffY) >> m_iDistShift) + ((( ((iDiffU * iDiffU) >> m_iDistShift) +((iDiffV * iDiffV) >> m_iDistShift) ) ) >> 2 ) ); } } template __inline Int TRenSingleModelC::xGetDist( Int iDiffY ) { if ( !bBitInc ) { return (iDiffY * iDiffY); } else { return ((iDiffY * iDiffY) >> m_iDistShift); } } #if H_3D_VSO_COLOR_PLANES template __inline Void TRenSingleModelC::xGetBlendedValue( Pel iYL, Pel iYR, Pel iUL, Pel iUR, Pel iVL, Pel iVR, Pel iDepthL, Pel iDepthR, Int iFilledL, Int iFilledR, Pel& riY, Pel& riU, Pel&riV ) #else template __inline Void TRenSingleModelC::xGetBlendedValue( Pel iYL, Pel iYR, Pel iDepthL, Pel iDepthR, Int iFilledL, Int iFilledR, Pel& riY ) #endif { RM_AOT( iBM != BLEND_AVRG && iBM != BLEND_LEFT && iBM != BLEND_RIGHT ); if (iBM != BLEND_AVRG ) { if (iBM == BLEND_LEFT ) { #if H_3D_VSO_COLOR_PLANES xGetBlendedValueBM1( iYL, iYR, iUL, iUR, iVL, iVR, iDepthL, iDepthR, iFilledL, iFilledR, riY, riU, riV ); #else xGetBlendedValueBM1( iYL, iYR, iDepthL, iDepthR, iFilledL, iFilledR, riY ); #endif } else { #if H_3D_VSO_COLOR_PLANES xGetBlendedValueBM2( iYL, iYR, iUL, iUR, iVL, iVR, iDepthL, iDepthR, iFilledL, iFilledR, riY, riU, riV ); #else xGetBlendedValueBM2( iYL, iYR, iDepthL, iDepthR, iFilledL, iFilledR, riY ); #endif } return; } if ( (iFilledL != REN_IS_HOLE ) && ( iFilledR != REN_IS_HOLE) ) { Int iDepthDifference = iDepthR - iDepthL; if ( abs ( iDepthDifference ) <= m_iBlendZThres ) { if ((iFilledL == REN_IS_FILLED) && ( iFilledR != REN_IS_FILLED)) { riY = xBlend( iYL, iYR, iFilledR >> 1 ); #if H_3D_VSO_COLOR_PLANES riU = xBlend( iUL, iUR, iFilledR >> 1 ); riV = xBlend( iVL, iVR, iFilledR >> 1 ); #endif } else if ((iFilledL != REN_IS_FILLED) && ( iFilledR == REN_IS_FILLED)) { riY = xBlend( iYR, iYL, (iFilledL >> 1) ); #if H_3D_VSO_COLOR_PLANES riU = xBlend( iUR, iUL, (iFilledL >> 1) ); riV = xBlend( iVR, iVL, (iFilledL >> 1) ); #endif } else { riY = xBlend( iYL, iYR, m_iBlendDistWeight ); #if H_3D_VSO_COLOR_PLANES riU = xBlend( iUL, iUR, m_iBlendDistWeight ); riV = xBlend( iVL, iVR, m_iBlendDistWeight ); #endif } } else if ( iDepthDifference < 0 ) { riY = iYL; #if H_3D_VSO_COLOR_PLANES riU = iUL; riV = iVL; #endif } else { riY = iYR; #if H_3D_VSO_COLOR_PLANES riU = iUR; riV = iVR; #endif } } else if ( (iFilledL == REN_IS_HOLE) && (iFilledR == REN_IS_HOLE)) { if ( iDepthR < iDepthL ) { riY = iYR; #if H_3D_VSO_COLOR_PLANES riU = iUR; riV = iVR; #endif } else { riY = iYL; #if H_3D_VSO_COLOR_PLANES riU = iUL; riV = iVL; #endif } } else { if (iFilledR == REN_IS_HOLE) { riY = iYL; #if H_3D_VSO_COLOR_PLANES riU = iUL; riV = iVL; #endif } else { riY = iYR; #if H_3D_VSO_COLOR_PLANES riU = iUR; riV = iVR; #endif } } } template __inline Void #if H_3D_VSO_COLOR_PLANES TRenSingleModelC::xGetBlendedValueBM1( Pel iYL, Pel iYR, Pel iUL, Pel iUR, Pel iVL, Pel iVR, Pel iDepthL, Pel iDepthR, Int iFilledL, Int iFilledR, Pel& riY, Pel& riU, Pel&riV ) #else TRenSingleModelC::xGetBlendedValueBM1( Pel iYL, Pel iYR, Pel iDepthL, Pel iDepthR, Int iFilledL, Int iFilledR, Pel& riY ) #endif { if ( iFilledL == REN_IS_FILLED || iFilledR == REN_IS_HOLE ) { riY = iYL; #if H_3D_VSO_COLOR_PLANES riU = iUL; riV = iVL; #endif } else if ( iFilledL == REN_IS_HOLE ) { riY = iYR; #if H_3D_VSO_COLOR_PLANES riU = iUR; riV = iVR; #endif } else { riY = xBlend( iYR, iYL, iFilledL ); #if H_3D_VSO_COLOR_PLANES riU = xBlend( iUR, iUL, iFilledL ); riV = xBlend( iVR, iUL, iFilledL ); #endif } } template __inline Void #if H_3D_VSO_COLOR_PLANES TRenSingleModelC::xGetBlendedValueBM2( Pel iYL, Pel iYR, Pel iUL, Pel iUR, Pel iVL, Pel iVR, Pel iDepthL, Pel iDepthR, Int iFilledL, Int iFilledR, Pel& riY, Pel& riU, Pel&riV ) #else TRenSingleModelC::xGetBlendedValueBM2( Pel iYL, Pel iYR, Pel iDepthL, Pel iDepthR, Int iFilledL, Int iFilledR, Pel& riY ) #endif { if ( iFilledR == REN_IS_FILLED || iFilledL == REN_IS_HOLE ) { riY = iYR; #if H_3D_VSO_COLOR_PLANES riU = iUR; riV = iVR; #endif } else if ( iFilledR == REN_IS_HOLE ) { riY = iYL; #if H_3D_VSO_COLOR_PLANES riU = iUL; riV = iVL; #endif } else { riY = xBlend( iYL, iYR, iFilledR ); #if H_3D_VSO_COLOR_PLANES riU = xBlend( iUL, iUR, iFilledR ); riV = xBlend( iVL, iUR, iFilledR ); #endif } } template __inline Pel TRenSingleModelC::xBlend( Pel pVal1, Pel pVal2, Int iWeightVal2 ) { return pVal1 + (Pel) ( ( (Int) ( pVal2 - pVal1) * iWeightVal2 + (1 << (REN_VDWEIGHT_PREC - 1)) ) >> REN_VDWEIGHT_PREC ); } template Void TRenSingleModelC::xCopy2PicYuv( Pel** ppiSrcVideoPel, Int* piStrides, TComPicYuv* rpcPicYuvTarget ) { TRenFilter::copy ( ppiSrcVideoPel[0], piStrides[0], m_iWidth, m_iUsedHeight, rpcPicYuvTarget->getLumaAddr() + m_iHorOffset * rpcPicYuvTarget->getStride() , rpcPicYuvTarget->getStride () ); TRenFilter::sampleDown2Tap13( ppiSrcVideoPel[1], piStrides[1], m_iWidth, m_iUsedHeight, rpcPicYuvTarget->getCbAddr () + (m_iHorOffset >> 1) * rpcPicYuvTarget->getCStride(), rpcPicYuvTarget->getCStride() ); TRenFilter::sampleDown2Tap13( ppiSrcVideoPel[2], piStrides[2], m_iWidth, m_iUsedHeight, rpcPicYuvTarget->getCrAddr () + (m_iHorOffset >> 1) * rpcPicYuvTarget->getCStride(), rpcPicYuvTarget->getCStride() ); } template class TRenSingleModelC; template class TRenSingleModelC; template class TRenSingleModelC; template class TRenSingleModelC; template class TRenSingleModelC; template class TRenSingleModelC; template class TRenSingleModelC; template class TRenSingleModelC; #if H_3D_VSO_EARLY_SKIP template __inline Bool TRenSingleModelC::xDetectEarlySkipL( Int iStartPosX, Int iStartPosY, Int iWidth, Int iHeight, Int iStride, Pel* piNewData,Pel* piOrgData, Int iOrgStride) { RM_AOF( m_bEarlySkip ); const Int iCurViewPos = 0; Int** ppiCurLUT = m_appiShiftLut [ iCurViewPos ]; Bool bNoDiff = true; for (Int iPosY=0; iPosY < iHeight; iPosY++) { m_pbHorSkip[iPosY] = true; for (Int iPosX = 0; iPosX < iWidth; iPosX++) { Int iDisparityRec = abs(ppiCurLUT[0][ RenModRemoveBitInc(piNewData[iPosX])]); Int iDispartyOrg = abs(ppiCurLUT[0][ RenModRemoveBitInc(piOrgData[iPosX])]); if( iDispartyOrg != iDisparityRec) { m_pbHorSkip[iPosY] = false; bNoDiff = false; break; } } piNewData += iStride; piOrgData += iOrgStride; } return bNoDiff; } template __inline Bool TRenSingleModelC::xDetectEarlySkipR( Int iStartPosX, Int iStartPosY, Int iWidth, Int iHeight, Int iStride, Pel* piNewData,Pel* piOrgData, Int iOrgStride) { RM_AOF( m_bEarlySkip ); Bool bNoDiff = true; const Int iCurViewPos = 1; Int** ppiCurLUT = m_appiShiftLut [ iCurViewPos ]; for ( Int iPosY = 0; iPosY < iHeight; iPosY++ ) { m_pbHorSkip[iPosY] = true; for (Int iPosX = 0; iPosX < iWidth; iPosX++) { Int iDisparityRec = abs( ppiCurLUT[0][ RenModRemoveBitInc(piNewData[iPosX])] ); Int iDisparityOrg = abs( ppiCurLUT[0][ RenModRemoveBitInc(piOrgData[iPosX])] ); if( iDisparityRec != iDisparityOrg ) { m_pbHorSkip[iPosY] = false; bNoDiff = false; break; } } piNewData += iStride; piOrgData += iOrgStride; } return bNoDiff; } #endif #endif // H_3D