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

📄 encoder_toplevel.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
📖 第 1 页 / 共 3 页
字号:
/******************************************************************** *                                                                  * * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE.   * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       * *                                                                  * * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003                * * by the Xiph.Org Foundation http://www.xiph.org/                  * *                                                                  * ********************************************************************  function:  last mod: $Id: encoder_toplevel.c 11442 2006-05-27 17:28:08Z giles $ ********************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <stdlib.h>#include <string.h>#include "toplevel_lookup.h"#include "toplevel.h"#include "dsp.h"#define A_TABLE_SIZE        29#define DF_CANDIDATE_WINDOW 5static void EClearFragmentInfo(CP_INSTANCE * cpi){  if(cpi->extra_fragments)    _ogg_free(cpi->extra_fragments);  if(cpi->FragmentLastQ)    _ogg_free(cpi->FragmentLastQ);  if(cpi->FragTokens)    _ogg_free(cpi->FragTokens);  if(cpi->FragTokenCounts)    _ogg_free(cpi->FragTokenCounts);  if(cpi->RunHuffIndices)    _ogg_free(cpi->RunHuffIndices);  if(cpi->LastCodedErrorScore)    _ogg_free(cpi->LastCodedErrorScore);  if(cpi->ModeList)    _ogg_free(cpi->ModeList);  if(cpi->MVList)    _ogg_free(cpi->MVList);  if(cpi->DCT_codes )    _ogg_free( cpi->DCT_codes );  if(cpi->DCTDataBuffer )    _ogg_free( cpi->DCTDataBuffer);  if(cpi->quantized_list)    _ogg_free( cpi->quantized_list);  if(cpi->OriginalDC)    _ogg_free( cpi->OriginalDC);  if(cpi->PartiallyCodedFlags)    _ogg_free(cpi->PartiallyCodedFlags);  if(cpi->PartiallyCodedMbPatterns)    _ogg_free(cpi->PartiallyCodedMbPatterns);  if(cpi->UncodedMbFlags)    _ogg_free(cpi->UncodedMbFlags);  if(cpi->BlockCodedFlags)    _ogg_free(cpi->BlockCodedFlags);  cpi->extra_fragments = 0;  cpi->FragmentLastQ = 0;  cpi->FragTokens = 0;  cpi->FragTokenCounts = 0;  cpi->RunHuffIndices = 0;  cpi->LastCodedErrorScore = 0;  cpi->ModeList = 0;  cpi->MVList = 0;  cpi->DCT_codes = 0;  cpi->DCTDataBuffer = 0;  cpi->quantized_list = 0;  cpi->OriginalDC = 0;  cpi->BlockCodedFlags = 0;}static void EInitFragmentInfo(CP_INSTANCE * cpi){  /* clear any existing info */  EClearFragmentInfo(cpi);  /* Perform Fragment Allocations */  cpi->extra_fragments =    _ogg_malloc(cpi->pb.UnitFragments*sizeof(unsigned char));  /* A note to people reading and wondering why malloc returns aren't     checked:     lines like the following that implement a general strategy of     'check the return of malloc; a zero pointer means we're out of     memory!'...:  if(!cpi->extra_fragments) { EDeleteFragmentInfo(cpi); return FALSE; }     ...are not useful.  It's true that many platforms follow this     malloc behavior, but many do not.  The more modern malloc     strategy is only to allocate virtual pages, which are not mapped     until the memory on that page is touched.  At *that* point, if     the machine is out of heap, the page fails to be mapped and a     SEGV is generated.     That means that if we want to deal with out of memory conditions,     we *must* be prepared to process a SEGV.  If we implement the     SEGV handler, there's no reason to to check malloc return; it is     a waste of code. */  cpi->FragmentLastQ =    _ogg_malloc(cpi->pb.UnitFragments*                sizeof(*cpi->FragmentLastQ));  cpi->FragTokens =    _ogg_malloc(cpi->pb.UnitFragments*                sizeof(*cpi->FragTokens));  cpi->OriginalDC =    _ogg_malloc(cpi->pb.UnitFragments*                sizeof(*cpi->OriginalDC));  cpi->FragTokenCounts =    _ogg_malloc(cpi->pb.UnitFragments*                sizeof(*cpi->FragTokenCounts));  cpi->RunHuffIndices =    _ogg_malloc(cpi->pb.UnitFragments*                sizeof(*cpi->RunHuffIndices));  cpi->LastCodedErrorScore =    _ogg_malloc(cpi->pb.UnitFragments*                sizeof(*cpi->LastCodedErrorScore));  cpi->BlockCodedFlags =    _ogg_malloc(cpi->pb.UnitFragments*                sizeof(*cpi->BlockCodedFlags));  cpi->ModeList =    _ogg_malloc(cpi->pb.UnitFragments*                sizeof(*cpi->ModeList));  cpi->MVList =    _ogg_malloc(cpi->pb.UnitFragments*                sizeof(cpi->MVList));  cpi->DCT_codes =    _ogg_malloc(64*                sizeof(*cpi->DCT_codes));  cpi->DCTDataBuffer =    _ogg_malloc(64*                sizeof(*cpi->DCTDataBuffer));  cpi->quantized_list =    _ogg_malloc(64*                sizeof(*cpi->quantized_list));  cpi->PartiallyCodedFlags =    _ogg_malloc(cpi->pb.MacroBlocks*                sizeof(*cpi->PartiallyCodedFlags));  cpi->PartiallyCodedMbPatterns =    _ogg_malloc(cpi->pb.MacroBlocks*                sizeof(*cpi->PartiallyCodedMbPatterns));  cpi->UncodedMbFlags =    _ogg_malloc(cpi->pb.MacroBlocks*                sizeof(*cpi->UncodedMbFlags));}static void EClearFrameInfo(CP_INSTANCE * cpi) {  if(cpi->ConvDestBuffer )    _ogg_free(cpi->ConvDestBuffer );  cpi->ConvDestBuffer = 0;  if(cpi->yuv0ptr)    _ogg_free(cpi->yuv0ptr);  cpi->yuv0ptr = 0;  if(cpi->yuv1ptr)    _ogg_free(cpi->yuv1ptr);  cpi->yuv1ptr = 0;  if(cpi->OptimisedTokenListEb )    _ogg_free(cpi->OptimisedTokenListEb);  cpi->OptimisedTokenListEb = 0;  if(cpi->OptimisedTokenList )    _ogg_free(cpi->OptimisedTokenList);  cpi->OptimisedTokenList = 0;  if(cpi->OptimisedTokenListHi )    _ogg_free(cpi->OptimisedTokenListHi);  cpi->OptimisedTokenListHi = 0;  if(cpi->OptimisedTokenListPl )    _ogg_free(cpi->OptimisedTokenListPl);  cpi->OptimisedTokenListPl = 0;}static void EInitFrameInfo(CP_INSTANCE * cpi){  int FrameSize = cpi->pb.ReconYPlaneSize + 2 * cpi->pb.ReconUVPlaneSize;  /* clear any existing info */  EClearFrameInfo(cpi);  /* allocate frames */  cpi->ConvDestBuffer =    _ogg_malloc(FrameSize*                sizeof(*cpi->ConvDestBuffer));  cpi->yuv0ptr =    _ogg_malloc(FrameSize*                sizeof(*cpi->yuv0ptr));  cpi->yuv1ptr =    _ogg_malloc(FrameSize*                sizeof(*cpi->yuv1ptr));  cpi->OptimisedTokenListEb =    _ogg_malloc(FrameSize*                sizeof(*cpi->OptimisedTokenListEb));  cpi->OptimisedTokenList =    _ogg_malloc(FrameSize*                sizeof(*cpi->OptimisedTokenList));  cpi->OptimisedTokenListHi =    _ogg_malloc(FrameSize*                sizeof(*cpi->OptimisedTokenListHi));  cpi->OptimisedTokenListPl =    _ogg_malloc(FrameSize*                sizeof(*cpi->OptimisedTokenListPl));}static void SetupKeyFrame(CP_INSTANCE *cpi) {  /* Make sure the "last frame" buffer contains the first frame data     as well. */  memcpy ( cpi->yuv0ptr, cpi->yuv1ptr,           cpi->pb.ReconYPlaneSize + 2 * cpi->pb.ReconUVPlaneSize );  /* Initialise the cpi->pb.display_fragments and other fragment     structures for the first frame. */  memset( cpi->pb.display_fragments, 1, cpi->pb.UnitFragments );  memset( cpi->extra_fragments, 1, cpi->pb.UnitFragments );  /* Set up for a KEY FRAME */  SetFrameType( &cpi->pb,KEY_FRAME );}static void AdjustKeyFrameContext(CP_INSTANCE *cpi) {  ogg_uint32_t i;  ogg_uint32_t  AvKeyFrameFrequency =    (ogg_uint32_t) (cpi->CurrentFrame / cpi->KeyFrameCount);  ogg_uint32_t  AvKeyFrameBytes =    (ogg_uint32_t) (cpi->TotKeyFrameBytes / cpi->KeyFrameCount);  ogg_uint32_t TotalWeight=0;  ogg_int32_t AvKeyFramesPerSecond;  ogg_int32_t MinFrameTargetRate;  /* Update the frame carry over. */  cpi->TotKeyFrameBytes += oggpackB_bytes(cpi->oggbuffer);  /* reset keyframe context and calculate weighted average of last     KEY_FRAME_CONTEXT keyframes */  for( i = 0 ; i < KEY_FRAME_CONTEXT ; i ++ ) {    if ( i < KEY_FRAME_CONTEXT -1) {      cpi->PriorKeyFrameSize[i] = cpi->PriorKeyFrameSize[i+1];      cpi->PriorKeyFrameDistance[i] = cpi->PriorKeyFrameDistance[i+1];    } else {      cpi->PriorKeyFrameSize[KEY_FRAME_CONTEXT - 1] =        oggpackB_bytes(cpi->oggbuffer);      cpi->PriorKeyFrameDistance[KEY_FRAME_CONTEXT - 1] =        cpi->LastKeyFrame;    }    AvKeyFrameBytes += PriorKeyFrameWeight[i] *      cpi->PriorKeyFrameSize[i];    AvKeyFrameFrequency += PriorKeyFrameWeight[i] *      cpi->PriorKeyFrameDistance[i];    TotalWeight += PriorKeyFrameWeight[i];  }  AvKeyFrameBytes /= TotalWeight;  AvKeyFrameFrequency /= TotalWeight;  AvKeyFramesPerSecond =  100 * cpi->Configuration.OutputFrameRate /    AvKeyFrameFrequency ;  /* Calculate a new target rate per frame allowing for average key     frame frequency over newest frames . */  if ( 100 * cpi->Configuration.TargetBandwidth >       AvKeyFrameBytes * AvKeyFramesPerSecond &&       (100 * cpi->Configuration.OutputFrameRate - AvKeyFramesPerSecond )){    cpi->frame_target_rate =      (ogg_int32_t)(100* cpi->Configuration.TargetBandwidth -                    AvKeyFrameBytes * AvKeyFramesPerSecond ) /      ( (100 * cpi->Configuration.OutputFrameRate - AvKeyFramesPerSecond ) );  } else {    /* don't let this number get too small!!! */    cpi->frame_target_rate = 1;  }  /* minimum allowable frame_target_rate */  MinFrameTargetRate = (cpi->Configuration.TargetBandwidth /                        cpi->Configuration.OutputFrameRate) / 3;  if(cpi->frame_target_rate < MinFrameTargetRate ) {    cpi->frame_target_rate = MinFrameTargetRate;  }  cpi->LastKeyFrame = 1;  cpi->LastKeyFrameSize=oggpackB_bytes(cpi->oggbuffer);}static void UpdateFrame(CP_INSTANCE *cpi){  double CorrectionFactor;  /* Reset the DC predictors. */  cpi->pb.LastIntraDC = 0;  cpi->pb.InvLastIntraDC = 0;  cpi->pb.LastInterDC = 0;  cpi->pb.InvLastInterDC = 0;  /* Initialise bit packing mechanism. */#ifndef LIBOGG2  oggpackB_reset(cpi->oggbuffer);#else  oggpackB_writeinit(cpi->oggbuffer, cpi->oggbufferstate);#endif  /* mark as video frame */  oggpackB_write(cpi->oggbuffer,0,1);  /* Write out the frame header information including size. */  WriteFrameHeader(cpi);  /* Copy back any extra frags that are to be updated by the codec     as part of the background cleanup task */  CopyBackExtraFrags(cpi);  /* Encode the data.  */  EncodeData(cpi);  /* Adjust drop frame trigger. */  if ( GetFrameType(&cpi->pb) != KEY_FRAME ) {    /* Apply decay factor then add in the last frame size. */    cpi->DropFrameTriggerBytes =      ((cpi->DropFrameTriggerBytes * (DF_CANDIDATE_WINDOW-1)) /       DF_CANDIDATE_WINDOW) + oggpackB_bytes(cpi->oggbuffer);  }else{    /* Increase cpi->DropFrameTriggerBytes a little. Just after a key       frame may actually be a good time to drop a frame. */    cpi->DropFrameTriggerBytes =      (cpi->DropFrameTriggerBytes * DF_CANDIDATE_WINDOW) /      (DF_CANDIDATE_WINDOW-1);  }  /* Test for overshoot which may require a dropped frame next time     around.  If we are already in a drop frame condition but the     previous frame was not dropped then the threshold for continuing     to allow dropped frames is reduced. */  if ( cpi->DropFrameCandidate ) {    if ( cpi->DropFrameTriggerBytes >         (cpi->frame_target_rate * (DF_CANDIDATE_WINDOW+1)) )      cpi->DropFrameCandidate = 1;    else      cpi->DropFrameCandidate = 0;  } else {    if ( cpi->DropFrameTriggerBytes >         (cpi->frame_target_rate * ((DF_CANDIDATE_WINDOW*2)-2)) )      cpi->DropFrameCandidate = 1;    else      cpi->DropFrameCandidate = 0;  }  /* Update the BpbCorrectionFactor variable according to whether or     not we were close enough with our selection of DCT quantiser.  */  if ( GetFrameType(&cpi->pb) != KEY_FRAME ) {    /* Work out a size correction factor. */    CorrectionFactor = (double)oggpackB_bytes(cpi->oggbuffer) /      (double)cpi->ThisFrameTargetBytes;    if ( (CorrectionFactor > 1.05) &&         (cpi->pb.ThisFrameQualityValue <          cpi->pb.QThreshTable[cpi->Configuration.ActiveMaxQ]) ) {      CorrectionFactor = 1.0 + ((CorrectionFactor - 1.0)/2);      if ( CorrectionFactor > 1.5 )        cpi->BpbCorrectionFactor *= 1.5;      else        cpi->BpbCorrectionFactor *= CorrectionFactor;      /* Keep BpbCorrectionFactor within limits */      if ( cpi->BpbCorrectionFactor > MAX_BPB_FACTOR )        cpi->BpbCorrectionFactor = MAX_BPB_FACTOR;    } else if ( (CorrectionFactor < 0.95) &&                (cpi->pb.ThisFrameQualityValue > VERY_BEST_Q) ){      CorrectionFactor = 1.0 - ((1.0 - CorrectionFactor)/2);      if ( CorrectionFactor < 0.75 )        cpi->BpbCorrectionFactor *= 0.75;      else        cpi->BpbCorrectionFactor *= CorrectionFactor;      /* Keep BpbCorrectionFactor within limits */      if ( cpi->BpbCorrectionFactor < MIN_BPB_FACTOR )        cpi->BpbCorrectionFactor = MIN_BPB_FACTOR;    }  }  /* Adjust carry over and or key frame context. */  if ( GetFrameType(&cpi->pb) == KEY_FRAME ) {    /* Adjust the key frame context unless the key frame was very small */    AdjustKeyFrameContext(cpi);  } else {    /* Update the frame carry over */    cpi->CarryOver += ((ogg_int32_t)cpi->frame_target_rate -                       (ogg_int32_t)oggpackB_bytes(cpi->oggbuffer));  }  cpi->TotalByteCount += oggpackB_bytes(cpi->oggbuffer);}static void CompressFirstFrame(CP_INSTANCE *cpi) {  ogg_uint32_t i;

⌨️ 快捷键说明

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