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

📄 umc_h264_tran_rc.cpp

📁 这是在PCA下的基于IPP库示例代码例子,在网上下了IPP的库之后,设置相关参数就可以编译该代码.
💻 CPP
字号:
/*////               INTEL CORPORATION PROPRIETARY INFORMATION//  This software is supplied under the terms of a license agreement or//  nondisclosure agreement with Intel Corporation and may not be copied//  or disclosed except in accordance with the terms of that agreement.//      Copyright (c) 2005 Intel Corporation. All Rights Reserved.////  Purpose//    frame adaptive bitrate control*/#include "umc_h264_pub.h"#include "umc_h264_video_encoder.h"namespace UMC {int H264VideoEncoder::PictureRateControl(){  PictureStructure picture_structure = m_PicParamSet.picture_structure;  int isfield = (picture_structure != FRAME_PICTURE);  double ip_delay;  // secondfield should be moved to class, code to frame start  // Should be corrected, if one decides to place a bottom field before the top.  int secondfield = (picture_structure == BOTTOM_FIELD);  EnumSliceType slice_type = m_SliceHeader.slice_type;  if(BitRate <= 0) {    changeQuant(qscale[slice_type]); // changes also intra_dc_precision, q_scale_type    vbv_delay = 0xffff;    return quantiser_scale_value;  }  // There is no warranty that there won't be a field coded picture.  rc_delay = rc_ave_frame_bits;  if(!isfield) rc_delay += rc_ave_frame_bits;  //if(encodeInfo.repeat_first_field) rc_delay += rc_ave_frame_bits;  rc_delay = rc_delay / 2;  if(slice_type != BPREDSLICE) {      ip_delay = rc_delay;      if(!isfield) {          rc_delay = rc_ip_delay;          rc_ip_delay = ip_delay;      } else if(secondfield) {          rc_delay = rc_ip_delay - rc_delay;          rc_ip_delay = 2*ip_delay;      }  }  vbv_delay = (int)(rc_vbv_fullness * 90000.0/BitRate);  if(vbv_delay < 0) vbv_delay = 0; // for a while  // vbv computations for len range  rc_vbv_max = (int)rc_vbv_fullness;  rc_vbv_min = (int)(rc_vbv_fullness - (VBV_BufferSize*16384 - rc_delay));  int q0, q2, sz1;  q0 = qscale[slice_type];   // proposed from post picture  q2 = prqscale[slice_type]; // last used scale  sz1 = prsize[slice_type];  // last coded size  // compute newscale again  // adaptation to current rate deviation  double target_size = rc_tagsize[slice_type];  int wanted_size = (int)(target_size - rc_dev / 3 * target_size / rc_tagsize[INTRASLICE]);  if     (sz1 > 2*wanted_size)   q2 = q2 * 3 / 2 + 1;  else if(sz1 > wanted_size+100) q2 ++;  else if(2*sz1 < wanted_size)   q2 = q2 * 3 / 4;  else if(sz1 < wanted_size-100) q2 --;  if(rc_dev > 0) {    q2 = max(q0,q2);  } else {    q2 = min(q0,q2);  }  // this call is used to accept small changes in value, which are mapped to the same code  // changeQuant bothers about to change scale code if value changes  q2 = changeQuant(q2);  qscale[slice_type] = q2;  return quantiser_scale_value;}// encoded size check, vbv computation, qscale code adaptation// returns positive bitcount when vbv overflow,//         negative bitcount when vbv underflow, 0 if OKint H264VideoEncoder::PostPictureRateControl(Ipp64s bits_encoded){  EnumSliceType slice_type = m_SliceHeader.slice_type;  int isfield = (m_PicParamSet.picture_structure != FRAME_PICTURE);  Ipp64s vbv_size = VBV_BufferSize * 16384;  int ret = 0;  {    Ipp64s tmp = bits_encoded - lastEncodedBits;    lastEncodedBits = bits_encoded;    bits_encoded = tmp;  }  prsize[slice_type] = (int)bits_encoded << isfield;  prqscale[slice_type] = qscale[slice_type];  if(BitRate <= 0) {    return 0;  }  rc_vbv_fullness = rc_vbv_fullness - bits_encoded;  rc_vbv_fullness += rc_delay; //  int cur_qscale = qscale[slice_type];  double target_size = rc_tagsize[slice_type];  rc_dev += bits_encoded - (isfield ? target_size/2 : target_size);  int wanted_size = (int)(target_size - rc_dev / 3 * target_size / rc_tagsize[INTRASLICE]);  int newscale;  int del_sc;  newscale = cur_qscale;  wanted_size >>= isfield;  if(bits_encoded > wanted_size) newscale ++;  if(bits_encoded > 2*wanted_size) newscale = cur_qscale * 3 / 2 + 1;  if(bits_encoded < wanted_size) newscale --;  if(2*bits_encoded < wanted_size) newscale = cur_qscale * 3 / 4;  // this call is used to accept small changes in value, which are mapped to the same code  // changeQuant bothers about to change scale code if value changes  newscale = changeQuant(newscale);  if(slice_type == INTRASLICE) {    if( newscale+1 > qscale[PREDSLICE] ) qscale[PREDSLICE] = newscale+1;    if( newscale+2 > qscale[BPREDSLICE] ) qscale[BPREDSLICE] = newscale+2;  } else if(slice_type == PREDSLICE) {    if( newscale < qscale[INTRASLICE] ) {      del_sc = qscale[INTRASLICE] - newscale;      qscale[INTRASLICE] -= del_sc/2;      newscale = qscale[INTRASLICE];      newscale = changeQuant(newscale);    }    if( newscale+1 > qscale[BPREDSLICE] ) qscale[BPREDSLICE] = newscale+1;  } else {    if( newscale < qscale[PREDSLICE] ) {      del_sc = qscale[PREDSLICE] - newscale;      qscale[PREDSLICE] -= del_sc/2;      newscale = qscale[PREDSLICE];      newscale = changeQuant(newscale);      if( qscale[PREDSLICE] < qscale[INTRASLICE] ) qscale[INTRASLICE] = qscale[PREDSLICE];    }  }  qscale[slice_type] = newscale;  if(rc_vbv_fullness > vbv_size) {    ret = (int)(rc_vbv_fullness - vbv_size);  }  if(rc_vbv_fullness < rc_delay) {    ret = (int)(rc_vbv_fullness - rc_delay);  }  return ret;}int H264VideoEncoder::ChangeBitrate(H264EncoderParams *new_info){    if (new_info->rate_controls.bitrate == (Ipp32u)BitRate)    {        return 0; // Nothing to be done.    }    int frame_width_in_mbs = (m_info.src_width + 15)/16;    int frame_height_in_mbs = (m_info.src_height + 15)/16;    m_info.rate_controls.bitrate = BitRate = new_info->rate_controls.bitrate;    InitRateControl(frame_width_in_mbs,                    frame_height_in_mbs);    return 0;}int H264VideoEncoder::InitRateControl(int frame_width_in_mbs,                                  int frame_height_in_mbs){  double ppb; //pixels per bit (~ density)  int i;  int block_count = 6; // for YUV420!!!  lastEncodedBits = 0;  if (BitRate <= 0) { // not given bitrate    BitRate = 0;    vbv_delay = 0xffff; // unused    qscale[INTRASLICE] = 4;      // values from air    qscale[PREDSLICE] = 6;    qscale[BPREDSLICE] = 8;    return 0;  }  //FrameRate = ratetab[encodeInfo.frame_rate_code - 1];  {    int YUVFrameSize = frame_width_in_mbs*frame_height_in_mbs*(256+128); // YUV 420!!!    double pixrate = 8/*bits*/*FrameRate * YUVFrameSize;    if((double)BitRate > pixrate)      BitRate = (int)(pixrate); // too high    if((double)BitRate < pixrate/500)      BitRate = (int)(pixrate/500); // too low#if defined _DEBUG    if (BitRate != BitRate)      fprintf(stderr,"BitRate value fixed\n");#endif //_DEBUG    BitRate = (BitRate+399)/400*400; // 400 bps step  }  // if 0 - could be no rc  rc_ave_frame_bits = BitRate/FrameRate;  if(VBV_BufferSize <= (int)(rc_ave_frame_bits / 16384 * 4) ) { // avoid too small    VBV_BufferSize = (int)(rc_ave_frame_bits / 16384 * 8);  }  VBV_BufferSize = VBV_BufferSize;  quantiser_scale_value = 0;  // one can vary weights, can be added to API  rc_weight[INTRASLICE] = 200;  rc_weight[PREDSLICE] = 40;  rc_weight[BPREDSLICE] = 12;  //M = encodeInfo.IPDistance;  //N = encodeInfo.gopSize;  if(!N) {      // Only the first I picture per stream.      N = 100; // Use this approximation instead.  }  double nr = N/M;  double Pnum = (nr > 1)? nr-1: min(nr, (double)(N>1));  double gopw = (M-1)*rc_weight[BPREDSLICE]*nr + rc_weight[PREDSLICE]*Pnum + rc_weight[INTRASLICE];  double u_len = rc_ave_frame_bits * N / gopw;  rc_tagsize[INTRASLICE] = u_len * rc_weight[INTRASLICE];  rc_tagsize[PREDSLICE] = u_len * rc_weight[PREDSLICE];  rc_tagsize[BPREDSLICE] = u_len * rc_weight[BPREDSLICE];  // we want ideal case - I frame to be centered in vbv buffer, compute start pos  rc_vbv_fullness =    VBV_BufferSize * 16384 / 2 +           // half of vbv_buffer    rc_tagsize[INTRASLICE] / 2 +                          // top to center length of I frame    (M-1) * (rc_ave_frame_bits - rc_tagsize[BPREDSLICE]); // first gop has no M-1 B frames: add'em  vbv_delay = (int)(rc_vbv_fullness*90000.0/BitRate); // bits to clocks  rc_vbv_max = (int)(rc_vbv_fullness);  rc_ip_delay = rc_ave_frame_bits;  rc_dev = 0; // deviation from ideal bitrate (should be float or renewed)  double rrel = gopw / (rc_weight[INTRASLICE] * N);  ppb = frame_width_in_mbs*frame_height_in_mbs*256*FrameRate/BitRate * (block_count-2) / (6-2);  qscale[INTRASLICE] = (int)(41.0 * rrel * ppb); // numbers are empiric  qscale[PREDSLICE] = (int)(60.0 * rrel * ppb);  qscale[BPREDSLICE] = (int)(120.0 * rrel * ppb);  for(i=0; i<3; i++) {    if     (qscale[i]< 1) qscale[i]= 1;    else if(qscale[i]>51) qscale[i]=51; // can be even more    prqscale[i] = qscale[i];    prsize[i] = (int)rc_tagsize[i]; // for first iteration  }  return 0;}int H264VideoEncoder::mapQuant(int quant_value){  int qs_code;  qs_code = quant_value;  if(qs_code < 1) qs_code = 1;  if(qs_code > 51) qs_code = 51;  return qs_code;}int H264VideoEncoder::changeQuant(int quant_value){  //int curq = m_fpar.quant_scale_value;  int curq = quantiser_scale_value;  if(quant_value == quantiser_scale_value) return quantiser_scale_value;  quantiser_scale_code = quant_value;  if(quantiser_scale_code < 1) quantiser_scale_code = 1;  if(quantiser_scale_code > 51) quantiser_scale_code = 51;  quantiser_scale_value = quantiser_scale_code;  if(quantiser_scale_value == curq) {    if(quant_value > curq)      if(quantiser_scale_code == 51) return quantiser_scale_value;      else quantiser_scale_code ++;    if(quant_value < curq)      if(quantiser_scale_code == 1) return quantiser_scale_value;      else quantiser_scale_code --;    quantiser_scale_value = quantiser_scale_code;  }  /*if(encodeInfo.mpeg1 || quantiser_scale_value >= 16)    encodeInfo.intra_dc_precision = 0;  else if(quantiser_scale_value >= 4)    encodeInfo.intra_dc_precision = 1;  else    encodeInfo.intra_dc_precision = 2;*/  // only for High profile  //if(quantiser_scale_value == 1) encodeInfo.intra_dc_precision = 3;  return quantiser_scale_value;}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -