📄 sequence.c
字号:
seq->prevPocLsb = slice->pic_order_cnt_lsb; seq->prevPocMsb = seq->pocMsb; }#ifdef ERROR_CONCEALMENT numBlks = currPic->width*currPic->height/(BLK_SIZE*BLK_SIZE); /* clear the flags for error concealment! */ for (blkIdx = 0; blkIdx < numBlks; blkIdx++) { seq->mbData->motVecTable[blkIdx].x = 0; seq->mbData->motVecTable[blkIdx].y = 0; seq->mbData->refIdxTable[blkIdx] = -1; }#endif return numOutput;}/* * * generateNonExistingFrames: * * Parameters: * seq Sequence object * * Function: * Generate non-existing frame for each unused frame number between * two closest existing frames in decoding order. Generated frames * are stored to dpb in finishCurrentPic function. * * Returns: * 0 : no frames were output * >0 : the number of frames output * <0 : error */static int generateNonExistingFrames(sequence_s *seq){ slice_s *slice; frmBuf_s *currPic; int32 nextFrameNum; int numOutput; slice = seq->currSlice; currPic = seq->recoBuf; slice->picHasMMCO5 = 0; slice->isIDR = 0; slice->adaptive_ref_pic_marking_mode_flag = 0; slice->nalType = NAL_TYPE_CODED_SLICE; slice->nalRefIdc = 1; currPic->forOutput = 0; currPic->nonExisting = 1; do { slice->frame_num = seq->unusedShortTermFrameNum; dpbUpdatePicNums(seq->dpb, slice->frame_num, slice->maxFrameNum); numOutput = finishCurrentPic(seq); nextFrameNum = (seq->unusedShortTermFrameNum + 1) % seq->nextSlice->maxFrameNum; if (nextFrameNum == (int)seq->nextSlice->frame_num) seq->unusedShortTermFrameNum = -1; else seq->unusedShortTermFrameNum = nextFrameNum; } while (numOutput == 0 && seq->unusedShortTermFrameNum >= 0); return numOutput;}/* * * initializeCurrentPicture: * * Parameters: * seq Sequence object * sps Active sequence parameter set * pps Active picture parameter set * width Picture width * height Picture height * * Function: * Current frame and dpb are initialized according to active * parameter sets. * * Returns: * SEQ_OK for no error, negative value for error */static int initializeCurrentPicture(sequence_s *seq, seq_parameter_set_s *sps, pic_parameter_set_s *pps, int width, int height){ frmBuf_s *currPic; slice_s *slice; int i;#ifdef CHECK_MV_RANGE if (sps->level_idc <= 10) maxVerticalMvRange = 64; else if (sps->level_idc <= 20) maxVerticalMvRange = 128; else if (sps->level_idc <= 30) maxVerticalMvRange = 256; else maxVerticalMvRange = 512;#endif currPic = seq->recoBuf; slice = seq->currSlice; if (slice->isIDR) { /* * (Re)initialize frame buffer for current picture if picture size has changed */ if (!currPic || width != currPic->width || height != currPic->height) { frmClose(currPic, seq->mbData); if ((currPic = frmOpen(&seq->mbData, width, height)) == NULL) return SEQ_ERR_MEM; seq->recoBuf = currPic;#ifdef ERROR_CONCEALMENT /* (Re)initialize the error concealment procedure if picture size has changed */ ercClose(seq->errConcealment); if ((seq->errConcealment = ercOpen(width/MBK_SIZE, height/MBK_SIZE)) == NULL) return SEQ_ERR_MEM;#endif } } for (i = 0; i < MAX_SLICE_GROUP_NUM; i++) seq->sliceNums[i] = 0; /* Build slice group map */ buildSliceGroups(seq, slice, sps, pps); /* By default picture will be output */ currPic->forOutput = 1; currPic->nonExisting = 0; currPic->isIDR = slice->isIDR; if (sps->frame_cropping_flag) { currPic->cropLeftOff = sps->frame_crop_left_offset; currPic->cropRightOff = sps->frame_crop_right_offset; currPic->cropTopOff = sps->frame_crop_top_offset; currPic->cropBottomOff = sps->frame_crop_bottom_offset; } else { currPic->cropLeftOff = 0; currPic->cropRightOff = 0; currPic->cropTopOff = 0; currPic->cropBottomOff = 0; } if (sps->vui_parameters_present_flag && sps->vui_parameters.timing_info_present_flag && sps->vui_parameters.num_units_in_tick != 0) currPic->frameRate = (float)(0.5 * (float)sps->vui_parameters.time_scale/(float)sps->vui_parameters.num_units_in_tick); else currPic->frameRate = 0.0; /* Get poc for current picture */ currPic->poc = decodePictureOrderCount(seq, slice, sps); /* Set chroma qp index offset */ currPic->chromaQpIndexOffset = pps->chroma_qp_index_offset;#ifdef ERROR_CONCEALMENT /* By default, this is not a scene cut picture */ currPic->sceneCut = 0;#endif return SEQ_OK;}#ifdef ERROR_CONCEALMENT/* * * setSceneCutFlag: * * Parameters: * seq Sequence object * * Function: * Tell if current picture is a scene cut picture or not. * * Returns: * - */static void setSceneCutFlag(sequence_s *seq){ seq->errConcealment->hasSceneInfo = seq->hasSceneInfo; /* Scene info messages are available, and there is newly decoded scene info SEI */ if (seq->hasSceneInfo && seq->sceneInfoDecoded) { seq->sceneInfoDecoded = 0; if (seq->prevSceneInfo->sceneId != seq->currSceneInfo->sceneId || seq->prevSceneInfo->sceneTransitionType != seq->currSceneInfo->sceneTransitionType ) seq->recoBuf->sceneCut = 1; }}#endif/* * * decodeSliceData: * * Parameters: * seq Sequence object * * Function: * Decode slice data of the current slice. Before decoding slice data, * current frame and dpb are initialized according to active * parameter sets. * * Returns: * SEQ_OK for no error, negative value for error */static int decodeSliceData(sequence_s *seq){ slice_s *slice; pic_parameter_set_s *pps; seq_parameter_set_s *sps; int width, height; const level_s *level; int dpbSize; int sliceGroupNum, sliceID; int retCode; /* New slice becomes current slice */ slice = seq->nextSlice; seq->nextSlice = seq->currSlice; seq->currSlice = slice; /* Get current parameter sets */ pps = seq->ppsList[slice->pic_parameter_set_id]; sps = seq->spsList[pps->seq_parameter_set_id]; /* Get picture size */ width = (sps->pic_width_in_mbs_minus1+1)*16; height = (sps->pic_height_in_map_units_minus1+1)*16; /* If this is the first slice of a picture, initialize picture */ if (seq->isFirstSliceOfSeq || seq->isPicBoundary) { if (slice->isIDR) { /* * Set dpb according to level */ level = getLevel(sps->level_idc); dpbSize = level->maxDPB/((int32)width*height*3/2); if (sps->vui_parameters_present_flag && sps->vui_parameters.bitstream_restriction_flag) dpbSize = min((unsigned)dpbSize, sps->vui_parameters.max_dec_frame_buffering); dpbSetSize(seq->dpb, dpbSize); seq->dpb->maxNumRefFrames = sps->num_ref_frames; } retCode = initializeCurrentPicture(seq, sps, pps, width, height); if (retCode < 0) return retCode;#ifdef ERROR_CONCEALMENT /* Reset error concealment */ ercClear(seq->errConcealment); /* Set the scene cut flag if scene info SEIs are available */ setSceneCutFlag(seq); if (seq->isFirstSliceOfSeq) seq->errConcealment->isFirstPicOfSeq = 1; else seq->errConcealment->isFirstPicOfSeq = 0; seq->errConcealment->alg = seq->ecAlg;#endif } /* Compute picture numbers for all reference frames */ if (!slice->isIDR) dpbUpdatePicNums(seq->dpb, slice->frame_num, slice->maxFrameNum); /* Get slice group number if there are more than 1 slice groups */ if (pps->num_slice_groups_minus1 == 0) sliceGroupNum = 0; else sliceGroupNum = seq->mbData->sliceMap[slice->first_mb_in_slice] & 0xF; /* Increment slice number for current slice group (slice numbers start from 1) */ seq->sliceNums[sliceGroupNum]++; /* sliceID for current slice */ sliceID = seq->sliceNums[sliceGroupNum]*16 | sliceGroupNum; /* * Go decode slice data */ retCode = sliceDecodeMacroblocks(slice, seq->recoBuf, seq->dpb,#ifdef ERROR_CONCEALMENT seq->errConcealment,#endif pps, seq->mbData, sliceID, seq->bitbuf); /* Update sequence variables */ seq->isFirstSliceOfSeq = 0; seq->isPicBoundary = 0; seq->isSliceDataDecodePending = 0; if (retCode < 0) return SEQ_ERROR; else return SEQ_OK;}#ifdef ERROR_CONCEALMENT/* * * concealFrames: * * Parameters: * seq Sequence object * * Function: * Try to recover an entirely lost picture. Compared to partly * corrupted picture, additional tasks have to be done to set * proper flags for the lost pictures. * * Returns: * 0 : no frames were output * >0 : the number of frames output * <0 : error * */static int concealFrames(sequence_s *seq){ slice_s *slice; frmBuf_s *currPic; int nextFrameNum; int numOutput; pic_parameter_set_s *pps; ercClear(seq->errConcealment); slice = seq->currSlice; currPic = seq->recoBuf; slice->picHasMMCO5 = 0; slice->isIDR = 0; slice->adaptive_ref_pic_marking_mode_flag = 0; slice->nalType = NAL_TYPE_CODED_SLICE; slice->nalRefIdc = 1; /* * Set the currPic->forOutput to 0 for the time being. The wholly lost pictures will not * be outputted by the video decoder. */ currPic->forOutput = 0; currPic->nonExisting = 1; pps = seq->ppsList[slice->pic_parameter_set_id]; do { slice->frame_num = seq->unusedShortTermFrameNum; deb1f(stderr, "Concealing frame num: %d\n", slice->frame_num); currPic->poc = 0; dpbUpdatePicNums(seq->dpb, slice->frame_num, slice->maxFrameNum); ercConcealWholePic(seq->errConcealment, seq->recoBuf, seq->mbData, seq->dpb); numOutput = finishCurrentPic(seq); nextFrameNum = (seq->unusedShortTermFrameNum + 1) % seq->nextSlice->maxFrameNum; if (nextFrameNum == (int)seq->nextSlice->frame_num) seq->unusedShortTermFrameNum = -1; else seq->unusedShortTermFrameNum = nextFrameNum; } while (numOutput == 0 && seq->unusedShortTermFrameNum >= 0); return numOutput;}#endif/* * * decodeSlice: * * Parameters: * seq Sequence object * nalType Type of nal unit * nalRefIdc Nal unit reference indicator * * Function: * Start decoding slice. Decode slice header and also * decode slice data if picture boundary is not detected. If * picture boundary is detected, current picture is finished and an * attempt is made to store it in the dpb. Possible gap * in frame numbers is detected and handled (by generating * non-existing frames). * * Returns: * SEQ_OK for ok, negative value for error */static int decodeSlice(sequence_s *seq, int nalType, int nalRefIdc){ slice_s *slice; int32 nextFrameNum; int numOutput; int retCode;#ifndef DECODE_ACCESS_UNITS pic_parameter_set_s *pps;#endif slice = seq->nextSlice; slice->nalType = nalType; slice->nalRefIdc = nalRefIdc; slice->isIDR = (nalType == NAL_TYPE_CODED_SLICE_IDR); retCode = sliceGetHeader(slice, seq->spsList, seq->ppsList, seq->bitbuf); if (retCode < 0) return SEQ_ERROR; /* Check if next slice belongs to next picture */ if (seq->isFirstSliceOfSeq) seq->isPicBoundary = 0; else seq->isPicBoundary = isPicBoundary(seq); if (!seq->isPicBoundary) { /* There is no picture boundary -> Decode new slice */ return decodeSliceData(seq); } else { /* Picture boundary reached. */#ifndef DECODE_ACCESS_UNITS pps = seq->ppsList[slice->pic_parameter_set_id];#ifdef ERROR_CONCEALMENT ercCheckAndConceal(seq->errConcealment, seq->recoBuf, seq->mbData, seq->dpb, pps);#endif /* Finish decoding of current picture */ numOutput = finishCurrentPic(seq); /* numOutput is the number of pictures in output queue */ /* If numOutput < 0, error occured */ if (numOutput < 0) return numOutput;#else numOutput = 0;#endif /* Compute expected next frame number */ nextFrameNum = (seq->prevRefFrameNum + 1) % slice->maxFrameNum; /* Check if there is a gap in frame numbers */ if (!slice->isIDR && (int)slice->frame_num != seq->prevRefFrameNum && (int)slice->frame_num != nextFrameNum) {#ifdef ERROR_CONCEALMENT /* Check if gaps in frame numbers are allowed */ if (!seq->spsList[seq->ppsList[slice->pic_parameter_set_id]->seq_parameter_set_id]->gaps_in_frame_num_value_allowed_flag) { /* * Start concealing the lost pictures */ deb1f(stderr, "Lost before frame num: %d\n", slice->frame_num);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -