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

📄 encoder_toplevel.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
📖 第 1 页 / 共 3 页
字号:
  /* set up context of key frame sizes and distances for more local     datarate control */  for( i = 0 ; i < KEY_FRAME_CONTEXT ; i ++ ) {    cpi->PriorKeyFrameSize[i] = cpi->Configuration.KeyFrameDataTarget;    cpi->PriorKeyFrameDistance[i] = cpi->pb.info.keyframe_frequency_force;  }  /* Keep track of the total number of Key Frames Coded. */  cpi->KeyFrameCount = 1;  cpi->LastKeyFrame = 1;  cpi->TotKeyFrameBytes = 0;  /* A key frame is not a dropped frame there for reset the count of     consequative dropped frames. */  cpi->DropCount = 0;  SetupKeyFrame(cpi);  /* Calculate a new target rate per frame allowing for average key     frame frequency and size thus far. */  if ( cpi->Configuration.TargetBandwidth >       ((cpi->Configuration.KeyFrameDataTarget *         cpi->Configuration.OutputFrameRate)/        cpi->pb.info.keyframe_frequency) ) {    cpi->frame_target_rate =      (ogg_int32_t)((cpi->Configuration.TargetBandwidth -                     ((cpi->Configuration.KeyFrameDataTarget *                       cpi->Configuration.OutputFrameRate)/                      cpi->pb.info.keyframe_frequency)) /                    cpi->Configuration.OutputFrameRate);  }else    cpi->frame_target_rate = 1;  /* Set baseline frame target rate. */  cpi->BaseLineFrameTargetRate = cpi->frame_target_rate;  /* A key frame is not a dropped frame there for reset the count of     consequative dropped frames. */  cpi->DropCount = 0;  /* Initialise drop frame trigger to 5 frames worth of data. */  cpi->DropFrameTriggerBytes = cpi->frame_target_rate * DF_CANDIDATE_WINDOW;  /* Set a target size for this key frame based upon the baseline     target and frequency */  cpi->ThisFrameTargetBytes = cpi->Configuration.KeyFrameDataTarget;  /* Get a DCT quantizer level for the key frame. */  cpi->MotionScore = cpi->pb.UnitFragments;  RegulateQ(cpi, cpi->pb.UnitFragments);  cpi->pb.LastFrameQualityValue = cpi->pb.ThisFrameQualityValue;  /* Initialise quantizer. */  UpdateQC(cpi, cpi->pb.ThisFrameQualityValue );  /* Initialise the cpi->pb.display_fragments and other fragment     structures for the first frame. */  for ( i = 0; i < cpi->pb.UnitFragments; i ++ )    cpi->FragmentLastQ[i] = cpi->pb.ThisFrameQualityValue;  /* Compress and output the frist frame. */  PickIntra( cpi,             cpi->pb.YSBRows, cpi->pb.YSBCols);  UpdateFrame(cpi);  /* Initialise the carry over rate targeting variables. */  cpi->CarryOver = 0;}static void CompressKeyFrame(CP_INSTANCE *cpi){  ogg_uint32_t  i;  /* Before we compress reset the carry over to the actual frame carry over */  cpi->CarryOver = cpi->Configuration.TargetBandwidth * cpi->CurrentFrame  /    cpi->Configuration.OutputFrameRate - cpi->TotalByteCount;  /* Keep track of the total number of Key Frames Coded */  cpi->KeyFrameCount += 1;  /* A key frame is not a dropped frame there for reset the count of     consequative dropped frames. */  cpi->DropCount = 0;  SetupKeyFrame(cpi);  /* set a target size for this frame */  cpi->ThisFrameTargetBytes = (ogg_int32_t) cpi->frame_target_rate +    ( (cpi->Configuration.KeyFrameDataTarget - cpi->frame_target_rate) *      cpi->LastKeyFrame / cpi->pb.info.keyframe_frequency_force );  if ( cpi->ThisFrameTargetBytes > cpi->Configuration.KeyFrameDataTarget )    cpi->ThisFrameTargetBytes = cpi->Configuration.KeyFrameDataTarget;  /* Get a DCT quantizer level for the key frame. */  cpi->MotionScore = cpi->pb.UnitFragments;  RegulateQ(cpi, cpi->pb.UnitFragments);  cpi->pb.LastFrameQualityValue = cpi->pb.ThisFrameQualityValue;  /* Initialise DCT tables. */  UpdateQC(cpi, cpi->pb.ThisFrameQualityValue );  /* Initialise the cpi->pb.display_fragments and other fragment     structures for the first frame. */  for ( i = 0; i < cpi->pb.UnitFragments; i ++ )    cpi->FragmentLastQ[i] = cpi->pb.ThisFrameQualityValue;  /* Compress and output the frist frame. */  PickIntra( cpi,             cpi->pb.YSBRows, cpi->pb.YSBCols);  UpdateFrame(cpi);}static void CompressFrame( CP_INSTANCE *cpi) {  ogg_int32_t min_blocks_per_frame;  ogg_uint32_t  i;  int DropFrame = 0;  ogg_uint32_t  ResidueBlocksAdded=0;  ogg_uint32_t  KFIndicator = 0;  double QModStep;  double QModifier = 1.0;  /* Clear down the macro block level mode and MV arrays. */  for ( i = 0; i < cpi->pb.UnitFragments; i++ ) {    cpi->pb.FragCodingMethod[i] = CODE_INTER_NO_MV;  /* Default coding mode */    cpi->pb.FragMVect[i].x = 0;    cpi->pb.FragMVect[i].y = 0;  }  /* Default to delta frames. */  SetFrameType( &cpi->pb, DELTA_FRAME );  /* Clear down the difference arrays for the current frame. */  memset( cpi->pb.display_fragments, 0, cpi->pb.UnitFragments );  memset( cpi->extra_fragments, 0, cpi->pb.UnitFragments );  /* Calculate the target bytes for this frame. */  cpi->ThisFrameTargetBytes = cpi->frame_target_rate;  /* Correct target to try and compensate for any overall rate error     that is developing */  /* Set the max allowed Q for this frame based upon carry over     history.  First set baseline worst Q for this frame */  cpi->Configuration.ActiveMaxQ = cpi->Configuration.MaxQ + 10;  if ( cpi->Configuration.ActiveMaxQ >= Q_TABLE_SIZE )    cpi->Configuration.ActiveMaxQ = Q_TABLE_SIZE - 1;  /* Make a further adjustment based upon the carry over and recent   history..  cpi->Configuration.ActiveMaxQ reduced by 1 for each 1/2   seconds worth of -ve carry over up to a limit of 6.  Also   cpi->Configuration.ActiveMaxQ reduced if frame is a   "DropFrameCandidate".  Remember that if we are behind the bit   target carry over is -ve. */  if ( cpi->CarryOver < 0 ) {    if ( cpi->DropFrameCandidate ) {      cpi->Configuration.ActiveMaxQ -= 4;    }    if ( cpi->CarryOver <         -((ogg_int32_t)cpi->Configuration.TargetBandwidth*3) )      cpi->Configuration.ActiveMaxQ -= 6;    else      cpi->Configuration.ActiveMaxQ +=        (ogg_int32_t) ((cpi->CarryOver*2) /                       (ogg_int32_t)cpi->Configuration.TargetBandwidth);    /* Check that we have not dropped quality too far */    if ( cpi->Configuration.ActiveMaxQ < cpi->Configuration.MaxQ )      cpi->Configuration.ActiveMaxQ = cpi->Configuration.MaxQ;  }  /* Calculate the Q Modifier step size required to cause a step down     from full target bandwidth to 40% of target between max Q and     best Q */  QModStep = 0.5 / (double)((Q_TABLE_SIZE - 1) -                            cpi->Configuration.ActiveMaxQ);  /* Set up the cpi->QTargetModifier[] table. */  for ( i = 0; i < cpi->Configuration.ActiveMaxQ; i++ ) {    cpi->QTargetModifier[i] = QModifier;  }  for ( i = cpi->Configuration.ActiveMaxQ; i < Q_TABLE_SIZE; i++ ) {    cpi->QTargetModifier[i] = QModifier;    QModifier -= QModStep;  }  /* if we are allowed to drop frames and are falling behind (eg more     than x frames worth of bandwidth) */  if ( cpi->pb.info.dropframes_p &&       ( cpi->DropCount < cpi->MaxConsDroppedFrames) &&       ( cpi->CarryOver <         -((ogg_int32_t)cpi->Configuration.TargetBandwidth)) &&       ( cpi->DropFrameCandidate) ) {    /* (we didn't do this frame so we should have some left over for       the next frame) */    cpi->CarryOver += cpi->frame_target_rate;    DropFrame = 1;    cpi->DropCount ++;    /* Adjust DropFrameTriggerBytes to account for the saving achieved. */    cpi->DropFrameTriggerBytes =      (cpi->DropFrameTriggerBytes *       (DF_CANDIDATE_WINDOW-1))/DF_CANDIDATE_WINDOW;    /* Even if we drop a frame we should account for it when        considering key frame seperation. */    cpi->LastKeyFrame++;  } else if ( cpi->CarryOver <              -((ogg_int32_t)cpi->Configuration.TargetBandwidth * 2) ) {    /* Reduce frame bit target by 1.75% for each 1/10th of a seconds       worth of -ve carry over down to a minimum of 65% of its       un-modified value. */    cpi->ThisFrameTargetBytes =      (ogg_uint32_t)(cpi->ThisFrameTargetBytes * 0.65);  } else if ( cpi->CarryOver < 0 ) {    /* Note that cpi->CarryOver is a -ve here hence 1.0 "+" ... */    cpi->ThisFrameTargetBytes =      (ogg_uint32_t)(cpi->ThisFrameTargetBytes *                     (1.0 + ( ((cpi->CarryOver * 10)/                               ((ogg_int32_t)cpi->                                Configuration.TargetBandwidth)) * 0.0175) ));  }  if ( !DropFrame ) {    /*  pick all the macroblock modes and motion vectors */    ogg_uint32_t InterError;    ogg_uint32_t IntraError;    /* Set Baseline filter level. */    ConfigurePP( &cpi->pp, cpi->pb.info.noise_sensitivity);    /* Score / analyses the fragments. */    cpi->MotionScore = YUVAnalyseFrame(&cpi->pp, &KFIndicator );    /* Get the baseline Q value */    RegulateQ( cpi, cpi->MotionScore );    /* Recode blocks if the error score in last frame was high. */    ResidueBlocksAdded  = 0;    for ( i = 0; i < cpi->pb.UnitFragments; i++ ){      if ( !cpi->pb.display_fragments[i] ){        if ( cpi->LastCodedErrorScore[i] >=             ResidueErrorThresh[cpi->pb.FrameQIndex] ) {          cpi->pb.display_fragments[i] = 1; /* Force block update */          cpi->extra_fragments[i] = 1;      /* Insures up to date                                               pixel data is used. */          ResidueBlocksAdded ++;        }      }    }    /* Adjust the motion score to allow for residue blocks       added. These are assumed to have below average impact on       bitrate (Hence ResidueBlockFactor). */    cpi->MotionScore = cpi->MotionScore +      (ResidueBlocksAdded / ResidueBlockFactor[cpi->pb.FrameQIndex]);    /* Estimate the min number of blocks at best Q */    min_blocks_per_frame =      (ogg_int32_t)(cpi->ThisFrameTargetBytes /                    GetEstimatedBpb( cpi, VERY_BEST_Q ));    if ( min_blocks_per_frame == 0 )      min_blocks_per_frame = 1;    /* If we have less than this number then consider adding in some       extra blocks */    if ( cpi->MotionScore < min_blocks_per_frame ) {      min_blocks_per_frame =        cpi->MotionScore +        (ogg_int32_t)(((min_blocks_per_frame - cpi->MotionScore) * 4) / 3 );      UpRegulateDataStream( cpi, VERY_BEST_Q, min_blocks_per_frame );    }else{      /* Reset control variable for best quality final pass. */      cpi->FinalPassLastPos = 0;    }    /* Get the modified Q prediction taking into account extra blocks added. */    RegulateQ( cpi, cpi->MotionScore );    /* Unless we are already well ahead (4 seconds of data) of the       projected bitrate */    if ( cpi->CarryOver <         (ogg_int32_t)(cpi->Configuration.TargetBandwidth * 4) ){      /* Look at the predicted Q (pbi->FrameQIndex).  Adjust the         target bits for this frame based upon projected Q and         re-calculate.  The idea is that if the Q is better than a         given (good enough) level then we will try and save some bits         for use in more difficult segments. */      cpi->ThisFrameTargetBytes =        (ogg_int32_t) (cpi->ThisFrameTargetBytes *                       cpi->QTargetModifier[cpi->pb.FrameQIndex]);      /* Recalculate Q again */      RegulateQ( cpi, cpi->MotionScore );    }    /* Select modes and motion vectors for each of the blocks : return       an error score for inter and intra */    PickModes( cpi, cpi->pb.YSBRows, cpi->pb.YSBCols,               cpi->pb.info.width,               &InterError, &IntraError );    /* decide whether we really should have made this frame a key frame */    /* forcing out a keyframe if the max interval is up is done at a higher level */    if( cpi->pb.info.keyframe_auto_p){      if( ( 2* IntraError < 5 * InterError )          && ( KFIndicator >= (ogg_uint32_t)               cpi->pb.info.keyframe_auto_threshold)          && ( cpi->LastKeyFrame > cpi->pb.info.keyframe_mindistance)          ){        CompressKeyFrame(cpi);  /* Code a key frame */        return;      }    }    /* Increment the frames since last key frame count */    cpi->LastKeyFrame++;    /* Proceed with the frame update. */    UpdateFrame(cpi);    cpi->DropCount = 0;    if ( cpi->MotionScore > 0 ){      /* Note the Quantizer used for each block coded. */      for ( i = 0; i < cpi->pb.UnitFragments; i++ ){        if ( cpi->pb.display_fragments[i] ){          cpi->FragmentLastQ[i] = cpi->pb.ThisFrameQualityValue;        }      }    }  }else{    /* even if we 'drop' a frame, a placeholder must be written as we       currently assume fixed frame rate timebase as Ogg mapping       invariant */    UpdateFrame(cpi);  }}/********************** The toplevel: encode ***********************/static int _ilog(unsigned int v){  int ret=0;  while(v){    ret++;    v>>=1;  }  return(ret);}int theora_encode_init(theora_state *th, theora_info *c){  int i;  CP_INSTANCE *cpi;  memset(th, 0, sizeof(*th));  /*Currently only the 4:2:0 format is supported.*/  if(c->pixelformat!=OC_PF_420)return OC_IMPL;  th->internal_encode=cpi=_ogg_calloc(1,sizeof(*cpi));  dsp_static_init (&cpi->dsp);  memcpy (&cpi->pb.dsp, &cpi->dsp, sizeof(DspFunctions));  c->version_major=VERSION_MAJOR;  c->version_minor=VERSION_MINOR;  c->version_subminor=VERSION_SUB;  InitTmpBuffers(&cpi->pb);  InitPPInstance(&cpi->pp, &cpi->dsp);  /* Initialise Configuration structure to legal values */  if(c->quality>63)c->quality=63;  if(c->quality<0)c->quality=32;  if(c->target_bitrate<0)c->target_bitrate=0;  /* we clamp target_bitrate to 24 bits after setting up the encoder */  cpi->Configuration.BaseQ = c->quality;  cpi->Configuration.FirstFrameQ = c->quality;  cpi->Configuration.MaxQ = c->quality;  cpi->Configuration.ActiveMaxQ = c->quality;  cpi->MVChangeFactor    =    14;  cpi->FourMvChangeFactor =   8;  cpi->MinImprovementForNewMV = 25;  cpi->ExhaustiveSearchThresh = 2500;  cpi->MinImprovementForFourMV = 100;  cpi->FourMVThreshold = 10000;  cpi->BitRateCapFactor = 1.50;  cpi->InterTripOutThresh = 5000;  cpi->MVEnabled = 1;  cpi->InterCodeCount = 127;  cpi->BpbCorrectionFactor = 1.0;  cpi->GoldenFrameEnabled = 1;  cpi->InterPrediction = 1;  cpi->MotionCompensation = 1;

⌨️ 快捷键说明

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