[xiph-commits] r16304 - in branches/theora-thusnelda: examples lib/enc

xiphmont at svn.xiph.org xiphmont at svn.xiph.org
Sat Jul 18 13:53:13 PDT 2009


Author: xiphmont
Date: 2009-07-18 13:53:13 -0700 (Sat, 18 Jul 2009)
New Revision: 16304

Modified:
   branches/theora-thusnelda/examples/Makefile.am
   branches/theora-thusnelda/lib/enc/analyze.c
   branches/theora-thusnelda/lib/enc/encint.h
   branches/theora-thusnelda/lib/enc/encode.c
   branches/theora-thusnelda/lib/enc/mcenc.c
   branches/theora-thusnelda/lib/enc/rate.c
Log:
Commit drop-frame support for rate control

Adjust MV handling to predict across dropped frames

Correct minor MV bugs that had nearly-negligable bitrate/psnr effects

eliminate accel prediction weighting in MV candidate calc; it
  had only been needed to begin with because GOLD accel was being
  calculated incorrectly

Minor Makefile.am fix in examples; don't explicitly set dependencies
(not setting the lib depndencies means nothing gets rebuilt on lib
changes, bad in static builds)



Modified: branches/theora-thusnelda/examples/Makefile.am
===================================================================
--- branches/theora-thusnelda/examples/Makefile.am	2009-07-18 20:33:54 UTC (rev 16303)
+++ branches/theora-thusnelda/examples/Makefile.am	2009-07-18 20:53:13 UTC (rev 16304)
@@ -15,12 +15,10 @@
 dump_video_SOURCES = dump_video.c
 EXTRA_dump_video_SOURCES = getopt.c getopt1.c getopt.h
 dump_video_LDADD = $(GETOPT_OBJS) $(LDADDDEC)
-dump_video_DEPENDENCIES = $(GETOPT_OBJS)
 
 dump_psnr_SOURCES = dump_psnr.c
 EXTRA_dump_psnr_SOURCES = getopt.c getopt1.c getopt.h
 dump_psnr_LDADD = $(GETOPT_OBJS) $(LDADDDEC) -lm
-dump_psnr_DEPENDENCIES = $(GETOPT_OBJS)
 
 player_example_SOURCES = player_example.c
 player_example_CFLAGS = $(SDL_CFLAGS) $(OGG_CFLAGS) $(VORBIS_CFLAGS)
@@ -30,12 +28,10 @@
 EXTRA_encoder_example_SOURCES = getopt.c getopt1.c getopt.h
 encoder_example_CFLAGS = $(OGG_CFLAGS) $(VORBIS_CFLAGS)
 encoder_example_LDADD = $(GETOPT_OBJS) $(LDADDENC) $(VORBIS_LIBS) $(VORBISENC_LIBS)
-encoder_example_DEPENDENCIES = $(GETOPT_OBJS)
 
 png2theora_SOURCES = png2theora.c
 png2theora_CFLAGS = $(OGG_CFLAGS) $(PNG_CFLAGS)
 png2theora_LDADD = $(GETOPT_OBJS) $(LDADD) $(PNG_LIBS)
-png2theora_DEPENDENCIES = $(GETOPT_OBJS)
 
 debug:
 	$(MAKE) all CFLAGS="@DEBUG@"

Modified: branches/theora-thusnelda/lib/enc/analyze.c
===================================================================
--- branches/theora-thusnelda/lib/enc/analyze.c	2009-07-18 20:33:54 UTC (rev 16303)
+++ branches/theora-thusnelda/lib/enc/analyze.c	2009-07-18 20:53:13 UTC (rev 16304)
@@ -1197,7 +1197,6 @@
   int                     pli;
   set_chroma_mvs=OC_SET_CHROMA_MVS_TABLE[_enc->state.info.pixel_fmt];
   _enc->state.frame_type=_frame_type;
-  if(!_recode&&_enc->state.curframe_num>0)oc_mcenc_start(_enc,&mcenc);
   oc_mode_scheme_chooser_reset(&_enc->chooser);
   oc_enc_tokenize_start(_enc);
   oc_enc_pipeline_init(_enc,&pipe);
@@ -1257,13 +1256,44 @@
           /*Motion estimation:
             We always do a basic 1MV search for all macroblocks, coded or not,
              keyframe or not.*/
+          int accumP[2]={0,0};
+          int accumG[2]={0,0};
+          if(_enc->prevframe_dropped){
+            accumP[0] = embs[mbi].analysis_mv[0][OC_FRAME_PREV][0];
+            accumP[1] = embs[mbi].analysis_mv[0][OC_FRAME_PREV][1];
+          }
+          accumG[0]=embs[mbi].analysis_mv[2][OC_FRAME_GOLD][0];
+          accumG[1]=embs[mbi].analysis_mv[2][OC_FRAME_GOLD][1];
+
+          embs[mbi].analysis_mv[0][OC_FRAME_PREV][0] -= embs[mbi].analysis_mv[2][OC_FRAME_PREV][0];
+          embs[mbi].analysis_mv[0][OC_FRAME_PREV][1] -= embs[mbi].analysis_mv[2][OC_FRAME_PREV][1];
+
           /*Move the motion vector predictors back a frame.*/
           memmove(embs[mbi].analysis_mv+1,
-           embs[mbi].analysis_mv,2*sizeof(embs[mbi].analysis_mv[0]));
+                  embs[mbi].analysis_mv,2*sizeof(embs[mbi].analysis_mv[0]));
+
           /*Search the last frame.*/
-          oc_mcenc_search(_enc,&mcenc,mbi,OC_FRAME_PREV);
+          oc_mcenc_search(_enc,&mcenc,accumP,mbi,OC_FRAME_PREV);
+          embs[mbi].analysis_mv[2][OC_FRAME_PREV][0]=accumP[0];
+          embs[mbi].analysis_mv[2][OC_FRAME_PREV][1]=accumP[1];
+
+          /* GOLDEN mvs are different from PREV mvs in that they're
+             each absolute offsets from some frame in the past rather
+             than relative offsets from the frame before.  For
+             predictor calculation to make sense, we need them to be
+             in the same form as PREV mvs */
+          embs[mbi].analysis_mv[1][OC_FRAME_GOLD][0]-=embs[mbi].analysis_mv[2][OC_FRAME_GOLD][0];
+          embs[mbi].analysis_mv[1][OC_FRAME_GOLD][1]-=embs[mbi].analysis_mv[2][OC_FRAME_GOLD][1];
+          embs[mbi].analysis_mv[2][OC_FRAME_GOLD][0]-=accumG[0];
+          embs[mbi].analysis_mv[2][OC_FRAME_GOLD][1]-=accumG[1];
           /*Search the golden frame.*/
-          oc_mcenc_search(_enc,&mcenc,mbi,OC_FRAME_GOLD);
+          oc_mcenc_search(_enc,&mcenc,accumG,mbi,OC_FRAME_GOLD);
+          /*Put GOLDEN mvs back into absolute offset form.  Newest MV is already an absolute offset*/
+          embs[mbi].analysis_mv[2][OC_FRAME_GOLD][0]+=accumG[0];
+          embs[mbi].analysis_mv[2][OC_FRAME_GOLD][1]+=accumG[1];
+          embs[mbi].analysis_mv[1][OC_FRAME_GOLD][0]+=embs[mbi].analysis_mv[2][OC_FRAME_GOLD][0];
+          embs[mbi].analysis_mv[1][OC_FRAME_GOLD][1]+=embs[mbi].analysis_mv[2][OC_FRAME_GOLD][1];
+
         }
         dx=dy=0;
         if(_enc->state.frame_type==OC_INTRA_FRAME){

Modified: branches/theora-thusnelda/lib/enc/encint.h
===================================================================
--- branches/theora-thusnelda/lib/enc/encint.h	2009-07-18 20:33:54 UTC (rev 16303)
+++ branches/theora-thusnelda/lib/enc/encint.h	2009-07-18 20:53:13 UTC (rev 16304)
@@ -193,8 +193,8 @@
 
 void oc_enc_calc_lambda(oc_enc_ctx *_enc,int _frame_type);
 void oc_rc_state_init(oc_rc_state *_rc,const oc_enc_ctx *_enc);
-void oc_enc_update_rc_state(oc_enc_ctx *_enc,
- long _bits,int _qti,int _qi,int _trial);
+int oc_enc_update_rc_state(oc_enc_ctx *_enc,
+  long _bits,int _qti,int _qi,int _trial,int _droppable);
 int oc_enc_select_qi(oc_enc_ctx *_enc,int _qti,int _clamp);
 
 
@@ -230,6 +230,8 @@
   unsigned char            vp3_compatible;
   /*Whether or not any INTER frames have been coded.*/
   unsigned char            coded_inter_frame;
+  /*Whether or not previous frame was dropped.*/
+  unsigned char            prevframe_dropped;
   /*Stores most recently chosen Huffman tables for each frame type, DC and AC
      coefficients, and luma and chroma tokens.
     The actual Huffman table used for a given coefficient depends not only on
@@ -295,17 +297,10 @@
   int                setb0;
   /*The total number of candidates.*/
   int                ncandidates;
-  /*Accelerated predictor weights for each frame type.*/
-  ogg_int32_t        mvapw1[2];
-  ogg_int32_t        mvapw2[2];
 };
 
-
-/*Prep the motion search for the next frame.*/
-void oc_mcenc_start(oc_enc_ctx *_enc,oc_mcenc_ctx *_mcenc);
-
 /*Search for a single MB MV (and with OC_FRAME_PREV, block MVs) in one frame.*/
-void oc_mcenc_search(oc_enc_ctx *_enc,oc_mcenc_ctx *_mcenc,int _mbi,int _frame);
+void oc_mcenc_search(oc_enc_ctx *_enc,oc_mcenc_ctx *_mcenc,int acc[2],int _mbi,int _frame);
 /*Refine a MB MV for one frame.*/
 void oc_mcenc_refine1mv(oc_enc_ctx *_enc,int _mbi,int _frame);
 /*Refine the block MVs.*/

Modified: branches/theora-thusnelda/lib/enc/encode.c
===================================================================
--- branches/theora-thusnelda/lib/enc/encode.c	2009-07-18 20:33:54 UTC (rev 16303)
+++ branches/theora-thusnelda/lib/enc/encode.c	2009-07-18 20:53:13 UTC (rev 16304)
@@ -936,6 +936,15 @@
   oc_state_clear(&_enc->state);
 }
 
+static void oc_enc_drop_frame(th_enc_ctx *_enc){
+  /* use the previous frame's reconstruction */
+  _enc->state.ref_frame_idx[OC_FRAME_SELF]=
+    _enc->state.ref_frame_idx[OC_FRAME_PREV];
+  /* flag motion vector analysis about the frame drop */
+  _enc->prevframe_dropped=1;
+  /* zero the packet */
+  oggpackB_reset(&_enc->opb);
+}
 
 static void oc_enc_compress_keyframe(oc_enc_ctx *_enc,int _recode){
   if(_enc->state.info.target_bitrate>0){
@@ -951,7 +960,7 @@
   if(!_recode&&_enc->state.curframe_num==0){
     if(_enc->state.info.target_bitrate>0){
       oc_enc_update_rc_state(_enc,oggpackB_bytes(&_enc->opb)<<3,
-       OC_INTRA_FRAME,_enc->state.qis[0],1);
+                             OC_INTRA_FRAME,_enc->state.qis[0],1,0);
     }
     oc_enc_compress_keyframe(_enc,1);
   }
@@ -974,8 +983,9 @@
          prime feed-forward statistics.*/
       _enc->coded_inter_frame=1;
       if(_enc->state.info.target_bitrate>0){
+        /* rate control also needs to prime */
         oc_enc_update_rc_state(_enc,oggpackB_bytes(&_enc->opb)<<3,
-         OC_INTER_FRAME,_enc->state.qis[0],1);
+                               OC_INTER_FRAME,_enc->state.qis[0],1,0);
       }
       oc_enc_compress_frame(_enc,1);
     }
@@ -1206,6 +1216,7 @@
   }
 }
 
+#include<stdio.h>
 int th_encode_ycbcr_in(th_enc_ctx *_enc,th_ycbcr_buffer _img){
   th_ycbcr_buffer img;
   int             cframe_width;
@@ -1218,6 +1229,7 @@
   int             vdec;
   int             pli;
   int             refi;
+  int             drop=0;
   /*Step 1: validate parameters.*/
   if(_enc==NULL||_img==NULL)return TH_EFAULT;
   if(_enc->packet_state==OC_PACKET_DONE)return TH_EINVAL;
@@ -1276,16 +1288,28 @@
    _enc->state.curframe_num-_enc->state.keyframe_num+_enc->dup_count>=
    _enc->keyframe_frequency_force){
     oc_enc_compress_keyframe(_enc,0);
+  }else{
+    oc_enc_compress_frame(_enc,0);
+    drop=1;
   }
-  /*Compress the frame.*/
-  else oc_enc_compress_frame(_enc,0);
   oc_restore_fpu(&_enc->state);
-  /*Update state variables.*/
+
+  /* drop is currently indicating if the frame is droppable.*/
+  if(_enc->state.info.target_bitrate>0)
+    drop=oc_enc_update_rc_state(_enc,oggpackB_bytes(&_enc->opb)<<3,
+                                _enc->state.frame_type,_enc->state.qis[0],0,drop);
+  else
+    drop=0;
+  /* drop now indicates if the frame was dropped */
+
+  if(drop){
+    oc_enc_drop_frame(_enc);
+    _enc->prevframe_dropped=1;
+  }else{
+    _enc->prevframe_dropped=0;
+  }
+
   _enc->packet_state=OC_PACKET_READY;
-  if(_enc->state.info.target_bitrate>0){
-    oc_enc_update_rc_state(_enc,oggpackB_bytes(&_enc->opb)<<3,
-     _enc->state.frame_type,_enc->state.qis[0],0);
-  }
   _enc->prev_dup_count=_enc->nqueued_dups=_enc->dup_count;
   _enc->dup_count=0;
 #if defined(OC_DUMP_IMAGES)

Modified: branches/theora-thusnelda/lib/enc/mcenc.c
===================================================================
--- branches/theora-thusnelda/lib/enc/mcenc.c	2009-07-18 20:33:54 UTC (rev 16303)
+++ branches/theora-thusnelda/lib/enc/mcenc.c	2009-07-18 20:53:13 UTC (rev 16304)
@@ -69,25 +69,9 @@
   {0,1,3}
 };
 
-
-void oc_mcenc_start(oc_enc_ctx *_enc,oc_mcenc_ctx *_mcenc){
-  ogg_int64_t nframes;
-  /*Set up the accelerated MV weights for previous frame prediction.*/
-  _mcenc->mvapw1[OC_FRAME_PREV]=(ogg_int32_t)1<<17;
-  _mcenc->mvapw2[OC_FRAME_PREV]=(ogg_int32_t)1<<16;
-  /*Set up the accelerated MV weights for golden frame prediction.*/
-  nframes=_enc->state.curframe_num-_enc->state.keyframe_num;
-  _mcenc->mvapw1[OC_FRAME_GOLD]=(ogg_int32_t)(
-   nframes!=1?(nframes<<17)/(nframes-1):0);
-  _mcenc->mvapw2[OC_FRAME_GOLD]=(ogg_int32_t)(
-   nframes!=2?(nframes<<16)/(nframes-2):0);
-}
-
 static void oc_mcenc_find_candidates(oc_enc_ctx *_enc,oc_mcenc_ctx *_mcenc,
- int _mbi,int _frame){
+                                     int _accum[2], int _mbi,int _frame){
   oc_mb_enc_info *embs;
-  ogg_int32_t     mvapw1;
-  ogg_int32_t     mvapw2;
   int             a[3][2];
   int             ncandidates;
   unsigned        nmbi;
@@ -106,11 +90,11 @@
     }
     /*Add a few additional vectors to set A: the vector used in the
        previous frame and the (0,0) vector.*/
-    _mcenc->candidates[ncandidates][0]=embs[_mbi].analysis_mv[1][_frame][0];
-    _mcenc->candidates[ncandidates][1]=embs[_mbi].analysis_mv[1][_frame][1];
+    _mcenc->candidates[ncandidates][0]=OC_CLAMPI(-31,embs[_mbi].analysis_mv[1][_frame][0]+_accum[0],31);
+    _mcenc->candidates[ncandidates][1]=OC_CLAMPI(-31,embs[_mbi].analysis_mv[1][_frame][1]+_accum[1],31);
     ncandidates++;
-    _mcenc->candidates[ncandidates][0]=0;
-    _mcenc->candidates[ncandidates][1]=0;
+    _mcenc->candidates[ncandidates][0]=OC_CLAMPI(-31,_accum[0],31);
+    _mcenc->candidates[ncandidates][1]=OC_CLAMPI(-31,_accum[1],31);
     ncandidates++;
     /*Use the first three vectors of set A to find our best predictor: their
        median.*/
@@ -128,30 +112,30 @@
     /*The upper-left most macro block has no neighbors at all
       We just use 0,0 as the median predictor and its previous motion vector
        for set A.*/
-    _mcenc->candidates[0][0]=0;
-    _mcenc->candidates[0][1]=1;
-    _mcenc->candidates[1][0]=embs[_mbi].analysis_mv[1][_frame][0];
-    _mcenc->candidates[1][1]=embs[_mbi].analysis_mv[1][_frame][1];
+    _mcenc->candidates[0][0]=OC_CLAMPI(-31,_accum[0],31);
+    _mcenc->candidates[0][1]=OC_CLAMPI(-31,_accum[1],31);
+    _mcenc->candidates[1][0]=OC_CLAMPI(-31,embs[_mbi].analysis_mv[1][_frame][0]+_accum[0],31);
+    _mcenc->candidates[1][1]=OC_CLAMPI(-31,embs[_mbi].analysis_mv[1][_frame][1]+_accum[1],31);
     ncandidates=2;
   }
+
   /*Fill in set B: accelerated predictors for this and adjacent macro
-     blocks.*/
+    blocks.*/
   _mcenc->setb0=ncandidates;
-  mvapw1=_mcenc->mvapw1[_frame];
-  mvapw2=_mcenc->mvapw2[_frame];
   /*The first time through the loop use the current macro block.*/
   nmbi=_mbi;
   for(i=0;;i++){
-    _mcenc->candidates[ncandidates][0]=OC_CLAMPI(-31,
-     OC_DIV_POW2_RE(embs[nmbi].analysis_mv[1][_frame][0]*mvapw1
-     -embs[nmbi].analysis_mv[2][_frame][0]*mvapw2,16),31);
-    _mcenc->candidates[ncandidates][1]=OC_CLAMPI(-31,
-     OC_DIV_POW2_RE(embs[nmbi].analysis_mv[1][_frame][1]*mvapw1
-     -embs[nmbi].analysis_mv[2][_frame][1]*mvapw2,16),31);
+    _mcenc->candidates[ncandidates][0]=
+      OC_CLAMPI(-31, 2*embs[_mbi].analysis_mv[1][_frame][0]-
+                embs[_mbi].analysis_mv[2][_frame][0]+_accum[0], 31);
+    _mcenc->candidates[ncandidates][1]=
+      OC_CLAMPI(-31, 2*embs[_mbi].analysis_mv[1][_frame][1]-
+                embs[_mbi].analysis_mv[2][_frame][1]+_accum[1], 31);
     ncandidates++;
     if(i>=embs[_mbi].npneighbors)break;
     nmbi=embs[_mbi].pneighbors[i];
   }
+
   /*Truncate to full-pel positions.*/
   for(i=0;i<ncandidates;i++){
     _mcenc->candidates[i][0]=OC_DIV2(_mcenc->candidates[i][0]);
@@ -246,9 +230,10 @@
   The actual motion vector is stored in the appropriate place in the
    oc_mb_enc_info structure.
   _mcenc:    The motion compensation context.
+  _accum:    drop frame/golden mv accumulators
   _mbi:      The macro block index.
   _frame:    The frame to search, either OC_FRAME_PREV or OC_FRAME_GOLD.*/
-void oc_mcenc_search(oc_enc_ctx *_enc,oc_mcenc_ctx *_mcenc,int _mbi,int _frame){
+void oc_mcenc_search(oc_enc_ctx *_enc,oc_mcenc_ctx *_mcenc,int _accum[2],int _mbi,int _frame){
   /*Note: Traditionally this search is done using a rate-distortion objective
      function of the form D+lambda*R.
     However, xiphmont tested this and found it produced a small degredation,
@@ -282,7 +267,7 @@
   int                  bi;
   embs=_enc->mb_info;
   /*Find some candidate motion vectors.*/
-  oc_mcenc_find_candidates(_enc,_mcenc,_mbi,_frame);
+  oc_mcenc_find_candidates(_enc,_mcenc,_accum,_mbi,_frame);
   /*Clear the cache of locations we've examined.*/
   memset(hit_cache,0,sizeof(hit_cache));
   /*Start with the median predictor.*/

Modified: branches/theora-thusnelda/lib/enc/rate.c
===================================================================
--- branches/theora-thusnelda/lib/enc/rate.c	2009-07-18 20:33:54 UTC (rev 16303)
+++ branches/theora-thusnelda/lib/enc/rate.c	2009-07-18 20:53:13 UTC (rev 16304)
@@ -129,15 +129,26 @@
   _rc->log_drop_scale=OC_Q57(0);
 }
 
-void oc_enc_update_rc_state(oc_enc_ctx *_enc,
- long _bits,int _qti,int _qi,int _trial){
+int oc_enc_update_rc_state(oc_enc_ctx *_enc,
+                           long _bits,int _qti,int _qi,int _trial,int _droppable){
+
   /*Note, setting OC_SCALE_SMOOTHING[1] to 0x80 (0.5), which one might expect
-     to be a reasonable value, actually causes a feedback loop with, e.g., 12
-     fps content encoded at 24 fps; use values near 0 or near 1 for now.
+    to be a reasonable value, actually causes a feedback loop with, e.g., 12
+    fps content encoded at 24 fps; use values near 0 or near 1 for now.
     TODO: Should probably revisit using an exponential moving average in the
-     first place at some point; dup tracking should help as well.*/
+    first place at some point; dup tracking should help as well.*/
   static const unsigned OC_SCALE_SMOOTHING[2]={0x13,0x00};
-  if(_bits>0){
+  int dropped=0;
+
+  if(_bits<=0){
+     /*  Update the buffering stats as if this dropped frame was a dup
+         of the previous frame. */
+    _enc->rc.prev_drop_count+=1+_enc->dup_count;
+    /*If this was the first frame of this type, lower the expected scale, but
+       don't set it to zero outright.*/
+    if(_trial)_enc->rc.log_scale[_qti]>>=1;
+    _bits=0;
+  }else{
     ogg_int64_t log_scale;
     ogg_int64_t log_bits;
     ogg_int64_t log_qexp;
@@ -150,29 +161,33 @@
     if(_trial)_enc->rc.log_scale[_qti]=log_scale;
     else{
       /*Otherwise update an exponential moving average.*/
+      /*log scale is updated regardless of dropping*/
       _enc->rc.log_scale[_qti]=log_scale
-       +(_enc->rc.log_scale[_qti]-log_scale+128>>8)*OC_SCALE_SMOOTHING[_qti];
-      /*And update a simple exponential moving average to estimate the "real"
-         frame rate taking drops and duplicates into account.*/
-      _enc->rc.log_drop_scale=_enc->rc.log_drop_scale
-       +oc_blog64(_enc->rc.prev_drop_count+1)>>1;
-      _enc->rc.prev_drop_count=_enc->dup_count;
+        +(_enc->rc.log_scale[_qti]-log_scale+128>>8)*OC_SCALE_SMOOTHING[_qti];
+      /* If this frame busts our budget, it must be dropped.*/
+      if(_droppable && _enc->rc.fullness+_enc->rc.bits_per_frame*
+         (1+_enc->dup_count)<_bits){
+        _enc->rc.prev_drop_count+=1+_enc->dup_count;
+        _bits=0;
+        dropped=1;
+      }else{
+        /*log_drop_scale is only updated if the frame is coded as it
+          needs final previous counts*/
+        /*update a simple exponential moving average to estimate the "real"
+          frame rate taking drops and duplicates into account.*/
+        _enc->rc.log_drop_scale=_enc->rc.log_drop_scale
+          +oc_blog64(_enc->rc.prev_drop_count+1)>>1;
+        _enc->rc.prev_drop_count=_enc->dup_count;
+      }
     }
   }
-  else{
-    /*We dropped this frame.*/
-    /*Add it to the previous frame's dup count.*/
-    _enc->rc.prev_drop_count+=1+_enc->dup_count;
-    /*If this was the first frame of this type, lower the expected scale, but
-       don't set it to zero outright.*/
-    if(_trial)_enc->rc.log_scale[_qti]>>=1;
-  }
   if(!_trial){
     /*And update the buffer fullness level.*/
     _enc->rc.fullness+=_enc->rc.bits_per_frame*(1+_enc->dup_count)-_bits;
     /*If we're too quick filling the buffer, that rate is lost forever.*/
     if(_enc->rc.fullness>_enc->rc.max)_enc->rc.fullness=_enc->rc.max;
   }
+  return dropped;
 }
 
 int oc_enc_select_qi(oc_enc_ctx *_enc,int _qti,int _clamp){
@@ -283,6 +298,7 @@
     if(log_scale0-log_qexp>log_hard_limit){
       log_qexp=log_scale0-log_hard_limit;
       log_qtarget=((log_qexp+(exp0>>1))/exp0<<6)+OC_Q57(2);
+      log_qtarget=OC_MINI(log_qtarget,OC_QUANT_MAX_LOG);
     }
   }
   qi=oc_enc_find_qi_for_target(_enc,_qti,old_qi,



More information about the commits mailing list