/*!
************************************************************************
* \brief
*    Encode Enhancement Layer.
************************************************************************
*/
void encode_enhancement_layer()
{
  //int previous_ref_idc = 1;

  if ((params->successive_Bframe != 0) && (IMG_NUMBER > 0) && (params->EnableIDRGOP == 0 || img->idr_gop_number)) // B-frame(s) to encode
  {
    set_slice_type( ( params->PReplaceBSlice ) ? P_SLICE : B_SLICE); // set slice type
    img->layer = (params->NumFramesInELSubSeq == 0) ? 0 : 1;
    img->nal_reference_idc = NALU_PRIORITY_DISPOSABLE;

    if (params->HierarchicalCoding)
    {
      for(img->b_frame_to_code = 1; img->b_frame_to_code <= params->successive_Bframe; img->b_frame_to_code++)
      {
        img->nal_reference_idc = NALU_PRIORITY_DISPOSABLE;
        set_slice_type( gop_structure[img->b_frame_to_code - 1].slice_type);

        if (img->last_ref_idc == 1)
        {
          img->frame_num++;                 //increment frame_num for each stored B slice
          img->frame_num %= max_frame_num;
        }
        
        img->nal_reference_idc = gop_structure[img->b_frame_to_code - 1].reference_idc;
        img->b_interval = ((double) (params->jumpd + 1) / (params->successive_Bframe + 1.0) );

        if (params->HierarchicalCoding == 3)
          img->b_interval = 1.0;

        if (IMG_NUMBER && (IMG_NUMBER <= params->intra_delay))
        {
          if(params->idr_period && ((!params->adaptive_idr_period && ( img->frm_number - img->lastIDRnumber ) % params->idr_period == 0)
            || (params->adaptive_idr_period == 1 && ( img->frm_number - imax(img->lastIntraNumber, img->lastIDRnumber) ) % params->idr_period == 0)) )
            img->toppoc = (int)(img->b_interval * (double)(1 + gop_structure[img->b_frame_to_code - 1].display_no));
          else
            img->toppoc = 2*((-img->frm_number + img->lastIDRnumber)*(params->jumpd + 1) 
            + (int)(img->b_interval * (double)(1 + gop_structure[img->b_frame_to_code -1].display_no)));

          if (img->b_frame_to_code == 1)
            img->delta_pic_order_cnt[0] = img->toppoc - 2*(start_tr_in_this_IGOP  + (params->intra_delay - IMG_NUMBER)*((params->jumpd + 1)));
          else
            img->delta_pic_order_cnt[0] = img->toppoc - 2*(start_tr_in_this_IGOP  + (params->intra_delay - IMG_NUMBER)*((params->jumpd + 1)) 
            + (int) (2.0 *img->b_interval * (double) (1 + gop_structure[img->b_frame_to_code - 2].display_no)));
        }
        else
        {
          if(params->idr_period && !params->adaptive_idr_period)
            img->toppoc = 2*((( ( img->frm_number - img->lastIDRnumber - params->intra_delay) % params->idr_period ) - 1)*(params->jumpd + 1) 
            + (int)(img->b_interval * (double)(1 + gop_structure[img->b_frame_to_code - 1].display_no)));
          else if(params->idr_period && params->adaptive_idr_period == 1)
            img->toppoc = 2*((( img->frm_number - img->lastIDRnumber - params->intra_delay ) - 1)*(params->jumpd + 1) 
            + (int)(img->b_interval * (double)(1 + gop_structure[img->b_frame_to_code - 1].display_no)));
          else
            img->toppoc = 2*((img->frm_number - img->lastIDRnumber - 1 - params->intra_delay)*(params->jumpd + 1) 
            + (int)(img->b_interval * (double)(1 + gop_structure[img->b_frame_to_code - 1].display_no)));

          if (img->b_frame_to_code == 1)
            img->delta_pic_order_cnt[0] = img->toppoc - 2*(start_tr_in_this_IGOP  + (img->frm_number - img->lastIDRnumber)*((params->jumpd + 1)));
          else
            img->delta_pic_order_cnt[0] = img->toppoc - 2*(start_tr_in_this_IGOP  + (img->frm_number - img->lastIDRnumber - 1)*((params->jumpd + 1)) 
            + (int) (2.0 *img->b_interval * (double) (1+ gop_structure[img->b_frame_to_code - 2].display_no)));
        }

        img->bottompoc = ((params->PicInterlace==FRAME_CODING)&&(params->MbInterlace==FRAME_CODING)) ? img->toppoc : img->toppoc + 1;
        img->framepoc = imin (img->toppoc, img->bottompoc);

        img->delta_pic_order_cnt[1]= 0;   
        FrameNumberInFile = CalculateFrameNumber();

        encode_one_frame();  // encode one frame
        
        img->last_ref_idc = img->nal_reference_idc ? 1 : 0;

        if (params->ReportFrameStats)
          report_frame_statistic();
      }
      img->b_frame_to_code = 0;
    }
    else
    {
      for(img->b_frame_to_code = 1; img->b_frame_to_code <= params->successive_Bframe; img->b_frame_to_code++)
      {
        img->nal_reference_idc = (params->BRefPictures == 1 ) ? NALU_PRIORITY_LOW : NALU_PRIORITY_DISPOSABLE;
        
        if (img->last_ref_idc)
        {
          img->frame_num++;                 //increment frame_num once for B-frames
          img->frame_num %= max_frame_num;
        }

        img->b_interval =
          ((double) (params->jumpd + 1) / (params->successive_Bframe + 1.0) );

        if (params->HierarchicalCoding == 3)
          img->b_interval = 1.0;

        if (IMG_NUMBER && (IMG_NUMBER <= params->intra_delay))
        { 
          if(params->idr_period && ((!params->adaptive_idr_period && ( img->frm_number - img->lastIDRnumber ) % params->idr_period == 0)
            || (params->adaptive_idr_period == 1 && ( img->frm_number - imax(img->lastIntraNumber, img->lastIDRnumber) ) % params->idr_period == 0)) )
            img->toppoc = (int) (img->b_interval * (double)img->b_frame_to_code);
          else
            img->toppoc = 2*((-img->frm_number + img->lastIDRnumber)*(params->jumpd + 1) 
            + (int) (img->b_interval * (double)img->b_frame_to_code));
        }
        else
        {
          if(params->idr_period && !params->adaptive_idr_period)
            img->toppoc = 2*((( ( img->frm_number - img->lastIDRnumber - params->intra_delay) % params->idr_period )-1)*(params->jumpd+1) + (int) (img->b_interval * (double)img->b_frame_to_code));
          else if(params->idr_period && params->adaptive_idr_period == 1)
            img->toppoc = 2*((( img->frm_number - img->lastIDRnumber - params->intra_delay )-1)*(params->jumpd+1) + (int) (img->b_interval * (double)img->b_frame_to_code));
          else
            img->toppoc = 2*((img->frm_number - img->lastIDRnumber - 1 - params->intra_delay)*(params->jumpd+1) + (int) (img->b_interval * (double)img->b_frame_to_code));
        }

        if ((params->PicInterlace==FRAME_CODING)&&(params->MbInterlace==FRAME_CODING))
          img->bottompoc = img->toppoc;     //progressive
        else
          img->bottompoc = img->toppoc+1;

        img->framepoc = imin (img->toppoc, img->bottompoc);

        //the following is sent in the slice header
        if (params->BRefPictures != 1)
        {
          img->delta_pic_order_cnt[0]= 2 * (img->b_frame_to_code - 1);
        }
        else
        {
          img->delta_pic_order_cnt[0]= -2;
        }

        img->delta_pic_order_cnt[1]= 0;   // POC200301
        FrameNumberInFile = CalculateFrameNumber();

        encode_one_frame();  // encode one B-frame
        
        img->last_ref_idc = img->nal_reference_idc ? 1 : 0;

        if (params->ReportFrameStats)
          report_frame_statistic();
      }
    }
  }
  img->b_frame_to_code = 0;
}
예제 #2
0
파일: image_mp.c 프로젝트: Foredoomed/JM
void frame_picture_mp_p_slice(VideoParameters *p_Vid, InputParameters *p_Inp)
{
  int   rd_pass = 0;
  int   rd_qp = p_Vid->p_curr_frm_struct->qp;
  float rateRatio = 1.0F;
  int   wp_pass=0;
  int   frame_type_pass = 0;
  CodingInfo coding_info;
  FrameCodingMethod best_method = REGULAR; 
  int frame_type = P_SLICE; 
  int apply_wp = 0;
  int selection;

  frame_picture (p_Vid, p_Vid->frame_pic[rd_pass], &p_Vid->imgData, rd_pass);
  store_coding_and_rc_info(p_Vid, &coding_info);

  if(p_Inp->WPIterMC)
    p_Vid->frameOffsetAvail = 1; 

#if (DBG_IMAGE_MP)
    printf("rd_pass = %d: %d (%.0f, %.0f, %.0f)\n", rd_pass, 
      p_Vid->frame_pic[0]->bits_per_picture, 
      p_Vid->frame_pic[0]->distortion.value[0], p_Vid->frame_pic[0]->distortion.value[1], p_Vid->frame_pic[0]->distortion.value[2]);
#endif

  rd_pass++;
  if(rd_pass >= p_Inp->RDPictureMaxPassPSlice)
  {
    frame_picture_mp_exit(p_Vid, &coding_info);
    return;
  }

  // for P_Slice, consider WP  
  wp_pass = 0;
  if (p_Inp->GenerateMultiplePPS)
  {
    Slice *dummy_slice = NULL;

    InitWP(p_Vid, p_Inp, 0);
    if ( p_Inp->WPMCPrecision )
      p_Vid->pWPX->curr_wp_rd_pass = p_Vid->pWPX->wp_rd_passes + 1;
    init_slice_lite(p_Vid, &dummy_slice, 0);

    if (p_Vid->TestWPPSlice(dummy_slice, 0) == 1)
    {
      // regular WP pass
      p_Vid->active_pps = p_Vid->PicParSet[1];
      if ( p_Inp->WPMCPrecision )
        p_Vid->pWPX->curr_wp_rd_pass->algorithm = WP_REGULAR;
      wp_pass = 1;
    }
    else if ( p_Inp->WPMCPrecision )
    {
      // WPMC pass
      p_Vid->active_pps = p_Vid->PicParSet[1];
      wp_pass = 1;
    }  

    // The way it is, the code would only reach here if prior conditional using 
    // generatemultiplepps is satisfied
    if(wp_pass)
    {
      p_Vid->write_macroblock = FALSE;
      p_Vid->p_curr_frm_struct->qp = p_Vid->qp;
      frame_picture (p_Vid, p_Vid->frame_pic[rd_pass], &p_Vid->imgData, rd_pass);
      selection = picture_coding_decision(p_Vid, p_Vid->frame_pic[0], p_Vid->frame_pic[rd_pass], rd_qp);
#if (DBG_IMAGE_MP)
      printf("rd_pass = %d, selection = %d\n", rd_pass, selection);
#endif
#if (DBG_IMAGE_MP)
      printf("rd_pass = %d: %d (%.0f, %.0f, %.0f)\n", rd_pass, 
        p_Vid->frame_pic[rd_pass]->bits_per_picture, 
        p_Vid->frame_pic[rd_pass]->distortion.value[0], p_Vid->frame_pic[rd_pass]->distortion.value[1], p_Vid->frame_pic[rd_pass]->distortion.value[2]);
#endif

      if (selection)
      {
        swap_frame_buffer(p_Vid, 0, rd_pass); 
        store_coding_and_rc_info(p_Vid, &coding_info);
        best_method = EXP_WP;
        apply_wp = 1;
      }

      if(p_Inp->WPMethod == 0 || p_Inp->WPMCPrecision) 
      {
        wp_pass = 0;
        if ( p_Inp->WPMCPrecision )
          p_Vid->pWPX->curr_wp_rd_pass = p_Vid->pWPX->wp_rd_passes + 2;
        if (p_Inp->WPMethod == 0 && p_Vid->TestWPPSlice(dummy_slice, 1) == 1)
        {
          // regular WP pass
          p_Vid->active_pps = p_Vid->PicParSet[1];
          if ( p_Inp->WPMCPrecision )
            p_Vid->pWPX->curr_wp_rd_pass->algorithm = WP_REGULAR;
          wp_pass = 1;
        }
        else if ( p_Inp->WPMCPrecision )
        {
          // WPMC pass
          p_Vid->active_pps = p_Vid->PicParSet[1];
          wp_pass = 1;
        }

        if(wp_pass)
        {
          p_Vid->write_macroblock = FALSE;
          p_Vid->p_curr_frm_struct->qp = p_Vid->qp;
          free_slice_list(p_Vid->frame_pic[rd_pass]);
          free_storable_picture(p_Vid, p_Vid->enc_frame_picture[rd_pass]);
          frame_picture (p_Vid, p_Vid->frame_pic[rd_pass], &p_Vid->imgData, rd_pass);
          selection = picture_coding_decision(p_Vid, p_Vid->frame_pic[0], p_Vid->frame_pic[rd_pass], rd_qp);
#if (DBG_IMAGE_MP)
          printf("rd_pass = %d, selection = %d\n", rd_pass, selection);
#endif
#if (DBG_IMAGE_MP)
          printf("rd_pass = %d: %d (%.0f, %.0f, %.0f)\n", rd_pass, 
            p_Vid->frame_pic[rd_pass]->bits_per_picture, 
            p_Vid->frame_pic[rd_pass]->distortion.value[0], p_Vid->frame_pic[rd_pass]->distortion.value[1], p_Vid->frame_pic[rd_pass]->distortion.value[2]);
#endif

          if (selection)
          {
            swap_frame_buffer(p_Vid, 0, rd_pass); 
            store_coding_and_rc_info(p_Vid, &coding_info);
            best_method = EXP_WP;
            apply_wp = 1;
          }
        }
      }

      rd_pass++;
      //free_slice(dummy_slice);

      if(rd_pass >= p_Inp->RDPictureMaxPassPSlice)
      {
        frame_picture_mp_exit(p_Vid, &coding_info);
        free_slice(dummy_slice);
        return;
      }
    }
    free_slice(dummy_slice);
  }


  // code as I? or maybe as B?
  frame_type_pass = 0;
  if(p_Inp->RDPSliceITest && (coding_info.intras * 100/p_Vid->FrameSizeInMbs) >= 75)
  {
    frame_type = I_SLICE; 
    set_slice_type(p_Vid, p_Inp, I_SLICE);
    populate_frame_slice_type( p_Inp, p_Vid->p_curr_frm_struct, I_SLICE, p_Vid->p_pred->max_num_slices );
    p_Vid->active_pps = p_Vid->PicParSet[0];
    frame_type_pass = 1;
  }
  else if (p_Inp->RDPSliceBTest && p_Vid->active_sps->profile_idc != BASELINE)
  // later need to add some automatic criterion to see if this (coding P as B) may be beneficial 
  {
    frame_type = B_SLICE; 
    set_slice_type(p_Vid, p_Inp, B_SLICE );
    populate_frame_slice_type( p_Inp, p_Vid->p_curr_frm_struct, B_SLICE, p_Vid->p_pred->max_num_slices );
    p_Vid->active_pps = p_Vid->PicParSet[0];
    frame_type_pass = 1;
  }

  if(frame_type_pass)
  {
    p_Vid->write_macroblock = FALSE;
    p_Vid->p_curr_frm_struct->qp = p_Vid->qp;
    frame_picture (p_Vid, p_Vid->frame_pic[rd_pass], &p_Vid->imgData, rd_pass);
    selection = picture_coding_decision(p_Vid, p_Vid->frame_pic[0], p_Vid->frame_pic[rd_pass], rd_qp);
#if (DBG_IMAGE_MP)
  printf("rd_pass = %d, selection = %d\n", rd_pass, selection);
#endif

    if (selection)
    {
      swap_frame_buffer(p_Vid, 0, rd_pass); 
      store_coding_and_rc_info(p_Vid, &coding_info);
      best_method = FRAME_TYPE; 
    }
    // reset frame_type
    else 
      frame_type = P_SLICE;

    rd_pass++;
    if(rd_pass >= p_Inp->RDPictureMaxPassPSlice)
    {
      frame_picture_mp_exit(p_Vid, &coding_info);
      return;
    }
  }

  if(p_Vid->EvaluateDBOff)
  {
    // Perform DB off coding pass
    p_Vid->active_pps = (best_method == EXP_WP?p_Vid->PicParSet[1]:p_Vid->PicParSet[0]);
    if(frame_type != P_SLICE)
    {
      set_slice_type(p_Vid, p_Inp, frame_type);
      populate_frame_slice_type( p_Inp, p_Vid->p_curr_frm_struct, frame_type, p_Vid->p_pred->max_num_slices );
    }
    p_Vid->TurnDBOff = 1; 
    p_Vid->write_macroblock = FALSE;
    p_Vid->p_curr_frm_struct->qp = p_Vid->qp;
    frame_picture (p_Vid, p_Vid->frame_pic[rd_pass], &p_Vid->imgData, rd_pass);
    selection = picture_coding_decision(p_Vid, p_Vid->frame_pic[0], p_Vid->frame_pic[rd_pass], rd_qp);
#if (DBG_IMAGE_MP)
  printf("DB OFF, rd_pass = %d, selection = %d\n", rd_pass, selection);
#endif

    if (selection)
    {
      swap_frame_buffer(p_Vid, 0, rd_pass); 
      store_coding_and_rc_info(p_Vid, &coding_info);
      best_method = DB_OFF; 
    }

    rd_pass++;
    if(rd_pass >= p_Inp->RDPictureMaxPassPSlice)
    {
      frame_picture_mp_exit(p_Vid, &coding_info);
      return;
    }
  }

  if(p_Inp->RDPictureFrameQPPSlice)
  {
    // frame QP pass
    p_Vid->active_pps = (apply_wp?p_Vid->PicParSet[1]:p_Vid->PicParSet[0]);
    if(frame_type != P_SLICE)
    {
      set_slice_type(p_Vid, p_Inp, frame_type);
      populate_frame_slice_type( p_Inp, p_Vid->p_curr_frm_struct, I_SLICE, p_Vid->p_pred->max_num_slices );
    }
    p_Vid->qp = (p_Vid->nal_reference_idc==0 ? rd_qp+1:rd_qp-1);
    p_Vid->qp = iClip3( p_Vid->RCMinQP, p_Vid->RCMaxQP, p_Vid->qp );
    if ( p_Inp->RCEnable )
    {
      rateRatio = p_Vid->nal_reference_idc ? 1.15F : 0.85F;
      rc_init_frame_rdpic( p_Vid, p_Inp, rateRatio );
    }
    p_Vid->TurnDBOff = 0;
    p_Vid->write_macroblock = FALSE;
    p_Vid->p_curr_frm_struct->qp = p_Vid->qp;
    frame_picture (p_Vid, p_Vid->frame_pic[rd_pass], &p_Vid->imgData, rd_pass);
    selection = picture_coding_decision(p_Vid, p_Vid->frame_pic[0], p_Vid->frame_pic[rd_pass], rd_qp);
#if (DBG_IMAGE_MP)
    printf("rd_pass = %d, selection = %d\n", rd_pass, selection);
#endif

    if (selection)
    {
      swap_frame_buffer(p_Vid, 0, rd_pass); 
      store_coding_and_rc_info(p_Vid, &coding_info);
      best_method = FRAME_QP;
    }

    rd_pass++;
    if(rd_pass >= p_Inp->RDPictureMaxPassPSlice)
    {
      frame_picture_mp_exit(p_Vid, &coding_info);
      return;
    }
  }

  frame_picture_mp_exit(p_Vid, &coding_info);
}