⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sequence.c

📁 Nokia H.264/AVC Encoder/Decoder Usage Manual
💻 C
📖 第 1 页 / 共 4 页
字号:
  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 + -