// (8.6.1) void decode_quantization_parameters(decoder_context* ctx, thread_context* tctx, int xC,int yC) { logtrace(LogTransform,"decode_quantization_parameters(int xC,int yC)=(%d,%d)\n", xC,yC); pic_parameter_set* pps = ctx->current_pps; seq_parameter_set* sps = ctx->current_sps; slice_segment_header* shdr = tctx->shdr; // top left pixel position of current quantization group int xQG = xC - (xC & ((1<<pps->Log2MinCuQpDeltaSize)-1)); int yQG = yC - (yC & ((1<<pps->Log2MinCuQpDeltaSize)-1)); // we only have to set QP in the first call in a quantization-group /* TODO: check why this does not work with HoneyBee stream if (xQG == tctx->currentQG_x && yQG == tctx->currentQG_y) { return; } */ // if first QG in CU, remember last QPY of last CU previous QG if (xQG != tctx->currentQG_x || yQG != tctx->currentQG_y) { tctx->lastQPYinPreviousQG = tctx->currentQPY; tctx->currentQG_x = xQG; tctx->currentQG_y = yQG; } int qPY_PRED; bool firstQGInSlice; bool firstQGInTile = false; // TODO bool firstInCTBRow = (xQG==0); // TODO int first_ctb_in_slice_RS = tctx->shdr->slice_segment_address; int SliceStartX = (first_ctb_in_slice_RS % sps->PicWidthInCtbsY) * sps->CtbSizeY; int SliceStartY = (first_ctb_in_slice_RS / sps->PicWidthInCtbsY) * sps->CtbSizeY; firstQGInSlice = (SliceStartX == xQG && SliceStartY == yQG); if (firstQGInSlice || firstQGInTile || (firstInCTBRow && pps->entropy_coding_sync_enabled_flag)) { qPY_PRED = tctx->shdr->SliceQPY; } else { qPY_PRED = tctx->lastQPYinPreviousQG; } int qPYA,qPYB; if (available_zscan(ctx->img,xQG,yQG, xQG-1,yQG)) { int xTmp = (xQG-1) >> sps->Log2MinTrafoSize; int yTmp = (yQG ) >> sps->Log2MinTrafoSize; int minTbAddrA = pps->MinTbAddrZS[xTmp + yTmp*sps->PicWidthInTbsY]; int ctbAddrA = (minTbAddrA>>2)*(sps->Log2CtbSizeY-sps->Log2MinTrafoSize); if (ctbAddrA == tctx->CtbAddrInTS) { qPYA = get_QPY(ctx->img,sps,xQG-1,yQG); } else { qPYA = qPY_PRED; } }
// (8.6.1) void decode_quantization_parameters(decoder_context* ctx, thread_context* tctx, int xC,int yC) { pic_parameter_set* pps = ctx->current_pps; seq_parameter_set* sps = ctx->current_sps; slice_segment_header* shdr = tctx->shdr; // top left pixel position of current quantization group int xQG = xC - (xC & ((1<<pps->Log2MinCuQpDeltaSize)-1)); int yQG = yC - (yC & ((1<<pps->Log2MinCuQpDeltaSize)-1)); // if first QG in CU, remember last QPY of last CU previous QG if ((xQG & ((1<<sps->Log2CtbSizeY)-1)) == 0 && (yQG & ((1<<sps->Log2CtbSizeY)-1)) == 0) { tctx->lastQPYinPreviousQG = tctx->currentQPY; } int qPY_PRED; bool firstQGInSlice; bool firstQGInTile = false; // TODO bool firstInCTBRow = (xC==0); // TODO int first_ctb_in_slice_RS = tctx->shdr->slice_segment_address; int SliceStartX = (first_ctb_in_slice_RS % sps->PicWidthInCtbsY) * sps->CtbSizeY; int SliceStartY = (first_ctb_in_slice_RS / sps->PicWidthInCtbsY) * sps->CtbSizeY; firstQGInSlice = (SliceStartX == xQG && SliceStartY == yQG); if (firstQGInSlice || firstQGInTile || (firstInCTBRow && pps->entropy_coding_sync_enabled_flag)) { qPY_PRED = tctx->shdr->SliceQPY; } else { qPY_PRED = tctx->lastQPYinPreviousQG; } int qPYA,qPYB; if (available_zscan(ctx,xQG,yQG, xQG-1,yQG)) { // unused: int xTmp = (xQG-1) >> sps->Log2MinTrafoSize; // unused: int yTmp = (yQG ) >> sps->Log2MinTrafoSize; // unused: int minTbAddrA = pps->MinTbAddrZS[xTmp + yTmp*sps->PicWidthInTbsY]; // unused: int ctbAddrA = (minTbAddrA>>2)*(sps->Log2CtbSizeY-sps->Log2MinTrafoSize); qPYA = get_QPY(ctx,xQG-1,yQG); } else { qPYA = qPY_PRED; } if (available_zscan(ctx,xQG,yQG, xQG,yQG-1)) { // unused: int xTmp = (xQG ) >> sps->Log2MinTrafoSize; // unused: int yTmp = (yQG-1) >> sps->Log2MinTrafoSize; // unused: int minTbAddrA = pps->MinTbAddrZS[xTmp + yTmp*sps->PicWidthInTbsY]; // unused: int ctbAddrA = (minTbAddrA>>2)*(sps->Log2CtbSizeY-sps->Log2MinTrafoSize); qPYB = get_QPY(ctx,xQG,yQG-1); } else { qPYB = qPY_PRED; } qPY_PRED = (qPYA + qPYB + 1)>>1; int QPY = ((qPY_PRED + shdr->CuQpDelta + 52+2*sps->QpBdOffset_Y) % (52 + sps->QpBdOffset_Y)) - sps->QpBdOffset_Y; tctx->qPYPrime = QPY + sps->QpBdOffset_Y; int qPiCb = Clip3(-sps->QpBdOffset_C,57, QPY+pps->pic_cb_qp_offset + shdr->slice_cb_qp_offset); int qPiCr = Clip3(-sps->QpBdOffset_C,57, QPY+pps->pic_cr_qp_offset + shdr->slice_cr_qp_offset); logtrace(LogTransform,"qPiCb:%d (%d %d), qPiCr:%d (%d %d)\n", qPiCb, pps->pic_cb_qp_offset, shdr->slice_cb_qp_offset, qPiCr, pps->pic_cr_qp_offset, shdr->slice_cr_qp_offset); int qPCb = table8_22(qPiCb); int qPCr = table8_22(qPiCr); tctx->qPCbPrime = qPCb + sps->QpBdOffset_C; tctx->qPCrPrime = qPCr + sps->QpBdOffset_C; set_QPY(ctx,xQG,yQG, QPY); tctx->currentQPY = QPY; logtrace(LogTransform,"qPY(%d,%d)= %d\n",xC,yC,QPY); }