Changeset 792 in 3DVCSoftware
- Timestamp:
- 23 Jan 2014, 05:06:49 (11 years ago)
- Location:
- branches/HTM-9.3-dev3-Samsung
- Files:
-
- 4 added
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/HTM-9.3-dev3-Samsung/source/Lib/TLibCommon/TComDataCU.cpp
r782 r792 123 123 #if H_3D_DIM_SDC 124 124 m_pbSDCFlag = NULL; 125 #if QC_SDC_UNIFY_G0130 125 #if QC_SDC_UNIFY_G0130 && !SEC_INTER_SDC_G0101 126 126 for( Int i = 0; i < 4; i++ ) 127 127 { … … 160 160 } 161 161 #endif 162 #if !SEC_INTER_SDC_G0101 162 163 m_pucInterSDCMask = NULL; 164 #endif 163 165 #endif 164 166 } … … 281 283 #if H_3D_DIM_SDC 282 284 m_pbSDCFlag = (Bool*)xMalloc(Bool, uiNumPartition); 283 #if QC_SDC_UNIFY_G0130 285 #if QC_SDC_UNIFY_G0130 && !SEC_INTER_SDC_G0101 284 286 for( Int i = 0; i < 4; i++ ) 285 287 { … … 305 307 m_acCUMvField[1].setNumPartition(uiNumPartition ); 306 308 } 309 #if !SEC_INTER_SDC_G0101 307 310 #if H_3D_INTER_SDC 308 311 m_pucInterSDCMask = (UChar* )xMalloc(UChar, g_uiMaxCUHeight*g_uiMaxCUWidth); 312 #endif 309 313 #endif 310 314 m_sliceStartCU = (UInt* )xMalloc(UInt, uiNumPartition); … … 416 420 #if H_3D_DIM_SDC 417 421 if ( m_pbSDCFlag ) { xFree(m_pbSDCFlag); m_pbSDCFlag = NULL; } 418 #if QC_SDC_UNIFY_G0130 422 #if QC_SDC_UNIFY_G0130 && !SEC_INTER_SDC_G0101 419 423 for( Int i = 0; i < 4; i++ ) 420 424 { … … 435 439 #endif 436 440 } 441 #if !SEC_INTER_SDC_G0101 437 442 #if H_3D_INTER_SDC 438 443 if ( m_pucInterSDCMask ) { xFree(m_pucInterSDCMask); m_pucInterSDCMask = NULL; } 444 #endif 439 445 #endif 440 446 m_pcCUAboveLeft = NULL; … … 639 645 #if H_3D_DIM_SDC 640 646 memset( m_pbSDCFlag + firstElement, 0, numElements * sizeof( *m_pbSDCFlag ) ); 641 #if QC_SDC_UNIFY_G0130 647 #if QC_SDC_UNIFY_G0130 && !SEC_INTER_SDC_G0101 642 648 for( Int i = 0; i < 4; i++ ) 643 649 { … … 818 824 #if H_3D_DIM_SDC 819 825 m_pbSDCFlag [ui] = false; 820 #if QC_SDC_UNIFY_G0130 826 #if QC_SDC_UNIFY_G0130 && !SEC_INTER_SDC_G0101 821 827 for( Int i = 0; i < 4; i++ ) 822 828 { … … 938 944 #if H_3D_DIM_SDC 939 945 memset( m_pbSDCFlag, 0, sizeof(Bool) * m_uiNumPartition ); 940 #if QC_SDC_UNIFY_G0130 946 #if QC_SDC_UNIFY_G0130 && !SEC_INTER_SDC_G0101 941 947 for( Int i = 0; i < 4; i++ ) 942 948 { … … 1022 1028 #if H_3D_DIM_SDC 1023 1029 m_pbSDCFlag [ui] = pcCU->m_pbSDCFlag [ uiPartOffset + ui ]; 1024 #if QC_SDC_UNIFY_G0130 1030 #if QC_SDC_UNIFY_G0130 && !SEC_INTER_SDC_G0101 1025 1031 for( Int i = 0; i < 4; i++ ) 1026 1032 { … … 1185 1191 #if H_3D_DIM_SDC 1186 1192 m_pbSDCFlag = pcCU->getSDCFlag() + uiPart; 1187 #if QC_SDC_UNIFY_G0130 1193 #if QC_SDC_UNIFY_G0130 && !SEC_INTER_SDC_G0101 1188 1194 for( Int i = 0; i < 4; i++ ) 1189 1195 { … … 1386 1392 #if H_3D_DIM_SDC 1387 1393 memcpy( m_pbSDCFlag + uiOffset, pcCU->getSDCFlag(), iSizeInBool ); 1388 #if QC_SDC_UNIFY_G0130 1394 #if QC_SDC_UNIFY_G0130 && !SEC_INTER_SDC_G0101 1389 1395 for( Int i = 0; i < 4; i++ ) 1390 1396 { … … 1515 1521 #if H_3D_DIM_SDC 1516 1522 memcpy( rpcCU->getSDCFlag() + m_uiAbsIdxInLCU, m_pbSDCFlag, iSizeInBool ); 1517 #if QC_SDC_UNIFY_G0130 1523 #if QC_SDC_UNIFY_G0130 && !SEC_INTER_SDC_G0101 1518 1524 for( Int i = 0; i < 4; i++ ) 1519 1525 { … … 1630 1636 #if H_3D_DIM_SDC 1631 1637 memcpy( rpcCU->getSDCFlag() + uiPartOffset, m_pbSDCFlag, iSizeInBool ); 1632 #if QC_SDC_UNIFY_G0130 1638 #if QC_SDC_UNIFY_G0130 && !SEC_INTER_SDC_G0101 1633 1639 for( Int i = 0; i < 4; i++ ) 1634 1640 { … … 2384 2390 #endif 2385 2391 2392 #if !SEC_INTER_SDC_G0101 2386 2393 Void TComDataCU::xSetInterSDCCUMask( TComDataCU *pcCU, UChar *pMask ) 2387 2394 { … … 2480 2487 2481 2488 } 2489 #endif 2482 2490 #endif 2483 2491 -
branches/HTM-9.3-dev3-Samsung/source/Lib/TLibCommon/TComDataCU.h
r782 r792 215 215 #if H_3D_DIM_SDC 216 216 Bool* m_pbSDCFlag; 217 #if QC_SDC_UNIFY_G0130 217 #if QC_SDC_UNIFY_G0130 && !SEC_INTER_SDC_G0101 218 218 Pel* m_apSegmentDCOffset[4]; 219 219 #else … … 227 227 Int* m_apSegmentInterDCOffset[4]; 228 228 #endif 229 #if !SEC_INTER_SDC_G0101 229 230 UChar* m_pucInterSDCMask; 231 #endif 230 232 #endif 231 233 #if H_3D … … 593 595 Void setInterSDCSegmentDCOffset( Int pOffset, UInt uiSeg, UInt uiPartIdx) { m_apSegmentInterDCOffset[uiSeg][uiPartIdx] = pOffset; } 594 596 #endif 597 #if !SEC_INTER_SDC_G0101 595 598 Void xSetInterSDCCUMask( TComDataCU *pcCU, UChar *pMask ); 596 599 597 600 UChar* getInterSDCMask () { return m_pucInterSDCMask; } 601 #endif 598 602 #endif 599 603 -
branches/HTM-9.3-dev3-Samsung/source/Lib/TLibCommon/TypeDef.h
r782 r792 239 239 #define QC_SDC_UNIFY_G0130 1 // Unify intra SDC and inter SDC 240 240 #endif 241 #define SEC_INTER_SDC_G0101 1 // Improved inter SDC with multiple DC candidates 241 242 #define H_3D_DIM_ENC 1 // Depth Intra encoder optimizations, includes: 242 243 // HHI_DEPTH_INTRA_SEARCH_RAU_C0160 -
branches/HTM-9.3-dev3-Samsung/source/Lib/TLibDecoder/TDecCu.cpp
r782 r792 652 652 UInt uiWidth = pcCU->getWidth ( 0 ); 653 653 UInt uiHeight = pcCU->getHeight( 0 ); 654 #if !SEC_INTER_SDC_G0101 654 655 UChar* pMask = pcCU->getInterSDCMask(); 655 656 656 657 memset( pMask, 0, uiWidth*uiHeight ); 657 658 pcCU->xSetInterSDCCUMask( pcCU, pMask ); 659 #endif 658 660 659 661 Pel *pResi; … … 666 668 for( uiPelX = 0; uiPelX < uiWidth; uiPelX++ ) 667 669 { 670 #if SEC_INTER_SDC_G0101 671 pResi[ uiPelX ] = pcCU->getSDCSegmentDCOffset( 0, 0 ); 672 #else 668 673 UChar uiSeg = pMask[ uiPelX + uiPelY*uiWidth ]; 669 674 #if QC_SDC_UNIFY_G0130 … … 671 676 #else 672 677 pResi[ uiPelX ] = pcCU->getInterSDCSegmentDCOffset( uiSeg, 0 ); 678 #endif 673 679 #endif 674 680 } -
branches/HTM-9.3-dev3-Samsung/source/Lib/TLibDecoder/TDecEntropy.cpp
r782 r792 814 814 } 815 815 816 #if SEC_INTER_SDC_G0101 817 if( !pcCU->getSlice()->getIsDepth() || pcCU->getPartitionSize( uiAbsPartIdx ) != SIZE_2Nx2N || pcCU->isSkipped( uiAbsPartIdx ) ) 818 #else 816 819 if( !pcCU->getSlice()->getIsDepth() || ( pcCU->isIntra( uiAbsPartIdx ) && pcCU->getPartitionSize( uiAbsPartIdx ) != SIZE_2Nx2N ) || pcCU->isSkipped( uiAbsPartIdx ) ) 817 { 818 return; 819 } 820 820 #endif 821 { 822 return; 823 } 824 825 #if SEC_INTER_SDC_G0101 826 assert( pcCU->getPartitionSize( uiAbsPartIdx ) == SIZE_2Nx2N || ( !pcCU->isIntra( uiAbsPartIdx ) && !pcCU->isSkipped( uiAbsPartIdx ) ) ); 827 #else 821 828 assert( ( pcCU->isIntra( uiAbsPartIdx ) && pcCU->getPartitionSize( uiAbsPartIdx ) == SIZE_2Nx2N ) || ( !pcCU->isIntra( uiAbsPartIdx ) && !pcCU->isSkipped( uiAbsPartIdx ) ) ); 829 #endif 822 830 823 831 m_pcEntropyDecoderIf->parseSDCFlag( pcCU, uiAbsPartIdx, uiDepth ); -
branches/HTM-9.3-dev3-Samsung/source/Lib/TLibDecoder/TDecSbac.cpp
r782 r792 2210 2210 else 2211 2211 { 2212 #if SEC_INTER_SDC_G0101 2213 uiNumSegments = 1; 2214 #else 2212 2215 PartSize cPartSize = pcCU->getPartitionSize( absPartIdx ); 2213 2214 2216 uiNumSegments = ( cPartSize == SIZE_2Nx2N ) ? 1 : ( cPartSize == SIZE_NxN ? 4 : 2 ); 2217 #endif 2215 2218 symbol = 1; 2216 2219 } -
branches/HTM-9.3-dev3-Samsung/source/Lib/TLibEncoder/TEncCu.cpp
r782 r792 1979 1979 if( rpcTempCU->getSlice()->getVPS()->getInterSDCFlag( rpcTempCU->getSlice()->getLayerIdInVps() ) && rpcTempCU->getSlice()->getIsDepth() && !uiNoResidual ) 1980 1980 { 1981 #if SEC_INTER_SDC_G0101 1982 for( Int uiOffest = -2 ; uiOffest <= 2 ; uiOffest++ ) 1983 { 1984 if( rpcTempCU != rpcTempCUPre ) 1985 { 1986 rpcTempCU->initEstData( uhDepth, orgQP ); 1987 rpcTempCU->copyPartFrom( rpcBestCU, 0, uhDepth ); 1988 } 1989 rpcTempCU->setSkipFlagSubParts( false, 0, uhDepth ); 1990 rpcTempCU->setTrIdxSubParts( 0, 0, uhDepth ); 1991 rpcTempCU->setCbfSubParts( 1, 1, 1, 0, uhDepth ); 1992 #if H_3D_VSO //M2 1993 if( m_pcRdCost->getUseRenModel() ) 1994 { //Reset 1995 UInt uiWidth = m_ppcOrigYuv[uhDepth]->getWidth (); 1996 UInt uiHeight = m_ppcOrigYuv[uhDepth]->getHeight (); 1997 Pel* piSrc = m_ppcOrigYuv[uhDepth]->getLumaAddr (); 1998 UInt uiSrcStride = m_ppcOrigYuv[uhDepth]->getStride (); 1999 m_pcRdCost->setRenModelData( rpcTempCU, 0, piSrc, uiSrcStride, uiWidth, uiHeight ); 2000 } 2001 #endif 2002 m_pcPredSearch->encodeResAndCalcRdInterSDCCU( rpcTempCU, 2003 m_ppcOrigYuv[uhDepth], 2004 ( rpcTempCU != rpcTempCUPre ) ? m_ppcPredYuvBest[uhDepth] : m_ppcPredYuvTemp[uhDepth], 2005 m_ppcResiYuvTemp[uhDepth], 2006 m_ppcRecoYuvTemp[uhDepth], 2007 uiOffest, 2008 uhDepth ); 2009 2010 xCheckDQP( rpcTempCU ); 2011 xCheckBestMode( rpcBestCU, rpcTempCU, uhDepth ); 2012 } 2013 #else 1981 2014 if( rpcTempCU != rpcTempCUPre ) 1982 2015 { … … 2006 2039 xCheckDQP( rpcTempCU ); 2007 2040 xCheckBestMode( rpcBestCU, rpcTempCU, uhDepth ); 2041 #endif 2008 2042 } 2009 2043 #endif … … 2202 2236 xCheckBestMode(rpcBestCU, rpcTempCU, uhDepth); 2203 2237 #if H_3D_INTER_SDC 2238 #if SEC_INTER_SDC_G0101 // ONLY_2NX2N_SDC 2239 if( rpcTempCU->getSlice()->getVPS()->getInterSDCFlag( rpcTempCU->getSlice()->getLayerIdInVps() ) && rpcTempCU->getSlice()->getIsDepth() && ePartSize == SIZE_2Nx2N) 2240 #else 2204 2241 if( rpcTempCU->getSlice()->getVPS()->getInterSDCFlag( rpcTempCU->getSlice()->getLayerIdInVps() ) && rpcTempCU->getSlice()->getIsDepth() ) 2205 { 2242 #endif 2243 { 2244 #if SEC_INTER_SDC_G0101 2245 for( Int uiOffest = -2 ; uiOffest <= 2 ; uiOffest++ ) 2246 { 2247 if( rpcTempCU != rpcTempCUPre ) 2248 { 2249 Int orgQP = rpcBestCU->getQP( 0 ); 2250 rpcTempCU->initEstData( uhDepth, orgQP ); 2251 rpcTempCU->copyPartFrom( rpcBestCU, 0, uhDepth ); 2252 } 2253 rpcTempCU->setSkipFlagSubParts( false, 0, uhDepth ); 2254 rpcTempCU->setTrIdxSubParts( 0, 0, uhDepth ); 2255 rpcTempCU->setCbfSubParts( 1, 1, 1, 0, uhDepth ); 2256 #if H_3D_VSO // M3 2257 if( m_pcRdCost->getUseRenModel() ) 2258 { 2259 UInt uiWidth = m_ppcOrigYuv[uhDepth]->getWidth ( ); 2260 UInt uiHeight = m_ppcOrigYuv[uhDepth]->getHeight( ); 2261 Pel* piSrc = m_ppcOrigYuv[uhDepth]->getLumaAddr( ); 2262 UInt uiSrcStride = m_ppcOrigYuv[uhDepth]->getStride(); 2263 m_pcRdCost->setRenModelData( rpcTempCU, 0, piSrc, uiSrcStride, uiWidth, uiHeight ); 2264 } 2265 #endif 2266 2267 m_pcPredSearch->encodeResAndCalcRdInterSDCCU( rpcTempCU, 2268 m_ppcOrigYuv[uhDepth], 2269 ( rpcTempCU != rpcTempCUPre ) ? m_ppcPredYuvBest[uhDepth] : m_ppcPredYuvTemp[uhDepth], 2270 m_ppcResiYuvTemp[uhDepth], 2271 m_ppcRecoYuvTemp[uhDepth], 2272 uiOffest, 2273 uhDepth ); 2274 2275 xCheckDQP( rpcTempCU ); 2276 xCheckBestMode(rpcBestCU, rpcTempCU, uhDepth); 2277 } 2278 #else 2206 2279 if( rpcTempCU != rpcTempCUPre ) 2207 2280 { … … 2233 2306 xCheckDQP( rpcTempCU ); 2234 2307 xCheckBestMode(rpcBestCU, rpcTempCU, uhDepth); 2308 #endif 2235 2309 } 2236 2310 #endif -
branches/HTM-9.3-dev3-Samsung/source/Lib/TLibEncoder/TEncEntropy.cpp
r782 r792 882 882 } 883 883 884 #if SEC_INTER_SDC_G0101 885 if( !pcCU->getSlice()->getIsDepth() || pcCU->getPartitionSize( uiAbsPartIdx ) != SIZE_2Nx2N || pcCU->isSkipped( uiAbsPartIdx ) ) 886 #else 884 887 if( !pcCU->getSlice()->getIsDepth() || ( pcCU->isIntra( uiAbsPartIdx ) && pcCU->getPartitionSize( uiAbsPartIdx ) != SIZE_2Nx2N ) || pcCU->isSkipped( uiAbsPartIdx ) ) 885 { 886 return; 887 } 888 888 #endif 889 { 890 return; 891 } 892 893 #if SEC_INTER_SDC_G0101 894 assert( pcCU->getPartitionSize( uiAbsPartIdx ) == SIZE_2Nx2N || ( !pcCU->isIntra( uiAbsPartIdx ) && !pcCU->isSkipped( uiAbsPartIdx ) ) ); 895 #else 889 896 assert( ( pcCU->isIntra( uiAbsPartIdx ) && pcCU->getPartitionSize( uiAbsPartIdx ) == SIZE_2Nx2N ) || ( !pcCU->isIntra( uiAbsPartIdx ) && !pcCU->isSkipped( uiAbsPartIdx ) ) ); 897 #endif 890 898 891 899 if( bRD ) … … 905 913 906 914 if( !pcCU->getSlice()->getIsDepth() || pcCU->isIntra( uiAbsPartIdx ) || pcCU->isSkipped( uiAbsPartIdx ) ) 907 {908 915 return; 909 916 } -
branches/HTM-9.3-dev3-Samsung/source/Lib/TLibEncoder/TEncSbac.cpp
r782 r792 2259 2259 else //all-zero inter SDC is not allowed 2260 2260 { 2261 #if SEC_INTER_SDC_G0101 2262 uiNumSegments = 1; 2263 #else 2261 2264 PartSize cPartSize = pcCU->getPartitionSize( absPartIdx ); 2262 2263 2265 uiNumSegments = ( cPartSize == SIZE_2Nx2N ) ? 1 : ( cPartSize == SIZE_NxN ? 4 : 2 ); 2266 #endif 2264 2267 dimDeltaDC = 1; 2265 2268 } -
branches/HTM-9.3-dev3-Samsung/source/Lib/TLibEncoder/TEncSearch.cpp
r782 r792 5633 5633 5634 5634 #if H_3D_INTER_SDC 5635 #if SEC_INTER_SDC_G0101 5636 Void TEncSearch::encodeResAndCalcRdInterSDCCU( TComDataCU* pcCU, TComYuv* pcOrg, TComYuv* pcPred, TComYuv* pcResi, TComYuv* pcRec, Int uiOffest, const UInt uiDepth ) 5637 #else 5635 5638 Void TEncSearch::encodeResAndCalcRdInterSDCCU( TComDataCU* pcCU, TComYuv* pcOrg, TComYuv* pcPred, TComYuv* pcResi, TComYuv* pcRec, const UInt uiDepth ) 5639 #endif 5636 5640 { 5637 5641 if( !pcCU->getSlice()->getIsDepth() || pcCU->isIntra( 0 ) ) … … 5647 5651 UInt uiWidth = pcCU->getWidth ( 0 ); 5648 5652 UInt uiHeight = pcCU->getHeight( 0 ); 5653 #if SEC_INTER_SDC_G0101 5654 UInt uiSegSize = 0; 5655 #else 5649 5656 UChar* pMask = pcCU->getInterSDCMask(); 5650 5657 memset( pMask, 0, uiWidth*uiHeight ); … … 5653 5660 5654 5661 UInt uiSegSize[4] = { 0, 0, 0, 0 }; 5662 #endif 5655 5663 Pel *pPred, *pOrg; 5656 5664 UInt uiPredStride = pcPred->getStride(); 5657 5665 UInt uiOrgStride = pcOrg->getStride(); 5658 5666 UInt uiPelX, uiPelY; 5667 #if !SEC_INTER_SDC_G0101 5659 5668 UInt uiPartitionSize = pcCU->getPartitionSize( 0 ); 5660 5669 UInt uiSegmentNum = ( uiPartitionSize == SIZE_2Nx2N ) ? 1 : ( uiPartitionSize == SIZE_NxN ? 4 : 2 ); 5670 #endif 5661 5671 5662 5672 pPred = pcPred->getLumaAddr( 0 ); 5663 5673 pOrg = pcOrg->getLumaAddr( 0 ); 5674 #if SEC_INTER_SDC_G0101 5675 Int pResDC = 0; 5676 #else 5664 5677 Int pResDC[4] = { 0, 0, 0, 0}; 5678 #endif 5665 5679 5666 5680 //calculate dc value for prediction and original signal, and calculate residual and reconstruction … … 5669 5683 for( uiPelX = 0; uiPelX < uiWidth; uiPelX++ ) 5670 5684 { 5685 #if SEC_INTER_SDC_G0101 5686 pResDC += (Int)( pOrg [uiPelX] - pPred[uiPelX] ); 5687 uiSegSize++; 5688 #else 5671 5689 UChar uiSeg = pMask[ uiPelX + uiPelY*uiWidth ]; 5672 5690 pResDC[uiSeg] += (Int)( pOrg [uiPelX] - pPred[uiPelX] ); 5673 5691 uiSegSize[uiSeg]++; 5692 #endif 5674 5693 } 5675 5694 pOrg += uiOrgStride; … … 5677 5696 } 5678 5697 5698 #if SEC_INTER_SDC_G0101 5699 Int iResiOffset = ( pResDC > 0 ? ( uiSegSize >> 1 ) : -1*( uiSegSize >> 1 ) ); 5700 pResDC = ( pResDC + iResiOffset ) / (Int) uiSegSize; 5701 5702 pcCU->setSDCSegmentDCOffset( pResDC + uiOffest, 0, 0 ); 5703 #else 5679 5704 for( UInt uiSeg = 0; uiSeg < uiSegmentNum; uiSeg++ ) 5680 5705 { … … 5687 5712 #endif 5688 5713 } 5714 #endif 5689 5715 5690 5716 Pel *pRec; … … 5697 5723 for( uiPelX = 0; uiPelX < uiWidth; uiPelX++ ) 5698 5724 { 5725 #if SEC_INTER_SDC_G0101 5726 pRec[ uiPelX ] = Clip3( 0, ( 1 << g_bitDepthY ) - 1, pPred[uiPelX] + pcCU->getSDCSegmentDCOffset(0, 0) ); 5727 #else 5699 5728 UChar uiSeg = pMask[ uiPelX + uiPelY*uiWidth ]; 5700 5729 assert( uiSeg < uiSegmentNum ); 5701 5730 5702 5731 pRec[ uiPelX ] = Clip3( 0, ( 1 << g_bitDepthY ) - 1, pPred[uiPelX] + pResDC[uiSeg] ); 5732 #endif 5703 5733 } 5704 5734 pPred += uiPredStride; … … 5745 5775 Bool bNonSkip = true; 5746 5776 #endif 5777 #if SEC_INTER_SDC_G0101 5778 bNonSkip |= ( pcCU->getSDCSegmentDCOffset( 0, 0 ) != 0 ) ? 1 : 0; 5779 #else 5747 5780 for( UInt uiSeg = 0; uiSeg < uiSegmentNum; uiSeg++ ) 5748 5781 { … … 5753 5786 #endif 5754 5787 } 5788 #endif 5755 5789 5756 5790 if( !bNonSkip ) -
branches/HTM-9.3-dev3-Samsung/source/Lib/TLibEncoder/TEncSearch.h
r781 r792 219 219 TComYuv* pcResi, 220 220 TComYuv* pcRec, 221 #if SEC_INTER_SDC_G0101 222 Int uiOffset, 223 #endif 221 224 const UInt uiDepth ); 222 225 #endif
Note: See TracChangeset for help on using the changeset viewer.