📄 sequence.c
字号:
int rightBound, bottomBound; int xDir, yDir; int mapUnitsInSliceGroup0; int mapUnitVacant; int sizeOfUpperLeftGroup; int iGroup, picSizeInMapUnits; int picWidthInMbs, picHeightInMapUnits; int i, j, k; int *sliceMap; sliceMap = seq->mbData->sliceMap; picWidthInMbs = sps->pic_width_in_mbs_minus1+1; picHeightInMapUnits = sps->pic_height_in_map_units_minus1+1; picSizeInMapUnits = picWidthInMbs * picHeightInMapUnits; if (pps->num_slice_groups_minus1 == 0) { /* Only one slice group */ for (i = 0; i < picSizeInMapUnits; i++) sliceMap[i] = 0; } else { /* There are more than one slice groups in this picture */ switch (pps->slice_group_map_type) { case PS_SLICE_GROUP_MAP_TYPE_INTERLEAVED: 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++) sliceMap[i+j] = iGroup; /* Only the group number */ } } while (i < picSizeInMapUnits); break; case PS_SLICE_GROUP_MAP_TYPE_DISPERSED: for ( i = 0; i < picSizeInMapUnits; i++ ) sliceMap[i] = ( ( i % picWidthInMbs ) + ( ( ( i / picWidthInMbs ) * ( pps->num_slice_groups_minus1 + 1 ) ) / 2 ) ) % ( pps->num_slice_groups_minus1 + 1 ); break; case PS_SLICE_GROUP_MAP_TYPE_FOREGROUND: for (i = 0; i < picSizeInMapUnits; i++) setLower4Bits(sliceMap[i], pps->num_slice_groups_minus1); for (iGroup = pps->num_slice_groups_minus1 - 1; iGroup >= 0; iGroup--) { 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++) sliceMap[y * picWidthInMbs + x] = iGroup; } break; case PS_SLICE_GROUP_MAP_TYPE_CHANGING_3: /* mapUnitsInSliceGroup0 */ mapUnitsInSliceGroup0 = min((int)(slice->slice_group_change_cycle * (pps->slice_group_change_rate_minus1+1)), picSizeInMapUnits); for (i = 0; i < picSizeInMapUnits; i++) sliceMap[i] = 1; // mapUnitToSliceGroupMap[ i ] = 1; x = (picWidthInMbs - pps->slice_group_change_direction_flag) / 2; y = (picHeightInMapUnits - pps->slice_group_change_direction_flag ) / 2; // ( leftBound, topBound ) = ( x, y ) leftBound = x; topBound = y; // ( rightBound, bottomBound ) = ( x, y ) rightBound = x; bottomBound = y; // ( xDir, yDir ) = ( slice_group_change_direction_flag - 1, slice_group_change_direction_flag ) xDir = pps->slice_group_change_direction_flag - 1; yDir = pps->slice_group_change_direction_flag; for (i = 0; i < mapUnitsInSliceGroup0; i += mapUnitVacant) { mapUnitVacant = ( (sliceMap[y * picWidthInMbs + x] & 0xF) == 1); if (mapUnitVacant) setLower4Bits(sliceMap[y * picWidthInMbs + x], 0); if (xDir == -1 && x == leftBound) { leftBound = max(leftBound - 1, 0); x = leftBound; //( xDir, yDir ) = ( 0, 2 * slice_group_change_direction_flag - 1 ) xDir = 0; yDir = 2 * pps->slice_group_change_direction_flag - 1; } else if (xDir == 1 && x == rightBound) { rightBound = min(rightBound + 1, picWidthInMbs - 1); x = rightBound; //( xDir, yDir ) = ( 0, 1 - 2 * slice_group_change_direction_flag ) xDir = 0; yDir = 1 - 2 * pps->slice_group_change_direction_flag; } else if (yDir == -1 && y == topBound) { topBound = max(topBound - 1, 0); y = topBound; //( xDir, yDir ) = ( 1 - 2 * slice_group_change_direction_flag, 0 ) xDir = 1 - 2 * pps->slice_group_change_direction_flag; yDir = 0; } else if (yDir == 1 && y == bottomBound) { bottomBound = min(bottomBound + 1, picHeightInMapUnits - 1); y = bottomBound; //( xDir, yDir ) = ( 2 * slice_group_change_direction_flag - 1, 0 ) xDir = 2 * pps->slice_group_change_direction_flag - 1; yDir = 0; } else { //( x, y ) = ( x + xDir, y + yDir ) x = x + xDir; y = y + yDir; } } break; case PS_SLICE_GROUP_MAP_TYPE_CHANGING_4: /* mapUnitsInSliceGroup0 */ mapUnitsInSliceGroup0 = min((int)(slice->slice_group_change_cycle * (pps->slice_group_change_rate_minus1+1)), picSizeInMapUnits); sizeOfUpperLeftGroup = ( pps->slice_group_change_direction_flag ? ( picSizeInMapUnits - mapUnitsInSliceGroup0 ) : mapUnitsInSliceGroup0 ); for( i = 0; i < picSizeInMapUnits; i++ ) if( i < sizeOfUpperLeftGroup ) sliceMap[ i ] = pps->slice_group_change_direction_flag; else sliceMap[ i ] = 1 - pps->slice_group_change_direction_flag; break; case PS_SLICE_GROUP_MAP_TYPE_CHANGING_5: /* mapUnitsInSliceGroup0 */ mapUnitsInSliceGroup0 = min((int)(slice->slice_group_change_cycle * (pps->slice_group_change_rate_minus1+1)), picSizeInMapUnits); sizeOfUpperLeftGroup = ( pps->slice_group_change_direction_flag ? ( picSizeInMapUnits - mapUnitsInSliceGroup0 ) : mapUnitsInSliceGroup0 ); k = 0; for( j = 0; j < picWidthInMbs; j++ ) for( i = 0; i < picHeightInMapUnits; i++ ) if( k++ < sizeOfUpperLeftGroup ) sliceMap[ i * picWidthInMbs + j ] = pps->slice_group_change_direction_flag; else sliceMap[ i * picWidthInMbs + j ] = 1 - pps->slice_group_change_direction_flag; break; case PS_SLICE_GROUP_MAP_TYPE_EXPLICIT: for (i = 0; i < picSizeInMapUnits; i++) sliceMap[i] = pps->slice_group_id[i]; break; default: break; } }}/* * * isPicBoundary: * * Parameters: * seq Sequence object * * Function: * Check if current slice and next slice belong to different pictures. * * Returns: * 1: slices belong to different pictures (picture boundary detected) * 0: slices belong to the same picture * */static int isPicBoundary(sequence_s *seq){ slice_s *currSlice, *nextSlice; seq_parameter_set_s *prevSps, *currSps; currSlice = seq->currSlice; nextSlice = seq->nextSlice; /* frame_num differs in value. */ if (currSlice->frame_num != nextSlice->frame_num) return 1; /* nal_ref_idc differs in value with one of the nal_ref_idc values being equal to 0. */ if ((currSlice->nalRefIdc != nextSlice->nalRefIdc) && (currSlice->nalRefIdc == 0 || nextSlice->nalRefIdc == 0)) return 1; /* nal_unit_type is equal to 5 for one coded slice NAL unit and */ /* is not equal to 5 in the other coded slice NAL unit */ if ((currSlice->nalType == NAL_TYPE_CODED_SLICE_IDR || nextSlice->nalType == NAL_TYPE_CODED_SLICE_IDR) && (currSlice->nalType != nextSlice->nalType)) return 1; /* nal_unit_type is equal to 5 for both and idr_pic_id differs in value. */ if (currSlice->nalType == NAL_TYPE_CODED_SLICE_IDR && nextSlice->nalType == NAL_TYPE_CODED_SLICE_IDR && (currSlice->idr_pic_id != nextSlice->idr_pic_id)) return 1; prevSps = seq->spsList[seq->ppsList[currSlice->pic_parameter_set_id]->seq_parameter_set_id]; currSps = seq->spsList[seq->ppsList[nextSlice->pic_parameter_set_id]->seq_parameter_set_id]; /* pic_order_cnt_type is equal to 0 for both and */ /* either pic_order_cnt_lsb differs in value, or delta_pic_order_cnt_bottom differs in value. */ if ((prevSps->pic_order_cnt_type == 0 && currSps->pic_order_cnt_type == 0) && ((currSlice->pic_order_cnt_lsb != nextSlice->pic_order_cnt_lsb) || (currSlice->delta_pic_order_cnt_bottom != nextSlice->delta_pic_order_cnt_bottom))) return 1; /* pic_order_cnt_type is equal to 1 for both and */ /* either delta_pic_order_cnt[ 0 ] differs in value, or delta_pic_order_cnt[ 1 ] differs in value. */ if ((prevSps->pic_order_cnt_type == 1 && currSps->pic_order_cnt_type == 1) && ((currSlice->delta_pic_order_cnt_0 != nextSlice->delta_pic_order_cnt_0) || (currSlice->delta_pic_order_cnt_1 != nextSlice->delta_pic_order_cnt_1))) return 1; return 0;}/* * * decodePictureOrderCount: * * Parameters: * seq Sequence object * slice Slice object * sps Sequence parameter set * * Function: * Decode picture order count using syntax elements in slice object. * * Returns: * poc * */static int decodePictureOrderCount(sequence_s* seq, slice_s *slice, seq_parameter_set_s *sps){ int i; int32 maxPocLsb; int32 expectedPicOrderCnt, picOrderCntCycleCnt = 0; int32 expectedDeltaPerPicOrderCntCycle, frameNumInPicOrderCntCycle = 0, absFrameNum; int32 tempPicOrderCnt; int32 poc = 0; /* POC */ if (sps->pic_order_cnt_type == 0) { /* Reset prevPocMsb, prevPocLsb if needed */ if (slice->isIDR || seq->prevPicHasMMCO5) { seq->prevPocMsb = seq->prevPocLsb = 0; } /* PicOrderCntMsb is derived: */ maxPocLsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); if ( (int32)slice->pic_order_cnt_lsb < seq->prevPocLsb && (seq->prevPocLsb - (int32)slice->pic_order_cnt_lsb ) >= (maxPocLsb / 2) ) seq->pocMsb = seq->prevPocMsb + maxPocLsb; else if ( (int32)slice->pic_order_cnt_lsb > seq->prevPocLsb && ((int32)slice->pic_order_cnt_lsb - seq->prevPocLsb) > (maxPocLsb / 2) ) seq->pocMsb = seq->prevPocMsb - maxPocLsb; else seq->pocMsb = seq->prevPocMsb; /* poc */ poc = seq->pocMsb + slice->pic_order_cnt_lsb; } else if (sps->pic_order_cnt_type == 1) { /* Reset prevFrameNumOffset if needed */ if (!slice->isIDR && seq->prevPicHasMMCO5) /* Todo: prevPicHasMMCO5 has not been tested. */ seq->prevFrameNumOffset = 0; /* frameNumOffset is derived as follows: */ if (slice->isIDR) seq->frameNumOffset = 0; else if (seq->prevFrameNum > (int32)slice->frame_num) seq->frameNumOffset = seq->prevFrameNumOffset + slice->maxFrameNum; else seq->frameNumOffset = seq->prevFrameNumOffset; /* absFrameNum is derived as follows: */ if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0) absFrameNum = seq->frameNumOffset + slice->frame_num; else absFrameNum = 0; if (slice->nalRefIdc == 0 && absFrameNum > 0) absFrameNum = absFrameNum - 1; /* When absFrameNum > 0, picOrderCntCycleCnt and frameNumInPicOrderCntCycle are derived as follows */ if (absFrameNum > 0) { picOrderCntCycleCnt = (absFrameNum - 1) / sps->num_ref_frames_in_pic_order_cnt_cycle; frameNumInPicOrderCntCycle = (absFrameNum - 1) % sps->num_ref_frames_in_pic_order_cnt_cycle; } /* expectedDeltaPerPicOrderCntCycle */ expectedDeltaPerPicOrderCntCycle = 0; for (i = 0; i < (int)sps->num_ref_frames_in_pic_order_cnt_cycle; i++) expectedDeltaPerPicOrderCntCycle += sps->offset_for_ref_frame[i]; /* expectedPicOrderCnt */ if (absFrameNum > 0) { expectedPicOrderCnt = picOrderCntCycleCnt * expectedDeltaPerPicOrderCntCycle; for (i = 0; i <= frameNumInPicOrderCntCycle; i++) expectedPicOrderCnt = expectedPicOrderCnt + sps->offset_for_ref_frame[i]; } else expectedPicOrderCnt = 0; if (slice->nalRefIdc == 0) expectedPicOrderCnt = expectedPicOrderCnt + sps->offset_for_non_ref_pic; /* poc */ poc = expectedPicOrderCnt + slice->delta_pic_order_cnt_0; } else if (sps->pic_order_cnt_type == 2) { /* prevFrameNumOffset is derived as follows */ if (!slice->isIDR && seq->prevPicHasMMCO5) seq->prevFrameNumOffset = 0; /* FrameNumOffset is derived as follows. */ if (slice->isIDR) seq->frameNumOffset = 0; else if (seq->prevFrameNum > (int32)slice->frame_num) seq->frameNumOffset = seq->prevFrameNumOffset + slice->maxFrameNum; else seq->frameNumOffset = seq->prevFrameNumOffset; /* tempPicOrderCnt is derived as follows */ if (slice->isIDR) tempPicOrderCnt = 0; else if (slice->nalRefIdc == 0) tempPicOrderCnt = 2 * (seq->frameNumOffset + slice->frame_num) - 1; else tempPicOrderCnt = 2 * (seq->frameNumOffset + slice->frame_num); /* poc */ poc = tempPicOrderCnt; } return poc;}/* * * getOutputPic: * * Parameters: * seq Sequence object * * Function: * Get one output picture. Pictures are output from output queue and * if queue is empty pictures are ouput from dpb. Ouput from dpb can only * happen if sequence is finished (i.e there are not more bits to decode). * * Returns: * 1: output picture is available * 0: output picture is not available */static int getOutputPic(sequence_s *seq, avcdYUVbuffer_s *outBuf){ frmBuf_s *srcBuf; seq_parameter_set_s *sps; /* If no slices have been decoded, there are no pictures available */ if (seq->isFirstSliceOfSeq) return 0; /* Check if there are pictures in output queue */ if (seq->numQueuedOutputPics == 0) { /* Get active sequence parameter set */ sps = seq->spsList[seq->ppsList[seq->currSlice->pic_parameter_set_id]->seq_parameter_set_id]; /* * There are no queued pictures, but we can still output a picture if * at least one of the following conditions is true: * - we have decoded all NAL units * - num_reorder_frames in VUI parameters is zero * - POC type is 2 */ if (seq->isSeqFinished || (sps->vui_parameters_present_flag && sps->vui_parameters.bitstream_restriction_flag && sps->vui_parameters.num_reorder_frames == 0) || sps->pic_order_cnt_type == 2) { int dummy; /* Check if there are pictures in dpb */ srcBuf = dpbGetNextOutputPic(seq->dpb, &dummy); if (!srcBuf) return 0; /* There were no pictures to output */ } else return 0; /* None of the conditions were true */ } else { /* Take next picture from queue. */ srcBuf = seq->outputQueue[seq->outputQueuePos]; seq->numQueuedOutputPics--; if (seq->numQueuedOutputPics == 0) seq->outputQueuePos = 0; else seq->outputQueuePos++; } outBuf->y = srcBuf->y; outBuf->u = srcBuf->u; outBuf->v = srcBuf->v; outBuf->width = srcBuf->width; outBuf->height = srcBuf->height; outBuf->poc = srcBuf->poc; outBuf->isIDR = srcBuf->isIDR; outBuf->idrCnt = srcBuf->idrPicID; outBuf->cropBottomOff = srcBuf->cropBottomOff; outBuf->cropLeftOff = srcBuf->cropLeftOff; outBuf->cropRightOff = srcBuf->cropRightOff; outBuf->cropTopOff = srcBuf->cropTopOff; outBuf->frameRate = srcBuf->frameRate; outBuf->numDecodedBits = 0; srcBuf->forOutput = 0; return 1;}/* * * finishCurrentPic: * * Parameters: * seq Sequence object * * Function: * Finish decoding of current picture. Call loopfilter for the picture * and try to store picture in dpb. Function also updates variables * for previous decoded frame and previous decoded reference frame. * * Returns: * 0 : no frames were output * >0 : the number of frames output * <0 : error */static int finishCurrentPic(sequence_s *seq){ slice_s *slice; frmBuf_s *currPic; int numOutput; int retVal;#ifdef ERROR_CONCEALMENT int blkIdx, numBlks;#endif slice = seq->currSlice; currPic = seq->recoBuf; if (!currPic->nonExisting) { filFilterFrame(currPic, seq->mbData, currPic->width, currPic->height, currPic->chromaQpIndexOffset); } if ((retVal = decRefPicMarking(seq)) < 0) return retVal; /* After the decoding of the current picture and the processing of the */ /* memory management control operations a picture including */ /* a memory_management_control_operation equal to 5 shall be inferred */ /* to have had frame_num equal to 0 for all subsequent use in the decoding */ /* process. */ if (slice->picHasMMCO5) currPic->frameNum = slice->frame_num = 0; /* Try to store current picture to dpb */ numOutput = dpbStorePicture(seq->dpb, currPic, seq->outputQueue); /* If numOutput != 0, picture was not stored */ if (numOutput != 0) { /* numOutput != 0 implies that pictures were output from dpb */ seq->outputQueuePos = 0; seq->numQueuedOutputPics = numOutput; /* Picture was not stored so we have to store it later */ seq->isDpbStorePending = 1; } else seq->isDpbStorePending = 0; seq->prevFrameNum = slice->frame_num; seq->prevFrameNumOffset = seq->frameNumOffset; seq->prevPicHasMMCO5 = slice->picHasMMCO5; /* prevRefFrameNum, prevPocLsb and prevPocMsb for latest reference picture */ if (slice->nalRefIdc != 0) { seq->prevRefFrameNum = slice->frame_num;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -