Example #1
0
void read_short_term_ref_pic_set(bitreader* br, ref_pic_set* sets, int idxRps, int num_short_term_ref_pic_sets)
{
  char inter_ref_pic_set_prediction_flag=0;

  if (idxRps != 0) {
    inter_ref_pic_set_prediction_flag = get_bits(br,1);
  }

  if (inter_ref_pic_set_prediction_flag) {

    int delta_idx;
    if (idxRps == num_short_term_ref_pic_sets) {
      delta_idx = get_uvlc(br)+1;
    } else {
      delta_idx = 1;
    }

    int RIdx = idxRps - delta_idx;
    assert(RIdx>=0);

    int delta_rps_sign = get_bits(br,1);
    int abs_delta_rps  = get_uvlc(br)+1;
    int DeltaRPS = (delta_rps_sign ? -abs_delta_rps : abs_delta_rps);

    // bits are stored in this order:
    // - all bits for negative Pocs (forward),
    // - then all bits for positive Pocs (forward),
    // - then bits for '0'

    logtrace(LogHeaders,"predicted from %d with delta %d\n",RIdx,DeltaRPS);

    int nDeltaPocsRIdx= sets[RIdx].NumDeltaPocs;
    char *const used_by_curr_pic_flag = (char *)alloca((nDeltaPocsRIdx+1) * sizeof(char));
    char *const use_delta_flag = (char *)alloca((nDeltaPocsRIdx+1) * sizeof(char));

    for (int j=0;j<=nDeltaPocsRIdx;j++) {
      used_by_curr_pic_flag[j] = get_bits(br,1);
      if (!used_by_curr_pic_flag[j]) {
        use_delta_flag[j] = get_bits(br,1);
      } else {
        use_delta_flag[j] = 1;
      }
    }

    logtrace(LogHeaders,"flags: ");
    for (int j=0;j<=nDeltaPocsRIdx;j++) {
      logtrace(LogHeaders,"%d ", use_delta_flag[j]);
    }
    logtrace(LogHeaders,"\n");

    int nNegativeRIdx = sets[RIdx].NumNegativePics;

    // --- update list 0 (negative Poc) ---
    // Iterate through all Pocs in decreasing value order (positive reverse, 0, negative forward).

    int i=0;
    for (int j=sets[RIdx].NumPositivePics-1;j>=0;j--) {
      int dPoc = sets[RIdx].DeltaPocS1[j] + DeltaRPS;
      if (dPoc<0 && use_delta_flag[nNegativeRIdx+j]) {
        sets[idxRps].DeltaPocS0[i] = dPoc;
        sets[idxRps].UsedByCurrPicS0[i] = used_by_curr_pic_flag[nNegativeRIdx+j];
        i++;
      }
    }

    if (DeltaRPS<0 && use_delta_flag[nDeltaPocsRIdx]) {
      sets[idxRps].DeltaPocS0[i] = DeltaRPS;
      sets[idxRps].UsedByCurrPicS0[i] = used_by_curr_pic_flag[nDeltaPocsRIdx];
      i++;
    }

    for (int j=0;j<nNegativeRIdx;j++) {
      int dPoc = sets[RIdx].DeltaPocS0[j] + DeltaRPS;
      if (dPoc<0 && use_delta_flag[j]) {
        sets[idxRps].DeltaPocS0[i] = dPoc;
        sets[idxRps].UsedByCurrPicS0[i] = used_by_curr_pic_flag[j];
        i++;
      }
    }

    sets[idxRps].NumNegativePics = i;


    // --- update list 1 (positive Poc) ---
    // Iterate through all Pocs in increasing value order (negative reverse, 0, positive forward)

    i=0;
    for (int j=sets[RIdx].NumNegativePics-1;j>=0;j--) {
      int dPoc = sets[RIdx].DeltaPocS0[j] + DeltaRPS;
      if (dPoc>0 && use_delta_flag[j]) {
        sets[idxRps].DeltaPocS1[i] = dPoc;
        sets[idxRps].UsedByCurrPicS1[i] = used_by_curr_pic_flag[j];
        i++;
      }
    }

    if (DeltaRPS>0 && use_delta_flag[nDeltaPocsRIdx]) {
      sets[idxRps].DeltaPocS1[i] = DeltaRPS;
      sets[idxRps].UsedByCurrPicS1[i] = used_by_curr_pic_flag[nDeltaPocsRIdx];
      i++;
    }

    for (int j=0;j<sets[RIdx].NumPositivePics;j++) {
      int dPoc = sets[RIdx].DeltaPocS1[j] + DeltaRPS;
      if (dPoc>0 && use_delta_flag[nNegativeRIdx+j]) {
        sets[idxRps].DeltaPocS1[i] = dPoc;
        sets[idxRps].UsedByCurrPicS1[i] = used_by_curr_pic_flag[nNegativeRIdx+j];
        i++;
      }
    }

    sets[idxRps].NumPositivePics = i;

    sets[idxRps].NumDeltaPocs = sets[idxRps].NumNegativePics + sets[idxRps].NumPositivePics;

  } else {
    int num_negative_pics = get_uvlc(br);
    int num_positive_pics = get_uvlc(br);

    assert(num_negative_pics + num_positive_pics <= MAX_NUM_REF_PICS);


    sets[idxRps].NumNegativePics = num_negative_pics;
    sets[idxRps].NumPositivePics = num_positive_pics;
    sets[idxRps].NumDeltaPocs = num_positive_pics + num_negative_pics;

    int lastPocS=0;
    for (int i=0;i<num_negative_pics;i++) {
      int  delta_poc_s0 = get_uvlc(br)+1;
      char used_by_curr_pic_s0_flag = get_bits(br,1);

      logtrace(LogHeaders,"neg: %d %d\n", delta_poc_s0, used_by_curr_pic_s0_flag);

      sets[idxRps].DeltaPocS0[i]      = lastPocS - delta_poc_s0;
      sets[idxRps].UsedByCurrPicS0[i] = used_by_curr_pic_s0_flag;
      lastPocS = sets[idxRps].DeltaPocS0[i];
    }

    lastPocS=0;
    for (int i=0;i<num_positive_pics;i++) {
      int  delta_poc_s1 = get_uvlc(br)+1;
      char used_by_curr_pic_s1_flag = get_bits(br,1);

      logtrace(LogHeaders,"pos: %d %d\n", delta_poc_s1, used_by_curr_pic_s1_flag);

      sets[idxRps].DeltaPocS1[i]      = lastPocS + delta_poc_s1;
      sets[idxRps].UsedByCurrPicS1[i] = used_by_curr_pic_s1_flag;
      lastPocS = sets[idxRps].DeltaPocS1[i];
    }
  }


  compute_NumPoc(&sets[idxRps]);
}
Example #2
0
/* A ref-pic-set is coded either coded
   - as a list of the relative POC deltas themselves, or
   - by shifting an existing ref-pic-set by some number of frames
   When shifting an existing set, the frame 0 is also shifted as an additional reference frame.
   When coding the ref-pic-sets in the SPS, predicition is always from the previous set.
   In the slice header, the ref-pic-set can use any previous set as reference.
 */
bool read_short_term_ref_pic_set(decoder_context* ctx,
                                 const seq_parameter_set* sps,
                                 bitreader* br,
                                 ref_pic_set* out_set, // where to store the read set
                                 int idxRps,  // index of the set to be read
                                 const ref_pic_set* sets, // previously read sets
                                 bool sliceRefPicSet) // is this in the slice header?
{
  // --- is this set coded in prediction mode (not possible for the first set)

  char inter_ref_pic_set_prediction_flag;

  if (idxRps != 0) {
    inter_ref_pic_set_prediction_flag = get_bits(br,1);
  }
  else {
    inter_ref_pic_set_prediction_flag = 0;
  }



  if (inter_ref_pic_set_prediction_flag) {
    int vlc;

    /* Only for the last ref_pic_set (that's the one coded in the slice header),
       we can specify relative to which reference set we code the set. */

    int delta_idx;
    if (sliceRefPicSet) { // idxRps == num_short_term_ref_pic_sets) {
      delta_idx = vlc = get_uvlc(br);
      delta_idx++;
    } else {
      delta_idx = 1;
    }

    int RIdx = idxRps - delta_idx; // this is our source set, which we will modify
    assert(RIdx>=0);

    int delta_rps_sign = get_bits(br,1);
    int abs_delta_rps  = vlc = get_uvlc(br);
    abs_delta_rps++;
    int DeltaRPS = (delta_rps_sign ? -abs_delta_rps : abs_delta_rps);

    // bits are stored in this order:
    // - all bits for negative Pocs (forward),
    // - then all bits for positive Pocs (forward),
    // - then bits for '0', shifting of the current picture
    // in total, these are 'nDeltaPocsRIdx'+1 bits

    logtrace(LogHeaders,"predicted from %d with delta %d\n",RIdx,DeltaRPS);

    int nDeltaPocsRIdx= sets[RIdx].NumDeltaPocs; // size of source set
    char *const used_by_curr_pic_flag = (char *)alloca((nDeltaPocsRIdx+1) * sizeof(char));
    char *const use_delta_flag = (char *)alloca((nDeltaPocsRIdx+1) * sizeof(char));

    for (int j=0;j<=nDeltaPocsRIdx;j++) {
      used_by_curr_pic_flag[j] = get_bits(br,1);
      if (used_by_curr_pic_flag[j]) {
        use_delta_flag[j] = 1;  // if this frame is used, we also have to apply the delta
      } else {
        use_delta_flag[j] = get_bits(br,1);  // otherwise, it is only optionally included
      }
    }

    logtrace(LogHeaders,"flags: ");
    for (int j=0;j<=nDeltaPocsRIdx;j++) {
      logtrace(LogHeaders,"%d ", use_delta_flag[j]);
    }
    logtrace(LogHeaders,"\n");

    int nNegativeRIdx = sets[RIdx].NumNegativePics;
    int nPositiveRIdx = sets[RIdx].NumPositivePics;

    // --- update list 0 (negative Poc) ---
    // Iterate through all Pocs in decreasing value order (positive reverse, 0, negative forward).

    int i=0; // target index

    // positive list
    for (int j=nPositiveRIdx-1;j>=0;j--) {
      int dPoc = sets[RIdx].DeltaPocS1[j] + DeltaRPS; // new delta
      if (dPoc<0 && use_delta_flag[nNegativeRIdx+j]) {
        out_set->DeltaPocS0[i] = dPoc;
        out_set->UsedByCurrPicS0[i] = used_by_curr_pic_flag[nNegativeRIdx+j];
        i++;
      }
    }

    // frame 0
    if (DeltaRPS<0 && use_delta_flag[nDeltaPocsRIdx]) {
      out_set->DeltaPocS0[i] = DeltaRPS;
      out_set->UsedByCurrPicS0[i] = used_by_curr_pic_flag[nDeltaPocsRIdx];
      i++;
    }

    // negative list
    for (int j=0;j<nNegativeRIdx;j++) {
      int dPoc = sets[RIdx].DeltaPocS0[j] + DeltaRPS;
      if (dPoc<0 && use_delta_flag[j]) {
        out_set->DeltaPocS0[i] = dPoc;
        out_set->UsedByCurrPicS0[i] = used_by_curr_pic_flag[j];
        i++;
      }
    }

    out_set->NumNegativePics = i;


    // --- update list 1 (positive Poc) ---
    // Iterate through all Pocs in increasing value order (negative reverse, 0, positive forward)

    i=0; // target index

    // negative list
    for (int j=nNegativeRIdx-1;j>=0;j--) {
      int dPoc = sets[RIdx].DeltaPocS0[j] + DeltaRPS;
      if (dPoc>0 && use_delta_flag[j]) {
        out_set->DeltaPocS1[i] = dPoc;
        out_set->UsedByCurrPicS1[i] = used_by_curr_pic_flag[j];
        i++;
      }
    }

    // frame 0
    if (DeltaRPS>0 && use_delta_flag[nDeltaPocsRIdx]) {
      out_set->DeltaPocS1[i] = DeltaRPS;
      out_set->UsedByCurrPicS1[i] = used_by_curr_pic_flag[nDeltaPocsRIdx];
      i++;
    }

    // positive list
    for (int j=0;j<nPositiveRIdx;j++) {
      int dPoc = sets[RIdx].DeltaPocS1[j] + DeltaRPS;
      if (dPoc>0 && use_delta_flag[nNegativeRIdx+j]) {
        out_set->DeltaPocS1[i] = dPoc;
        out_set->UsedByCurrPicS1[i] = used_by_curr_pic_flag[nNegativeRIdx+j];
        i++;
      }
    }

    out_set->NumPositivePics = i;

    out_set->NumDeltaPocs = out_set->NumNegativePics + out_set->NumPositivePics;

  } else {

    // --- first, read the number of past and future frames in this set ---

    int num_negative_pics = get_uvlc(br);
    int num_positive_pics = get_uvlc(br);

    // total number of reference pictures may not exceed buffer capacity
    if (num_negative_pics + num_positive_pics >
        sps->sps_max_dec_pic_buffering[ sps->sps_max_sub_layers-1 ]) {
      add_warning(ctx, DE265_WARNING_MAX_NUM_REF_PICS_EXCEEDED, false);
      return false;
    }


    out_set->NumNegativePics = num_negative_pics;
    out_set->NumPositivePics = num_positive_pics;
    out_set->NumDeltaPocs = num_positive_pics + num_negative_pics;


    // --- now, read the deltas between the reference frames to fill the lists ---

    // past frames

    int lastPocS=0;
    for (int i=0;i<num_negative_pics;i++) {
      int  delta_poc_s0 = get_uvlc(br)+1;
      char used_by_curr_pic_s0_flag = get_bits(br,1);

      out_set->DeltaPocS0[i]      = lastPocS - delta_poc_s0;
      out_set->UsedByCurrPicS0[i] = used_by_curr_pic_s0_flag;
      lastPocS = out_set->DeltaPocS0[i];
    }

    // future frames

    lastPocS=0;
    for (int i=0;i<num_positive_pics;i++) {
      int  delta_poc_s1 = get_uvlc(br)+1;
      char used_by_curr_pic_s1_flag = get_bits(br,1);

      out_set->DeltaPocS1[i]      = lastPocS + delta_poc_s1;
      out_set->UsedByCurrPicS1[i] = used_by_curr_pic_s1_flag;
      lastPocS = out_set->DeltaPocS1[i];
    }
  }


  compute_NumPoc(out_set);

  return true;
}