Newer
Older
if (pu.mmvdMergeFlag)
{
CHECK(pu.mhIntraFlag == true, "invalid MHIntra and mmvd");
return;
}
if (pu.cu->affine)
{
CHECK(pu.mhIntraFlag == true, "invalid MHIntra and affine");
return;
}
if (pu.cu->lwidth() * pu.cu->lheight() < 64 || pu.cu->lwidth() >= MAX_CU_SIZE || pu.cu->lheight() >= MAX_CU_SIZE)
{
CHECK(pu.mhIntraFlag == true, "invalid MHIntra and blk");
return;
}
m_BinEncoder.encodeBin(pu.mhIntraFlag, Ctx::MHIntraFlag());
DTRACE(g_trace_ctx, D_SYNTAX, "MHIntra_flag() MHIntra=%d pos=(%d,%d) size=%dx%d\n", pu.mhIntraFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height);
void CABACWriter::MHIntra_luma_pred_modes(const CodingUnit& cu)
{
if (!cu.Y().valid())
{
return;
}
const int numMPMs = 3;
int numBlocks = CU::getNumPUs(cu);
unsigned mpm_idxs[4];
unsigned pred_modes[4];
const PredictionUnit* pu = cu.firstPU;
unsigned mpm_pred[numMPMs];
for (int k = 0; k < numBlocks; k++)
{
unsigned& mpm_idx = mpm_idxs[k];
unsigned& pred_mode = pred_modes[k];
PU::getMHIntraMPMs(*pu, mpm_pred);
pred_mode = pu->intraDir[0];
mpm_idx = numMPMs;
for (int idx = 0; idx < numMPMs; idx++)
{
if (pred_mode == mpm_pred[idx])
{
mpm_idx = idx;
break;
}
}
if (PU::getNarrowShape(pu->lwidth(), pu->lheight()) == 0)
{
m_BinEncoder.encodeBin(mpm_idx < numMPMs, Ctx::MHIntraPredMode());
}
pu = pu->next;
}
pu = cu.firstPU;

Karsten Suehring
committed
// mpm_idx / rem_intra_luma_pred_mode
for (int k = 0; k < numBlocks; k++)
{
const unsigned& mpm_idx = mpm_idxs[k];
if (mpm_idx < numMPMs)
{
m_BinEncoder.encodeBinEP(mpm_idx > 0);
if (mpm_idx)
{
m_BinEncoder.encodeBinEP(mpm_idx > 1);
}
}
DTRACE(g_trace_ctx, D_SYNTAX, "intra_luma_pred_modes() idx=%d pos=(%d,%d) mode=%d\n", k, pu->lumaPos().x, pu->lumaPos().y, pu->intraDir[0]);
pu = pu->next;
}
}

Karsten Suehring
committed
void CABACWriter::triangle_mode( const CodingUnit& cu )
{
if( !cu.cs->slice->getSPS()->getUseTriangle() || !cu.cs->slice->isInterB() || cu.lwidth() * cu.lheight() < TRIANGLE_MIN_SIZE || cu.affine )
{
return;
}
Ruoyang Yu
committed
if ( cu.firstPU->mmvdMergeFlag || cu.mmvdSkip )
{
return;
}
if ( cu.firstPU->mhIntraFlag )
{
return;
}
#if JVET_N600_AMVR_TPM_CTX_REDUCTION
m_BinEncoder.encodeBin( cu.triangle, Ctx::TriangleFlag(0) );
#else
unsigned flag_idx = DeriveCtx::CtxTriangleFlag( cu );
m_BinEncoder.encodeBin( cu.triangle, Ctx::TriangleFlag(flag_idx) );
DTRACE( g_trace_ctx, D_SYNTAX, "triangle_mode() triangle_mode=%d pos=(%d,%d) size: %dx%d\n", cu.triangle, cu.Y().x, cu.Y().y, cu.lumaSize().width, cu.lumaSize().height );
}

Karsten Suehring
committed
//================================================================================
// clause 7.3.8.7
//--------------------------------------------------------------------------------
// void pcm_samples( tu )
//================================================================================
void CABACWriter::pcm_samples( const TransformUnit& tu )
{
CHECK( !tu.cu->ipcm, "pcm mode expected" );
const SPS& sps = *tu.cu->cs->sps;
const CodingStructure *cs = tu.cs;
const ChannelType chType = tu.chType;
ComponentID compStr = (CS::isDualITree(*cs) && !isLuma(chType)) ? COMPONENT_Cb: COMPONENT_Y;
ComponentID compEnd = (CS::isDualITree(*cs) && isLuma(chType)) ? COMPONENT_Y : COMPONENT_Cr;
for( ComponentID compID = compStr; compID <= compEnd; compID = ComponentID(compID+1) )

Karsten Suehring
committed
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
{
const CPelBuf samples = tu.getPcmbuf( compID );
const unsigned sampleBits = sps.getPCMBitDepth( toChannelType(compID) );
for( unsigned y = 0; y < samples.height; y++ )
{
for( unsigned x = 0; x < samples.width; x++ )
{
m_BinEncoder.encodeBinsPCM( samples.at(x, y), sampleBits );
}
}
}
m_BinEncoder.restart();
}
//================================================================================
// clause 7.3.8.8
//--------------------------------------------------------------------------------
// void transform_tree ( cs, area, cuCtx, chromaCbfs )
// bool split_transform_flag( split, depth )
// bool cbf_comp ( cbf, area, depth )
//================================================================================
void CABACWriter::transform_tree( const CodingStructure& cs, Partitioner& partitioner, CUCtx& cuCtx, ChromaCbfs& chromaCbfs, const PartSplit ispType, const int subTuIdx )

Karsten Suehring
committed
{
ChromaCbfs chromaCbfsLastDepth;
chromaCbfsLastDepth.Cb = chromaCbfs.Cb;
chromaCbfsLastDepth.Cr = chromaCbfs.Cr;

Karsten Suehring
committed
const UnitArea& area = partitioner.currArea();
int subTuCounter = subTuIdx;
const TransformUnit& tu = *cs.getTU( area.blocks[partitioner.chType].pos(), partitioner.chType, subTuIdx );

Karsten Suehring
committed
const CodingUnit& cu = *tu.cu;
const unsigned trDepth = partitioner.currTrDepth;
const bool split = ( tu.depth > trDepth );
const bool chromaCbfISP = area.blocks[COMPONENT_Cb].valid() && cu.ispMode && !split;
#if JVET_N0492_NO_HIERARCH_CBF
bool max_tu_split = false;
#endif

Karsten Suehring
committed
// split_transform_flag

Karsten Suehring
committed
{
#if JVET_N0492_NO_HIERARCH_CBF
max_tu_split = true;
#endif

Karsten Suehring
committed
}
else if( cu.sbtInfo && partitioner.canSplit( PartSplit( cu.getSbtTuSplit() ), cs ) )
{
CHECK( !split, "transform split implied - sbt" );
}
CHECK( split && !cu.ispMode, "transform split not allowed with QTBT" );

Karsten Suehring
committed
// cbf_cb & cbf_cr
if( area.chromaFormat != CHROMA_400 && area.blocks[COMPONENT_Cb].valid() && ( !CS::isDualITree( cs ) || partitioner.chType == CHANNEL_TYPE_CHROMA ) && ( !cu.ispMode || chromaCbfISP ) )

Karsten Suehring
committed
{
{
unsigned cbfDepth = chromaCbfISP ? trDepth - 1 : trDepth;
#if JVET_N0492_NO_HIERARCH_CBF
if (!max_tu_split || chromaCbfISP)
#else
if (trDepth == 0 || chromaCbfs.Cb || chromaCbfISP)
#endif
{
chromaCbfs.Cb = TU::getCbfAtDepth( tu, COMPONENT_Cb, trDepth );
if( !( cu.sbtInfo && trDepth == 1 ) )
cbf_comp( cs, chromaCbfs.Cb, area.blocks[COMPONENT_Cb], cbfDepth );
}
#if !JVET_N0492_NO_HIERARCH_CBF
else
{
CHECK( TU::getCbfAtDepth( tu, COMPONENT_Cb, cbfDepth ) != chromaCbfs.Cb, "incorrect Cb cbf" );
}
#if JVET_N0492_NO_HIERARCH_CBF
if (!max_tu_split || chromaCbfISP)
#else
if (trDepth == 0 || chromaCbfs.Cr || chromaCbfISP)
#endif
{
chromaCbfs.Cr = TU::getCbfAtDepth( tu, COMPONENT_Cr, trDepth );
if( !( cu.sbtInfo && trDepth == 1 ) )
cbf_comp( cs, chromaCbfs.Cr, area.blocks[COMPONENT_Cr], cbfDepth, chromaCbfs.Cb );
}
#if !JVET_N0492_NO_HIERARCH_CBF
else
{
CHECK( TU::getCbfAtDepth( tu, COMPONENT_Cr, cbfDepth ) != chromaCbfs.Cr, "incorrect Cr cbf" );
}

Karsten Suehring
committed
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
}
}
else if( CS::isDualITree( cs ) )
{
chromaCbfs = ChromaCbfs( false );
}
if( split )
{
if( area.chromaFormat != CHROMA_400 )
{
chromaCbfs.Cb = TU::getCbfAtDepth( tu, COMPONENT_Cb, trDepth );
chromaCbfs.Cr = TU::getCbfAtDepth( tu, COMPONENT_Cr, trDepth );
}
if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
{
#if ENABLE_TRACING
const CompArea &tuArea = partitioner.currArea().blocks[partitioner.chType];
DTRACE( g_trace_ctx, D_SYNTAX, "transform_tree() maxTrSplit chType=%d pos=(%d,%d) size=%dx%d\n", partitioner.chType, tuArea.x, tuArea.y, tuArea.width, tuArea.height );
#endif
partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
}
else if( cu.ispMode )
{
partitioner.splitCurrArea( ispType, cs );
}
else if( cu.sbtInfo && partitioner.canSplit( PartSplit( cu.getSbtTuSplit() ), cs ) )
{
partitioner.splitCurrArea( PartSplit( cu.getSbtTuSplit() ), cs );
}

Karsten Suehring
committed
else
THROW( "Implicit TU split not available" );
do
{
ChromaCbfs subChromaCbfs = chromaCbfs;
transform_tree( cs, partitioner, cuCtx, subChromaCbfs, ispType, subTuCounter );
subTuCounter += subTuCounter != -1 ? 1 : 0;

Karsten Suehring
committed
} while( partitioner.nextPart( cs ) );
partitioner.exitCurrSplit();
}
else
{
DTRACE( g_trace_ctx, D_SYNTAX, "transform_unit() pos=(%d,%d) size=%dx%d depth=%d trDepth=%d\n", tu.blocks[tu.chType].x, tu.blocks[tu.chType].y, tu.blocks[tu.chType].width, tu.blocks[tu.chType].height, cu.depth, partitioner.currTrDepth );
if( !isChroma( partitioner.chType ) )
{
if( !CU::isIntra( cu ) && trDepth == 0 && !chromaCbfs.sigChroma( area.chromaFormat ) )
{
CHECK( !TU::getCbfAtDepth( tu, COMPONENT_Y, trDepth ), "Luma cbf must be true for inter units with no chroma coeffs" );
}
else if( cu.sbtInfo && tu.noResidual )
{
CHECK( TU::getCbfAtDepth( tu, COMPONENT_Y, trDepth ), "Luma cbf must be false for inter sbt no-residual tu" );
}
else if( cu.sbtInfo && !chromaCbfsLastDepth.sigChroma( area.chromaFormat ) )
{
assert( !tu.noResidual );
CHECK( !TU::getCbfAtDepth( tu, COMPONENT_Y, trDepth ), "Luma cbf must be true for inter sbt residual tu" );
}

Karsten Suehring
committed
else
{
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
bool previousCbf = false;
bool rootCbfSoFar = false;
bool lastCbfIsInferred = false;
if( cu.ispMode )
{
uint32_t nTus = cu.ispMode == HOR_INTRA_SUBPARTITIONS ? cu.lheight() >> g_aucLog2[tu.lheight()] : cu.lwidth() >> g_aucLog2[tu.lwidth()];
if( subTuCounter == nTus - 1 )
{
TransformUnit* tuPointer = cu.firstTU;
for( int tuIdx = 0; tuIdx < subTuCounter; tuIdx++ )
{
rootCbfSoFar |= TU::getCbfAtDepth( *tuPointer, COMPONENT_Y, trDepth );
tuPointer = tuPointer->next;
}
if( !rootCbfSoFar )
{
lastCbfIsInferred = true;
}
}
if( !lastCbfIsInferred )
{
previousCbf = TU::getPrevTuCbfAtDepth( tu, COMPONENT_Y, partitioner.currTrDepth );
}
}
if( !lastCbfIsInferred )
{
cbf_comp( cs, TU::getCbfAtDepth( tu, COMPONENT_Y, trDepth ), tu.Y(), trDepth, previousCbf, cu.ispMode );
}

Karsten Suehring
committed
}
}
transform_unit( tu, cuCtx, chromaCbfs );
}
}
void CABACWriter::cbf_comp( const CodingStructure& cs, bool cbf, const CompArea& area, unsigned depth, const bool prevCbCbf, const bool useISP )
{
const unsigned ctxId = DeriveCtx::CtxQtCbf( area.compID, depth, prevCbCbf, useISP && isLuma(area.compID) );

Karsten Suehring
committed
const CtxSet& ctxSet = Ctx::QtCbf[ area.compID ];
#if JVET_N0413_RDPCM
if( area.compID == COMPONENT_Y && cs.getCU( area.pos(), ChannelType( area.compID ) )->bdpcmMode )
{
m_BinEncoder.encodeBin( cbf, ctxSet( 4 ) );
}
else
{

Karsten Suehring
committed
m_BinEncoder.encodeBin( cbf, ctxSet( ctxId ) );
}
#else
m_BinEncoder.encodeBin( cbf, ctxSet( ctxId ) );
#endif

Karsten Suehring
committed
DTRACE( g_trace_ctx, D_SYNTAX, "cbf_comp() etype=%d pos=(%d,%d) ctx=%d cbf=%d\n", area.compID, area.x, area.y, ctxId, cbf );
}
//================================================================================
// clause 7.3.8.9
//--------------------------------------------------------------------------------
// void mvd_coding( pu, refList )
//================================================================================
void CABACWriter::mvd_coding( const Mv &rMvd, int8_t imv )

Karsten Suehring
committed
{
int horMvd = rMvd.getHor();
int verMvd = rMvd.getVer();

Karsten Suehring
committed
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
{
CHECK( (horMvd % 4) != 0 && (verMvd % 4) != 0, "IMV: MVD is not a multiple of 4" );
horMvd >>= 2;
verMvd >>= 2;
if( imv == 2 )//IMV_4PEL
{
CHECK( (horMvd % 4) != 0 && (verMvd % 4) != 0, "IMV: MVD is not a multiple of 8" );
horMvd >>= 2;
verMvd >>= 2;
}
}
unsigned horAbs = unsigned( horMvd < 0 ? -horMvd : horMvd );
unsigned verAbs = unsigned( verMvd < 0 ? -verMvd : verMvd );
// abs_mvd_greater0_flag[ 0 | 1 ]
m_BinEncoder.encodeBin( (horAbs > 0), Ctx::Mvd() );
m_BinEncoder.encodeBin( (verAbs > 0), Ctx::Mvd() );
// abs_mvd_greater1_flag[ 0 | 1 ]
if( horAbs > 0 )
{
m_BinEncoder.encodeBin( (horAbs > 1), Ctx::Mvd(1) );
}
if( verAbs > 0 )
{
m_BinEncoder.encodeBin( (verAbs > 1), Ctx::Mvd(1) );
}
// abs_mvd_minus2[ 0 | 1 ] and mvd_sign_flag[ 0 | 1 ]
if( horAbs > 0 )
{
if( horAbs > 1 )
{
exp_golomb_eqprob( horAbs - 2, 1 );
}
m_BinEncoder.encodeBinEP( (horMvd < 0) );
}
if( verAbs > 0 )
{
if( verAbs > 1 )
{
exp_golomb_eqprob( verAbs - 2, 1 );
}
m_BinEncoder.encodeBinEP( (verMvd < 0) );
}
}
//================================================================================
// clause 7.3.8.10
//--------------------------------------------------------------------------------
// void transform_unit ( tu, cuCtx, chromaCbfs )
// void cu_qp_delta ( cu )
// void cu_chroma_qp_offset ( cu )
//================================================================================
void CABACWriter::transform_unit( const TransformUnit& tu, CUCtx& cuCtx, ChromaCbfs& chromaCbfs )
{
CodingUnit& cu = *tu.cu;
bool lumaOnly = ( cu.chromaFormat == CHROMA_400 || !tu.blocks[COMPONENT_Cb].valid() );
bool cbf[3] = { TU::getCbf( tu, COMPONENT_Y ), chromaCbfs.Cb, chromaCbfs.Cr };
bool cbfLuma = ( cbf[ COMPONENT_Y ] != 0 );
bool cbfChroma = false;
Santiago de Luxán Hernández
committed
if( !lumaOnly )

Karsten Suehring
committed
{
if( tu.blocks[COMPONENT_Cb].valid() )
{
cbf [ COMPONENT_Cb ] = TU::getCbf( tu, COMPONENT_Cb );
cbf [ COMPONENT_Cr ] = TU::getCbf( tu, COMPONENT_Cr );
}
cbfChroma = ( cbf[ COMPONENT_Cb ] || cbf[ COMPONENT_Cr ] );
}
if( cbfLuma || cbfChroma )
{
if( cu.cs->pps->getUseDQP() && !cuCtx.isDQPCoded )
{

Christian Helmrich
committed
if (!CS::isDualITree(*tu.cs) || isLuma(tu.chType))
{
cu_qp_delta(cu, cuCtx.qp, cu.qp);
cuCtx.qp = cu.qp;
cuCtx.isDQPCoded = true;
}

Karsten Suehring
committed
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
}
if( cu.cs->slice->getUseChromaQpAdj() && cbfChroma && !cu.transQuantBypass && !cuCtx.isChromaQpAdjCoded )
{
cu_chroma_qp_offset( cu );
cuCtx.isChromaQpAdjCoded = true;
}
if( cbfLuma )
{
residual_coding( tu, COMPONENT_Y );
}
if( !lumaOnly )
{
for( ComponentID compID = COMPONENT_Cb; compID <= COMPONENT_Cr; compID = ComponentID( compID + 1 ) )
{
if( TU::hasCrossCompPredInfo( tu, compID ) )
{
cross_comp_pred( tu, compID );
}
if( cbf[ compID ] )
{
residual_coding( tu, compID );
}
}
}
}
}
void CABACWriter::cu_qp_delta( const CodingUnit& cu, int predQP, const int8_t qp )
{
CHECK(!( predQP != std::numeric_limits<int>::max()), "Unspecified error");
int DQp = qp - predQP;
int qpBdOffsetY = cu.cs->sps->getQpBDOffset( CHANNEL_TYPE_LUMA );
DQp = ( DQp + (MAX_QP + 1) + (MAX_QP + 1) / 2 + qpBdOffsetY + (qpBdOffsetY / 2)) % ((MAX_QP + 1) + qpBdOffsetY) - (MAX_QP + 1) / 2 - (qpBdOffsetY / 2);
unsigned absDQP = unsigned( DQp < 0 ? -DQp : DQp );
unsigned unaryDQP = std::min<unsigned>( absDQP, CU_DQP_TU_CMAX );
unary_max_symbol( unaryDQP, Ctx::DeltaQP(), Ctx::DeltaQP(1), CU_DQP_TU_CMAX );
if( absDQP >= CU_DQP_TU_CMAX )
{
exp_golomb_eqprob( absDQP - CU_DQP_TU_CMAX, CU_DQP_EG_k );
}
if( absDQP > 0 )
{
m_BinEncoder.encodeBinEP( DQp < 0 );
}
DTRACE_COND( ( isEncoding() ), g_trace_ctx, D_DQP, "x=%d, y=%d, d=%d, pred_qp=%d, DQp=%d, qp=%d\n", cu.blocks[cu.chType].lumaPos().x, cu.blocks[cu.chType].lumaPos().y, cu.qtDepth, predQP, DQp, qp );
}
void CABACWriter::cu_chroma_qp_offset( const CodingUnit& cu )
{
// cu_chroma_qp_offset_flag
unsigned qpAdj = cu.chromaQpAdj;
if( qpAdj == 0 )
{
m_BinEncoder.encodeBin( 0, Ctx::ChromaQpAdjFlag() );
}
else
{
m_BinEncoder.encodeBin( 1, Ctx::ChromaQpAdjFlag() );
int length = cu.cs->pps->getPpsRangeExtension().getChromaQpOffsetListLen();
if( length > 1 )
{
unary_max_symbol( qpAdj-1, Ctx::ChromaQpAdjIdc(), Ctx::ChromaQpAdjIdc(), length-1 );
}
}
}
//================================================================================
// clause 7.3.8.11
//--------------------------------------------------------------------------------
// void residual_coding ( tu, compID )
// void transform_skip_flag ( tu, compID )
// void explicit_rdpcm_mode ( tu, compID )
// void last_sig_coeff ( coeffCtx )
// void residual_coding_subblock( coeffCtx )
//================================================================================
#if JVET_N0054_JOINT_CHROMA
void CABACWriter::joint_cb_cr( const TransformUnit& tu )
{
m_BinEncoder.encodeBin( tu.jointCbCr ? 1 : 0, Ctx::JointCbCrFlag( 0 ) );
}
#endif

Karsten Suehring
committed
void CABACWriter::residual_coding( const TransformUnit& tu, ComponentID compID )
{
const CodingUnit& cu = *tu.cu;
DTRACE( g_trace_ctx, D_SYNTAX, "residual_coding() etype=%d pos=(%d,%d) size=%dx%d predMode=%d\n", tu.blocks[compID].compID, tu.blocks[compID].x, tu.blocks[compID].y, tu.blocks[compID].width, tu.blocks[compID].height, cu.predMode );
// Joint Cb-Cr residual mode is signalled if both Cb and Cr cbfs are true
if ( compID == COMPONENT_Cr && TU::getCbf( tu, COMPONENT_Cb ) )
{
joint_cb_cr( tu );
// No Cr residual in bitstream in joint Cb-Cr residual mode
if ( tu.jointCbCr )
return;
}
#endif

Karsten Suehring
committed
// code transform skip and explicit rdpcm mode

Karsten Suehring
committed
explicit_rdpcm_mode( tu, compID );
#if JVET_N0280_RESIDUAL_CODING_TS
#if JVET_N0413_RDPCM
if( isLuma( compID ) && ( tu.mtsIdx == 1 || tu.cu->bdpcmMode ) )
#else
if( isLuma( compID ) && tu.mtsIdx==1 )
{
residual_codingTS( tu, compID );
return;
}
#endif

Karsten Suehring
committed
#if HEVC_USE_SIGN_HIDING
// determine sign hiding
bool signHiding = ( cu.cs->slice->getSignDataHidingEnabledFlag() && !cu.transQuantBypass && tu.rdpcm[compID] == RDPCM_OFF );
if( signHiding && CU::isIntra(cu) && CU::isRDPCMEnabled(cu) && tu.mtsIdx==1 )

Karsten Suehring
committed
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
{
const ChannelType chType = toChannelType( compID );
const unsigned intraMode = PU::getFinalIntraMode( *cu.cs->getPU( tu.blocks[compID].pos(), chType ), chType );
if( intraMode == HOR_IDX || intraMode == VER_IDX )
{
signHiding = false;
}
}
#endif
// init coeff coding context
#if HEVC_USE_SIGN_HIDING
CoeffCodingContext cctx ( tu, compID, signHiding );
#else
CoeffCodingContext cctx ( tu, compID );
#endif
const TCoeff* coeff = tu.getCoeffs( compID ).buf;
// determine and set last coeff position and sig group flags
int scanPosLast = -1;
std::bitset<MLS_GRP_NUM> sigGroupFlags;
for( int scanPos = 0; scanPos < cctx.maxNumCoeff(); scanPos++)
{
unsigned blkPos = cctx.blockPos( scanPos );
if( coeff[blkPos] )
{
scanPosLast = scanPos;
sigGroupFlags.set( scanPos >> cctx.log2CGSize() );
}
}
CHECK( scanPosLast < 0, "Coefficient coding called for empty TU" );
cctx.setScanPosLast(scanPosLast);
// code last coeff position

Karsten Suehring
committed
// code subblocks
const int stateTab = ( tu.cs->slice->getDepQuantEnabledFlag() ? 32040 : 0 );
int state = 0;
for( int subSetId = ( cctx.scanPosLast() >> cctx.log2CGSize() ); subSetId >= 0; subSetId--)
{
cctx.initSubblock ( subSetId, sigGroupFlags[subSetId] );
if( ( tu.mtsIdx > 1 || ( tu.cu->sbtInfo != 0 && tu.blocks[ compID ].height <= 32 && tu.blocks[ compID ].width <= 32 ) ) && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
{
if( ( tu.blocks[ compID ].height == 32 && cctx.cgPosY() >= ( 16 >> cctx.log2CGHeight() ) )
|| ( tu.blocks[ compID ].width == 32 && cctx.cgPosX() >= ( 16 >> cctx.log2CGWidth() ) ) )
{
continue;
}
}
residual_coding_subblock( cctx, coeff, stateTab, state );

Karsten Suehring
committed
}
}
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
void CABACWriter::mts_coding( const TransformUnit& tu, ComponentID compID )
{
const CodingUnit &cu = *tu.cu;
const bool tsAllowed = TU::isTSAllowed ( tu, compID );
const bool mtsAllowed = TU::isMTSAllowed( tu, compID );
if( !mtsAllowed && !tsAllowed ) return;
int symbol = 0;
int ctxIdx = 0;
if( tsAllowed )
{
symbol = 1 - ( tu.mtsIdx == 1 ? 1 : 0 );
ctxIdx = 6;
m_BinEncoder.encodeBin( symbol, Ctx::MTSIndex( ctxIdx ) );
}
if( tu.mtsIdx != 1 )
{
if( mtsAllowed )
{
symbol = tu.mtsIdx != 0 ? 1 : 0;
ctxIdx = std::min( (int)cu.qtDepth, 5 );
m_BinEncoder.encodeBin( symbol, Ctx::MTSIndex( ctxIdx ) );

Karsten Suehring
committed
if( symbol )
{
ctxIdx = 7;
for( int i = 0; i < 3; i++, ctxIdx++ )
{
symbol = tu.mtsIdx > i + 2 ? 1 : 0;
m_BinEncoder.encodeBin( symbol, Ctx::MTSIndex( ctxIdx ) );
if( !symbol )
{
break;
}
}
}
}
}
DTRACE( g_trace_ctx, D_SYNTAX, "mts_coding() etype=%d pos=(%d,%d) mtsIdx=%d\n", COMPONENT_Y, cu.lx(), cu.ly(), tu.mtsIdx );
}

Karsten Suehring
committed
void CABACWriter::isp_mode( const CodingUnit& cu )
{
#if INCLUDE_ISP_CFG_FLAG
#if JVET_N0413_RDPCM
if( !CU::isIntra( cu ) || !isLuma( cu.chType ) || cu.firstPU->multiRefIdx || cu.ipcm || !cu.cs->sps->getUseISP() || cu.bdpcmMode )
#else
if( !CU::isIntra( cu ) || !isLuma( cu.chType ) || cu.firstPU->multiRefIdx || cu.ipcm || !cu.cs->sps->getUseISP() )
#endif
#else
#if JVET_N0413_RDPCM
if( !CU::isIntra( cu ) || !isLuma( cu.chType ) || cu.firstPU->multiRefIdx || cu.ipcm || cu.bdpcmMode )
Santiago de Luxán Hernández
committed
if( !CU::isIntra( cu ) || !isLuma( cu.chType ) || cu.firstPU->multiRefIdx || cu.ipcm )
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
{
CHECK( cu.ispMode != NOT_INTRA_SUBPARTITIONS, "error: cu.intraSubPartitions != 0" );
return;
}
const ISPType allowedSplits = CU::canUseISPSplit( cu, getFirstComponentOfChannel( cu.chType ) );
if( allowedSplits == NOT_INTRA_SUBPARTITIONS ) return;
if( cu.ispMode == NOT_INTRA_SUBPARTITIONS )
{
m_BinEncoder.encodeBin( 0, Ctx::ISPMode( 0 ) );
}
else
{
m_BinEncoder.encodeBin( 1, Ctx::ISPMode( 0 ) );
if( allowedSplits == CAN_USE_VER_AND_HORL_SPLITS )
{
m_BinEncoder.encodeBin( cu.ispMode - 1, Ctx::ISPMode( 1 ) );
}
}
DTRACE( g_trace_ctx, D_SYNTAX, "intra_subPartitions() etype=%d pos=(%d,%d) ispIdx=%d\n", cu.chType, cu.blocks[cu.chType].x, cu.blocks[cu.chType].y, (int)cu.ispMode );
}

Karsten Suehring
committed
void CABACWriter::explicit_rdpcm_mode( const TransformUnit& tu, ComponentID compID )
{
const CodingUnit& cu = *tu.cu;
if( !CU::isIntra(cu) && CU::isRDPCMEnabled(cu) && ( tu.mtsIdx==1 || cu.transQuantBypass ) )

Karsten Suehring
committed
{
ChannelType chType = toChannelType( compID );
switch( tu.rdpcm[compID] )
{
case RDPCM_VER:
m_BinEncoder.encodeBin( 1, Ctx::RdpcmFlag(chType) );
m_BinEncoder.encodeBin( 1, Ctx::RdpcmDir (chType) );
break;
case RDPCM_HOR:
m_BinEncoder.encodeBin( 1, Ctx::RdpcmFlag(chType) );
m_BinEncoder.encodeBin( 0, Ctx::RdpcmDir (chType) );
break;
default: // RDPCM_OFF
m_BinEncoder.encodeBin( 0, Ctx::RdpcmFlag(chType) );
}
}
}
void CABACWriter::last_sig_coeff( CoeffCodingContext& cctx, const TransformUnit& tu, ComponentID compID )

Karsten Suehring
committed
{
unsigned blkPos = cctx.blockPos( cctx.scanPosLast() );
unsigned posX, posY;
#if HEVC_USE_MDCS
if( cctx.scanType() == SCAN_VER )
{
posX = blkPos / cctx.width();
posY = blkPos - ( posX * cctx.width() );
}
else
#endif
{
posY = blkPos / cctx.width();
posX = blkPos - ( posY * cctx.width() );
}
unsigned CtxLast;
unsigned GroupIdxX = g_uiGroupIdx[ posX ];
unsigned GroupIdxY = g_uiGroupIdx[ posY ];
unsigned maxLastPosX = cctx.maxLastPosX();
unsigned maxLastPosY = cctx.maxLastPosY();
if( ( tu.mtsIdx > 1 || ( tu.cu->sbtInfo != 0 && tu.blocks[ compID ].width <= 32 && tu.blocks[ compID ].height <= 32 ) ) && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
maxLastPosX = ( tu.blocks[compID].width == 32 ) ? g_uiGroupIdx[ 15 ] : maxLastPosX;
maxLastPosY = ( tu.blocks[compID].height == 32 ) ? g_uiGroupIdx[ 15 ] : maxLastPosY;

Karsten Suehring
committed
for( CtxLast = 0; CtxLast < GroupIdxX; CtxLast++ )
{
m_BinEncoder.encodeBin( 1, cctx.lastXCtxId( CtxLast ) );
}

Karsten Suehring
committed
{
m_BinEncoder.encodeBin( 0, cctx.lastXCtxId( CtxLast ) );
}
for( CtxLast = 0; CtxLast < GroupIdxY; CtxLast++ )
{
m_BinEncoder.encodeBin( 1, cctx.lastYCtxId( CtxLast ) );
}

Karsten Suehring
committed
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
{
m_BinEncoder.encodeBin( 0, cctx.lastYCtxId( CtxLast ) );
}
if( GroupIdxX > 3 )
{
posX -= g_uiMinInGroup[ GroupIdxX ];
for (int i = ( ( GroupIdxX - 2 ) >> 1 ) - 1 ; i >= 0; i-- )
{
m_BinEncoder.encodeBinEP( ( posX >> i ) & 1 );
}
}
if( GroupIdxY > 3 )
{
posY -= g_uiMinInGroup[ GroupIdxY ];
for ( int i = ( ( GroupIdxY - 2 ) >> 1 ) - 1 ; i >= 0; i-- )
{
m_BinEncoder.encodeBinEP( ( posY >> i ) & 1 );
}
}
}
void CABACWriter::residual_coding_subblock( CoeffCodingContext& cctx, const TCoeff* coeff, const int stateTransTable, int& state )
{
//===== init =====
const int minSubPos = cctx.minSubPos();
const bool isLast = cctx.isLast();
int firstSigPos = ( isLast ? cctx.scanPosLast() : cctx.maxSubPos() );
int nextSigPos = firstSigPos;
//===== encode significant_coeffgroup_flag =====
if( !isLast && cctx.isNotFirst() )
{
if( cctx.isSigGroup() )
{
m_BinEncoder.encodeBin( 1, cctx.sigGroupCtxId() );
}
else
{
m_BinEncoder.encodeBin( 0, cctx.sigGroupCtxId() );
return;
}
}
uint8_t ctxOffset[16];
//===== encode absolute values =====
const int inferSigPos = nextSigPos != cctx.scanPosLast() ? ( cctx.isNotFirst() ? minSubPos : -1 ) : nextSigPos;
#if HEVC_USE_SIGN_HIDING
int firstNZPos = nextSigPos;
int lastNZPos = -1;
#endif
int remAbsLevel = -1;
int numNonZero = 0;
unsigned signPattern = 0;
bool is2x2subblock = ( cctx.log2CGSize() == 2 );
int remRegBins = ( is2x2subblock ? MAX_NUM_REG_BINS_2x2SUBBLOCK : MAX_NUM_REG_BINS_4x4SUBBLOCK );
int firstPosMode2 = minSubPos - 1;

Karsten Suehring
committed
for( ; nextSigPos >= minSubPos && remRegBins >= 4; nextSigPos-- )

Karsten Suehring
committed
{
TCoeff Coeff = coeff[ cctx.blockPos( nextSigPos ) ];
unsigned sigFlag = ( Coeff != 0 );
if( numNonZero || nextSigPos != inferSigPos )
{
const unsigned sigCtxId = cctx.sigCtxIdAbs( nextSigPos, coeff, state );
m_BinEncoder.encodeBin( sigFlag, sigCtxId );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "sig_bin() bin=%d ctx=%d\n", sigFlag, sigCtxId );
remRegBins--;

Karsten Suehring
committed
}
if( sigFlag )
{
uint8_t& ctxOff = ctxOffset[ nextSigPos - minSubPos ];
ctxOff = cctx.ctxOffsetAbs();
numNonZero++;
#if HEVC_USE_SIGN_HIDING
firstNZPos = nextSigPos;
lastNZPos = std::max<int>( lastNZPos, nextSigPos );
#endif
remAbsLevel = abs( Coeff ) - 1;
if( nextSigPos != cctx.scanPosLast() ) signPattern <<= 1;
if( Coeff < 0 ) signPattern++;
unsigned gt1 = !!remAbsLevel;
m_BinEncoder.encodeBin( gt1, cctx.greater1CtxIdAbs(ctxOff) );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "gt1_flag() bin=%d ctx=%d\n", gt1, cctx.greater1CtxIdAbs(ctxOff) );
remRegBins--;
if( gt1 )
{
remAbsLevel -= 1;
m_BinEncoder.encodeBin( remAbsLevel&1, cctx.parityCtxIdAbs( ctxOff ) );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "par_flag() bin=%d ctx=%d\n", remAbsLevel&1, cctx.parityCtxIdAbs( ctxOff ) );
remAbsLevel >>= 1;
remRegBins--;
unsigned gt2 = !!remAbsLevel;
m_BinEncoder.encodeBin(gt2, cctx.greater2CtxIdAbs(ctxOff));
DTRACE(g_trace_ctx, D_SYNTAX_RESI, "gt2_flag() bin=%d ctx=%d\n", gt2, cctx.greater2CtxIdAbs(ctxOff));
remRegBins--;

Karsten Suehring
committed
}
state = ( stateTransTable >> ((state<<2)+((Coeff&1)<<1)) ) & 3;
}
firstPosMode2 = nextSigPos;

Karsten Suehring
committed
//===== 2nd PASS: Go-rice codes =====
unsigned ricePar = 0;
for( int scanPos = firstSigPos; scanPos > firstPosMode2; scanPos-- )
#if JVET_N0188_UNIFY_RICEPARA
int sumAll = cctx.templateAbsSum(scanPos, coeff, 4);
ricePar = g_auiGoRiceParsCoeff[sumAll];
#endif
unsigned absLevel = abs( coeff[ cctx.blockPos( scanPos ) ] );
if( absLevel >= 4 )
{
unsigned rem = ( absLevel - 4 ) >> 1;
m_BinEncoder.encodeRemAbsEP( rem, ricePar, cctx.extPrec(), cctx.maxLog2TrDRange() );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "rem_val() bin=%d ctx=%d\n", rem, ricePar );
if( ricePar < 3 && rem > (3<<ricePar)-1 )
{
ricePar++;
}
}
}
//===== coeff bypass ====
for( int scanPos = firstPosMode2; scanPos >= minSubPos; scanPos-- )
{
TCoeff Coeff = coeff[ cctx.blockPos( scanPos ) ];
unsigned absLevel = abs( Coeff );
int sumAll = cctx.templateAbsSum(scanPos, coeff, 0);
#else
int sumAll = cctx.templateAbsSum(scanPos, coeff);
int rice = g_auiGoRiceParsCoeff [sumAll];
int pos0 = g_auiGoRicePosCoeff0[std::max(0, state - 1)][sumAll];
unsigned rem = ( absLevel == 0 ? pos0 : absLevel <= pos0 ? absLevel-1 : absLevel );
m_BinEncoder.encodeRemAbsEP( rem, rice, cctx.extPrec(), cctx.maxLog2TrDRange() );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "rem_val() bin=%d ctx=%d\n", rem, rice );
state = ( stateTransTable >> ((state<<2)+((absLevel&1)<<1)) ) & 3;
if( absLevel )
{
numNonZero++;
#if HEVC_USE_SIGN_HIDING
lastNZPos = std::max<int>( lastNZPos, scanPos );
#endif
signPattern <<= 1;
if( Coeff < 0 ) signPattern++;
}
}

Karsten Suehring
committed
//===== encode sign's =====
#if HEVC_USE_SIGN_HIDING
unsigned numSigns = numNonZero;
if( cctx.hideSign( firstNZPos, lastNZPos ) )
{
numSigns --;
signPattern >>= 1;
}
m_BinEncoder.encodeBinsEP( signPattern, numSigns );
#else
m_BinEncoder.encodeBinsEP( signPattern, numNonZero );
#endif
}
#if JVET_N0280_RESIDUAL_CODING_TS
void CABACWriter::residual_codingTS( const TransformUnit& tu, ComponentID compID )
{
DTRACE( g_trace_ctx, D_SYNTAX, "residual_codingTS() etype=%d pos=(%d,%d) size=%dx%d\n", tu.blocks[compID].compID, tu.blocks[compID].x, tu.blocks[compID].y, tu.blocks[compID].width, tu.blocks[compID].height );
// init coeff coding context
#if JVET_N0413_RDPCM
CoeffCodingContext cctx ( tu, compID, false, tu.cu->bdpcmMode );
#else
CoeffCodingContext cctx ( tu, compID, false );
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
const TCoeff* coeff = tu.getCoeffs( compID ).buf;
cctx.setNumCtxBins( 2 * tu.lwidth()*tu.lheight() );
// determine and set last coeff position and sig group flags
std::bitset<MLS_GRP_NUM> sigGroupFlags;
for( int scanPos = 0; scanPos < cctx.maxNumCoeff(); scanPos++)
{
unsigned blkPos = cctx.blockPos( scanPos );
if( coeff[blkPos] )
{
sigGroupFlags.set( scanPos >> cctx.log2CGSize() );
}
}
// code subblocks
for( int subSetId = 0; subSetId <= ( cctx.maxNumCoeff() - 1 ) >> cctx.log2CGSize(); subSetId++ )
{
cctx.initSubblock ( subSetId, sigGroupFlags[subSetId] );
residual_coding_subblockTS( cctx, coeff );
}
}
void CABACWriter::residual_coding_subblockTS( CoeffCodingContext& cctx, const TCoeff* coeff )
{
//===== init =====
const int minSubPos = cctx.maxSubPos();
int firstSigPos = cctx.minSubPos();
int nextSigPos = firstSigPos;
//===== encode significant_coeffgroup_flag =====
if( !cctx.isLastSubSet() || !cctx.only1stSigGroup() )
{
if( cctx.isSigGroup() )
{
if( cctx.isContextCoded() )
{