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

xiphmont at svn.xiph.org xiphmont at svn.xiph.org
Sun Jun 15 03:31:45 PDT 2008


Author: xiphmont
Date: 2008-06-15 03:31:44 -0700 (Sun, 15 Jun 2008)
New Revision: 15040

Modified:
   branches/theora-thusnelda/examples/player_example.c
   branches/theora-thusnelda/lib/enc/codec_internal.h
   branches/theora-thusnelda/lib/enc/encode.c
   branches/theora-thusnelda/lib/enc/encoder_lookup.h
   branches/theora-thusnelda/lib/enc/encoder_toplevel.c
   branches/theora-thusnelda/lib/enc/mcenc.c
   branches/theora-thusnelda/lib/enc/mode.c
Log:
Get initial RD-based skip determination into SVN.  Lambda currently 
hardwired.



Modified: branches/theora-thusnelda/examples/player_example.c
===================================================================
--- branches/theora-thusnelda/examples/player_example.c	2008-06-14 15:43:28 UTC (rev 15039)
+++ branches/theora-thusnelda/examples/player_example.c	2008-06-15 10:31:44 UTC (rev 15040)
@@ -591,11 +591,11 @@
     theora_control(&td,TH_DECCTL_SET_PPLEVEL,&pp_level,sizeof(pp_level));
     pp_inc=0;
 
-    {
+    /*{
       int arg = 0xffff;
       theora_control(&td,TH_DECCTL_SET_TELEMETRY_MBMODE,&arg,sizeof(arg));
       theora_control(&td,TH_DECCTL_SET_TELEMETRY_MV,&arg,sizeof(arg));
-    }
+      }*/
   }else{
     /* tear down the partial theora setup */
     theora_info_clear(&ti);

Modified: branches/theora-thusnelda/lib/enc/codec_internal.h
===================================================================
--- branches/theora-thusnelda/lib/enc/codec_internal.h	2008-06-14 15:43:28 UTC (rev 15039)
+++ branches/theora-thusnelda/lib/enc/codec_internal.h	2008-06-15 10:31:44 UTC (rev 15040)
@@ -129,6 +129,7 @@
   coding_mode_t mode;
 
   /* per-block final motion vectors */
+  /* raster order */
   mv_t mv[4];
 
   /* Motion vectors for a macro block for the current frame and the
@@ -270,6 +271,8 @@
   /********************************************************************/
   /* Setup */
   int              keyframe_granule_shift;
+  int              skip_lambda;
+  int              mv_lambda;
   int              BaseQ;
   int              GoldenFrameEnabled;
   int              InterPrediction;
@@ -325,13 +328,13 @@
 extern void oc_mcenc_start(CP_INSTANCE *cpi,
 			   mc_state *mcenc);
 
-extern int oc_mcenc_search(CP_INSTANCE *cpi, 
-			   mc_state *_mcenc,
-			   int _mbi,
-			   int _goldenp,
-			   mv_t *_bmvs,
-			   int *best_err,
-			   int best_block_err[4]);
+extern void oc_mcenc_search(CP_INSTANCE *cpi, 
+			    mc_state *_mcenc,
+			    int _mbi,
+			    int _goldenp,
+			    mv_t *_bmvs,
+			    int *best_err,
+			    int best_block_err[4]);
 
 extern void oc_mcenc_refine1mv(CP_INSTANCE *cpi, 
 			      int _mbi,

Modified: branches/theora-thusnelda/lib/enc/encode.c
===================================================================
--- branches/theora-thusnelda/lib/enc/encode.c	2008-06-14 15:43:28 UTC (rev 15039)
+++ branches/theora-thusnelda/lib/enc/encode.c	2008-06-15 10:31:44 UTC (rev 15040)
@@ -335,8 +335,14 @@
 
       if(mbp->mode==CODE_INTER_PLUS_MV || mbp->mode==CODE_GOLDEN_MV){
 	/* One MV for the macroblock */
-	oggpackB_write( opb, MvPatternPtr[mbp->mv[0].x], MvBitsPtr[mbp->mv[0].x] );
-	oggpackB_write( opb, MvPatternPtr[mbp->mv[0].y], MvBitsPtr[mbp->mv[0].y] );
+	for(B=0; B<4; B++ ){
+	  if(mbp->coded & (1<<B)){
+	    oggpackB_write( opb, MvPatternPtr[mbp->mv[B].x], MvBitsPtr[mbp->mv[B].x] );
+	    oggpackB_write( opb, MvPatternPtr[mbp->mv[B].y], MvBitsPtr[mbp->mv[B].y] );
+	    break;
+	  }
+	}
+
       }else if (mbp->mode == CODE_INTER_FOURMV){
 	/* MV for each codedblock */
 	for(B=0; B<4; B++ ){

Modified: branches/theora-thusnelda/lib/enc/encoder_lookup.h
===================================================================
--- branches/theora-thusnelda/lib/enc/encoder_lookup.h	2008-06-14 15:43:28 UTC (rev 15039)
+++ branches/theora-thusnelda/lib/enc/encoder_lookup.h	2008-06-15 10:31:44 UTC (rev 15040)
@@ -158,3 +158,4 @@
   2,  /* CODE_GOLDEN_MV       6 => Encoded diff from included MV MB golden frame */
   1   /* CODE_INTER_FOUR_MV   7 => Encoded diff from included 4 separate MV blocks */
 };
+

Modified: branches/theora-thusnelda/lib/enc/encoder_toplevel.c
===================================================================
--- branches/theora-thusnelda/lib/enc/encoder_toplevel.c	2008-06-14 15:43:28 UTC (rev 15039)
+++ branches/theora-thusnelda/lib/enc/encoder_toplevel.c	2008-06-15 10:31:44 UTC (rev 15040)
@@ -123,6 +123,10 @@
   if(c->target_bitrate<0)c->target_bitrate=0;
   cpi->BaseQ = c->quality;
 
+  /* temporary while the RD code is only partially complete */
+  cpi->skip_lambda=64;
+  cpi->mv_lambda=0;
+
   /* Set encoder flags. */
   /* if not AutoKeyframing cpi->ForceKeyFrameEvery = is frequency */
   if(!c->keyframe_auto_p)

Modified: branches/theora-thusnelda/lib/enc/mcenc.c
===================================================================
--- branches/theora-thusnelda/lib/enc/mcenc.c	2008-06-14 15:43:28 UTC (rev 15039)
+++ branches/theora-thusnelda/lib/enc/mcenc.c	2008-06-15 10:31:44 UTC (rev 15040)
@@ -368,7 +368,7 @@
    _frame:    The frame to search, either OC_FRAME_PREV or OC_FRAME_GOLD.
    _bmvs:     Returns the individual block motion vectors. */
 
-int oc_mcenc_search(CP_INSTANCE *cpi, 
+void oc_mcenc_search(CP_INSTANCE *cpi, 
 		    mc_state *_mcenc,
 		    int _mbi,
 		    int _goldenp,
@@ -385,7 +385,6 @@
   mv_t            best_block_vec[4];
   mv_t            cand;
   int             bi;
-  int             bflag=0;
   macroblock_t   *mb = &cpi->macro[_mbi];
 
   /*Find some candidate motion vectors.*/
@@ -548,7 +547,6 @@
 		  if(err<*best_err){
 		    *best_err=err;
 		    best_vec=cand;
-		    bflag=1;
 		  }
 		  for(bj=0;bj<4;bj++)
 		    if(block_err[bj]<best_block_err[bj]){
@@ -570,14 +568,12 @@
   mb->analysis_mv[0][_goldenp].x=best_vec.x<<1;;
   mb->analysis_mv[0][_goldenp].y=best_vec.y<<1;;
 
-  if(_bmvs && bflag){
+  if(_bmvs){
     for(bi=0;bi<4;bi++){
       _bmvs[bi].x=best_block_vec[bi].x<<1;
       _bmvs[bi].y=best_block_vec[bi].y<<1;
     }
   }
-
-  return bflag;
 }
 
 

Modified: branches/theora-thusnelda/lib/enc/mode.c
===================================================================
--- branches/theora-thusnelda/lib/enc/mode.c	2008-06-14 15:43:28 UTC (rev 15039)
+++ branches/theora-thusnelda/lib/enc/mode.c	2008-06-15 10:31:44 UTC (rev 15040)
@@ -181,7 +181,6 @@
   int ri;
   int si;
 
-  mb->mode = _mode;
   chooser->mode_counts[_mode]++;
 
   /* Re-order the scheme0 mode list if necessary. */
@@ -354,6 +353,28 @@
   return cost + (oc_mode_cost(cpi,mode) << OC_BIT_SCALE);
 }
 
+static int cost_inter_nomv(CP_INSTANCE *cpi, int qi, int mbi){
+  unsigned char *cp = cpi->frag_coded;
+  macroblock_t *mb = &cpi->macro[mbi];
+  int i,j;
+  int cost = 0;
+  for(i=0;i<3;i++){
+    for(j=0;j<4;j++){
+      int fi=mb->Ryuv[i][j];
+      if(cp[fi]){
+	int bi = cpi->frag_buffer_index[fi];
+	int stride = cpi->stride[i];  
+	int sad =  dsp_sad8x8 (cpi->dsp, cpi->frame+bi, cpi->lastrecon+bi, stride);
+
+	if(i)sad<<=2;
+	cost += BINMAP(mode_rate[qi][i][0],sad);
+	
+      }
+    }
+  }
+  return cost + (oc_mode_cost(cpi,CODE_INTER_NO_MV) << OC_BIT_SCALE);
+}
+
 static int cost_inter1mv(CP_INSTANCE *cpi, int qi, int mbi, int golden, int *bits0){
   unsigned char *cp = cpi->frag_coded;
   macroblock_t *mb = &cpi->macro[mbi];
@@ -419,28 +440,20 @@
   cost += (oc_mode_cost(cpi,CODE_INTER_FOURMV) << OC_BIT_SCALE);
 
   *bits0 = *bits1 = 0;
+
+  *bits0 += MvBits[mb->mv[0].x + MAX_MV_EXTENT] + 
+    MvBits[mb->mv[0].y+MAX_MV_EXTENT];
+  *bits1 += 12;
+  *bits0 += MvBits[mb->mv[1].x+MAX_MV_EXTENT] + 
+    MvBits[mb->mv[1].y+MAX_MV_EXTENT];
+  *bits1 += 12;
+  *bits0 += MvBits[mb->mv[2].x+MAX_MV_EXTENT] + 
+    MvBits[mb->mv[2].y+MAX_MV_EXTENT];
+  *bits1 += 12;
+  *bits0 += MvBits[mb->mv[3].x+MAX_MV_EXTENT] + 
+    MvBits[mb->mv[3].y+MAX_MV_EXTENT];
+  *bits1 += 12;
       
-  if(mb->coded & 1){
-    *bits0 += MvBits[mb->mv[0].x + MAX_MV_EXTENT] + 
-      MvBits[mb->mv[0].y+MAX_MV_EXTENT];
-    *bits1 += 12;
-  }
-  if(mb->coded & 2){
-    *bits0 += MvBits[mb->mv[1].x+MAX_MV_EXTENT] + 
-      MvBits[mb->mv[1].y+MAX_MV_EXTENT];
-    *bits1 += 12;
-  }
-  if(mb->coded & 4){
-    *bits0 += MvBits[mb->mv[2].x+MAX_MV_EXTENT] + 
-      MvBits[mb->mv[2].y+MAX_MV_EXTENT];
-    *bits1 += 12;
-  }
-  if(mb->coded & 8){
-    *bits0 += MvBits[mb->mv[3].x+MAX_MV_EXTENT] + 
-      MvBits[mb->mv[3].y+MAX_MV_EXTENT];
-    *bits1 += 12;
-  }
-      
   return cost + ((OC_MINI(cpi->MVBits_0 + *bits0, cpi->MVBits_1 + *bits1)-
 		  OC_MINI(cpi->MVBits_0, cpi->MVBits_1)) << OC_BIT_SCALE);
 }
@@ -489,126 +502,192 @@
 
 #include "quant_lookup.h"
 
-static void TQB (CP_INSTANCE *cpi, int mode, int fi, mv_t mv, int plane, ogg_int16_t re_q[2][3][64], long *rho_count){
-  if ( cpi->frag_coded[fi] ) {
-    int qi = cpi->BaseQ; /* temporary */;
-    int inter = (mode != CODE_INTRA);
-    ogg_int32_t *iq = cpi->iquant_tables[inter][plane][qi];
-    ogg_int16_t buffer[64];
-    ogg_int16_t *data = cpi->frag_dct[fi].data;
-    int bi = cpi->frag_buffer_index[fi];
-    int stride = cpi->stride[plane];
-    int xqp = (plane && cpi->info.pixelformat != OC_PF_444);
-    int yqp = (plane && cpi->info.pixelformat == OC_PF_420);
-    unsigned char *frame_ptr = &cpi->frame[bi];
-    unsigned char *lastrecon = ((mode == CODE_USING_GOLDEN || 
-				 mode == CODE_GOLDEN_MV) ? 
-				cpi->golden : cpi->lastrecon)+bi;
-    unsigned char *thisrecon = cpi->recon+bi;
-    int nonzero=63;
+#include <stdio.h>
 
-    /* motion comp */
-    switch(mode){
-    case CODE_INTER_PLUS_MV:
-    case CODE_INTER_LAST_MV:
-    case CODE_INTER_PRIOR_LAST:
-    case CODE_GOLDEN_MV:
-    case CODE_INTER_FOURMV:
+
+static int TQB (CP_INSTANCE *cpi, int mode, int fi, mv_t mv, int plane, ogg_int16_t re_q[2][3][64], 
+		 long *rho_count, int keyframe){
+
+  int qi = cpi->BaseQ; /* temporary */;
+  int inter = (mode != CODE_INTRA);
+  ogg_int32_t *iq = cpi->iquant_tables[inter][plane][qi];
+  ogg_int16_t buffer[64];
+  ogg_int16_t *data = cpi->frag_dct[fi].data;
+  int bi = cpi->frag_buffer_index[fi];
+  int stride = cpi->stride[plane];
+  int xqp = (plane && cpi->info.pixelformat != OC_PF_444);
+  int yqp = (plane && cpi->info.pixelformat == OC_PF_420);
+  unsigned char *frame_ptr = &cpi->frame[bi];
+  unsigned char *lastrecon = ((mode == CODE_USING_GOLDEN || 
+			       mode == CODE_GOLDEN_MV) ? 
+			      cpi->golden : cpi->lastrecon)+bi;
+  unsigned char *thisrecon = cpi->recon+bi;
+  int nonzero=63;
+  ogg_int16_t *dequant = re_q[inter][plane];
+  int uncoded_ssd=0,coded_ssd=0,sad=0;
+
+  /* motion comp */
+  switch(mode){
+  case CODE_INTER_PLUS_MV:
+  case CODE_INTER_LAST_MV:
+  case CODE_INTER_PRIOR_LAST:
+  case CODE_GOLDEN_MV:
+  case CODE_INTER_FOURMV:
+    
+    {    
+      int mx = mvmap[xqp][mv.x+31];
+      int my = mvmap[yqp][mv.y+31];
+      int mx2 = mvmap2[xqp][mv.x+31];
+      int my2 = mvmap2[yqp][mv.y+31];
       
-      {    
-	int mx = mvmap[xqp][mv.x+31];
-	int my = mvmap[yqp][mv.y+31];
-	int mx2 = mvmap2[xqp][mv.x+31];
-	int my2 = mvmap2[yqp][mv.y+31];
-	
-	unsigned char *r1 = lastrecon + my * stride + mx;
-	
-	if(mx2 || my2){
-	  unsigned char *r2 = r1 + my2 * stride + mx2;
-	  dsp_copy8x8_half (cpi->dsp, r1, r2, thisrecon, stride);
-	  dsp_sub8x8(cpi->dsp, frame_ptr, thisrecon, data, stride);
-	}else{
-	  dsp_copy8x8 (cpi->dsp, r1, thisrecon, stride);
-	  dsp_sub8x8(cpi->dsp, frame_ptr, r1, data, stride);
-	}
+      unsigned char *r1 = lastrecon + my * stride + mx;
+      
+      if(mx2 || my2){
+	unsigned char *r2 = r1 + my2 * stride + mx2;
+	dsp_copy8x8_half (cpi->dsp, r1, r2, thisrecon, stride);
+	dsp_sub8x8(cpi->dsp, frame_ptr, thisrecon, data, stride);
+      }else{
+	dsp_copy8x8 (cpi->dsp, r1, thisrecon, stride);
+	dsp_sub8x8(cpi->dsp, frame_ptr, r1, data, stride);
       }
-      break;
-      
-    case CODE_USING_GOLDEN:
-    case CODE_INTER_NO_MV:
-      dsp_copy8x8 (cpi->dsp, lastrecon, thisrecon, stride);
-      dsp_sub8x8(cpi->dsp, frame_ptr, lastrecon, data, stride);
-      break;
-    case CODE_INTRA:
-      dsp_sub8x8_128(cpi->dsp, frame_ptr, data, stride);
-      dsp_set8x8(cpi->dsp, 128, thisrecon, stride);
-      break;
     }
+    break;
+    
+  case CODE_USING_GOLDEN:
+  case CODE_INTER_NO_MV:
+    dsp_copy8x8 (cpi->dsp, lastrecon, thisrecon, stride);
+    dsp_sub8x8(cpi->dsp, frame_ptr, lastrecon, data, stride);
+    break;
+  case CODE_INTRA:
+    dsp_sub8x8_128(cpi->dsp, frame_ptr, data, stride);
+    dsp_set8x8(cpi->dsp, 128, thisrecon, stride);
+    break;
+  }
 
-    /* transform */
-    dsp_fdct_short(cpi->dsp, data, buffer);
+  if(!keyframe){
+    int i;
+    if(mode==CODE_INTER_NO_MV){
+      for(i=0;i<64;i++)
+	uncoded_ssd += data[i]*data[i];
+    }else{
+      dsp_sub8x8(cpi->dsp, frame_ptr, cpi->lastrecon+bi, buffer, stride);
+      for(i=0;i<64;i++)
+	uncoded_ssd += buffer[i]*buffer[i];
+    }
+
+    for(i=0;i<64;i++)
+      sad += abs(data[i]);
+
+    if(mode==CODE_INTRA){
+      sad >>=6;
+    }else{
+      if(plane)sad<<=2;
+    }
+  }
+
+  /* transform */
+  dsp_fdct_short(cpi->dsp, data, buffer);
+  
+  /* collect rho metrics, quantize */
+  {
+    int i;
+    quant_tables *qq = &(cpi->quant_tables[inter][plane]);
     
-    /* collect rho metrics, quantize */
-    {
-      /* modified rho-domain (track zero-runs as well) */
-	/* ZXZ; splits one zero run into two zero runs and a nonzero; +2
-	   ZXN; adds one nonzero token; +1
-	   NXZ; adds one nonzero token; +1
-	   NXN; replaces a zero run with a nonzero; +0  */
-      int i;
-      quant_tables *qq = &(cpi->quant_tables[inter][plane]);
+    for(i=0;i<64;i++){
+      int ii = dezigzag_index[i];
+      int pos;
+      int val = abs(buffer[ii])<<1;
+      ogg_int16_t *qqq = (*qq)[i];
+      for(pos=64;pos>0;pos--)
+	if(val < qqq[pos-1])break;
+      
+      /* rho-domain distribution */
+      rho_count[pos]++;
 
-      for(i=0;i<64;i++){
-	int ii = dezigzag_index[i];
-	int pos;
-	int val = abs(buffer[ii])<<1;
-	ogg_int16_t *qqq = (*qq)[i];
-	for(pos=64;pos>0;pos--)
-	  if(val < qqq[pos-1])break;
-	
-	/* rho-domain distribution */
-	rho_count[pos]++;
-
-	if(qi<pos){
-	  data[i] = 0;
-	}else{
-	  int val = (((iq[ii]>>15)*buffer[ii]) + (1<<15) + (((iq[ii]&0x7fff)*buffer[ii])>>15)) >>16;
-	  data[i] = (val>511?511:(val<-511?-511:val));
-	}
+      if(qi<pos){
+	data[i] = 0;
+      }else{
+	int val = (((iq[ii]>>15)*buffer[ii]) + (1<<15) + (((iq[ii]&0x7fff)*buffer[ii])>>15)) >>16;
+	data[i] = (val>511?511:(val<-511?-511:val));
       }
     }
+  }
+  
+  cpi->frag_dc[fi] = data[0];
+  
+  /* reconstruct */
+  while(!data[nonzero] && --nonzero);
+  switch(nonzero){
+  case 0:
+    IDct1( data, dequant, buffer );
+    break;
+  case 1: case 2:
+    dsp_IDct3(cpi->dsp, data, dequant, buffer );
+    break;
+  case 3:case 4:case 5:case 6:case 7:case 8: case 9:
+    dsp_IDct10(cpi->dsp, data, dequant, buffer );
+    break;
+  default:
+    dsp_IDctSlow(cpi->dsp, data, dequant, buffer );
+  }
+  
+  dsp_recon8x8 (cpi->dsp, thisrecon, buffer, stride);
 
-    cpi->frag_dc[fi] = data[0];
+  if(!keyframe){
+    int i;
+    int cost = BINMAP(mode_rate[qi][plane][mode==CODE_INTRA],sad);
+    if(cost<0)cost=0; /* some of the trained fits can return a negative cost for zero entropy */
 
-    /* reconstruct */
-    while(!data[nonzero] && --nonzero);
-    switch(nonzero){
-    case 0:
-      IDct1( data, re_q[inter][plane], buffer );
-      break;
-    case 1: case 2:
-      dsp_IDct3(cpi->dsp, data, re_q[inter][plane], buffer );
-      break;
-    case 3:case 4:case 5:case 6:case 7:case 8: case 9:
-      dsp_IDct10(cpi->dsp, data, re_q[inter][plane], buffer );
-      break;
-    default:
-      dsp_IDctSlow(cpi->dsp, data, re_q[inter][plane], buffer );
+    /* in retrospect, should we have skipped this block? */
+    /* we are free to apply any distortion measure we like as we have
+       the full original block and fully reconstructed block with
+       which to do so.*/
+    /* for now, straight up SSD */
+    dsp_sub8x8(cpi->dsp, frame_ptr, thisrecon, buffer, stride);    
+    for(i=0;i<64;i++)
+      coded_ssd += buffer[i]*buffer[i];
+
+    if(plane){
+      coded_ssd*=4;
+      uncoded_ssd*=4;
     }
     
-    dsp_recon8x8 (cpi->dsp, thisrecon, buffer, stride);
+    if(uncoded_ssd <= coded_ssd+((cpi->skip_lambda*cost)>>(OC_BIT_SCALE))){ 
+      /* mark uncoded */
+      cpi->frag_coded[fi]=0;
       
+      /* replace reconstruction with a block copy */
+      dsp_copy8x8 (cpi->dsp, cpi->lastrecon+bi, thisrecon, stride);
+      
+      return 0;
+    }
   }
+    
+
+  return 1;
 }
 
-static void TQMB ( CP_INSTANCE *cpi, macroblock_t *mb, int qi, ogg_int16_t req[2][3][64], long *rc){
+static int TQMB ( CP_INSTANCE *cpi, macroblock_t *mb, int qi, ogg_int16_t req[2][3][64], 
+		  long *rc, int keyframe){
   int pf = cpi->info.pixelformat;
   int mode = mb->mode;
   int i;
-
+  int coded=0;
+  
   for(i=0;i<4;i++)
-    TQB(cpi,mode,mb->Ryuv[0][i],mb->mv[i],0,req,rc);
+    if(TQB(cpi,mode,mb->Ryuv[0][i],mb->mv[i],0,req,rc,keyframe))
+      coded++;
+    else{
+      if(mode == CODE_INTER_FOURMV) 
+	mb->mv[i]=(mv_t){0,0};
+    }
 
+  if(coded==0){
+    mode = mb->mode = CODE_INTER_NO_MV; /* No luma blocks coded, mode is forced */
+    mb->coded = 0;
+    mb->mv[0] = mb->mv[1] = mb->mv[2] = mb->mv[3] = (mv_t){0,0};
+  }
+
   switch(pf){
   case OC_PF_420:
     if(mode == CODE_INTER_FOURMV){
@@ -620,11 +699,11 @@
       mv.x = ( mv.x >= 0 ? (mv.x + 2) / 4 : (mv.x - 2) / 4);
       mv.y = ( mv.y >= 0 ? (mv.y + 2) / 4 : (mv.y - 2) / 4);
       
-      TQB(cpi,mode,mb->Ryuv[1][0],mv,1,req,rc);
-      TQB(cpi,mode,mb->Ryuv[2][0],mv,2,req,rc);
+      coded+=TQB(cpi,mode,mb->Ryuv[1][0],mv,1,req,rc,keyframe);
+      coded+=TQB(cpi,mode,mb->Ryuv[2][0],mv,2,req,rc,keyframe);
     }else{ 
-      TQB(cpi,mode,mb->Ryuv[1][0],mb->mv[0],1,req,rc);
-      TQB(cpi,mode,mb->Ryuv[2][0],mb->mv[0],2,req,rc);
+      coded+=TQB(cpi,mode,mb->Ryuv[1][0],mb->mv[0],1,req,rc,keyframe);
+      coded+=TQB(cpi,mode,mb->Ryuv[2][0],mb->mv[0],2,req,rc,keyframe);
     }
     break;
 
@@ -642,26 +721,29 @@
       mvB.x = ( mvB.x >= 0 ? (mvB.x + 1) / 2 : (mvB.x - 1) / 2);
       mvB.y = ( mvB.y >= 0 ? (mvB.y + 1) / 2 : (mvB.y - 1) / 2);
       
-      TQB(cpi,mode,mb->Ryuv[1][0],mvA,1,req,rc);
-      TQB(cpi,mode,mb->Ryuv[1][1],mvB,1,req,rc);
-      TQB(cpi,mode,mb->Ryuv[2][0],mvA,2,req,rc);
-      TQB(cpi,mode,mb->Ryuv[2][1],mvB,2,req,rc);
+      coded+=TQB(cpi,mode,mb->Ryuv[1][0],mvA,1,req,rc,keyframe);
+      coded+=TQB(cpi,mode,mb->Ryuv[1][1],mvB,1,req,rc,keyframe);
+      coded+=TQB(cpi,mode,mb->Ryuv[2][0],mvA,2,req,rc,keyframe);
+      coded+=TQB(cpi,mode,mb->Ryuv[2][1],mvB,2,req,rc,keyframe);
 
     }else{ 
-      TQB(cpi,mode,mb->Ryuv[1][0],mb->mv[0],1,req,rc);
-      TQB(cpi,mode,mb->Ryuv[1][1],mb->mv[0],1,req,rc);
-      TQB(cpi,mode,mb->Ryuv[2][0],mb->mv[0],2,req,rc);
-      TQB(cpi,mode,mb->Ryuv[2][1],mb->mv[0],2,req,rc);
+      coded+=TQB(cpi,mode,mb->Ryuv[1][0],mb->mv[0],1,req,rc,keyframe);
+      coded+=TQB(cpi,mode,mb->Ryuv[1][1],mb->mv[0],1,req,rc,keyframe);
+      coded+=TQB(cpi,mode,mb->Ryuv[2][0],mb->mv[0],2,req,rc,keyframe);
+      coded+=TQB(cpi,mode,mb->Ryuv[2][1],mb->mv[0],2,req,rc,keyframe);
     }
     break;
     
   case OC_PF_444:
     for(i=0;i<4;i++)
-      TQB(cpi,mode,mb->Ryuv[1][i],mb->mv[i],1,req,rc);
+      coded+=TQB(cpi,mode,mb->Ryuv[1][i],mb->mv[i],1,req,rc,keyframe);
     for(i=0;i<4;i++)
-      TQB(cpi,mode,mb->Ryuv[2][i],mb->mv[i],2,req,rc);
+      coded+=TQB(cpi,mode,mb->Ryuv[2][i],mb->mv[i],2,req,rc,keyframe);
     break;
   }
+
+  return coded;
+
 }
 
 int PickModes(CP_INSTANCE *cpi, int recode){
@@ -698,6 +780,9 @@
   for(; sb<sb_end; sb++){
     for(j = 0; j<4; j++){ /* mode addressing is through Y plane, always 4 MB per SB */
       int mbi = sb->m[j];
+
+      if(mbi >= cpi->macro_total) continue;
+
       int cost[8] = {0,0,0,0, 0,0,0,0};
       int mb_mv_bits_0;
       int mb_gmv_bits_0;
@@ -707,7 +792,6 @@
       int aerror;
       int gerror;
       int block_err[4];
-      int flag4mv=0;
 
       macroblock_t *mb = &cpi->macro[mbi];
 
@@ -718,17 +802,17 @@
 	memmove(mb->analysis_mv+1,mb->analysis_mv,2*sizeof(mb->analysis_mv[0]));
 	
 	/* basic 1MV search always done for all macroblocks, coded or not, keyframe or not */
-	flag4mv = oc_mcenc_search(cpi, &mcenc, mbi, 0, mb->mv, &aerror, block_err);
+	oc_mcenc_search(cpi, &mcenc, mbi, 0, mb->mv, &aerror, block_err);
 	
 	/* replace the block MVs for not-coded blocks with (0,0).*/   
-	mb->coded = 0;
+	/*mb->coded = 0;
 	for ( bi=0; bi<4; bi++ ){
 	  int fi = mb->Ryuv[0][bi];
 	  if(!cp[fi]) 
 	    mb->mv[bi]=(mv_t){0,0};
 	  else
 	    mb->coded |= (1<<bi);
-	}
+	    }*/
 	
 	/* search golden frame */
 	oc_mcenc_search(cpi, &mcenc, mbi, 1, NULL, &gerror, NULL);
@@ -737,8 +821,11 @@
 
       if(cpi->FrameType == KEY_FRAME){
 	mb->mode = CODE_INTRA;
+	/* Transform, quantize, collect rho metrics */
+	TQMB(cpi, mb, qi, req, rho_count, 1);
+	
       }else{
-	
+
 	/**************************************************************
            Find the block choice with the lowest estimated coding cost
 
@@ -750,17 +837,14 @@
 	/* block coding cost is estimated from correlated SAD metrics */
 	/* At this point, all blocks that are in frame are still marked coded */
 
-	cost[CODE_INTER_NO_MV] = cost_inter(cpi, qi, mbi, (mv_t){0,0}, CODE_INTER_NO_MV);
+	cost[CODE_INTER_NO_MV] = cost_inter_nomv(cpi, qi, mbi);
 	cost[CODE_INTRA] = cost_intra(cpi, qi, mbi, &intrabits);
 	cost[CODE_INTER_PLUS_MV] = cost_inter1mv(cpi, qi, mbi, 0, &mb_mv_bits_0);
 	cost[CODE_INTER_LAST_MV] = cost_inter(cpi, qi, mbi, last_mv, CODE_INTER_LAST_MV);
 	cost[CODE_INTER_PRIOR_LAST] = cost_inter(cpi, qi, mbi, prior_mv, CODE_INTER_PRIOR_LAST);
 	cost[CODE_USING_GOLDEN] = cost_inter(cpi, qi, mbi, (mv_t){0,0},CODE_USING_GOLDEN);
 	cost[CODE_GOLDEN_MV] = cost_inter1mv(cpi, qi, mbi, 1, &mb_gmv_bits_0);
-	if(flag4mv)
-	  cost[CODE_INTER_FOURMV] = cost_inter4mv(cpi, qi, mbi, &mb_4mv_bits_0, &mb_4mv_bits_1);
-	else
-	  cost[CODE_INTER_FOURMV] = 99999999;
+	cost[CODE_INTER_FOURMV] = cost_inter4mv(cpi, qi, mbi, &mb_4mv_bits_0, &mb_4mv_bits_1);
 	
 	/* train this too... because the bit cost of an MV should be
 	   considered in the context of LAST_MV and PRIOR_LAST. */
@@ -769,7 +853,7 @@
 	/* the explicit MV modes (2,6,7) have not yet gone through
 	   halfpel refinement. We choose the explicit mv mode that's
 	   already furthest ahead on bits and refine only that one */
-	if(flag4mv && cost[CODE_INTER_FOURMV]<cost[CODE_INTER_PLUS_MV] && cost[CODE_INTER_FOURMV]<cost[CODE_GOLDEN_MV]){
+	if(cost[CODE_INTER_FOURMV]<cost[CODE_INTER_PLUS_MV] && cost[CODE_INTER_FOURMV]<cost[CODE_GOLDEN_MV]){
 	  oc_mcenc_refine4mv(cpi, mbi, block_err);
 	  cost[CODE_INTER_FOURMV] = cost_inter4mv(cpi, qi, mbi, &mb_4mv_bits_0, &mb_4mv_bits_1);
 	}else if (cost[CODE_GOLDEN_MV]<cost[CODE_INTER_PLUS_MV]){
@@ -786,7 +870,7 @@
 	for(i=1;i<8;i++)
 	  if(cost[i]<cost[mode])
 	    mode=i;
-	
+
 	/* add back such that inter/intra counting are relatively correct */
 	cost[CODE_INTER_PLUS_MV] += 384;
 	
@@ -794,22 +878,17 @@
 	case CODE_INTER_PLUS_MV:
 	  cpi->MVBits_0 += mb_mv_bits_0;
 	  cpi->MVBits_1 += 12;
-	  prior_mv = last_mv;
-	  last_mv = mb->mv[0] = mb->mv[1] = mb->mv[2] = mb->mv[3] = mb->analysis_mv[0][0];
+	  mb->mv[0] = mb->mv[1] = mb->mv[2] = mb->mv[3] = mb->analysis_mv[0][0];
 	  break;
 	case CODE_INTER_LAST_MV:
 	  mb->mv[0] = mb->mv[1] = mb->mv[2] = mb->mv[3] = last_mv;
 	  break;
 	case CODE_INTER_PRIOR_LAST:
 	  mb->mv[0] = mb->mv[1] = mb->mv[2] = mb->mv[3] = prior_mv;
-	  prior_mv = last_mv;
-	  last_mv = mb->mv[0];
 	  break;
 	case CODE_INTER_FOURMV:
 	  cpi->MVBits_0 += mb_4mv_bits_0;
 	  cpi->MVBits_1 += mb_4mv_bits_1;
-	  prior_mv = last_mv;
-	  last_mv = mb->mv[3]; /* if coded, it is still used forced to 0,0 according to spec */
 	  break;
 	case CODE_GOLDEN_MV:
 	  cpi->MVBits_0 += mb_gmv_bits_0;
@@ -820,9 +899,56 @@
 	  mb->mv[0] = mb->mv[1] = mb->mv[2] = mb->mv[3] = (mv_t){0,0};
 	  break;
 	}
-	oc_mode_set(cpi,mb,mode);      
+	mb->mode = mode;
 	
-	interbits += cost[mb->mode];
+	/* Transform, quantize, collect rho metrics */
+	if(!TQMB(cpi, mb, qi, req, rho_count, 0)){
+
+	  /* ended up not coding the macroblock at all */
+	  mb->coded = 0;
+	  mb->mode = CODE_INTER_NO_MV;
+
+	}else{
+
+	  /* still coding the MB */
+
+	  /* replace the block MVs for not-coded blocks with (0,0).*/   
+	  mb->coded = 0;
+	  for ( bi=0; bi<4; bi++ ){
+	    int fi = mb->Ryuv[0][bi];
+	    if(cp[fi]) 
+	      mb->coded |= (1<<bi);
+	  }
+
+	  switch(mb->mode){
+	  case CODE_INTER_PLUS_MV:
+	    prior_mv = last_mv;
+	    last_mv = mb->analysis_mv[0][0];
+	    break;
+	  case CODE_INTER_PRIOR_LAST:
+	    {
+	      mv_t temp = prior_mv;
+	      prior_mv = last_mv;
+	      last_mv = temp;
+	    }
+	    break;
+	  case CODE_INTER_FOURMV:
+	    prior_mv = last_mv;
+	    if(mb->coded & 0x8)
+	      last_mv = mb->mv[3];
+	    else if(mb->coded & 0x4)
+	      last_mv = mb->mv[2];
+	    else if(mb->coded & 0x2)
+	      last_mv = mb->mv[1];
+	    else 
+	      last_mv = mb->mv[0];
+	    break;
+	  }
+	  
+	  oc_mode_set(cpi,mb,mb->mode);      
+	  
+	  interbits += cost[mb->mode];
+	}
       }
 
 #ifdef COLLECT_METRICS
@@ -836,10 +962,6 @@
 	}
       }
 #endif
-
-      /* Transform, quantize, collect rho metrics */
-      TQMB(cpi, mb, qi, req, rho_count);
-
     }
   }
 



More information about the commits mailing list