📄 slice.c
字号:
mapUnitsInSliceGroup0 = slice->sliceGroupChangeCycle * (pps->slice_group_change_rate_minus1 + 1); mapUnitsInSliceGroup0 = min(mapUnitsInSliceGroup0, picSizeInMapUnits); switch (pps->slice_group_map_type) { /* type 0, 1 can be moved to the function activating parameter set. */ case SLICE_MAP_INTERLEAVED: // the parameters should not violate the frame constraints i = 0; do { for (iGroup = 0; iGroup <= (int)pps->num_slice_groups_minus1 && i < picSizeInMapUnits; i += pps->run_length_minus1[iGroup++] + 1) { for (j = 0; j <= (int)pps->run_length_minus1[iGroup] && i+j < picSizeInMapUnits; j++) pMbStateArr[i+j].sliceMap |= iGroup; /* Only the group number */ } } while (i < picSizeInMapUnits); break; case SLICE_MAP_DISPERSED: { int numGroups, offset; numGroups = pps->num_slice_groups_minus1 + 1; for (i = 0; i < picSizeInMapUnits; i ++) { // offset makes an even row start with group 0, // an odd row start with group "numGroups/2" offset = ((i/picWidthInMbs) * numGroups)/2; pMbStateArr[i].sliceMap = (int16) (((i % picWidthInMbs) + offset) % numGroups); } } break; case SLICE_MAP_FOREGROUND: // background, with the largest ground ID for (i = 0; i < picSizeInMapUnits; i++) pMbStateArr[i].sliceMap = (int16) pps->num_slice_groups_minus1; // foreground, rectangles can overlap // overlapping area will be in the group with the smallest ID for (iGroup = pps->num_slice_groups_minus1 - 1; iGroup >= 0; iGroup--) { int xTopLeft, yTopLeft, xBottomRight, yBottomRight; yTopLeft = pps->top_left[iGroup] / picWidthInMbs; xTopLeft = pps->top_left[iGroup] % picWidthInMbs; yBottomRight = pps->bottom_right[iGroup] / picWidthInMbs; xBottomRight = pps->bottom_right[iGroup] % picWidthInMbs; for (y = yTopLeft; y <= yBottomRight; y++) for (x = xTopLeft; x <= xBottomRight; x++) pMbStateArr[y * picWidthInMbs + x].sliceMap = (int16) iGroup; } break; case SLICE_MAP_BOX_OUT: { int leftBound, topBound, rightBound, bottomBound; int xDir, yDir; int mapUnitVacant; for (i = 0; i < picSizeInMapUnits; i++) pMbStateArr[i].sliceMap = 1; x = (picWidthInMbs - pps->slice_group_change_direction_flag)/2; y = (picHeightInMapUnits - pps->slice_group_change_direction_flag)/2; leftBound = x; topBound = y; rightBound = x; bottomBound = y; xDir = pps->slice_group_change_direction_flag - 1; yDir = pps->slice_group_change_direction_flag; for (i = 0; i < mapUnitsInSliceGroup0; i += mapUnitVacant) { mapUnitVacant = (pMbStateArr[y * picWidthInMbs + x].sliceMap == 1); if (mapUnitVacant) pMbStateArr[y * picWidthInMbs + x].sliceMap = 0; if (xDir == -1 && x == leftBound) { // reach left bound, shift one step left, then move vertically leftBound = max(leftBound - 1, 0); x = leftBound; xDir = 0; // move up if direction_flag is 0, otherwise move down yDir = 2 * pps->slice_group_change_direction_flag - 1; } else if (xDir == 1 && x == rightBound) { // reach right bound, shift one step right, then move vertically rightBound = min(rightBound + 1, picWidthInMbs - 1); x = rightBound; xDir = 0; // move down if direction_flag is 0, otherwise move up yDir = 1 - 2 * pps->slice_group_change_direction_flag; } else if (yDir == -1 && y == topBound) { // reach top bound, shift one step up, then move horizontally topBound = max(topBound - 1, 0); y = topBound; // move to right if direction_flag is 0, otherwise move to left xDir = 1 - 2 * pps->slice_group_change_direction_flag; yDir = 0; } else if (yDir == 1 && y == bottomBound) { // reach bottom bound, shift one step down, then move horizontally bottomBound = min(bottomBound + 1, picHeightInMapUnits - 1); y = bottomBound; // move to left if direction_flag is 0, otherwise move to right xDir = 2 * pps->slice_group_change_direction_flag - 1; yDir = 0; } else { // just move according to pre-determined direction x = x + xDir; y = y + yDir; } } } break; case SLICE_MAP_RASTER: case SLICE_MAP_WIPE: sizeOfUpperLeftGroup = pps->slice_group_change_direction_flag ? (picSizeInMapUnits - mapUnitsInSliceGroup0) : mapUnitsInSliceGroup0; iGroup = pps->slice_group_change_direction_flag; if (pps->slice_group_map_type == SLICE_MAP_RASTER) { for (i = 0; i < picSizeInMapUnits; i ++) { if (i >= sizeOfUpperLeftGroup) // change to another slice group iGroup = 1 - pps->slice_group_change_direction_flag; pMbStateArr[i].sliceMap = (int16) iGroup; } } else { k = 0; for (j = 0; j < picWidthInMbs; j ++) for (i = 0; i < picHeightInMapUnits; i ++) { if( k ++ >= sizeOfUpperLeftGroup ) // change to another slice group iGroup = 1 - pps->slice_group_change_direction_flag; pMbStateArr[i * picWidthInMbs + j].sliceMap = (int16) iGroup; } } break; case SLICE_MAP_BITMAP: for (i = 0; i < picSizeInMapUnits; i++) pMbStateArr[i].sliceMap = pps->slice_group_id[i]; break; default: break; } }}/* * sliceEncode * * Parameters: * slice SLice object * sliceIdxInGroup Index of this slice within a slice group * sps Sequence parameter set * pps Picture parameter set * pBrc pointer to bit rate control engine, * * Function: * Encode one slice * * Returns: * 0 This is not the last slice in the current frame * 1 This is the last slice in the current slice group of the current frame */int sliceEncode(slice_s *slice, int sliceIdxInGroup, dpbBuf_s *dpbBuf, encParams_s *encPar, int tuneFactor, int *mapRIR, seq_parameter_set_s *sps, pic_parameter_set_s *pps, int forcedIRNo, int *forcedIR, rateCtrl_s *pbRC){ int numBits; int sliceDataStartBits; int sliceStartBits, maxSliceSize; int maxMbsPerSlice; int mbNum, numIntraMbs; macroblock_s *mb; meProfile_s *pMeProf; refFrmBuf_s **refFrmBufs; /* Interface for MB layer. */ mbState_s *mbStateArr; void *stream; int numRefFrms; int nextSliceAddr; int temp_header= 0; int temp_texture = 0; mbStateArr = slice->mbStateArr; mb = & slice->mb; pMeProf = & slice->meProfile; sliceStartBits = bibGetNumBits(slice->bitbuf); sliceDataStartBits = sliceStartBits; // just to avoid compiler complaint dpbRefListNormalOrder(dpbBuf); // Reference picture list (Interface for MB layer) refFrmBufs = dpbBuf->refPicList0; // setup the motion estimation profile if (IS_SLICE_P(slice->sliceType)) mesPrepareProfile(pMeProf, refFrmBufs[0], encPar, dpbBuf->numRefFrms); // if nBytesPerSlice is 0, no fixed length slices, set the size to max maxSliceSize = (encPar->nBytesPerSlice == 0) ? INT_MAX : 8 * (encPar->nBytesPerSlice - 4); // If nMbsPerSlice is 0, set number of mbs per slice to max maxMbsPerSlice = (encPar->nMbsPerSlice == 0) ? INT_MAX : encPar->nMbsPerSlice; // Initialize macroblock before the slice is encoded mbkBeforeSlice(mb, slice->qp); stream = slice->bitbuf; // in the first run, the best frame order will be found numIntraMbs = 0; // perform the reordering of the reference frame pointers numRefFrms = dpbBuf->numRefFrms; slice->frmStat->bitsHdr += startSlice(slice, encPar, slice->firstMbAddr, dpbBuf, sps, pps, & slice->frmStat->bitsNAL); sliceDataStartBits = bibGetNumBits(slice->bitbuf); // Scan through all macroblocks in slice nextSliceAddr = slice->firstMbAddr; mbNum = 0; do { mbState_s *pMbState; // setup the address of the current macroblock mb->mbAddr = nextSliceAddr; mb->idxX = nextSliceAddr % slice->mbksPerLine; mb->idxY = nextSliceAddr / slice->mbksPerLine; // look for the next MB in the same slice group do { nextSliceAddr ++; } while (nextSliceAddr < slice->picSizeInMbs && (mbStateArr[nextSliceAddr].sliceMap & 0xF) != slice->groupId); // if next MB is available, nextSliceAddr should be within the frame mb->isLastMb = (nextSliceAddr == slice->picSizeInMbs) || (mbNum+1 == maxMbsPerSlice); // Perform bit-rate control numBits = bibGetNumBits(slice->bitbuf); if(pbRC->bit_rate != 0) { temp_header = slice->frmStat->bitsNAL + slice->frmStat->bitsHdr + slice->frmStat->bitsSkipLen + slice->frmStat->bitsMBtype + slice->frmStat->bitsPred + slice->frmStat->bitsVec + slice->frmStat->bitsCBP; temp_texture = slice->frmStat->bitsCoefLumaDC + slice->frmStat->bitsCoefLuma + slice->frmStat->bitsCoefChromaDC + slice->frmStat->bitsCoefChroma + slice->frmStat->bitsArithmeticStream ; } // this is to collect the statistics mbkStartEnc(mb, slice->mbStateArr, slice->origBuf, slice->recoBuf, encPar, slice->qp, tuneFactor); // mbAddr is calculated in mbkStartEnc pMbState = & mbStateArr[mb->mbAddr]; // differentiate slices within the same slice group pMbState->sliceMap |= sliceIdxInGroup << 4; // Put loopfilter mode pMbState->filterMode = (char) encPar->filterMode; pMbState->alphaOffset = (char) encPar->alphaOffset; pMbState->betaOffset = (char) encPar->betaOffset; mbkModeSelection(pbRC,mb, pMeProf, refFrmBufs, numRefFrms, slice->sliceType, encPar, mapRIR, slice->recoBuf->channelDistortion, forcedIRNo, forcedIR, mb->idxY*encPar->picWidth/MBK_SIZE+mb->idxX); slice->qp = (short) mb->qp; //printf("%d ",slice->qp); // otherwise (temporary), intra-4x4 was fully processed, using nominal qp mbkProcessData(mb, slice->sliceType, encPar); // VLC coding of macroblock mbkSend(stream, mb, numRefFrms, slice->sliceType, slice->frmStat); numBits = bibGetNumBits(slice->bitbuf); if ((numBits - sliceStartBits) >= maxSliceSize) mb->isLastMb = 1; // some bookkeeping at the end of encoding mbkFinishEnc(mb, slice->frmStat); if (mb->type == MBK_INTRA) numIntraMbs ++; if (mb->type == MBK_INTRA) pbRC->numIntraMBs++; if(pbRC->bit_rate != 0) { temp_header = slice->frmStat->bitsNAL + slice->frmStat->bitsHdr + slice->frmStat->bitsSkipLen + slice->frmStat->bitsMBtype + slice->frmStat->bitsPred + slice->frmStat->bitsVec + slice->frmStat->bitsCBP - temp_header; temp_texture = slice->frmStat->bitsCoefLumaDC + slice->frmStat->bitsCoefLuma + slice->frmStat->bitsCoefChromaDC + slice->frmStat->bitsCoefChroma + slice->frmStat->bitsArithmeticStream - temp_texture; rc_updateMB(pbRC,temp_texture,temp_header,mb,mb->idxY*encPar->picWidth / MBK_SIZE+mb->idxX); } mbNum++; } while (!mb->isLastMb); // Check if skip flag needs to be sent at the end of slice if (encPar->entropyEncoder == ENTROPY_CAVLC && IS_SLICE_P(slice->sliceType) && mb->numSkipped > 0) streamSendMbSkipFlag(stream, mb, 0); // end the slice by sending the trailing bits slice->frmStat->bitsHdr += bibTrailingBits(slice->bitbuf); return numIntraMbs;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -